膜法小工具

方便生活,快乐分享

  1. // ==UserScript==
  2. // @name 膜法小工具
  3. // @version 0.6.2
  4. // @author dolacmeo
  5. // @description 方便生活,快乐分享
  6. // @license MIT; https://opensource.org/licenses/MIT
  7. // @namespace https://gf.qytechs.cn/users/57661
  8. // @namespace https://gf.qytechs.cn/zh-CN/scripts/37822/
  9. // @supportURL https://gf.qytechs.cn/zh-CN/scripts/37822/feedback
  10. // @require https://cdn.jsdelivr.net/npm/js-base64@2.4.3/base64.min.js
  11. // @resource country_code https://w.url.cn/s/AQenoiI
  12. // @include *://free-ss.*
  13. // @grant GM_log
  14. // @grant GM_info
  15. // @grant GM_addStyle
  16. // @grant GM_setClipboard
  17. // @grant GM_getResourceText
  18. // @grant GM_xmlhttpRequest
  19. // @grant GM_openInTab
  20. // @grant unsafeWindow
  21. // @run-at document-idle
  22. // ==/UserScript==
  23. // @0.6.2 2020-07-10 代码优化、更换订阅转换接口
  24. // @0.6.1 2020-07-08 错误修复、使用paste.rs充当临时订阅
  25. // @0.6.0 2020-06-15 错误修复、样式优化
  26. // 抱歉很久没更新,报错是因为淘宝ip接口已不支持公用、移除了客户端检查
  27. // @0.5.9 2018-05-15 样式优化
  28. // @0.5.8 2018-05-14 样式优化、错误修复、新增功能
  29. // 鼠标悬停显示二维码、增加移除客户端无效协议功能
  30. // @0.5.7 2018-05-11 样式优化
  31. // 预更新线路检测功能
  32. // @0.5.6 2018-05-09 样式优化
  33. // 移除低速后移除无效区域
  34. // @0.5.5 2018-05-04 样式优化
  35. // @0.5.4 2018-05-04 样式优化、代码优化
  36. // 优化页面样式,中文化区域选择
  37. // @0.5.3 2018-05-03 错误修复、可用性维护
  38. // @0.5.2 2018-05-02 样式优化、新增功能
  39. // @0.5.1 2018-04-27 错误修复
  40. // @0.5.0 2018-04-27 样式优化、代码优化
  41. // 变更了插件名称及其他信息
  42. // @0.4.6 2018-04-23 应站长要求移除订阅功能
  43. // @0.4.5 2018-04-23 可用性维护
  44. // @0.4.4 2018-04-09 错误修复
  45. // @0.4.2 2018-04-08 新增功能
  46. // @0.4.1 2018-04-07 错误修复、新增功能
  47. // 新增移除低速按钮,一键清爽(6分以下)
  48. // @0.4.0 2018-04-05 代码优化
  49. // @0.3.8 2018-03-22 可用性维护
  50. // @0.3.7 2018-03-03 可用性维护
  51. // @0.3.6 2018-02-27 可用性维护
  52. // 增加镜像站
  53. // @0.3.5 2018-02-24 可用性维护
  54. // @0.3.4 2018-02-13 代码优化
  55. // @0.3.3 2018-02-06 可用性维护
  56. // @0.3.2 2018-02-02 样式优化
  57. // 点击二维码按钮生成两种链接与二维码
  58. // @0.3.1 2018-02-02 样式优化、代码优化
  59. // 可进行多选,再生成链接,不选择生成所有
  60. // @0.3.0 2018-02-02 可用性维护、代码优化
  61. // @0.2.1 2018-01-31 错误修复
  62. // @0.2.0 2018-01-31 样式优化、新增功能
  63. // @0.1.0 2018-01-26 初始版本
  64.  
  65. // $(".banner").remove(); // 去广告
  66. var today_date = new Date();
  67. var date_str = today_date.toISOString().slice(0,10)+'_';
  68. var enb64 = Base64.encodeURI, deb64 = Base64.decode;
  69. var ss_id, ss_links_str = "", ssr_links_str = "",rss_url,
  70. link_count=0, areas=[], xyz="http://"+deb64("c3NyLjEyMzQ1NjYueHl6"),
  71. ok_method=['aes-128-cfb','aes-128-ctr','aes-192-cfb','aes-192-ctr','aes-256-cfb','aes-256-ctr',
  72. 'bf-cfb','camellia-128-cfb','camellia-192-cfb','camellia-256-cfb','chacha20','chacha20-ietf','rc4-md5','salsa20'],
  73. order={point:0,address:1,port:2,password:3,method:4,clock:5,globe:6,qrcode:7};
  74. var country_code = JSON.parse(""+GM_getResourceText('country_code'));
  75. $("table").each(function (){if ($("#"+this.id+"_wrapper").css("height") === undefined) {ss_id = "#"+this.id;}});
  76. layer.load(0, {shade:false,time:3000});$(ss_id).before("<ul id='tools'></ul>");
  77. $('#qrcode').after('<div style="display:none" id="qrcode0"></div>');
  78. GM_addStyle("body{margin:0;}"+
  79. "h3 small a{font-weight:bold;color:#4CAF50;font-size:10px;text-decoration:none;}"+
  80. "h3 small button{padding:2px 5px;border:none;font-size:1em;cursor:pointer;}"+
  81. "li.a {padding:0 40px;}li.q {padding:0 20px;}"+
  82. "li.aff {float:none;display:inline-block;}"+
  83. "#tools {margin:0;padding-left:10px;}"+
  84. "#tools p{margin:0;height:23px;}"+"#sel{color:#000080}"+
  85. "#tools button{cursor:pointer;margin-left:3px;height:23px;border: 0;}"+
  86. "#tools p,#tools span,#tools small{cursor:default;}"+
  87. "#tools .txt{display:inline-block;float:left;font-weight:bold;color:#f66;}"+
  88. "#tools .btn{display:inline-block;float:right;}"+
  89. "#tools .btn small{color:#e91e63;font-weight: bold;}"+
  90. ".qr-link {width: 298px;display: inline-block;background-color: darkgrey;border: darkgreen solid 1px;}"+
  91. ".qr-link a, .qr-link input[type='checkbox']{font-size: 30px;font-weight: bold;}.qr-link input[type='checkbox'] {width: 20px; height: 20px;float: right;}"+
  92. ".qr-link canvas {width: 90%;margin: 10px;}"+
  93. ".showup {opacity: 1;} .showoff {opacity: 0;}"+
  94. "#ss_area {display:inline-block;float:right;margin-left:3px;padding:1px 6px;height:23px;cursor:pointer;color:blue;}");
  95.  
  96. // 工具对象
  97. var tools = {
  98. // 查询当前页面次序
  99. order: function () {
  100. var o = [],d = {}, v;
  101. $(ss_id).find("th").each(function () {
  102. v = $(this).html();
  103. if (v.split("/").length-1 >= 2) {
  104. o.push("point");
  105. } else if (v.search("clock") != -1) {
  106. o.push("clock");
  107. } else if (v.search("globe") != -1) {
  108. o.push("globe");
  109. } else if (v.search("qrcode") != -1) {
  110. o.push("qrcode");
  111. } else {o.push(v.toLowerCase());}
  112. });
  113. for (var x=0;x<o.length;x++) {d[o[x]] = x;}
  114. return d;
  115. },
  116. // 整理链接区域
  117. area: function() {
  118. var ssdatas = ss_table.data(), column = 6, l=[];
  119. if (order != undefined) {column = order.globe;}
  120. $.each(ssdatas, function(i, data){if ($.inArray(data[column], l) == -1) {if (data[column][0] != '*'){l.push(data[column]);}}});
  121. areas = l;return l;
  122. },
  123. // ss://method:password@server:port
  124. ss: function (data) {
  125. var method=data[order.method],
  126. password=data[order.password],
  127. server=data[order.address],
  128. port=data[order.port],
  129. remark=data[order.globe]+'['+data[order.point]+']'+'('+date_str+data[order.clock]+')';
  130. return 'ss://'+enb64(method+':'+password+'@'+server+':'+port)+'#'+remark.replace(/↑/g,'').replace(/↓/g,'');
  131. },
  132. // ssr://server:port:protocol:method:obfs:password_base64/?params_base64
  133. ssr: function (data) {
  134. var server=data[order.address],
  135. port=data[order.port],
  136. protocol="origin",
  137. method=data[order.method],
  138. obfs="plain",
  139. password=data[order.password],
  140. remarks=data[order.globe]+'['+data[order.point]+']'+'('+date_str+data[order.clock]+')',
  141. group="ZnJlZS1zcw";
  142. return 'ssr://'+enb64(server+':'+port+':'+protocol+':'+method+':'+obfs+':'+enb64(password)+'/?remarks='+enb64(remarks.replace(/↑/g,'').replace(/↓/g,''))+'&group='+group);
  143. },
  144. // 将数据处理成链接
  145. datas: function () {
  146. var ssdatas;
  147. if (ss_table.rows('.selected').data().length > 0) {ssdatas = ss_table.rows('.selected').data();} else {ssdatas = ss_table.data();}
  148. ss_links_str = "";ssr_links_str = "";
  149. $.each(ssdatas, function(i, data){
  150. ss_links_str = ss_links_str + tools.ss(data) + '\n';
  151. ssr_links_str = ssr_links_str + tools.ssr(data) + '\n';
  152. });
  153. return ssdatas;
  154. },
  155. // 处理二维码事件
  156. qr: function (data) {
  157. var ss = tools.ss(data), ssr =tools.ssr(data);
  158. var qrcode = $('#qrcode0');
  159. qrcode.html('<div class="qr-link"><a href="">SS</a><input type="checkbox" name="ssqr" checked="checked"><br></div>'+
  160. '<div class="qr-link"><a href="">SSR</a><input type="checkbox" name="ssrqr" checked="checked"><br></div>');
  161. qrcode.find('a').eq(0).attr('href', ss);
  162. qrcode.find('.qr-link').eq(0).qrcode({render:'canvas',background:'#FFFFFF',ecLevel:'M',label: 'SS link',text:ss});
  163. qrcode.find('a').eq(1).attr('href', ssr);
  164. qrcode.find('.qr-link').eq(1).qrcode({render:'canvas',background:'#FFFFFF',ecLevel:'M',label: 'SSR link',text:ssr});
  165. $('input:checkbox').click(function () {
  166. this.blur(); this.focus();
  167. $(this).siblings("canvas").eq(0).toggleClass('showoff');
  168. });
  169. layer.closeAll();
  170. layer.open({
  171. type:1,
  172. title:data[1]+':'+data[2]+' ('+data[6]+')',
  173. closeBtn:0,
  174. shade:0.1,
  175. area:'600px',
  176. shadeClose:true,
  177. content:qrcode
  178. });
  179. },
  180. upload: function () {
  181. function RssAlert(rss){
  182. layer.closeAll();
  183. layer.alert(
  184. '<a href="https://42one.fun/subconverter/">机场订阅转换工具--Subconverter</a><br><br>'+
  185. '㊣SSR:<a href="'+rss+'">'+rss+'</a><br>'+
  186. '⇲Clash:<a href="https://sub.42one.fun/sub?target=clash&url='+encodeURI(rss)+'">转换链接</a><br>',
  187. {title:'临时订阅地址'});
  188. }
  189. if (rss_url===undefined){
  190. GM_xmlhttpRequest({
  191. method:'POST',
  192. url: "https://paste.rs/",
  193. data: enb64(ssr_links_str),
  194. onloadstart: function() { layer.load(2, { time: 10000 }); },
  195. onload: function(response) {
  196. rss_url=response.responseText;
  197. GM_log(response);RssAlert(rss_url);
  198. //window.open(response.responseText);
  199. },
  200. onerror: onload,
  201. ontimeout: onload
  202. });
  203. } else {RssAlert(rss_url);}
  204. return rss_url;
  205. }
  206. };
  207.  
  208. document.onkeydown = function(e) { if (e.ctrlKey && 81 == e.keyCode) { tools.upload(); } }; // Ctrl+q
  209.  
  210. function make_area(){
  211. tools.area();
  212. $("#ss_area").html("");
  213. $("#ss_area").append("<option value=''></option>");
  214. for (var x=-1;x++,x<areas.length;){$('#ss_area').append("<option value='"+areas[x]+"'>"+country_code[areas[x]]+"</option>");}
  215. }
  216.  
  217. function check_method(){
  218. ss_table.$('tr.selected').removeClass('selected');
  219. $(ss_id+ ' tbody').find('tr').each(function(){
  220. var m = $(this).find('td').eq(order.method).text();
  221. if (ok_method.indexOf(m)==-1) {$(this).toggleClass('selected');}
  222. });
  223. if (ss_table.rows('.selected').data().length > 0){
  224. layer.msg("已移除不兼容SSR的协议("+ss_table.rows('.selected').data().length+"条)", {time:1500});
  225. ss_table.rows('.selected').remove().draw();
  226. } else {
  227. layer.msg("所有链接协议可用", {time:1000});
  228. }
  229. $("#total").html("共 "+ ss_table.data().length+" 条");
  230. }
  231.  
  232. function start(){
  233. layer.closeAll();
  234. $(".fa-info-circle").remove();
  235. site_info();
  236. ss_table = $(ss_id).DataTable( { retrieve: true } );
  237. unsafeWindow.ss_table = ss_table;
  238. order = tools.order();tools.datas();
  239. ss_table.order( [ 0, 'asc' ] ).draw();
  240. link_count = tools.datas().length;
  241. $("h3").eq(-1).append(
  242. "<small> <a title='"+GM_info.script.name+"' target='_blank' href='"+GM_info.script.supportURL+"'><i class='fa fa-bolt'></i> "+GM_info.script.version+"</a></small>"+
  243. "<small style='float:right'>"+
  244. "<button id='rss-upload' style='background-color:initial;'><i class='fa fa-rss'></i></button>"+
  245. "<button id='site_info' style='background-color:initial;'><i class='fa fa-question-circle'></i></button>"+
  246. "</small>"
  247. );$("title").append("⚡");
  248. $('#site_info').on('click',function(){site_info();});
  249. $('#rss-upload').on('click',function(){tools.upload();});
  250. $("#tools").html(
  251. "<li class='txt'>"+
  252. "<p id='link_num'><span id='total'>共 "+ss_table.data().length+" 条</span><span id='sel'></span></p></li>"+
  253. "<li class='btn'>"+
  254. "<button id='btn_clear' title='移除评分6以下'>移除不稳定</button>"+
  255. "<button id='btn_ss'>复制 SS</button>"+
  256. "<button id='btn_ssr'>复制SSR</button>"+
  257. "<select id='ss_area'></select>"+
  258. "</li>"
  259. );
  260. make_area();
  261. $('#ss_area').on('change', function(){
  262. $(ss_id+ ' tbody').find('tr').each(function(){
  263. if ($('#ss_area').val() == ''){
  264. $(this).removeClass('selected');
  265. $("#sel").html("");
  266. } else {
  267. if($(this).find('td').eq(order.globe).text().indexOf($('#ss_area').val()) != -1){
  268. $(this).toggleClass('selected');
  269. } else {
  270. $(this).removeClass('selected');
  271. }
  272. layer.msg("已选中 "+country_code[$('#ss_area').val()]+" 区域", {time:1000});
  273. $("#sel").html(",已选 "+ss_table.rows('.selected').data().length+" 条");
  274. ss_table.order( [ order.globe, 'asc' ] ).draw();
  275. }
  276. });
  277. });
  278. $('#btn_ss').on('click',function(){
  279. layer.msg("SS 链接复制成功("+tools.datas().length+"条)", {time:1000});
  280. GM_setClipboard(ss_links_str);});
  281. $('#btn_ssr').on('click',function(){
  282. layer.msg("SSR链接复制成功("+tools.datas().length+"条)", {time:1000});
  283. GM_setClipboard(ssr_links_str);});
  284. $('#btn_clear').on('click',function(){
  285. ss_table.$('tr.selected').removeClass('selected');
  286. $(ss_id+ ' tbody').find('tr').each(function(){
  287. var point_str = $(this).find('td').eq(0).text().replace(/↑/g,'').replace(/↓/g,'');
  288. var ping = point_str.split('/');
  289. if (point_str.match(/[a-zA-Z]/g)) {$(this).toggleClass('selected');}
  290. else if (ping.length) {for (var x in ping) {if (Number(ping[x])<=5){$(this).toggleClass('selected');break;} } } });
  291. if (ss_table.rows('.selected').data().length > 0){
  292. layer.msg("已移除不稳定链接("+ss_table.rows('.selected').data().length+"条)", {time:1000});
  293. $('#btn_clear').before("<small> (已移除"+ss_table.rows('.selected').data().length+"条) </small>");
  294. ss_table.rows('.selected').remove().draw();
  295. } else {
  296. layer.msg("所有链接较为稳定(>5)", {time:1000});
  297. }
  298. ss_table.order( [ 0, 'asc' ] ).draw();
  299. $("#total").html("共 "+ ss_table.data().length+" 条");
  300. $('#btn_clear').remove();
  301. make_area();
  302. method_clear();
  303. });
  304. ss_table.$('tr').click( function () {
  305. $(this).toggleClass('selected');
  306. if (ss_table.rows('.selected').data().length){
  307. $("#sel").html(",已选 "+ss_table.rows('.selected').data().length+" 条");
  308. } else {
  309. $("#sel").html("");
  310. }
  311. } );
  312. // 等待1s
  313. setTimeout(function(){
  314. $(ss_id+' tbody').off('click','i');
  315. $(ss_id+' tbody').on('click','i',function(){tools.qr(ss_table.row($(this).closest('tr')).data());});
  316. },1000);
  317. }
  318.  
  319. function client_info(){
  320. $('#client').show();
  321. layer.open({
  322. type:1,
  323. title:false,
  324. closeBtn:0,
  325. shade:0.7,
  326. area: '500px',
  327. shadeClose:true,
  328. content:$('#client'),
  329. end : function(){$('#client').hide();}
  330. });
  331. }
  332.  
  333. function site_info(){
  334. $('div.footer').show();
  335. layer.open({
  336. type:1,
  337. title:false,
  338. closeBtn:0,
  339. shade:0.7,
  340. area: '500px',
  341. shadeClose:true,
  342. content:$('div.footer'),
  343. end : function(){$('div.footer').hide();}
  344. });
  345. }
  346.  
  347. function failed(){
  348. if (link_count === 0) {
  349. layer.confirm(ss_id+' 貌似脚本加载失败了!?<br>请等待页面加载,或者...', {
  350. title: GM_info.script.name+" "+GM_info.script.version,
  351. closeBtn: 0,
  352. shade: 0.5,
  353. shadeClose: true,
  354. resize: false,
  355. btn: ['刷新','反馈']
  356. }, function(){
  357. location.reload();
  358. }, function(){
  359. GM_openInTab(GM_info.script.supportURL);
  360. });
  361. }
  362. }
  363.  
  364. function method_clear() {
  365. layer.confirm('是否移除不兼容SSR的协议?', {
  366. title: false,
  367. closeBtn: 0,
  368. shade: 0.5,
  369. shadeClose: true,
  370. resize: false,
  371. btn: ['确定','取消']
  372. }, function(index){
  373. check_method();
  374. layer.close(index);
  375. }, function(index){
  376. layer.close(index);
  377. });
  378. }
  379.  
  380. unsafeWindow.tools = tools;
  381. unsafeWindow.start = start;
  382.  
  383. $(document).ready(function() {
  384. $(ss_id).on('init.dt', function (){ start(); });
  385. setTimeout(function(){failed();},5000);
  386. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址