aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/jamesbarnett/redditlite/service/SubredditService.kt
blob: 8c01c930b59a957db470393ff3662a081f4ed2a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package io.jamesbarnett.redditlite.service

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.treeToValue
import io.jamesbarnett.redditlite.model.Comment
import io.jamesbarnett.redditlite.model.Post
import io.jamesbarnett.redditlite.model.PostDetail
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.stereotype.Service
import org.springframework.web.client.RestTemplate
import java.time.Duration

const val REDDIT_API_ROOT_URL = "https://reddit.com/r/"

@Service
class SubredditService (restTemplateBuilder: RestTemplateBuilder) {

  val objectMapper: ObjectMapper = jacksonObjectMapper()
      .registerModule(JavaTimeModule())

  val restTemplate: RestTemplate = restTemplateBuilder
      .setConnectTimeout(Duration.ofSeconds(5))
      .setReadTimeout(Duration.ofSeconds(10))
      // Custom UA required to prevent rate limiting: https://github.com/reddit-archive/reddit/wiki/API#rules
      .defaultHeader("User-Agent", "reddit-lite")
      .build()

  fun getPosts(subreddit: String, postsAfterId: String?): List<Post> {
    val jsonResponse = restTemplate.getForObject("${REDDIT_API_ROOT_URL}${subreddit}/.json${if (postsAfterId != null) "?after=${postsAfterId}" else ""}", String::class.java)
    return objectMapper.readTree(jsonResponse)
      .path("data")
      .path("children")
      .findValues("data")
      .map { objectMapper.treeToValue(it, Post::class.java) }
  }

  fun getPostDetail(subreddit: String, postId: String): PostDetail {
    val jsonResponse = restTemplate.getForObject("${REDDIT_API_ROOT_URL}${subreddit}/comments/${postId}/.json", String::class.java)
    val rootNode = objectMapper.readTree(jsonResponse)

    val post = objectMapper.treeToValue(
      rootNode
        .path(0)
        .path("data")
        .path("children")
        .path(0)
        .path("data"),
      Post::class.java)

    val comments = rootNode
      .path(1)
      .path("data")
      .path("children")
      .findValues("data")
      .map { Comment(it, objectMapper) }

    return PostDetail(post, comments)
  }

}