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.7
  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. var stories = document.querySelector(friendsSelector);
  96. if (!stories) {
  97. return;
  98. }
  99. var story = stories.querySelectorAll(storySelector);
  100. if (!story.length) {
  101. story = stories.querySelectorAll(storySelector2);
  102. if (!story.length) {
  103. return;
  104. }
  105. }
  106. for (var i2 = 0; i2 < story.length; i2++) {
  107. block(story[i2]);
  108. }
  109. GM_setValue(document.forms.save.listname.value, JSON.stringify(users));
  110. }
  111. }
  112.  
  113. function processpage() {
  114. if(document.forms.save.dosave.value == "true" && document.forms.save.listname.value != ""){
  115. var stories = friendssel;
  116. if (!stories || stories == 'div[class="uiScrollableAreaContent"]'){
  117. return;
  118. }
  119. var story = stories.querySelectorAll(storySelector3);
  120. if (!story.length) {
  121. return;
  122. }
  123. for (var i2 = 0; i2 < story.length; i2++) {
  124. block2(story[i2]);
  125. }
  126. GM_setValue(document.forms.save.listname.value, JSON.stringify(users));
  127. }
  128. }
  129.  
  130. function waitForEl(selector, callback, timer=100){
  131. var poller1 = setInterval(function(){
  132. $jObject = jQuery(selector);
  133. if($jObject.length < 1){
  134. return;
  135. }
  136. clearInterval(poller1);
  137. callback($jObject);
  138. },timer);
  139. }
  140.  
  141. function uToken(username, id){
  142. var newdiv = document.createElement('span');
  143. newdiv.className = "removable uiToken";
  144. var newdiv2 = document.createElement('span');
  145. newdiv2.className = "uiTokenText";
  146. newdiv2.innerHTML = username;
  147. var newdiv3 = document.createElement('input');
  148. newdiv3.name="members[]";
  149. newdiv3.autocomplete="off";
  150. newdiv3.type="hidden";
  151. newdiv3.value = id;
  152. var newdiv4 = document.createElement('input');
  153. newdiv4.value=username;
  154. newdiv4.name="text_members[]";
  155. newdiv4.autocomplete="off";
  156. newdiv4.type="hidden";
  157. var newdiv5 = document.createElement('a');
  158. newdiv5.href="#";
  159. newdiv5.aria_label="Remove " + username;
  160. newdiv5.className="remove uiCloseButton uiCloseButtonSmall";
  161. newdiv.appendChild(newdiv2);
  162. newdiv.appendChild(newdiv3);
  163. newdiv.appendChild(newdiv4);
  164. newdiv.appendChild(newdiv5);
  165. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].appendChild(newdiv);
  166. }
  167.  
  168. function listpaste(){
  169. if(document.getElementById('createListMembers')){
  170. if(document.getElementById('createListname') && document.forms.load.listnames.value){
  171. document.getElementById('createListname').value = document.forms.load.listnames.value;
  172. }
  173. if(document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0]){
  174. document.getElementById('fbFriendListTokenizer').getElementsByClassName('tokenarea')[0].className = "tokenarea";
  175. }
  176. for (var i = 0; i < users.length; i++) {
  177. uToken(users[i].name, users[i].id);
  178. }
  179. }
  180. else{
  181. setTimeout(listpaste, 1000);
  182. }
  183. }
  184.  
  185. function observebody(){
  186. if(document.forms.save.dosave.value == "true"){
  187. var listname = document.forms.save.listname.value.toLowerCase().replace(/[^a-zA-Z0-9]+/g, "");
  188. users = JSON.parse(GM_getValue(listname, "[]"));
  189. if(!users){
  190. console.warn("error");
  191. }
  192. users.includes = includes;
  193. if(location.href.indexOf('/friends') != -1){
  194. process();
  195. }
  196. else{
  197. processpage();
  198. }
  199. }
  200. else{
  201. setTimeout(observebody, 1000);
  202. }
  203. }
  204.  
  205. function loadbegin(){
  206. if(document.forms.load.doload.value == "true"){
  207. users = JSON.parse(GM_getValue(document.forms.load.listnames.value, "[]"));
  208. if(!users){
  209. console.warn("error");
  210. }
  211. users.includes = includes;
  212. if(contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0]){
  213. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].addEventListener('click', listpaste, false);
  214. contentarea.getElementsByClassName('uiHeaderActions')[0].childNodes[0].click();
  215. }
  216. }
  217. else if(document.forms.load.dodelete.value == "true"){
  218. var select = document.forms.load.listnames;
  219. GM_deleteValue(select.value);
  220. dvalue = select.selectedIndex;
  221. select.removeChild(select[dvalue]);
  222. }
  223. else{
  224. setTimeout(loadbegin, 1000);
  225. }
  226. }
  227.  
  228. function loadfindpage(el){
  229. var savebut = document.createElement('div');
  230. savebut.innerHTML = saveDiv;
  231. el.insertAdjacentElement('afterbegin', savebut);
  232. var observer = new mutationObserver(processpage);
  233. observer.observe(document.querySelector('body'), {
  234. 'childList': true,
  235. 'subtree': true
  236. });
  237. observebody();
  238. }
  239.  
  240. function findpage(){
  241. var divs = document.querySelectorAll(friendsSelector2);
  242. var found = false;
  243. for (var i = 0; i < divs.length; ++i) {
  244. if(divs[i].querySelectorAll(storySelector3).length){
  245. friendssel = divs[i];
  246. found = true;
  247. }
  248. }
  249. if(found){
  250. loadfindpage(friendssel);
  251. }
  252. else{
  253. setTimeout(findpage, 1000);
  254. }
  255. }
  256.  
  257. if(location.href.indexOf('bookmarks/lists') != -1){
  258. var contentarea = document.getElementById('contentArea');
  259. waitForEl(contentarea, function() {
  260. var loadbut = document.createElement('div');
  261. loadbut.innerHTML = loadDiv;
  262. var x = document.createElement("select");
  263. x.name="listnames";
  264. var alllists = GM_listValues();
  265. for (var i = 0; i < alllists.length; i++) {
  266. var option = document.createElement("option");
  267. option.text = alllists[i];
  268. x.add(option);
  269. }
  270. contentarea.insertAdjacentElement('afterbegin', loadbut);
  271. document.forms.load.appendChild(x);
  272. loadbegin();
  273. });
  274. }
  275. else if(location.href.indexOf('/friends') != -1){
  276. waitForEl(document.querySelector(friendsSelector), function() {
  277. var savebut = document.createElement('div');
  278. savebut.innerHTML = saveDiv;
  279. document.querySelector(friendsSelector).insertAdjacentElement('afterbegin', savebut);
  280. var observer = new mutationObserver(process);
  281. observer.observe(document.querySelector('body'), {
  282. 'childList': true,
  283. 'subtree': true
  284. });
  285. observebody();
  286. },500);
  287. }
  288. else{
  289. findpage();
  290. }