"use strict"; const markdown = SnuOwnd.getParser(); const thread_url = `https://oauth.reddit.com/r/${subreddit}/comments/${thread_id}`; const morechildren_url = `https://oauth.reddit.com/api/morechildren?link_id=t3_${thread_id}&children=`; const single_comment_url = `https://oauth.reddit.com/r/${subreddit}/api/info/?id=t1_`; const removed_comments_url = "/comments/?c="; const main_div = document.getElementById("main"); const loading_comments = document.getElementById("loading-comments"); const comment_ids = new Set(); const comment_lookup = new Map(); const comments_to_generate = []; const comments_to_generate_ids = new Set(); let ajax_calls_left = 0; let total_comments; get_multiple([single_comment_url+"dlg744z",single_comment_url+"dlu05ei",single_comment_url+"dlu08gp"], response => console.log(response), () => console.log("done with all") ); /* get(thread_url, response => { const json = JSON.parse(response); generate_thread(json[0].data.children[0].data); get_comment_ids(json[1].data.children); });*/ function generate_thread(thread) { const thread_div = document.createElement("div"); thread_div.id = "thread"; const thread_string = `
${pretty_score(thread.score)}
${thread.link_flair_text !== null ? ''+thread.link_flair_text+'' : ''} ${thread.title} (${thread.domain})
submitted ${pretty_date(thread.created_utc)} by ${thread.author} to /r/${subreddit}
${thread.selftext !== '' ? '
'+markdown.render(thread.selftext)+'
':''}
`; thread_div.innerHTML = thread_string; main_div.insertBefore(thread_div, loading_comments); total_comments = thread.num_comments; } function get_comment_ids(comments) { comments.forEach(comment => extract_id_from_comment(comment)); if(ajax_calls_left == 0) { get_all_comment_ids(); } } function extract_id_from_comment(comment) { // "Show more"-comments if(comment.kind == "more") { const children = comment.data.children; // Some "show more"-comments were missing, need to do more ajax-calls if(children.length < comment.data.count){ ajax_calls_left++; get(morechildren_url + children.join(), response => handle_show_more_comments(JSON.parse(response))); } if(children.length > 0) { comment_ids.add(...children); } } // Normal comment else { const data = comment.data; if(data.replies) { data.replies.data.children.forEach(child => extract_id_from_comment(child)); } delete data.replies; comment_lookup.set(data.id, data); comment_ids.add(data.id); } } function handle_show_more_comments(comments) { comments.jquery[14][3][0].forEach(comment => { if(comment.kind == "more") { let children = comment.data.children; if(children.length < comment.data.count) { ajax_calls_left++; get(morechildren_url + children.join(), response => handle_show_more_comments(JSON.parse(response))); } comment_ids.add(...children); } else { comment_ids.add(comment.data.id); comment_lookup.set(comment.data.id, comment.data); } }); ajax_calls_left--; if(ajax_calls_left == 0) { get_all_comment_ids(); } } function get_all_comment_ids() { const ids_diff = new Set([...all_ids].filter(x => !comment_ids.has(x))); console.log(all_ids); console.log(comment_ids); console.log(ids_diff); if(ids_diff.size > 144) { alert("very many removal, aborting"); return; } get(removed_comments_url + [...ids_diff].join(), response => create_comments(JSON.parse(response).data)); } function create_comments(comments) { create_comment_info(comments.length); comments.forEach(comment => { comment["removed"] = true; comments_to_generate.push(comment); comments_to_generate_ids.add(comment.id); comment_lookup.set(comment.id, comment); }); create_parent_comments(); } function create_parent_comments() { let done = true; let parent_id; let comment; for(let i = comments_to_generate.length - 1; i >= 0; i--) { comment = comments_to_generate[i]; parent_id = comment_lookup.get(comment.id).parent_id.split("_")[1]; // Done with this comment if(parent_id == thread_id || comments_to_generate_ids.has(parent_id)) {} // parent comment exists in lookup but hasnt been added to the queue yet else if(comment_lookup.has(parent_id)) { console.log(i, "finding parent in lookup"); comments_to_generate.push(comment_lookup.get(parent_id)); comments_to_generate_ids.add(parent_id); done = false; } // parent comment doesn't exists else { get(single_comment_url + parent_id, response => { let new_comment = JSON.parse(response).data.children[0].data; comments_to_generate.push(new_comment); comments_to_generate_ids.add(new_comment.id); create_parent_comments(); console.log(parent_id, " created via /api/info ???"); }); done = false; console.log(i, " doesn't exist"); } } if(!done) { create_parent_comments(); } else { generate_comments(); } } function generate_comments() { const comment_section = document.createElement("div"); comment_section.id = thread_id; main_div.insertBefore(comment_section, loading_comments); comments_to_generate.sort(function(a, b) { if(a.score == b.score) { return 0; } return a.score > b.score ? 1 : -1; }); const generated_comment_ids = new Set([thread_id]); let parent_id; let comment; while(comments_to_generate.length > 0) { for(let i = comments_to_generate.length -1; i >= 0; i--) { comment = comments_to_generate[i]; parent_id = comment.parent_id.split("_")[1]; if(generated_comment_ids.has(parent_id)) { document.getElementById(parent_id).appendChild(create_comment(comment_lookup.get(comment.id))); generated_comment_ids.add(comment.id); comments_to_generate.splice(i, 1); } } } } function create_comment(comment) { const comment_div = document.createElement("div"); //comment_div.className = "comment " + (comment.hasOwnProperty("removed") ? "comment-removed" : ); if(comment.hasOwnProperty("removed")) { comment_div.className = "comment comment-removed"; } else { comment_div.className = "comment comment-" + (comment.depth % 2 == 0 ? "even" : "odd"); } comment_div.id = comment.id; const comment_html = `
[–] ${comment.author} ${comment.score} point${(comment.score == 1) ? '': 's'} ${pretty_date(comment.created_utc) }
${markdown.render(comment.body)}
`; comment_div.innerHTML = comment_html; return comment_div; } function create_comment_info(removed_comments) { const comment_info = document.createElement("div"); comment_info.innerHTML = `
removed comments: ${removed_comments}/${total_comments} (${ (100 * removed_comments / total_comments).toFixed(1)}%)
sorted by: top
`; main_div.insertBefore(comment_info, loading_comments); } // ---------------- Other less interesting functions ------------------------ function get(url, callback) { const xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { callback(JSON.parse(this.responseText)); } else if (this.readyState == 4) { alert(this.status + " error: " + this.responseText); // Error handle } } xhttp.open("GET", url, true); xhttp.setRequestHeader("Authorization", "bearer " + token); xhttp.send(); } function get_multiple(urls, callback, all_completed_callback) { let num_calls_left = urls.length; urls.forEach(url => { get(url, function(data){ callback(data); num_calls_left--; if(num_calls_left == 0) { all_completed_callback(); } }); }); } // UTC -> "Reddit time format" function pretty_date(created_utc) { const current_utc = Math.floor((new Date()).getTime() / 1000); const second_diff = current_utc - created_utc; const day_diff = Math.floor(second_diff / 86400); if(day_diff < 0) return ''; if(day_diff == 0) { if(second_diff < 10) return "just now"; if(second_diff < 60) return second_diff + " seconds ago"; if(second_diff < 120) return "a minute ago"; if(second_diff < 3600) return Math.floor(second_diff / 60) + " minutes ago"; if(second_diff < 7200) return "an hour ago"; if(second_diff < 86400) return Math.floor(second_diff / 3600) + " hours ago"; } if(day_diff == 1) return "Yesterday"; if(day_diff < 7) return day_diff + " days ago"; if(day_diff < 31) return Math.floor(day_diff / 7) + " weeks ago"; if(day_diff < 365) return Math.floor(day_diff / 30) + " months ago"; return Math.floor(day_diff / 365) + " years ago"; } function pretty_score(score) { if(score >= 10000) { return (score / 1000).toFixed(1) + "k"; } else { return score; } }