"use strict"; var app = (function(){ return { loadPage: function() { // Just fucking crach if the user is retarded if(_.isUndefined(Reddit.threadID) || _.isUndefined(Reddit.subreddit)) { Status.error("Missing necessary parts of the URL"); return; } Status.loading("Loading thread..."); Reddit.fetchToken() .then(function(){ return Promise.all([ fetch(URLs.thread, Reddit.init) .then(Fetch2.json) .then(ThreadHTML.createThread), fetch(URLs.pushshiftIDs) .then(Fetch2.json) .then(_.property("data")) ]) }) .then(function(results) { var thread = results[0]; Comments.allIDs = results[1]; Status.loading("Loading comments from reddit..."); HandleIDs.normal(thread); console.log("After normal", Comments.ids.length); return HandleIDs.morechildren(); }) .then(function(){ console.log("After morechildren", Comments.ids.length); return Promise.all(_.map(_.uniq(Comments.countinuethread), function(id) { return fetch(URLs.thread+"/_/"+id.split("_")[1], Reddit.init) .then(Fetch2.json) })); }).then(function(smallerThreads){ _.forEach(smallerThreads, function(thread){ HandleIDs.normal(thread); }) console.log("After continueThisThread", Comments.ids.length); console.log("Total", Comments.ids.length); console.log("Unique", _.uniq(Comments.ids).length); Status.loading("Getting removed comments..."); HandleIDs.removed(); console.log("Removed", Comments.removed.length); ThreadHTML.createCommentInfo(Comments.removed.length); return Fetch2.multiple(URLs.format(URLs.pushshiftComments, Comments.removed), null, "data"); }) .then(function(removedComments){ Status.loading("Generating comments..."); return Comments.generate(removedComments); }) .then(function(){ Status.success(); }); } }})() // ------------------------------------------------------------------------------ // ----------------------- Store and genrates comments -------------------------- // ------------------------------------------------------------------------------ var Comments = (function() { var totalComments; var lookup = {}; var toBeCreated = []; var getParentComments = function(toLookup){ var newCommentsToLookup = []; var commentsToFetch = []; _.forEach(toLookup, function(id){ var parentID = lookup[id].parent_id.split("_")[1]; if(parentID === Reddit.threadID) {} // Has no parent (is parent of thread) else if(_.includes(Comments.toBeCreated, parentID)) {} // Parent already exists, do nothing else if(_.includes(newCommentsToLookup, parentID)) {} // Parent already exists (this iteration) else if(_.has(lookup, parentID)) { newCommentsToLookup.push(parentID); } else{ commentsToFetch.push(parentID); } Comments.toBeCreated.push(id); }); return new Promise(function(resolve, reject){ if(_.uniq(commentsToFetch).length !== 0) { fetch(URLs.singleComments + _.join(_.map(_.uniq(commentsToFetch),function(comments){ return "t1_" + comments; })), Reddit.init) .then(Fetch2.json) .then(function(json){ _.forEach(json.data.children, function(comment) { lookup[comment.data.id] = comment.data; newCommentsToLookup.push(comment.data.id); }); }) .then(function(){ resolve(); }); } else { resolve(); } }) .then(function(){ if(newCommentsToLookup.length !== 0) { return getParentComments(newCommentsToLookup) } }); }; return { ids: [], // The comments we found morechildren: [], countinuethread: [], allIDs: [], // All the comments that we were suppose to find removed: [], deleted: [], toBeCreated: toBeCreated, lookup: lookup, getTotalComments: function() { return totalComments; }, setTotalComments: function(total) { totalComments = total; }, getRoot: function() { if(Reddit.permalink !== undefined && Reddit.permalink === "") { return Reddit.threadID; } if(Reddit.permalink === undefined) { return Reddit.threadID; } if(_.has(Comments.lookup, Reddit.permalink)) { return Comments.lookup[Reddit.permalink].parent_id.split("_")[1]; } return ""; }, generate: function(removedComments) { removedComments.forEach(function(comment){ if(_.includes(Comments.deleted, comment.id)) { comment["deleted"] = true; } else { comment["removed"] = true; } Comments.lookup[comment.id] = comment; }); Comments.removed = _.map(removedComments, function(comment){ return comment.id; }); return getParentComments(Comments.removed) .then(function(){ //console.log("Removed length", Comments.removed.length) //console.log("ToBeCreated", Comments.toBeCreated); ThreadHTML.createCommentSection(); ThreadHTML.createComments(); }) } }})() // ------------------------------------------------------------------------------ // ----------------- Handle comments from different requests -------------------- // ------------------------------------------------------------------------------ var HandleIDs = (function(){ var normal = function(thread){ return _.flatten(_.map(thread[1].data.children, Extract.normal)) }; var morechildren = function(){ return Promise.all(_.map(_.uniq(Comments.morechildren), function(idArray){ return Fetch2.multiple(URLs.format(URLs.moreChildren, idArray), Reddit.init); })) .then(function(responseArrays){ Comments.morechildren.length = 0; _.forEach(responseArrays, function(responseArray){ _.forEach(responseArray, function(response){ _.forEach(response.jquery[10][3][0], function(comment){ Extract.normal(comment); }) }); }); }).then(function(){ if(Comments.morechildren.length !== 0) { return morechildren(); } }); }; var removed = function(){ Comments.removed = _.difference(Comments.allIDs, Comments.ids); Comments.ids.forEach(function(id){ if(! _.has(Comments.lookup, id)) { return; } if(Comments.lookup[id].body === "[removed]") { Comments.removed.push(id); } else if (Comments.lookup[id].body === "[deleted]"){ Comments.removed.push(id); Comments.deleted.push(id); } }); Comments.removed = _.uniq(Comments.removed); }; return { normal: normal, morechildren: morechildren, removed: removed }; })() // ------------------------------------------------------------------------------ // ----------------------- Extract ID from comments ----------------------------- // ------------------------------------------------------------------------------ var Extract = (function(){ var normal = function(comment){ var data = comment.data; if(comment.kind == "more") { // "Show more"-comment if(data.id === "_") { // = "continue this thread" comment Comments.countinuethread.push(data.parent_id); } else if(data.children.length < data.count){ // "Load more"-comment (that is missing some of its children) Comments.morechildren.push(data.children); } Comments.ids.push.apply(Comments.ids, data.children); } else { // Normal comment if(data.replies) { data.replies.data.children.forEach(function(child){ normal(child); }); delete data.replies; } Comments.ids.push(data.id); Comments.lookup[data.id] = data; } }; return { normal: normal }; })() // ------------------------------------------------------------------------------ // ---------------------------- Generating HTML --------------------------------- // ------------------------------------------------------------------------------ var ThreadHTML = (function(){ var mainDiv = document.getElementById("main"); // I actually haven't found a better way of doing this... // Imgur has image-links with no indication that they are actually images var imageHosts = ["i.redd.it", "flickr.com", "i.imgur.com", "imgur.com", "m.imgur.com"]; var createThread = function(data) { var thread = data[0].data.children[0].data; Comments.setTotalComments(thread.num_comments); document.title = thread.title+" : "+thread.subreddit; var threadDiv = document.createElement("div"); threadDiv.innerHTML = ' \
\
\
\
'+Format.prettyScore(thread.score)+'
\
\
\
\
\ '+(thread.link_flair_text !== null ? ''+thread.link_flair_text+'' : '') + ''+thread.title+' \ ('+thread.domain+') \
\ submitted '+Format.prettyDate(thread.created_utc)+' by \ '+thread.author+' to \ /r/'+thread.subreddit+' \
' + (thread.selftext !== '' ? '
'+Format.parse(thread.selftext)+'
':'') + '' + (thread.media !== null ? HTML.parse(thread.media_embed.content) : '') + (_.includes(imageHosts, thread.domain) && _.has(thread, "preview") ? '' : '') + '
\
\ '; mainDiv.appendChild(threadDiv); return data; }; var createCommentInfo = function(totalRemovedComments){ var div = document.createElement("div"); div.innerHTML = ' \
\ removed comments: '+totalRemovedComments+'/'+Comments.getTotalComments()+' ('+(100 * totalRemovedComments / Comments.getTotalComments()).toFixed(1)+'%) \
\
sorted by: top
\ '; mainDiv.appendChild(div); }; var createCommentSection = function(){ var div = document.createElement("div"); div.id = Comments.getRoot(); mainDiv.appendChild(div); }; var createComments = function(){ var commentsToCreate = _.sortBy(_.uniq(Comments.toBeCreated), function(id) { return Comments.lookup[id].score; }); var createdComments = [Comments.getRoot()]; var didSomething = false; while(commentsToCreate.length > 0) { didSomething = false; for(var i = commentsToCreate.length - 1; i >= 0; i--) { var id = commentsToCreate[i]; var parentID = Comments.lookup[id].parent_id.split("_")[1]; if(_.includes(createdComments, parentID)) { document.getElementById(parentID).appendChild(createComment(Comments.lookup[id])); createdComments.push(id); commentsToCreate.splice(i, 1); didSomething = true; } } // Fail safe (parents missing for the rest of the comments, shouldn't happend but oh well :D) if(!didSomething) { console.error("Didn't generate all comments correctly"); break; } } }; var createComment = function(comment){ var isRemoved = _.has(comment,"removed"); var isDeleted = _.has(comment,"deleted"); // Sorry var commentCss = "comment-" + (isRemoved ? "removed" : (isDeleted ? "deleted" : (comment.depth % 2 == 0 ? "even" : "odd"))); var commentDiv = document.createElement("div"); commentDiv.id = comment.id; commentDiv.className = "comment " + commentCss; commentDiv.innerHTML = ' \
\ [–] \ '+comment.author+(isDeleted ? " (deleted by user)" : "")+' \ '+Format.prettyScore(comment.score)+' point'+((comment.score == 1) ? '': 's')+' \ '+Format.prettyDate(comment.created_utc)+' \
\
'+(comment.body === "[removed]" && isRemoved ? "

[likely removed by automoderator]

" : Format.parse(comment.body))+'
\ '; return commentDiv; }; return { createThread: createThread, createCommentInfo: createCommentInfo, createCommentSection: createCommentSection, createComments: createComments } })() app.loadPage()