diff --git a/static/script.js b/static/script.js index 54ae828..30d6f78 100644 --- a/static/script.js +++ b/static/script.js @@ -1,38 +1,214 @@ "use strict"; -const markdown = SnuOwnd.getParser(); +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 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 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; +const comment_ids = [] +const morechildren_ids = [] +const continuethisthread_ids = [] +const max_ids_per_call = 100 +const comment_lookup = new Map() +const comments_to_create = [] +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); -});*/ +const reddit_init = { + headers: { "Authorization": "bearer " + token } +} -function generate_thread(thread) { - const thread_div = document.createElement("div"); - thread_div.id = "thread"; +load_page() - const thread_string = ` +async function load_page() { + const json = await fetch(thread_url, reddit_init).then(thread => thread.json()) + + generate_thread(json) + comment_ids.push(...get_comment_ids(json)) + + const smaller_threads = await Promise.all(continuethisthread_ids.map(id =>fetch(thread_url + "/_/" + id.split("_")[1], reddit_init))) + const smaller_threads_json = await Promise.all(smaller_threads.map(x => x.json())) + smaller_threads_json.forEach(thread => comment_ids.push(...get_comment_ids(thread))) + + await get_morechildren_ids() + const removed_comments = await get_removed_comments() + + generate_comments(removed_comments) +} + +async function get_removed_comments() { + const ids_diff = all_ids.filter(x => !comment_ids.includes(x)) + generate_comment_info(ids_diff.length) + console.log(all_ids) + console.log(comment_ids) + console.log(comment_ids.length, new Set(comment_ids).size) + console.log(ids_diff) + return fetch_multiple(removed_comments_url, ids_diff, ["data"], true) +} + +async function get_continuethisthread_ids() { + return +} + +async function get_morechildren_ids() { + console.log("asdf") + const responses = await Promise.all(split_array(morechildren_ids, max_ids_per_call).map(ids => fetch(morechildren_url + ids.join(), reddit_init))) + const responses_json = await Promise.all(responses.map(x => x.json())) + morechildren_ids.length = 0 + responses_json.forEach(extract_morechildren_ids) + + if(morechildren_ids.length !== 0) { + await get_morechildren_ids() + } +} + +function extract_morechildren_ids(comments) { + comments.jquery[14][3][0].forEach(comment => { + if(comment.kind == "more") { + const children = comment.data.children + + if(children.length < comment.data.count) { + morechildren_ids.push(...children) + } + comment_ids.push(...children) + + } else { + comment_ids.push(comment.data.id) + comment_lookup.set(comment.data.id, comment.data) + } + }); +} +function get_comment_ids(data) { + return flatten_array(data[1].data.children.map(extract_id_from_comment)) +} + +function extract_id_from_comment(comment) { + const data = comment.data + // "Show more"-comments + if(comment.kind == "more") { + console.log(data.id) + console.log(data.name) + console.log(data.parent_id) + console.log(data.children) + console.log(data.children.length + "/" + data.count) + console.log("-----------------------") + + if(data.id === "_") { + continuethisthread_ids.push(data.parent_id) + return [] + } + if(data.children.length < data.count){ + morechildren_ids.push(...data.children) + // ???????????????????? maybe wrong, data.id? ytest this + //return [] //----------------------------------- + } + return data.children + } + // Normal comment + let replies_ids = [data.id] + + if(data.replies) { + data.replies.data.children.forEach(child => replies_ids.push(...extract_id_from_comment(child))) + delete data.replies + } + + comment_lookup.set(data.id, data) + return replies_ids +} + +// ------------------------------------------------------------------------------------- +// ----------------- Comment generating functions --------------------- +// ------------------------------------------------------------------------------------- + +async function generate_comments(removed_comments) { + const comment_section = document.createElement("div") + comment_section.id = thread_id + main_div.insertBefore(comment_section, loading_comments) + + removed_comments.forEach(comment => { + comment["removed"] = true + comment_lookup.set(comment.id, comment) + console.log(comment.id) + }) + + const comments_to_lookup = removed_comments.map(comment => comment.id) + await get_comments_to_generate(comments_to_lookup) + + comments_to_create.sort(function(a, b) { + const a_score = comment_lookup.get(a).score + const b_score = comment_lookup.get(b).score + + return a_score === b_score ? 0 : (a_score > b_score ? 1 : -1) + }); + + create_comments() +} + +async function get_comments_to_generate(comments_to_lookup) { + const new_comments_to_lookup = [] + + comments_to_lookup.forEach(id => { + const parent_id = comment_lookup.get(id).parent_id.split("_")[1] + + if(parent_id === thread_id) {} // Has no parent (is parent of thread) + else if(comments_to_create.includes(parent_id)) {} // Parent already exists, do nothing + else if(new_comments_to_lookup.includes(parent_id)) {} // Parent already exists (this iteration) + else if(comment_lookup.has(parent_id)) { + new_comments_to_lookup.push(parent_id) + } else{ + console.error("Comment doesn't exists, HALP") + console.log(id) + console.log(parent_id) + } + + comments_to_create.push(id) + }) + + if(new_comments_to_lookup.length !== 0) { + await get_comments_to_generate(new_comments_to_lookup) + } +} + +function create_comments() { + const created_comment_ids = [thread_id] + let id, parent_id + let did_something + + while(comments_to_create.length > 0) { + did_something = false + + for(let i = comments_to_create.length -1; i >= 0; i--) { + id = comments_to_create[i] + parent_id = comment_lookup.get(id).parent_id.split("_")[1] + + if(created_comment_ids.includes(parent_id)) { + document.getElementById(parent_id).appendChild(create_comment(comment_lookup.get(id))) + created_comment_ids.push(id) + comments_to_create.splice(i, 1) + did_something = true + } + } + + if(!did_something) { + console.error("Didn't generate all comments correctly") + break + } + } +} + +// ------------------------------------------------------------------------------------- +// --------------------- HTML-generating functions ---------------------- +// ------------------------------------------------------------------------------------- + +function generate_thread(data) { + const thread = data[0].data.children[0].data + const thread_div = document.createElement("div") + thread_div.id = "thread" + thread_div.innerHTML = `
${pretty_score(thread.score)}
@@ -50,283 +226,104 @@ function generate_thread(thread) {
${thread.selftext !== '' ? '
'+markdown.render(thread.selftext)+'
':''} - `; + ` - thread_div.innerHTML = thread_string; - main_div.insertBefore(thread_div, loading_comments); - total_comments = thread.num_comments; + 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 = ` + const comment_div = document.createElement("div") + comment_div.id = comment.id + comment_div.className = "comment comment-" + (comment.hasOwnProperty("removed") ? "removed" : (comment.depth % 2 == 0 ? "even" : "odd")); + comment_div.innerHTML = `
[–] ${comment.author} - ${comment.score} point${(comment.score == 1) ? '': 's'} + ${pretty_score(comment.score)} point${(comment.score == 1) ? '': 's'} ${pretty_date(comment.created_utc) }
${markdown.render(comment.body)}
- `; - - comment_div.innerHTML = comment_html; - return comment_div; + ` + return comment_div } -function create_comment_info(removed_comments) { - const comment_info = document.createElement("div"); +function generate_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); + ` + main_div.insertBefore(comment_info, loading_comments) } +// ------------------------------------------------------------------------------------- +// ----------------------------- AJAX-functions --------------------------------- +// ------------------------------------------------------------------------------------- -// ---------------- Other less interesting functions ------------------------ +async function fetch_multiple(url, data, json_walkdown=[], flattening=false) { + const responses = await Promise.all(split_array(data, max_ids_per_call).map(single_request_data => fetch(url + single_request_data.join()))) + let json = await Promise.all(responses.map(x => x.json())) + json_walkdown.forEach(property =>{ + json.forEach((x, i) => json[i] = json[i][property]) + }) + return flattening ? flatten_array(json) : json +} +// ------------------------------------------------------------------------------------- +// ---------------- 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 - } - } +function split_array(array, size) { + const array_split = [] - xhttp.open("GET", url, true); - xhttp.setRequestHeader("Authorization", "bearer " + token); - xhttp.send(); + for(let i = 0, len = array.length ; i < len; i += size) { + array_split.push(array.slice(i, i + size)) + } + + return array_split } -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(); - } - }); - }); +function flatten_array(arrays) { + return arrays.reduce((array, item) => { return array.concat(item) }, []) } // 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); + 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 ''; + return '' if(day_diff == 0) { if(second_diff < 10) - return "just now"; + return "just now" if(second_diff < 60) - return second_diff + " seconds ago"; + return second_diff + " seconds ago" if(second_diff < 120) - return "a minute ago"; + return "a minute ago" if(second_diff < 3600) - return Math.floor(second_diff / 60) + " minutes ago"; + return Math.floor(second_diff / 60) + " minutes ago" if(second_diff < 7200) - return "an hour ago"; + return "an hour ago" if(second_diff < 86400) - return Math.floor(second_diff / 3600) + " hours ago"; + return Math.floor(second_diff / 3600) + " hours ago" } if(day_diff == 1) - return "Yesterday"; + return "Yesterday" if(day_diff < 7) - return day_diff + " days ago"; + return day_diff + " days ago" if(day_diff < 31) - return Math.floor(day_diff / 7) + " weeks ago"; + 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"; + 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; - } + return score >= 10000 ? (score / 1000).toFixed(1) + "k" : score } \ No newline at end of file diff --git a/static/style.css b/static/style.css index c5abb3f..983214a 100644 --- a/static/style.css +++ b/static/style.css @@ -40,11 +40,6 @@ a:hover { color: #6a98af; } -/* -.user-link:hover { - text-decoration: underline; -}*/ - #header { background-color: #181818; @@ -53,11 +48,13 @@ a:hover { #header a { color: #ddd; + transition: color 0.3s; } #header a:hover { - color: #fff; + color: #ca302c; text-decoration: none; + } #header-title { @@ -159,7 +156,7 @@ a:hover { } #comment-info { - color: red; + color: #ca302c; margin-top: 10px; padding-bottom: 5px; border-bottom: 1px dotted #808080; @@ -199,6 +196,7 @@ a:hover { } .comment-body { + max-width: 840px; line-height: 20px; } diff --git a/templates/header.html b/templates/header.html index cba62d6..aa9d634 100644 --- a/templates/header.html +++ b/templates/header.html @@ -2,7 +2,7 @@ - +Removeddit diff --git a/templates/thread.html b/templates/thread.html index df3b410..38b8c2a 100644 --- a/templates/thread.html +++ b/templates/thread.html @@ -9,7 +9,7 @@ const thread_id = "{{ thread_id }}"; const token = "{{ token }}"; const subreddit = "{{ subreddit }}"; -const all_ids = new Set({{ comment_ids|safe }}); +const all_ids = {{ comment_ids|safe }}; {% endblock %}