Facebook User List Maker

Save and Load Friend Lists for Facebook Lists

目前為 2017-12-07 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Facebook User List Maker
  3. // @namespace facebookuserlistmaker
  4. // @version 1.3.8
  5. // @author Tophness
  6. // @match http://www.facebook.com/*
  7. // @match https://www.facebook.com/*
  8. // @description Save and Load Friend Lists for Facebook Lists
  9. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_deleteValue
  13. // @grant GM_listValues
  14. // @run-at document-idle
  15. // ==/UserScript==
  16.  
  17. var friendsSelector = 'div[id$="_friends"]';
  18. var friendsSelector2 = 'div[role="dialog"]';
  19. var storySelector = 'div[id^="friends_"]';
  20. var storySelector2 = 'div[data-testid="friend_list_item"]';
  21. var storySelector3 = 'a[data-hovercard]';
  22. var users = [];
  23. var friendsel;
  24. var saveDiv = '<form name="save"><input type=button onclick="document.forms.save.dosave.value=true;" value="Save List"><input type=text name=listname><input type=hidden name=dosave value="false"></form>';
  25. var loadDiv = '<form name="load"><input type=button onclick="document.forms.load.doload.value=true;" value="Load List"><input type=hidden name=doload value="false"><input type=hidden name=dodelete value="false"><input type=button onclick="document.forms.load.dodelete.value=true;" value="Delete List"></form>';
  26. var mutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
  27.  
  28. function includes(k) {
  29. for(var i=0; i < this.length; i++){
  30. if( this[i].name === k ){
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36.  
  37. function block(story) {
  38. if (!story) {
  39. return;
  40. }
  41. if (story.getElementsByTagName('a').length) {
  42. var links = story.getElementsByTagName('a');
  43. for (var i = 0; i < links.length; i++) {
  44. if(links[i].outerHTML.indexOf('data-hovercard') != -1){
  45. var uname = links[i].innerText;
  46. var uid = links[i].getAttribute('data-hovercard');
  47. uid = uid.substring(uid.indexOf('id=') + 3);
  48. if(uid.indexOf('&') == -1){
  49. uid = uid.substring(0, uid.indexOf('"'));
  50. }
  51. else{
  52. uid = uid.substring(0, uid.indexOf('&'));
  53. }
  54. if(uname != ""){
  55. var newuser = {};
  56. newuser.name = uname;
  57. newuser.id = uid;
  58. if(!users.includes(newuser.name)){
  59. users.push(newuser);
  60. }
  61. }
  62. }
  63. }
  64. }
  65. }
  66.  
  67. function block2(link){
  68. if(link.outerHTML.indexOf('data-hovercard') != -1){
  69. var uname = link.innerText;
  70. var uid = link.getAttribute('uid');
  71. if(uname != "" && !users.includes(uname)){
  72. var newuser = {};
  73. newuser.name = uname;
  74. if(uid){
  75. newuser.id = uid;
  76. }
  77. else{
  78. uid = link.getAttribute('data-hovercard');
  79. uid = uid.substring(uid.indexOf('id=') + 3);
  80. if(uid.indexOf('&') == -1){
  81. uid = uid.substring(0, uid.indexOf('"'));
  82. }
  83. else{
  84. uid = uid.substring(0, uid.indexOf('&'));
  85. }
  86. newuser.id = uid;
  87. }
  88. users.push(newuser);
  89. }
  90. }
  91. }
  92.  
  93. function process() {
  94. if(document.forms.save.dosave.value == "true" && document.forms.save.listname.value != ""){
  95. if(location.href.indexOf('/friends') != -1){
  96. var stories = document.querySelector(friendsSelector);
  97. if (!stories) {
  98. return;
  99. }
  100. var story = stories.querySelectorAll(storySelector);
  101. if (!story.length) {
  102. story = stories.querySelectorAll(storySelector2);
  103. if (!story.length) {
  104. return;
  105. }
  106. }
  107. for (var i = 0; i < story.length; i++) {
  108. block(story[i]);
  109. }
  110. }
  111. else{
  112. var storiesb = friendssel;
  113. if (!storiesb){
  114. return;
  115. }
  116. var storyb = storiesb.querySelectorAll(storySelector3);
  117. if (!storyb.length) {
  118. return;
  119. }
  120. for (var i2 = 0; i2 < storyb.length; i2++) {
  121. block2(storyb[i2]);
  122. }
  123. }
  124. GM_setValue(document.forms.save.listname.value, JSON.stringify(users));
  125. }
  126. }
  127.  
  128. function waitForEl(selector, callback, timer=100){
  129. var poller1 = setInterval(function(){
  130. $jObject = jQuery(selector);
  131. if($jObject.length < 1){
  132. return;
  133. }
  134. clearInterval(poller1);
  135. callback($jObject);
  136. },timer);
  137. }
  138.  
  139. function uToken(username, id){
  140. var newdiv = document.createElement('span');
  141. newdiv.className = "removable uiToken";
  142. var newdiv2 = document.createElement('span');
  143. newdiv2.className = "uiTokenText";
  144. newdiv2.innerHTML = username;
  145. var newdiv3 = document.createElement('input');
  146. newdiv3.name="members[]";
  147. newdiv3.autocomplete="off";
  148. newdiv3.type="hidden";
  149. newdiv3.value = id;
  150. var newdiv4 = document.createElement('input');
  151. newdiv4.value=username;
  152. newdiv4.name="text_members[]";
  153. newdiv4.autocomplete="off";
  154. newdiv4.type="hidden";
  155. var newdiv5 = document.createElement('a');
  156. newdiv5.href="#";
  157. newdiv5.aria_label="Remove " + username;
  158. newdiv5.className="remove uiCloseButton uiCloseButtonSmall";
  159. newdiv.appendChild(newdiv2);
  160. newdiv.appendChild(newdiv3);
  161. newdiv.appendChild(newdiv4);
  162. newdiv.appendChild(newdiv5);
  163. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].appendChild(newdiv);
  164. }
  165.  
  166. function listpaste(){
  167. if(document.getElementById('createListMembers')){
  168. if(document.getElementById('createListname') && document.forms.load.listnames.value){
  169. document.getElementById('createListname').value = document.forms.load.listnames.value;
  170. }
  171. if(document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0]){
  172. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].className = "tokenarea";
  173. }
  174. for (var i = 0; i < users.length; i++) {
  175. uToken(users[i].name, users[i].id);
  176. }
  177. }
  178. else{
  179. setTimeout(listpaste, 1000);
  180. }
  181. }
  182.  
  183. function observebody(){
  184. if(document.forms.save.dosave.value == "true"){
  185. var listname = document.forms.save.listname.value.toLowerCase().replace(/[^a-zA-Z0-9]+/g, "");
  186. users = JSON.parse(GM_getValue(listname, "[]"));
  187. if(!users){
  188. console.warn("error");
  189. }
  190. users.includes = includes;
  191. process();
  192. }
  193. else{
  194. setTimeout(observebody, 1000);
  195. }
  196. }
  197.  
  198. function loadbegin(){
  199. if(document.forms.load.doload.value == "true"){
  200. users = JSON.parse(GM_getValue(document.forms.load.listnames.value, "[]"));
  201. if(!users){
  202. console.warn("error");
  203. }
  204. users.includes = includes;
  205. if(contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0]){
  206. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].addEventListener('click', listpaste, false);
  207. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].click();
  208. }
  209. }
  210. else if(document.forms.load.dodelete.value == "true"){
  211. var select = document.forms.load.listnames;
  212. GM_deleteValue(select.value);
  213. dvalue = select.selectedIndex;
  214. select.removeChild(select[dvalue]);
  215. }
  216. else{
  217. setTimeout(loadbegin, 1000);
  218. }
  219. }
  220.  
  221. function startObserver(){
  222. var observer = new mutationObserver(process);
  223. observer.observe(document.querySelector('body'), {
  224. 'childList': true,
  225. 'subtree': true
  226. });
  227. observebody();
  228. }
  229.  
  230. function loadfindpage(el){
  231. var savebut = document.createElement('div');
  232. savebut.innerHTML = saveDiv;
  233. el.insertAdjacentElement('afterbegin', savebut);
  234. startObserver();
  235. }
  236.  
  237. function findpage(){
  238. var divs = document.querySelectorAll(friendsSelector2);
  239. var found = false;
  240. for (var i = 0; i < divs.length; ++i) {
  241. if(divs[i].querySelectorAll(storySelector3).length){
  242. friendssel = divs[i];
  243. found = true;
  244. }
  245. }
  246. if(found){
  247. loadfindpage(friendssel);
  248. }
  249. else{
  250. setTimeout(findpage, 1000);
  251. }
  252. }
  253.  
  254. if(location.href.indexOf('bookmarks/lists') != -1){
  255. var contentarea = document.getElementById('contentArea');
  256. waitForEl(contentarea, function() {
  257. var loadbut = document.createElement('div');
  258. loadbut.innerHTML = loadDiv;
  259. var x = document.createElement("select");
  260. x.name="listnames";
  261. var alllists = GM_listValues();
  262. for (var i = 0; i < alllists.length; i++) {
  263. var option = document.createElement("option");
  264. option.text = alllists[i];
  265. x.add(option);
  266. }
  267. contentarea.insertAdjacentElement('afterbegin', loadbut);
  268. document.forms.load.appendChild(x);
  269. loadbegin();
  270. });
  271. }
  272. else if(location.href.indexOf('/friends') != -1){
  273. waitForEl(document.querySelector(friendsSelector), function() {
  274. var savebut = document.createElement('div');
  275. savebut.innerHTML = saveDiv;
  276. document.querySelector(friendsSelector).insertAdjacentElement('afterbegin', savebut);
  277. startObserver();
  278. },500);
  279. }
  280. else{
  281. findpage();
  282. }