View difference between Paste ID: 0v2BhYdK and
SHOW:
|
|
- or go back to the newest paste.
1 | - | |
1 | + | // ==UserScript== |
2 | // @name Friend or Foe | |
3 | // @version 1.0.2 | |
4 | // @author TheRedTeam | |
5 | // @namespace reddit | |
6 | // @description Create list of friends and foes and perform actions on them | |
7 | // @include *reddit.com/r/* | |
8 | // @exclude *iframe*reddit.com/* | |
9 | // ==/UserScript== | |
10 | ||
11 | /* | |
12 | Changelog: | |
13 | 09/23/10:1.0.0: First release, works decent | |
14 | 09/23/10:1.0.1: Fixed race condition if multiple tabs open | |
15 | 11/01/10:1.0.2: Fixed opacity disallowing link clicking on right floating div | |
16 | ||
17 | */ | |
18 | ||
19 | ||
20 | // current lists | |
21 | var friend_list = []; | |
22 | var foe_list = []; | |
23 | var fof_user = ""; | |
24 | var fof_usercolors = []; // cache of link colors | |
25 | ||
26 | // reddit can't handle clicking things too fast or it will miss some | |
27 | // so we save all objects to click in an array, and use an interval on a timer | |
28 | // this does the clicking asycronously in the background for us | |
29 | var clicklist = new Array(); | |
30 | var clickinterval = null; | |
31 | ||
32 | // prototype the crap out of the array object | |
33 | Array.prototype.has = function (obj) { | |
34 | for (var i = 0, j = this.length; i < j; i++) { | |
35 | if (this[i] == obj) | |
36 | return true; | |
37 | } | |
38 | return false; | |
39 | }; | |
40 | Array.prototype.remove = function(obj) { | |
41 | for(i=0; i<this.length; i++) | |
42 | if(this[i] == obj){ | |
43 | this.splice(i, 1); | |
44 | i--; | |
45 | } | |
46 | }; | |
47 | ||
48 | ||
49 | // get jquery from reddit | |
50 | $ = unsafeWindow.$; | |
51 | ||
52 | // add menu bar items | |
53 | var mymenu = document.createElement("div"); | |
54 | mymenu.className = "sidecontentbox"; | |
55 | var side = document.getElementsByClassName("side")[0]; | |
56 | side.style.zIndex = 100; | |
57 | side.insertBefore(mymenu,side.firstChild); | |
58 | // we do inline CSS here to override reddit's styles because | |
59 | // they use the !important attribute on everything >:( | |
60 | mymenu.innerHTML = "<div class='content' style='-moz-border-radius-bottomright: 10px; -moz-border-radius-bottomleft: 10px; border-top: 0px; background-color: #FFFFBB;'> \ | |
61 | <div style='text-align: center; border-bottom: 1px solid #888;'><span style='font-family: arial; font-size: 14px; font-weight: bold; color: #996633;'>Friend or Foe</span></div> \ | |
62 | <div style='margin-bottom: 5px; font-family: arial; font-size: 10px; color: #444;'><span id='fofcounts'></span> (<a href='javascript:userViewLists();'>details</a>)</div> \ | |
63 | <ul> \ | |
64 | <li><a href='javascript: autoh();'>auto-hide</a></li> \ | |
65 | </ul> \ | |
66 | <div style='margin-top: 5px; font-family: arial; font-size: 10px; color: #444;' id='fofstatus'></div> \ | |
67 | </div>"; | |
68 | ||
69 | ||
70 | ||
71 | ||
72 | /* | |
73 | ######################## Start Helper Functions ############################ | |
74 | */ | |
75 | ||
76 | unsafeWindow.userViewLists = | |
77 | function(){ | |
78 | alert("Friends: "+friend_list.toString()+"\n\nFoes: "+foe_list.toString()); | |
79 | }; | |
80 | ||
81 | ||
82 | function userSetCounts(){ | |
83 | var counts = document.getElementById('fofcounts'); | |
84 | counts.innerHTML = friend_list.length+" friends and "+foe_list.length+" foes"; | |
85 | }; | |
86 | ||
87 | // pull lists | |
88 | function getlists(){ | |
89 | var t1 = GM_getValue('fof_foelist',''); | |
90 | var t2 = GM_getValue('fof_friendlist',''); | |
91 | // see if there is a difference | |
92 | if(t1=='') foe_list = []; | |
93 | else foe_list = t1.split(','); | |
94 | if(t2=='') friend_list = []; | |
95 | else friend_list = t2.split(','); | |
96 | } | |
97 | ||
98 | // save changes to lists | |
99 | function savelists(){ | |
100 | // get current lists again to see if another tab/window updated anything | |
101 | var t1 = GM_getValue('fof_foelist',''); | |
102 | var t2 = GM_getValue('fof_friendlist',''); | |
103 | // if difference save changes | |
104 | if(t1 != foe_list.toString()){ | |
105 | GM_setValue('fof_foelist',foe_list.toString()); | |
106 | } | |
107 | if(t2 != friend_list.toString()){ | |
108 | GM_setValue('fof_friendlist',friend_list.toString()); | |
109 | } | |
110 | } | |
111 | ||
112 | ||
113 | ||
114 | // Add a Foe function | |
115 | unsafeWindow.userAddFoe = | |
116 | function(s){ | |
117 | fof_user = s; | |
118 | // run in timeout so we can call GM_ funcs | |
119 | setTimeout( | |
120 | function (){ | |
121 | if(foe_list.has(fof_user)) | |
122 | return; | |
123 | getlists(); | |
124 | foe_list.push(fof_user); | |
125 | savelists(); | |
126 | addButtons(); | |
127 | userSetCounts(); | |
128 | setstatus("Set '"+fof_user+"' as Foe"); | |
129 | }, | |
130 | 0); | |
131 | }; | |
132 | ||
133 | // Add a Friend function | |
134 | unsafeWindow.userAddFriend = | |
135 | function (s){ | |
136 | fof_user = s; | |
137 | // run in timeout so we can call GM_ funcs | |
138 | setTimeout( | |
139 | function (){ | |
140 | if(friend_list.has(fof_user)) | |
141 | return; | |
142 | getlists(); | |
143 | friend_list.push(fof_user); | |
144 | savelists(); | |
145 | addButtons(); | |
146 | userSetCounts(); | |
147 | setstatus("Set '"+fof_user+"' as Friend"); | |
148 | }, | |
149 | 0); | |
150 | }; | |
151 | ||
152 | // unset user from both friend and foe lists | |
153 | unsafeWindow.userUnset = | |
154 | function (s){ | |
155 | fof_user = s; | |
156 | // run in timeout so we can call GM_ funcs | |
157 | setTimeout( | |
158 | function (){ | |
159 | getlists() | |
160 | friend_list.remove(fof_user); | |
161 | foe_list.remove(fof_user); | |
162 | savelists(); | |
163 | addButtons(); | |
164 | userSetCounts(); | |
165 | setstatus("Removed '"+fof_user+"' from lists"); | |
166 | }, | |
167 | 0); | |
168 | }; | |
169 | ||
170 | // create click event to use on divs and anchor tags | |
171 | function clickevent(){ | |
172 | var evt = document.createEvent("MouseEvents"); | |
173 | evt.initMouseEvent("click", true, true, window,0, 0, 0, 0, 0, false, false, false, false, 0, null); | |
174 | return evt; | |
175 | } | |
176 | ||
177 | // shortcut to set the status | |
178 | function setstatus(s){ | |
179 | var stat = document.getElementById('fofstatus'); | |
180 | stat.innerHTML = stat.innerHTML+s+"<br>"; | |
181 | } | |
182 | ||
183 | // loop through and click everything in the list | |
184 | // note we kill the interval that calls this when the list is empty | |
185 | function clickloop(){ | |
186 | if(clicklist.length==0){ | |
187 | clickinterval = null; | |
188 | return; | |
189 | } | |
190 | var elm = clicklist.pop(); | |
191 | elm.dispatchEvent(clickevent()); | |
192 | } | |
193 | ||
194 | // get a css property, you'd think this would be easier... | |
195 | function getStyle(x,styleProp) | |
196 | { | |
197 | if (x.currentStyle) | |
198 | var y = x.currentStyle[styleProp]; | |
199 | else if (window.getComputedStyle) | |
200 | var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp); | |
201 | return y; | |
202 | } | |
203 | ||
204 | ||
205 | ||
206 | ||
207 | ||
208 | /* | |
209 | ######################## Start Main Functions ############################ | |
210 | */ | |
211 | ||
212 | ||
213 | function addButtons(){ | |
214 | // div that holds all the submissions | |
215 | var t = document.getElementsByClassName("midcol"); | |
216 | // loop through submissions | |
217 | for(i=0; i < t.length; i++){ | |
218 | // parent node is the div container for the submission | |
219 | submission = t[i].parentNode; | |
220 | // try to find the username | |
221 | var userbox = submission.getElementsByClassName("tagline")[0]; | |
222 | var title = submission.getElementsByClassName("title loggedin")[0]; | |
223 | // if in the recently viewed box (no username shown there) skip it | |
224 | try{ | |
225 | var user = userbox.getElementsByTagName("a")[0]; | |
226 | }catch(e){ | |
227 | continue; // no username section | |
228 | } | |
229 | if(user == undefined) | |
230 | continue; // user is [deleted] | |
231 | var username = user.innerHTML; | |
232 | // save reddit's user colors so we can reset if needed | |
233 | if(fof_usercolors[username]==undefined){ | |
234 | fof_usercolors[username] = getStyle(user, "color"); | |
235 | } | |
236 | // now chose what colors to use according to the user | |
237 | if(foe_list.has(username)){ | |
238 | user.style.color = fof_usercolors[username]; //"#336699" | |
239 | $(submission).css('opacity',0.3); | |
240 | submission.style.marginRight = "300px"; // opacity annoyance | |
241 | } | |
242 | else if(friend_list.has(username)){ | |
243 | user.style.color = "#00AA00"; | |
244 | title.style.color = "#00AA00"; | |
245 | $(submission).css('opacity',1); | |
246 | } | |
247 | else{ | |
248 | user.style.color = fof_usercolors[username]; //"#336699" | |
249 | title.style.color = "inherit"; | |
250 | $(submission).css('opacity',1); | |
251 | } | |
252 | // see if userops is already set, if not append it | |
253 | var userops = userbox.getElementsByClassName("userops")[0]; | |
254 | if(userops == undefined){ | |
255 | userops = document.createElement("span"); | |
256 | userops.className = "userops"; | |
257 | userbox.appendChild(userops); | |
258 | } | |
259 | // now fill with appropriate links | |
260 | if(foe_list.has(username) | friend_list.has(username)) | |
261 | userops.innerHTML = " (<a style='color: #666;' href=\"javascript:userUnset('"+username+"');\">unset</a>)"; | |
262 | else | |
263 | userops.innerHTML = " (<a style='color: #666;' href=\"javascript:userAddFoe('"+username+"');\">foe</a>|<a style='color: #666;' href=\"javascript:userAddFriend('"+username+"');\">friend</a>)"; | |
264 | } | |
265 | } | |
266 | ||
267 | ||
268 | // This goes through and clicks the "hide" button on the submissions | |
269 | // we add it to the reddit context so the link we add can call it | |
270 | unsafeWindow.autoh = | |
271 | function (){ | |
272 | // div that holds all the submissions | |
273 | var t = document.getElementsByClassName("midcol"); | |
274 | var c = 0; | |
275 | var v = 0; | |
276 | // loop through submissions | |
277 | for(i=0; i < t.length; i++){ | |
278 | // parent node is the div container for the submission | |
279 | submission = t[i].parentNode; | |
280 | var userbox = submission.getElementsByClassName("tagline")[0]; | |
281 | // if in the recently viewed box (no username shown there) skip it | |
282 | try{ | |
283 | var username = userbox.getElementsByTagName("a")[0].innerHTML; | |
284 | }catch(e){ | |
285 | continue; // no username section | |
286 | } | |
287 | // if not a bad user, skip this iteration | |
288 | if(!foe_list.has(username)) | |
289 | continue; | |
290 | c++; | |
291 | // hide it if it's down voted only | |
292 | if(t[i].className == "midcol dislikes"){ | |
293 | // add object to click to the clicklist | |
294 | clicklist.push(submission.getElementsByClassName('state-button hide-button')[0].getElementsByTagName('a')[0]); | |
295 | v++; | |
296 | } | |
297 | } | |
298 | // start hiding (3 second time due to stupid fade out effect) | |
299 | clickinterval = setInterval(clickloop, 3000); | |
300 | // set status | |
301 | setstatus("Hid "+v+" of "+c+" bad submissions"); | |
302 | }; | |
303 | ||
304 | ||
305 | ||
306 | ||
307 | // function to perform action on submissions | |
308 | function autov(){ | |
309 | try{ | |
310 | // get all submissions | |
311 | var t = document.getElementsByClassName("midcol"); | |
312 | // loop through unvoted submissions | |
313 | var c = 0; | |
314 | var v = 0; | |
315 | for(i=0; i < t.length; i++){ | |
316 | // parent node is the div container for the submission | |
317 | var submission = t[i].parentNode; | |
318 | // now get the appropriate objects we check | |
319 | var downarrow = submission.getElementsByClassName("arrow down")[0]; | |
320 | var userbox = submission.getElementsByClassName("tagline")[0]; | |
321 | // if in the recently viewed box (no username shown there) skip it | |
322 | try{ | |
323 | var username = userbox.getElementsByTagName("a")[0].innerHTML; | |
324 | }catch(e){ | |
325 | continue; // no username section | |
326 | } | |
327 | // if not a bad user, skip this iteration | |
328 | if(!foe_list.has(username)) | |
329 | continue; | |
330 | c++; | |
331 | // if not already down voted, down vote it | |
332 | if(t[i].className == "midcol unvoted"){ | |
333 | // save arrow to an array for down-voting later | |
334 | clicklist.push(downarrow); | |
335 | v++; | |
336 | } | |
337 | } | |
338 | // start down voting form the list we made (1 second timer) | |
339 | clickinterval = setInterval(clickloop, 1000); | |
340 | // set status | |
341 | if(c==0) | |
342 | setstatus("No bad submissions found"); | |
343 | else | |
344 | setstatus("Auto down voted "+v+" of "+c+" bad submissions"); | |
345 | } | |
346 | catch(e){ | |
347 | setstatus("Error: "+e); | |
348 | } | |
349 | } | |
350 | ||
351 | ||
352 | ||
353 | ||
354 | /* | |
355 | ######################## Begin auto-procedures ############################ | |
356 | */ | |
357 | ||
358 | // do auto-voting only if we are on a table with submissions listed | |
359 | if(document.getElementById('siteTable') != null){ | |
360 | getlists(); | |
361 | userSetCounts(); | |
362 | autov(); | |
363 | addButtons(); | |
364 | } |