Post a Link to the Reddit API – 发布到Reddit API的链接

最后修改: 2015年 3月 4日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this second article of the series, we’ll build some simple functionality to post on Reddit from our application, via their API.

系列的第二篇文章中,我们将构建一些简单的功能,通过Reddit的API,从我们的应用程序中发布到Reddit上。

2. Necessary Security

2.必要的安全

First – let’s get the security aspect out of the way.

首先–让我们把安全方面的问题说出来。

In order to Submit a Link to Reddit, we need to define an OAuth protected Resource with the scope of “submit“:

为了向Reddit提交链接,我们需要定义一个OAuth保护的资源,范围为”submit“。

@Bean
public OAuth2ProtectedResourceDetails reddit() {
    AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
    details.setId("reddit");
    details.setClientId(clientID);
    details.setClientSecret(clientSecret);
    details.setAccessTokenUri(accessTokenUri);
    details.setUserAuthorizationUri(userAuthorizationUri);
    details.setTokenName("oauth_token");
    details.setScope(Arrays.asList("identity", "submit"));
    details.setGrantType("authorization_code");
    return details;
}

Note that we’re also specifying the scopeidentity” because we also need access the user account information.

注意,我们还指定了scopeidentity“,因为我们还需要访问用户账户信息。

3. Is Captcha Needed?

3.是否需要验证码?

Users that are new to Reddit have to fill in a Captcha in order to submit; that is before they pass a certain karma threshold within Reddit.

新加入Reddit的用户必须填写一个验证码才能提交;这是在他们在Reddit内通过一定的业力门槛之前。

For these users, we first need to check if the Captcha is needed:

对于这些用户,我们首先需要检查是否需要验证码。

private String needsCaptcha() {
    String result = redditRestTemplate.getForObject(
      "https://oauth.reddit.com/api/needs_captcha.json", String.class);
    return result;
}

private String getNewCaptcha() {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity req = new HttpEntity(headers);

    Map<String, String> param = new HashMap<String, String>();
    param.put("api_type", "json");

    ResponseEntity<String> result = redditRestTemplate.postForEntity(
      "https://oauth.reddit.com/api/new_captcha", req, String.class, param);
    String[] split = result.getBody().split("""); 
    return split[split.length - 2];
}

4. The “Submit Post” Form

4.”提交帖子“表格

Next, let’s create the main form for submitting new posts to Reddit. Submitting a Link requires the following details:

接下来,让我们创建向Reddit提交新帖子的主表单。提交一个链接需要以下细节。

  • title – the title of the article
  • url – the URL of the article
  • subreddit – the sub-reddit to submit the link to

So let’s see how we can display this simple submission page:

因此,让我们看看如何显示这个简单的提交页面。

@RequestMapping("/post")
public String showSubmissionForm(Model model) throws JsonProcessingException, IOException {
    String needsCaptchaResult = needsCaptcha();
    if (needsCaptchaResult.equalsIgnoreCase("true")) {
        String iden = getNewCaptcha();
        model.addAttribute("iden", iden);
    }
    return "submissionForm";
}

And of course the basic submissionForm.html:

当然还有基本的submissionForm.html

<form>
    <input name="title"/>
    <input name="url" />
    <input name="sr"/>
    <input  type="checkbox" name="sendReplies" value="true"/>

    <div th:if="${iden != null}">
        <input type="hidden" name="iden" value="${iden}"/>
        <input name="captcha"/>
        <img src="http://www.reddit.com/captcha/${iden}" alt="captcha" width="200"/>
    </div>
    <button type="submit" onclick="submitPost()">Post</button>
</form>

<script>
function submitPost(){
    var data = {};
    $('form').serializeArray().map(function(x){data[x.name] = x.value;});
    $.ajax({
        url: "api/posts",
        data: JSON.stringify(data),
        type: 'POST',
        contentType:'application/json'
    }).done(function(data) {
        if(data.length < 2){ alert(data[0]);}
        else{
            window.location.href="submissionResponse?msg="+
              data[0]+"&url="+data[1];
        }
    }).fail(function(error) { alert(error.responseText); }); 
}
</script>

5. Submit a Link to Reddit

5.向Reddit提交链接

Now – let’s take a look at the final step – submitting the actual link via the Reddit API.

现在–让我们看看最后一步–通过Reddit API提交实际链接。

We’ll POST a submit request to Reddit using the parameters from our submissionForm:

我们将使用我们的submissionForm的参数向Reddit发送一个提交请求。

@Controller
@RequestMapping(value = "/api/posts")
public class RedditPostRestController {

    @Autowired
    private RedditService service;

    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public List<String> submit(@Valid @RequestBody PostDto postDto) {
        return service.submitPost(postDto);
    }
}

Here’s the actual method implementation:

下面是实际的方法实现。

public List<String> submitPost(PostDto postDto) {
    MultiValueMap<String, String> param1 = constructParams(postDto);
    JsonNode node = redditTemplate.submitPost(param1);
    return parseResponse(node);
}

private MultiValueMap<String, String> constructParams(PostDto postDto) {
    MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
    param.add("title", postDto.getTitle());
    param.add("sr", postDto.getSubreddit());
    param.add("url", postDto.getUrl());
    param.add("iden", postDto.getIden());
    param.add("captcha", postDto.getCaptcha());
    if (postDto.isSendReplies()) {
        param.add("sendReplies", "true");
    }

    param.add("api_type", "json");
    param.add("kind", "link");
    param.add("resubmit", "true");
    param.add("then", "comments");
    return param;
}

And the simple parsing logic, handling the response from the Reddit API:

还有简单的解析逻辑,处理来自Reddit API的响应

private List<String> parseResponse(JsonNode node) {
    String result = "";
    JsonNode errorNode = node.get("json").get("errors").get(0);
    if (errorNode != null) {
        for (JsonNode child : errorNode) {
            result = result + child.toString().replaceAll("\"|null", "") + "<br>";
        }
        return Arrays.asList(result);
    } else {
        if ((node.get("json").get("data") != null) && 
            (node.get("json").get("data").get("url") != null)) {
            return Arrays.asList("Post submitted successfully", 
              node.get("json").get("data").get("url").asText());
        } else {
            return Arrays.asList("Error Occurred while parsing Response");
        }
    }
}

All of this is working with a basic DTO:

所有这些都是用一个基本的DTO工作。

public class PostDto {
    @NotNull
    private String title;

    @NotNull
    private String url;

    @NotNull
    private String subreddit;

    private boolean sendReplies;

    private String iden;
    private String captcha;
}

Finally – the submissionResponse.html:

最后–submissionResponse.html

<html>
<body>
    <h1 th:text="${msg}">Hello</h1>
    <h1 th:if="${param.containsKey('msg')}" th:text="${param.msg[0]}">Hello</h1>
    <h2 th:if="${param.containsKey('url')}"><a th:href="${param.url[0]}">Here</a></h2>
</body>
</html>

6. Conclusion

6.结论

In this quick tutorial we implemented some basic Submit to Reddit functionality – simplistic but fully functional.

在这个快速教程中,我们实现了一些基本的Submit to Reddit功能–简单但功能齐全。

In the next part of this case study, we’ll implement a Schedule Post for Later functionality into our app.

在本案例研究的下一部分,我们将在我们的应用程序中实现Schedule Post for Later功能。

The full implementation of this tutorial can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

本教程的完整实现可以在github 项目中找到 – 这是一个基于 Eclipse 的项目,因此应该可以轻松导入并按原样运行。