├── README.md ├── gm_viewer.v2.user.js └── viewer.v2.user.js /README.md: -------------------------------------------------------------------------------- 1 | # PPCG Sandbox Viewer 2 | 3 | > **NOTE: ** Firefox is NOT supported. I am working on it 4 | 5 | A userscript which makes a sandbox viewer for the PPCG sandbox. 6 | 7 | --- 8 | 9 | ## Screenshots 10 | 11 | 12 | -------------------------------------------------------------------------------- /gm_viewer.v2.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Sandbox Viewer 3 | // @namespace https://github.com/vihanb/PPCG-SandboxViewer 4 | // @version 2.3 5 | // @description PPCG Sandbox Viewer 6 | // @author Downgoat 7 | // @match *://*.stackexchange.com/* 8 | // @grant GM_xmlhttpRequest 9 | // @updateURL https://rawgit.com/vihanb/PPCG-SandboxViewer/master/viewer.v2.user.js 10 | // ==/UserScript== 11 | 12 | function InjectSandboxScript() { 13 | 14 | var OPENED = false; 15 | $("body").prepend(''); 16 | $("body").prepend(''); 17 | $('#SandboxViewer').prepend('
'); 18 | $('#SandboxViewer').append('
x
Loading...
'); 19 | 20 | $(".topbar .topbar-wrapper .network-items").append(''); 21 | 22 | var POSTCOUNTER = 0; 23 | 24 | function PopupDisplay(text) { 25 | $("#SandboxPopdisp").html(text); 26 | $("#SandboxPopdisp").fadeIn(200, function () { 27 | $(this).delay(1000).fadeOut(200); 28 | }); 29 | } 30 | 31 | function VotePost(post, state) { 32 | // States: 33 | // 2 - Upvote 34 | // 3 - Downvote 35 | // 10- Delete 36 | // Post: http://.com/posts//vote/ 37 | GM_xmlhttpRequest({ 38 | method: "POST", 39 | data: "fkey=" + StackExchange.options.user.fkey, 40 | url: post+"/vote/"+state, 41 | headers: { 42 | "Content-Type": "application/x-www-form-urlencoded" 43 | }, 44 | onload:function(response) { 45 | } 46 | }); 47 | } 48 | function PostPost(title, body, id) { 49 | console.log(title, body); 50 | GM_xmlhttpRequest({ 51 | method: "POST", 52 | data:"qualityBanWarningShown=False&priorAttemptCount=0&title="+title+"&post-text="+encodeURIComponent(body)+"&fkey=" + StackExchange.options.user.fkey + "&author=&wmd-input-42=&tagnames=" + body.match(/\[tag:[^\]]+/g).map(function(l){return l.slice(5);}).join(","), 53 | url: "http://codegolf.stackexchange.com/questions/ask/submit/", 54 | headers: { 55 | "Content-Type": "application/x-www-form-urlencoded" 56 | }, 57 | onload:function(response){ 58 | var url = (response.responseText.match(/' + post.title + '' + 87 | '
score: +' + post.score.up + ''+ 88 | ' -' + post.score.down + '' + 89 | '
active: ' + TimeSince( post.active ) + '' 90 | // + '
Post to main'; 91 | }).join("\n") || "
You currently have no Sandboxed posts
    ") + '
'; 92 | 93 | HTML += '

Latest Activity

