From 8477579e0b353a0a85fba50812a5dda0127912bb Mon Sep 17 00:00:00 2001
From: Omar Roth <omarroth@hotmail.com>
Date: Sat, 21 Apr 2018 18:04:01 -0500
Subject: [PATCH] Clean up Reddit mapping

---
 src/helpers.cr      | 78 ++++++++++++++++++++++++++++-----------------
 src/views/watch.ecr |  4 +--
 2 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/src/helpers.cr b/src/helpers.cr
index 851b7e3a..20477241 100644
--- a/src/helpers.cr
+++ b/src/helpers.cr
@@ -114,36 +114,50 @@ class User
   })
 end
 
-class RedditSubmit
+class RedditThing
   JSON.mapping({
-    data: RedditSubmitData,
+    kind: String,
+    data: RedditComment | RedditLink | RedditMore | RedditListing,
   })
 end
 
-class RedditSubmitData
+class RedditComment
   JSON.mapping({
-    children: Array(RedditThread),
+    author:    String,
+    body_html: String,
+    replies:   RedditThing | String,
+    score:     Int32,
+    depth:     Int32,
   })
 end
 
-class RedditThread
+class RedditLink
   JSON.mapping({
-    data: RedditThreadData,
-  })
-end
-
-class RedditThreadData
-  JSON.mapping({
-    subreddit:    String,
-    id:           String,
-    num_comments: Int32,
-    score:        Int32,
     author:       String,
+    score:        Int32,
+    subreddit:    String,
+    num_comments: Int32,
+    id:           String,
     permalink:    String,
     title:        String,
   })
 end
 
+class RedditMore
+  JSON.mapping({
+    children: Array(String),
+    count:    Int32,
+    depth:    Int32,
+  })
+end
+
+class RedditListing
+  JSON.mapping({
+    children: Array(RedditThing),
+    modhash:  String,
+  })
+end
+
 # See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
 def ci_lower_bound(pos, n)
   if n == 0
@@ -376,35 +390,39 @@ def get_reddit_comments(id, client, headers)
   search_results = client.get("/search.json?q=#{query}", headers)
 
   if search_results.status_code == 200
-    search_results = RedditSubmit.from_json(search_results.body)
+    search_results = RedditThing.from_json(search_results.body)
 
-    thread = search_results.data.children.sort_by { |child| child.data.score }[-1]
-    result = client.get("/r/#{thread.data.subreddit}/comments/#{thread.data.id}?limit=100&sort=top", headers).body
-    result = JSON.parse(result)
+    thread = search_results.data.as(RedditListing).children.sort_by { |child| child.data.as(RedditLink).score }[-1]
+    thread = thread.data.as(RedditLink)
+
+    result = client.get("/r/#{thread.subreddit}/comments/#{thread.id}?limit=100&sort=top", headers).body
+    result = Array(RedditThing).from_json(result)
   elsif search_results.status_code == 302
-    search_results = client.get(search_results.headers["Location"], headers).body
+    result = client.get(search_results.headers["Location"], headers).body
+    result = Array(RedditThing).from_json(result)
 
-    result = JSON.parse(search_results)
-    thread = RedditThread.from_json(result[0]["data"]["children"][0].to_json)
+    thread = result[0].data.as(RedditListing).children[0].data.as(RedditLink)
   else
     raise "Got error code #{search_results.status_code}"
   end
 
-  comments = result[1]["data"]["children"]
+  comments = result[1].data.as(RedditListing).children
   return comments, thread
 end
 
 def template_comments(root)
   html = ""
   root.each do |child|
-    if child["data"]["body_html"]?
-      author = child["data"]["author"]
-      score = child["data"]["score"]
-      body_html = HTML.unescape(child["data"]["body_html"].as_s)
+    if child.data.is_a?(RedditComment)
+      child = child.data.as(RedditComment)
+      author = child.author
+      score = child.score
+      body_html = HTML.unescape(child.body_html)
 
       replies_html = ""
-      if child["data"]["replies"] != ""
-        replies_html = template_comments(child["data"]["replies"]["data"]["children"])
+      if child.replies.is_a?(RedditThing)
+        replies = child.replies.as(RedditThing)
+        replies_html = template_comments(replies.data.as(RedditListing).children)
       end
 
       content = <<-END_HTML
@@ -417,7 +435,7 @@ def template_comments(root)
       </div>
       END_HTML
 
-      if child["data"]["depth"].as_i > 0
+      if child.depth > 0
         html += <<-END_HTML
           <div class="pure-g">
           <div class="pure-u-1-24">
diff --git a/src/views/watch.ecr b/src/views/watch.ecr
index 653d7cfb..97bd9927 100644
--- a/src/views/watch.ecr
+++ b/src/views/watch.ecr
@@ -186,10 +186,10 @@ player.src(currentSources);
                 <div>
                     <h3>
                         <a href="javascript:void(0)" onclick="toggle_comments(this)">[ - ]</a> 
-                        <%= reddit_thread.data.title %>
+                        <%= reddit_thread.title %>
                     </h3>
                     <b>
-                        <a target="_blank" href="https://reddit.com<%= reddit_thread.data.permalink %>">View more comments on Reddit</a>
+                        <a target="_blank" href="https://reddit.com<%= reddit_thread.permalink %>">View more comments on Reddit</a>
                     </b>
                 </div>
                 <div>