First commit; calling this version 0.1
[imgurfusker.git] / ImgurFusker.html
blob9a7ca4252aa28f05e35eb1385057432319049a61
1 <!DOCTYPE html>
2 <html data-VERSION='0.1'>
3 <!--
4 ***************** ImgurFusker version 0.1 *****************
5 ******** imgurfusker@hmamail.com (expires 7/3/14) *********
6 **************** Written on July 4th, 2014. ***************
7 *********** God bless America. God bless nudes. ***********
9 ~~~ ABOUT ~~~
11 This is a small utility to automatically search for nudes on Imgur via a brute force method.
12 (This is known as "fusking").
14 It was inspired by http://noisediary.com/.
16 I also refer to nudes as "nuuus" throughout this page because I don't fucking feel like putting 'nudes' everywhere.
17 Deal with it.
19 ~~~ DEPEDENCIES ~~~
21 The code was originally ripped right from NoiseDiary, but since then it has been heavily
22 modified and rewritten. Honestly, the person who wrote NoiseDiary can't fucking code anyway.
24 This page uses jQuery. If you don't know what jQuery is then fuck off.
26 The image detection is done by a library known as nude.js.
27 https://github.com/pa7/nude.js
29 ~~~ QUESTIONS ~~~
31 Q: Why did you do this?
32 A: Hello? Fucking nudes.
34 Q: Why does it keep finding non-nudes and skip B&W nudes?
35 A: Because fuck you, that's why. I didn't write the library.
36 You think you can do better? Go write a better library and come back to me. I'll use your library.
38 Q: Why is it freezing up my computer? You fucking suck at this.
39 A: No YOU suck. Scanning the image is resource intensive and can freeze your browser if the FAIL_TIME option is set too low.
42 ~~~ LICENSING BULLSHIT ~~~
44 This program is free software. It comes without any warranty, to
45 the extent permitted by applicable law. You can redistribute it
46 and/or modify it under the terms of the Do What The Fuck You Want
47 To Public License, Version 2, as published by Sam Hocevar. See
48 http://www.wtfpl.net/ for more details.
50 -->
51 <head>
52 <meta http-equiv="content-type" content="text/html; charset=UTF-8">
53 <meta charset="utf-8">
54 <meta http-equiv="X-UA-Compatible" content="IE=edge">
55 <meta name="viewport" content="width=device-width, initial-scale=1.0">
56 <meta name="description" content="">
57 <meta name="author" content="">
59 <title>ImgurFusker</title>
60 <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic">
61 <style>
62 body {
63 font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
65 @media (min-width: 1200px) { /* Large desktop */
66 body { padding: 0 50px; }
69 @media (min-width: 768px) and (max-width: 1199px) { /* Portrait tablet to landscape and desktop */
70 body { padding: 0 30px; }
73 @media (max-width: 767px) { /* Landscape phone to portrait tablet */
74 body { padding: 0 20px; }
77 @media (max-width: 480px) { /* Landscape phones and down */
78 body { padding: 0 5px; }
81 h1 {
82 font-size: 2.7em;
83 margin: .2em .4em;
84 font-family: 'Open Sans','Courier';
85 font-weight: 100;
87 h1 small {
88 font-size: .3em;
90 h2 {
91 font-size: 2.3;
92 font-family: 'Open Sans','Courier';
93 font-weight: 400;
94 margin: 0;
97 a:hover, a:visited, a:link, a:active {
98 text-decoration: none;
101 img {
102 vertical-align: text-bottom;
105 .btn {
106 display: inline-block;
107 margin-bottom: 0px;
108 font-weight: normal;
109 text-align: center;
110 vertical-align: middle;
111 cursor: pointer;
112 background-image: none;
114 white-space: nowrap;
115 padding: 0.5em 1em;
116 font-size: 1em;
117 line-height: 1;
119 color: #333;
120 background-color: #E7E7E7;
121 border: 1px solid #DADADA;
123 .btn:hover {
124 background-color: #DADADA;
126 .btn-block {
127 display: block;
128 width: 100%;
129 padding: 1em 2em;
132 #images {
133 margin: 20px 0;
136 .thumb-container {
137 display:inline-block;
138 position:relative;
139 overflow:show;
140 min-height:110px;
141 min-width:110px;
142 clear:both;
144 .thumb {
145 height: 110px;
146 width: 110px;
149 #images img {
150 margin-right: 5px;
151 border: 2px solid transparent;
153 #images img:hover, .delort:hover{
154 border-color: #ff0000;
157 .sauce, .delort {
158 z-index:1000;
159 height:16px;
160 width:16px;
161 position:absolute;
162 padding:0px;
164 .sauce {
165 bottom:10px;
166 margin-right: 0;
167 right:12px;
169 .delort {
170 right:7px;
171 border: 2px solid transparent;
172 font-weight: bold;
173 font-size: 20px;
174 text-align:center;
175 cursor: pointer;
176 line-height:.6;
177 background-color: #333;
179 .delort, .delort:focus, .delort:hover {
180 color: red;
182 .delort:hover {
183 border-color: #ff0000;
186 #examining {
187 font-weight: 100;
188 font-size: 20px;
190 #examining i {
191 font-style: italic;
192 color: #888;
195 #current {
196 text-align:center;
197 height: 340px;
198 background-color: #FFFFE0;
200 #current img {
201 max-height: 300px;
202 max-width: 400px;
205 #cache-popup {
206 position: absolute;
207 display: block;
208 min-height: 100px; //adjust as per need
209 min-width: 350px; //adjust as per need
210 z-index: 200;
211 background: white;
212 top: 150px;
213 border: 2px solid #999;
214 border-radius: 10px 10px;
215 padding: 15px;
216 width: 600px;
217 left: 0;
218 right: 0;
219 margin: auto;
222 </style>
227 </head>
229 <body>
230 <h1>ImgurFusker</h1>
232 <button id="bigass-button" class="btn btn-block">Start!</button>
234 <div id="current">
235 <h4 id="examining"></h4>
236 <img id="current-img">
237 </div>
239 <div id="images"></div>
241 <div onclick='document.getElementById("cache-popup").style.visibility="visible";' class="btn" style="float: right">
242 Past
243 </div>
244 <div id="cache-popup" style="visibility: hidden;" >
245 <button onclick='document.getElementById("cache-popup").style.visibility="hidden";' class="btn" style="float:right; padding:0 2px; font-weight:100">x</button>
246 <h2>Past Images</h2>
247 <div id="cache-images">
248 </div>
249 </div>
251 <div class='thumb-container' id='img-template' style="display:none">
252 <a href='' target='_blank' class='thumb'>
253 <img src='' class=''>
254 </a>
255 <span class='delort'>x</span>
256 <a href='' class='sauce' target='_blank' rel='noreferrer' alt='original imgur page'>
257 <img src='http://imgur.com/favicon.ico'>
258 </a>
259 </div>
260 <canvas id="myCvs" style="display:none"></canvas>
261 <!-- Popup itself -->
263 <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
264 <script src="nude.js" type="text/javascript"></script>
265 <script src="worker.nude.js" type="text/javascript"></script>
266 <!--<script src="noworker.nude.js" type="text/javascript"></script>-->
269 <script type="text/javascript">
272 var VERSION = $(document.getElementsByTagName("html")[0]).data('version')
274 var opt = {
275 DEBUG: false, // Will flag EVERY image as a nuuu.
276 FAIL_TIME: 500, // How long to wait, in ms, between tries (NOTE: Setting this too low may cause your browser to freeze)
277 SUCCESS_TIME: 10000, // How long to wait, in ms, after finding a nuuu to continue searching (This is just for you to look at the nuuu.)
278 STOP_WHEN_FIND: false, // Whether or not to automatically stop after
279 SCAN_THUMBNAILS: false, // Scan the thumbnail instead of the full image. Will be a lot faster, but will lead to MANY more false positives.
280 SHOW_CURRENT: true, // Whether or not to show the image currently being scanned.
283 var imgurcache = new Array();
285 var thumb_link = function(id) { return 'http://i.imgur.com/'+id+'s.png'}
286 var img_link = function(id) { return 'http://i.imgur.com/'+id+'.jpg'}
289 $('h1').append(" v" + VERSION);
290 document.title = document.title + " v" + VERSION;
291 if(opt.DEBUG)
292 $('h1').append("<small style='color:red; font-size:.3em;'>Debug mode</small>");
293 if(!opt.SHOW_CURRENT) {
294 $('#current').css('height', 'auto');
295 $('#current img').css('display', 'none');
300 var Imgur = {
301 stop: false,
302 status: function(txt, clr) {
303 $('#examining').text(txt);
304 $('#examining').css('color', clr);
305 console.log(txt);
308 hunt: function() {
309 var self=this;
310 console.log(self.stop());
311 if(self.stop())
312 return;
314 var id = self.random(5),
315 img = new Image;
316 img.crossOrigin = "Anonymous";
318 function fail(fail_id, fail_reason) {
320 self.status("Checked " + fail_id + ". " + fail_reason, '#333')
321 if(self.stop())
322 return;
323 setTimeout(function(){self.hunt()}, opt.FAIL_TIME);
325 img.onerror = fail;
326 img.onload = function() {
327 // PHASE 1: Look for an actual image
328 if ((img.width==198 && img.height==160) || (img.width==161 && img.height==81)) {
329 // assume this is an imgur error image, and retry.
330 fail(id, "Hunting for next image...");
331 } else {
333 //We've found AN image; now to do the actual checking
334 $('#cache-images').append('<a href="'+img_link(id)+'"><img src="'+thumb_link(id)+'"></a>');
336 var cvs = document.getElementById('myCvs'),
337 ctx = cvs.getContext('2d');
338 cvs.height = img.height;
339 cvs.width = img.width;
340 ctx.drawImage( img, 0, 0);
341 var datum = cvs.toDataURL();
345 var img2 = document.getElementById('current-img');
346 img2.onerror = function(wat) {
347 self.status("A horrible error occurred during Phase 2.", 'red')
348 if(self.stop())
349 return;
350 console.log(wat);
352 img2.onload = function() {
353 self.status("Checking " + id + " for nuuity", '#000');
354 if(self.stop())
355 return;
356 nude.load(img);
357 if(self.stop())
358 return;
359 nude.scan(function(is_nude){
360 if(is_nude || opt.DEBUG)
361 self.found(id);
362 else
363 fail(id, "Not a nude.");
366 self.status("Checking " + id, '#000')
367 if(self.stop())
368 return;
369 img2.src = datum;
371 }; // </onload>
372 if(opt.SCAN_THUMBNAILS)
373 img.src = thumb_link(id);
374 else
375 img.src = img_link(id);
376 }, // </hunt>
377 found: function(id) {
378 var self=this;
380 var new_node = $('#img-template').clone();
381 new_node.css('display', 'inline');
382 new_node.attr('id', "thumb" + id);
383 new_node.find('.thumb').attr("href", img_link(id));
384 new_node.find('.thumb img').attr("src", thumb_link(id));
385 new_node.find('.thumb img').addClass("thumb" + id);
386 new_node.find('.sauce').attr('href', "http://imgur.com/" + id);
387 new_node.find('.delort').click(function() { $(this).parent().remove() });
388 $('#images').append(new_node);
390 self.status("Aw yiss, found a nuuu at " + id, '#3c0');
391 if(self.stop(true))
392 return;
393 if(!(opt.SUCCESS_TIME>0)) {
394 self.hunt();
395 return;
397 // Wait a few seconds so we can view the nuuu
398 var until = opt.SUCCESS_TIME;
399 $('#examining').append(' <b>' + (until/100) + '</b>');
400 var until_f = function() {
401 if(self.stop()) {
402 $('#examining b').remove();
403 return;
406 until-=100;
407 if(until<0)
408 self.hunt();
409 else {
410 $('#examining b').text((until/100));
411 console.log("Starting again in " + until);
412 setTimeout(until_f, 100);
415 setTimeout(until_f, 100);
417 random: function(len) {
418 var text = new Array();
419 var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
420 for (var i=0; i < len; i++) {
421 imgurchar = possible.charAt(Math.floor(Math.random() * possible.length));
422 possible.replace(imgurchar, '');
423 text.push(imgurchar);
425 text = text.join('');
426 if (imgurcache.indexOf(text) == -1) {
427 imgurcache.push(text);
428 return text;
429 } else {
430 self.random(5);
431 return false;
434 start: function(e) {
435 console.log("The hunt is on");
436 self.stop_plz = false; //gooby, pls
437 Imgur.hunt();
438 $('#bigass-button').unbind('click', self.start);
439 $('#bigass-button').bind('click', function() {
440 console.log("Stopping");
441 self.stop_plz = true;
443 $('#examining i').remove();
444 $("#bigass-button").text("Stop");
446 stop: function(nuuu_obtained) {
447 if(self.stop_plz || (nuuu_obtained!=undefined && opt.STOP_WHEN_FIND)) {
448 if($('#examining i').remove())
449 $('#examining').prepend("<i>[Stopped]</i> ");
450 $("#bigass-button").text("Resume");
451 $("#bigass-button").unbind('click', self.stop);
452 $("#bigass-button").bind('click', Imgur.start);
453 return true;
455 return false;
458 $('#bigass-button').click(Imgur.start);
459 </script>
461 </body>
462 </html>