' + (GetComments(posts).map(function(comment, i, a) { 94 | return '
' + comment.post + ', ' + comment.user + ': ' + comment.text + " - " + TimeSince(comment.timestamp) + "
"; 96 | }).join("") || "
You currently have no Sandboxed posts
") + '
'; 97 | $("#SandboxContent").prepend('
' + HTML + "
"); 98 | }); 99 | GetChallenges("*nofilter*", function(posts) { 100 | 101 | function UpdatePreviewComments() { 102 | var Comments = GetComments([posts[POSTCOUNTER]]).reverse(); 103 | var LIMIT = 2; 104 | var a = false; 105 | if (Comments.length > LIMIT) a = true; 106 | $("#SandboxPreviewComments").html( (a ? '
(show all)
' : "") + Comments.map(function(comment,index,a) { 107 | return '' 111 | }).join("\n") + "
"); 112 | $(document).on('click', "#SPshow", function() { 113 | $(".SPrevH").show(); 114 | $("#SPshow").html("(hide some comments)"); 115 | $("#SPshow").attr("id", "SPhide"); 116 | }); 117 | 118 | $(document).on('click', "#SPhide", function() { 119 | $(".SPrevH").hide(); 120 | $("#SPhide").html("(show all comments)"); 121 | $("#SPhide").attr("id", "SPshow"); 122 | }); 123 | } 124 | 125 | function ConstructPost(post) { 126 | UpdatePreviewComments(); 127 | $(".FVoteActive").removeClass("FVoteActive"); 128 | $(".FVoteUp").attr('src', 'http://i.stack.imgur.com/EQ1ko.png'); 129 | $(".FVoteDown").attr('src', 'http://i.stack.imgur.com/OwtQb.png'); 130 | return '
' + post.body + '
'; 131 | } 132 | 133 | function CommentPost(post, comment) { 134 | GM_xmlhttpRequest({ 135 | method: "POST", 136 | data: "fkey=" + StackExchange.options.user.fkey + "&comment=" + encodeURIComponent(comment), 137 | url: post+"/comments/", 138 | headers: { 139 | "Content-Type": "application/x-www-form-urlencoded" 140 | }, 141 | onload:function(response){ 142 | PopupDisplay("  Posted.  "); 143 | UpdatePreviewComments(); 144 | } 145 | }); 146 | } 147 | 148 | var HTML = ""; 149 | HTML += '
'+ 150 | '
'+ 151 | '
'+ 152 | '
' + 153 | 154 | 'Voting / Commenting is currently unsupported on GreaseMonkey due to sandboxing' + 155 | '' + 156 | ''+ 157 | '
'+ 158 | '
' + ConstructPost(posts[POSTCOUNTER]) + '
'; 159 | 160 | $("#SandboxContent").append('
' + HTML + '
'); 161 | UpdatePreviewComments(); 162 | $(".sandboxbtn").click(function() { 163 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 164 | setTimeout(function() { 165 | $("#SandboxChallengePreview").html(ConstructPost(posts[++POSTCOUNTER])); 166 | UpdatePreviewComments(); 167 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 168 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 169 | else $("#FPREV").prop('disabled', false); 170 | }, 200); 171 | }); 172 | }); 173 | $("#FPREV").click(function(){ 174 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 175 | setTimeout(function() { 176 | $("#SandboxChallengePreview").html(ConstructPost(posts[--POSTCOUNTER])); 177 | UpdatePreviewComments(); 178 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 179 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 180 | else $("#FPREV").prop('disabled', false); 181 | }, 200); 182 | }); 183 | }); 184 | $("#FHIDE").click(function() { 185 | var H=JSON.parse(localStorage.getItem("FHIDE") || '[]'); 186 | H.push(posts[POSTCOUNTER].id); 187 | localStorage.setItem("FHIDE", JSON.stringify(H)); 188 | $(".FNEXT").click(); 189 | }); 190 | $(document).on('click', ".FVoteUp:not(.FVoteActive)", function() { 191 | VotePost("http://meta.codegolf.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 2); 192 | // PopupDisplay("+1'd"); 193 | $(".FVoteActive").removeClass("FVoteActive"); 194 | $(".FVoteDown").attr('src', 'http://i.stack.imgur.com/OwtQb.png'); 195 | $(".FVoteUp").attr('src', 'http://i.stack.imgur.com/iu7y5.png'); 196 | $(".FVoteUp").addClass("FVoteActive"); 197 | }); 198 | $(document).on('click', ".FVoteDown:not(.FVoteActive)", function() { 199 | VotePost("http://meta.codegolf.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 3); 200 | // PopupDisplay("-1'd"); 201 | $(".FVoteActive").removeClass("FVoteActive"); 202 | $(".FVoteUp").attr('src', 'http://i.stack.imgur.com/EQ1ko.png'); 203 | $(".FVoteDown").attr('src', 'http://i.stack.imgur.com/LyK6V.png'); 204 | $(".FVoteDown").addClass("FVoteActive"); 205 | }); 206 | $(document).on('click', ".FVoteActive", function() { 207 | VotePost("http://meta.codegolf.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 0); 208 | // PopupDisplay("±0"); 209 | $(".FVoteActive").removeClass("FVoteActive"); 210 | $(".FVoteUp").attr('src', 'http://i.stack.imgur.com/EQ1ko.png'); 211 | $(".FVoteDown").attr('src', 'http://i.stack.imgur.com/OwtQb.png'); 212 | }) 213 | $("#FComment").click(function(){ 214 | CommentPost("http://meta.codegolf.stackexchange.com/posts/" + posts[POSTCOUNTER].id, $("#FCText").val()); 215 | }); 216 | $(".FLink").click(function(){ window.open(posts[POSTCOUNTER].url, "_blank"); }); 217 | $(".Fmtom").click(function(){ Request("GET", "http://api.stackexchange.com/2.2/answers/"+$(this).data('postid')+"?order=desc&sort=activity&key=Ccn4VoktkZPX*Haf3)iubw((&site=meta.codegolf&filter=!GeEyUcJFJeRCA", function(response) { 218 | var res = JSON.parse(response.responseText).items[0].body_markdown; 219 | PostPost(GetPostTitle(res), res, $(this).data('postid')); 220 | }); }); 221 | }); 222 | $("#USERLOAD").remove(); 223 | } 224 | }); 225 | 226 | $('#SandboxBlur, #closeviewer').click(function() { 227 | $('#SandboxViewer').fadeOut(100); 228 | }); 229 | 230 | /*== Functions ==*/ 231 | function FormatDate(d) { 232 | return [d.getMonth() + 1, d.getDate(), d.getYear()+1900].join('/') + ' ' + 233 | [d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()].join(':'); 234 | } 235 | 236 | function TimeSince(d) { 237 | var s = Math.floor((new Date() - new Date(+(d+'e3'))) / 1000); 238 | var interval = Math.floor(s / 31536000); 239 | if (interval > 1) return interval + " years ago"; 240 | interval = Math.floor(s / 2592000); 241 | if (interval > 1) return interval + " months ago"; 242 | interval = Math.floor(s / 86400); 243 | if (interval > 1) return interval + " days ago"; 244 | interval = Math.floor(s / 3600); 245 | if (interval > 1) return interval + " hours ago"; 246 | interval = Math.floor(s / 60); 247 | if (interval > 1) return interval + " minutes ago"; 248 | return Math.floor(s) + " seconds ago"; 249 | } 250 | 251 | function GetComments(posts) { 252 | return posts.reduce(function(data, post) { 253 | var comments = post.comments || []; 254 | comments.forEach(function(cm) { 255 | data.push({ 256 | timestamp: cm.creation_date, 257 | user: cm.owner.display_name, 258 | userid: cm.owner.user_id, 259 | postlink: post.post.link, 260 | link: cm.link, 261 | text: cm.body, 262 | post: GetPostTitle(post.post.body_markdown) 263 | }); 264 | }); 265 | data.sort(function(a, b) { 266 | return b.timestamp - a.timestamp; 267 | }); 268 | return data; 269 | }, []); 270 | } 271 | 272 | function GetPostTitle(markdown) { 273 | return (markdown.match(/(?:\n|^)#+(.+)/) || ["", "Unknown Title"])[1]; 274 | } 275 | 276 | function GetChallenges(userid, callback) { 277 | GetUserPosts(userid, function(posts) { 278 | callback(posts.map(function(p) { 279 | //console.log(p); 280 | return { 281 | title: GetPostTitle(p.body_markdown), 282 | score: { 283 | up: p.up_vote_count, 284 | down: p.down_vote_count 285 | }, 286 | url: p.link, 287 | comments: p.comments, 288 | id: p.answer_id, 289 | body: p.body, 290 | post: p, 291 | active: p.last_activity_date 292 | }; 293 | })); 294 | }); 295 | } 296 | 297 | function OpenSockets() { 298 | var ws = new WebSocket("ws://qa.sockets.stackexchange.com/"); 299 | ws.onmessage = function(e) { 300 | // If this shows up then it's good 301 | console.log("Hi, you must be looking at your console wondering what the heck this message means. It means you should be happy that this message is being logged otherwise something very wrong happened"); 302 | try { 303 | var wsd = JSON.parse(JSON.parse(e.data).data); 304 | if (wsd.a === "answer-add") { 305 | // answer added 306 | $("#SandboxViewerToggle").css("background-image", "url(http://i.stack.imgur.com/COtrF.png)"); 307 | } 308 | } catch(e) { 309 | console.log("error during websocket update"); 310 | } 311 | }; 312 | ws.onopen = function() { 313 | ws.send("202-question-2140"); 314 | } 315 | } 316 | 317 | if (true) OpenSockets(); // Use WS? 318 | 319 | function GetUserPosts(userid, callback) { 320 | /// 321 | var hideitem = JSON.parse(localStorage.getItem("FHIDE") || '[]'); 322 | if (userid === "*nofilter*") { 323 | Request("GET", "https://api.stackexchange.com/2.2/questions/2140/answers?order=desc&sort=activity&key=Ccn4VoktkZPX*Haf3)iubw((&site=meta.codegolf&filter=!-2qNq(tTGQYRU3SZ87hedUU)5htvSK6RNae3(IkBC-M8i", function(req) { 324 | var items = JSON.parse(req.response).items; 325 | callback(items.filter(function(item) { 326 | return !~hideitem.indexOf(item.answer_id) && item.owner.user_id !== StackExchange.options.user.userId; 327 | })); 328 | }); 329 | } else { 330 | Request("GET", "http://api.stackexchange.com/2.2/search/excerpts?order=desc&sort=activity&title=Sandbox%20for%20Proposed%20Challenges&user="+StackExchange.options.user.userId+"&site=meta.codegolf", function(data) { 331 | var items = JSON.parse(data.response).items; 332 | function Loop(i, a) { 333 | if (i > items.length - 1) { 334 | callback(a); 335 | } else { 336 | Request("GET", 'http://api.stackexchange.com/2.2/answers/'+items[i].answer_id+'?pagesize=100&order=desc&sort=activity&site=meta.codegolf&filter=!-2qNq(tTGQYRU3SZ87hedUU)5htvSK6RNae3(IkBC-M8i', function(r) { 337 | a.push(JSON.parse(r.response).items[0]); 338 | Loop(i + 1, a); 339 | }); 340 | } 341 | } 342 | Loop(0, []); 343 | }); 344 | } 345 | } 346 | 347 | function Request(type, url, callback) { 348 | var r = new XMLHttpRequest(); 349 | r.onreadystatechange = function() { 350 | if (r.readyState === 4) 351 | if (r.status === 200) callback(r); 352 | }; 353 | r.open(type, url); 354 | if (type.toUpperCase() === "POST") r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 355 | r.send(); 356 | } 357 | } 358 | 359 | var script = document.createElement('script'); 360 | script.appendChild(document.createTextNode('('+ InjectSandboxScript +')();')); 361 | (document.body || document.head || document.documentElement).appendChild(script); -------------------------------------------------------------------------------- /viewer.v2.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Sandbox Viewer 3 | // @namespace https://github.com/vihanb/PPCG-SandboxViewer 4 | // @version 2.7 5 | // @description PPCG Sandbox Viewer 6 | // @author Downgoat 7 | // @match *://*.stackexchange.com/* 8 | // @grant GM_xmlhttpRequest 9 | // @connect codegolf.meta.stackexchange.com 10 | // @updateURL https://rawgit.com/vihanb/PPCG-SandboxViewer/master/viewer.v2.user.js 11 | // ==/UserScript== 12 | 13 | function InjectSandboxScript() { 14 | 15 | console.log("PPCG Sandbox Viewer Running"); 16 | 17 | var OPENED = false; 18 | $("body").prepend(''); 19 | $("body").prepend(''); 20 | $('#SandboxViewer').prepend('
'); 21 | $('#SandboxViewer').append('
x
Loading...
'); 22 | 23 | $(".top-bar .-secondary").append('
  • '); 24 | 25 | var POSTCOUNTER = 0; 26 | 27 | var ALLPOSTS = null; 28 | 29 | function PopupDisplay(text) { 30 | $("#SandboxPopdisp").html(text); 31 | $("#SandboxPopdisp").fadeIn(200, function () { 32 | $(this).delay(1000).fadeOut(200); 33 | }); 34 | } 35 | 36 | function VotePost(post, state) { 37 | // States: 38 | // 2 - Upvote 39 | // 3 - Downvote 40 | // 10- Delete 41 | // Post: https://.com/posts//vote/ 42 | GM_xmlhttpRequest({ 43 | method: "POST", 44 | data: "fkey=" + StackExchange.options.user.fkey, 45 | url: post+"/vote/"+state, 46 | headers: { 47 | "Content-Type": "application/x-www-form-urlencoded" 48 | }, 49 | onload:function(response) { 50 | } 51 | }); 52 | } 53 | function PostPost(title, body, id) { 54 | console.log(title, body); 55 | GM_xmlhttpRequest({ 56 | method: "POST", 57 | data:"qualityBanWarningShown=False&priorAttemptCount=0&title="+title+"&post-text="+encodeURIComponent(body)+"&fkey=" + StackExchange.options.user.fkey + "&author=&wmd-input-42=&tagnames=" + body.match(/\[tag:[^\]]+/g).map(function(l){return l.slice(5);}).join(","), 58 | url: "https://codegolf.stackexchange.com/questions/ask/submit/", 59 | headers: { 60 | "Content-Type": "application/x-www-form-urlencoded" 61 | }, 62 | onload:function(response){ 63 | var url = (response.responseText.match(/' + post.body + ''; 88 | } 89 | 90 | function UpdatePreviewComments(posts) { 91 | var Comments = GetComments([posts[POSTCOUNTER]]).reverse(); 92 | console.log("obtained comments: ", Comments); 93 | var LIMIT = 2; 94 | var a = false; 95 | if (Comments.length > LIMIT) a = true; 96 | $("#SandboxPreviewComments").html( (a ? '' : "") + Comments.map(function(comment,index,a) { 97 | return '' 101 | }).join("\n") + "
    "); 102 | $('#FCText').keyup(function (e) { 103 | if ( (e.keyCode || e.which) === 13 ) $("#FComment").click(); 104 | }); 105 | $(document).on('click', "#SPshow", function() { 106 | $(".SPrevH").show(); 107 | $("#SPshow").html("(hide some comments)"); 108 | $("#SPshow").attr("id", "SPhide"); 109 | }); 110 | 111 | $(document).on('click', "#SPhide", function() { 112 | $(".SPrevH").hide(); 113 | $("#SPhide").html("(show all comments)"); 114 | $("#SPhide").attr("id", "SPshow"); 115 | }); 116 | } 117 | 118 | function INITVIEWER(posts) { 119 | 120 | ALLPOSTS = posts; 121 | 122 | function CommentPost(post, comment) { 123 | console.log(post + "/comments/", "fkey=" + StackExchange.options.user.fkey + "&comment=" + encodeURIComponent(comment)); 124 | GM_xmlhttpRequest({ 125 | method: "POST", 126 | data: "fkey=" + StackExchange.options.user.fkey + "&comment=" + encodeURIComponent(comment), 127 | url: post+"/comments/", 128 | headers: { 129 | "Content-Type": "application/x-www-form-urlencoded" 130 | }, 131 | onload:function(response){ 132 | if (response.status === 500) { 133 | alert("Error posting. Is your comment > 15 chars?"); 134 | } else { 135 | PopupDisplay("  Posted.  "); 136 | UpdatePreviewComments(posts); 137 | } 138 | } 139 | }); 140 | } 141 | 142 | var HTML = ""; 143 | HTML += '
    '+ 144 | '
    '+ 145 | '
    '+ 146 | '
    ' + 147 | 148 | '' + 149 | ''+ 150 | '
    '+ 151 | 152 | '' + 153 | 154 | '
    ' + ConstructPost(posts[POSTCOUNTER]) + '
    '; 155 | 156 | $("#SandboxContent").append('
    ' + HTML + '
    '); 157 | UpdatePreviewComments(posts); 158 | $(".sandboxbtn").click(function() { 159 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 160 | setTimeout(function() { 161 | $("#SandboxChallengePreview").html(ConstructPost(posts[++POSTCOUNTER])); 162 | UpdatePreviewComments(posts); 163 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 164 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 165 | else $("#FPREV").prop('disabled', false); 166 | }, 200); 167 | }); 168 | }); 169 | $("#FPREV").click(function(){ 170 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 171 | setTimeout(function() { 172 | $("#SandboxChallengePreview").html(ConstructPost(posts[--POSTCOUNTER])); 173 | UpdatePreviewComments(posts); 174 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 175 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 176 | else $("#FPREV").prop('disabled', false); 177 | }, 200); 178 | }); 179 | }); 180 | $("#FHIDE").click(function() { 181 | var H=JSON.parse(localStorage.getItem("FHIDE") || '[]'); 182 | H.push(posts[POSTCOUNTER].id); 183 | localStorage.setItem("FHIDE", JSON.stringify(H)); 184 | $(".FNEXT").click(); 185 | }); 186 | $(document).on('click', ".FVoteUp:not(.FVoteActive)", function() { 187 | VotePost("https://codegolf.meta.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 2); 188 | // PopupDisplay("+1'd"); 189 | $(".FVoteActive").removeClass("FVoteActive"); 190 | $(".FVoteDown").attr('src', 'https://i.stack.imgur.com/OwtQb.png'); 191 | $(".FVoteUp").attr('src', 'https://i.stack.imgur.com/iu7y5.png'); 192 | $(".FVoteUp").addClass("FVoteActive"); 193 | }); 194 | $(document).on('click', ".FVoteDown:not(.FVoteActive)", function() { 195 | VotePost("https://codegolf.meta.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 3); 196 | // PopupDisplay("-1'd"); 197 | $(".FVoteActive").removeClass("FVoteActive"); 198 | $(".FVoteUp").attr('src', 'https://i.stack.imgur.com/EQ1ko.png'); 199 | $(".FVoteDown").attr('src', 'https://i.stack.imgur.com/LyK6V.png'); 200 | $(".FVoteDown").addClass("FVoteActive"); 201 | }); 202 | $(document).on('click', ".FVoteActive", function() { 203 | VotePost("https://codegolf.meta.stackexchange.com/posts/" + posts[POSTCOUNTER].id, 0); 204 | // PopupDisplay("±0"); 205 | $(".FVoteActive").removeClass("FVoteActive"); 206 | $(".FVoteUp").attr('src', 'https://i.stack.imgur.com/EQ1ko.png'); 207 | $(".FVoteDown").attr('src', 'https://i.stack.imgur.com/OwtQb.png'); 208 | }); 209 | $(document).on('click', "#FComment", function() { 210 | CommentPost("https://codegolf.meta.stackexchange.com/posts/" + posts[POSTCOUNTER].id, $("#FCText").val()); 211 | }); 212 | $(".FLink").click(function(){ window.open(posts[POSTCOUNTER].url, "_blank"); }); 213 | $(".Fmtom").click(function(){ Request("GET", "https://api.stackexchange.com/2.2/answers/"+$(this).data('postid')+"?order=desc&sort=activity&key=Ccn4VoktkZPX*Haf3)iubw((&site=meta.codegolf&filter=!GeEyUcJFJeRCA", function(response) { 214 | var res = JSON.parse(response.responseText).items[0].body_markdown; 215 | PostPost(GetPostTitle(res), res, $(this).data('postid')); 216 | }); }); 217 | } 218 | 219 | $(document).on('click', "#SandboxViewerToggle", function() { 220 | $('#SandboxViewer').fadeIn(100); 221 | if (OPENED === false) { 222 | OPENED = true; 223 | $("#SandboxViewerToggle").css("background-image", "url(https://i.stack.imgur.com/lBskr.png)"); 224 | GetChallenges(StackExchange.options.user.userId, function(posts, anposts) { 225 | var HTML = ""; 226 | HTML += '

    Your Sandboxed Posts

      ' + (posts.map(function(post, index) { 227 | return '
    • ' + post.title + '' + 228 | '
      score: +' + post.score.up + ''+ 229 | ' -' + post.score.down + '' + 230 | '
      active: ' + TimeSince( post.active ) + '' 231 | // + '
      Post to main
    • '; 232 | }).join("\n") || "
    You currently have no Sandboxed posts
      ") + '
    '; 233 | 234 | $(document).on('click', ".OPENPOST", function() { 235 | var POST = posts[$(this).data('idn')]; 236 | var PID = +$(this).data('idn'); 237 | if (POST) { 238 | var NOWRITEC = Number(POSTCOUNTER); 239 | 240 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 241 | setTimeout(function() { 242 | $("#SandboxChallengePreview").html(ConstructPost(POST)); 243 | POSTCOUNTER = PID; 244 | UpdatePreviewComments(posts); 245 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 246 | $("#FBOwnerBack").show(); 247 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 248 | else $("#FPREV").prop('disabled', false); 249 | }, 200); 250 | }); 251 | 252 | $(document).on('click', "#FBOwnerBack", function() { 253 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 0, function() { 254 | setTimeout(function() { 255 | console.log(posts[NOWRITEC], posts, NOWRITEC, PID, POST, POSTCOUNTER); 256 | $("#SandboxChallengePreview").html(ConstructPost(anposts[NOWRITEC])); 257 | POSTCOUNTER = NOWRITEC; 258 | UpdatePreviewComments(anposts); 259 | $("#SandboxChallengePreview, #SandboxPreviewComments").fadeTo(100, 1); 260 | $("#FBOwnerBack").hide(); 261 | if(POSTCOUNTER === 0) $("#FPREV").prop('disabled', true); 262 | else $("#FPREV").prop('disabled', false); 263 | }, 200); 264 | }); 265 | }); 266 | } else { 267 | if (!PID) { 268 | alert("An error occured identifying this sandbox post."); 269 | } else if (POST) { 270 | alert("This post is too old to load."); 271 | } 272 | } 273 | }); 274 | 275 | HTML += '

    Latest Activity

    ' + (GetComments(posts).map(function(comment, i, a) { 276 | return '"; 278 | }).join("") || "
    You currently have no Sandboxed posts
    ") + '
    '; 279 | $("#SandboxContent").prepend('
    ' + HTML + "
    "); 280 | }); 281 | GetChallenges("*nofilter*", INITVIEWER); 282 | $("#USERLOAD").remove(); 283 | } 284 | }); 285 | 286 | $('#SandboxBlur, #closeviewer').click(function() { 287 | $('#SandboxViewer').fadeOut(100); 288 | }); 289 | 290 | /*== Functions ==*/ 291 | function FormatDate(d) { 292 | return [d.getMonth() + 1, d.getDate(), d.getYear()+1900].join('/') + ' ' + 293 | [d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds()].join(':'); 294 | } 295 | 296 | function TimeSince(d) { 297 | var s = Math.floor((new Date() - new Date(+(d+'e3'))) / 1000); 298 | var interval = Math.floor(s / 31536000); 299 | if (interval > 1) return interval + " years ago"; 300 | interval = Math.floor(s / 2592000); 301 | if (interval > 1) return interval + " months ago"; 302 | interval = Math.floor(s / 86400); 303 | if (interval > 1) return interval + " days ago"; 304 | interval = Math.floor(s / 3600); 305 | if (interval > 1) return interval + " hours ago"; 306 | interval = Math.floor(s / 60); 307 | if (interval > 1) return interval + " minutes ago"; 308 | return Math.floor(s) + " seconds ago"; 309 | } 310 | 311 | function GetComments(posts) { 312 | return posts.reduce(function(data, post) { 313 | var comments = post.comments || []; 314 | comments.forEach(function(cm) { 315 | data.push({ 316 | timestamp: cm.creation_date, 317 | user: cm.owner.display_name, 318 | userid: cm.owner.user_id, 319 | postlink: post.post.link, 320 | link: cm.link, 321 | text: cm.body, 322 | post: GetPostTitle(post.post.body_markdown) 323 | }); 324 | }); 325 | data.sort(function(a, b) { 326 | return b.timestamp - a.timestamp; 327 | }); 328 | return data; 329 | }, []); 330 | } 331 | 332 | function GetPostTitle(markdown) { 333 | return (markdown.match(/(?:\n|^)#+(.+)/) || ["", "Unknown Title"])[1]; 334 | } 335 | 336 | function GetPostData(p) { 337 | return { 338 | title: GetPostTitle(p.body_markdown), 339 | score: { 340 | up: p.up_vote_count, 341 | down: p.down_vote_count 342 | }, 343 | url: p.link, 344 | comments: p.comments, 345 | id: p.answer_id, 346 | body: p.body, 347 | post: p, 348 | active: p.last_activity_date 349 | }; 350 | } 351 | 352 | function GetChallenges(userid, callback) { 353 | GetUserPosts(userid, function(posts, all) { 354 | if (all) callback(posts.map(GetPostData), all.map(GetPostData)); 355 | else callback(posts.map(GetPostData)); 356 | }); 357 | } 358 | 359 | function OpenSockets() { 360 | var ws = new WebSocket("wss://qa.sockets.stackexchange.com/"); 361 | ws.onmessage = function(e) { 362 | // If this shows up then it's good 363 | console.log("Hi, you must be looking at your console wondering what the heck this message means. It means you should be happy that this message is being logged otherwise something very wrong happened"); 364 | try { 365 | var wsd = JSON.parse(JSON.parse(e.data).data); 366 | if (wsd.a === "answer-add") { 367 | // answer added 368 | $("#SandboxViewerToggle").css("background-image", "url(https://i.stack.imgur.com/COtrF.png)"); 369 | } 370 | } catch(e) { 371 | console.log("error during websocket update"); 372 | } 373 | }; 374 | ws.onopen = function() { 375 | ws.send("202-question-2140"); 376 | } 377 | } 378 | 379 | if (true) OpenSockets(); // Use WS? 380 | 381 | function GetUserPosts(userid, callback) { 382 | /// 383 | var hideitem = JSON.parse(localStorage.getItem("FHIDE") || '[]'); 384 | if (userid === "*nofilter*") { 385 | Request("GET", "https://api.stackexchange.com/2.2/questions/2140/answers?order=desc&sort=activity&key=Ccn4VoktkZPX*Haf3)iubw((&site=meta.codegolf&filter=!-2qNq(tTGQYRU3SZ87hedUU)5htvSK6RNae3(IkBC-M8i", function(req) { 386 | var items = JSON.parse(req.response).items; 387 | callback(items.filter(function(item) { 388 | return !~hideitem.indexOf(item.answer_id) && item.owner.user_id !== StackExchange.options.user.userId; 389 | })); 390 | }); 391 | } else { 392 | Request("GET", "https://api.stackexchange.com/2.2/search/excerpts?order=desc&sort=activity&title=Sandbox%20for%20Proposed%20Challenges&user="+StackExchange.options.user.userId+"&site=meta.codegolf", function(data) { 393 | var items = JSON.parse(data.response).items; 394 | function Loop(i, a) { 395 | if (i > items.length - 1) { 396 | GetUserPosts("*nofilter*", function (nonposts) { 397 | callback(a, nonposts); 398 | }); 399 | } else { 400 | Request("GET", 'https://api.stackexchange.com/2.2/answers/'+items[i].answer_id+'?pagesize=100&order=desc&sort=activity&site=meta.codegolf&filter=!-2qNq(tTGQYRU3SZ87hedUU)5htvSK6RNae3(IkBC-M8i', function(r) { 401 | a.push(JSON.parse(r.response).items[0]); 402 | Loop(i + 1, a); 403 | }); 404 | } 405 | } 406 | Loop(0, []); 407 | }); 408 | } 409 | } 410 | 411 | function Request(type, url, callback) { 412 | var r = new XMLHttpRequest(); 413 | r.onreadystatechange = function() { 414 | if (r.readyState === 4) 415 | if (r.status === 200) callback(r); 416 | }; 417 | r.open(type, url); 418 | if (type.toUpperCase() === "POST") r.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 419 | r.send(); 420 | } 421 | } 422 | 423 | InjectSandboxScript(); 424 | 425 | 426 | --------------------------------------------------------------------------------