微博媒体下载

读取微博媒体的链接,发送到下载下载,并保存

  1. // ==UserScript==
  2. // @name 微博媒体下载
  3. // @namespace http://your.namespace.com
  4. // @version 5.37
  5. // @released 2024-04-18_08:43:54_346
  6. // @description 读取微博媒体的链接,发送到下载下载,并保存
  7. // @author 果心豆腐酱
  8. // @license MIT
  9. // @run-at document-start
  10. // @match https://*.weibo.com/*
  11. // @match https://*.weibo.cn/*
  12. // @match https://police.lanzouw.com/b01a8pxgj
  13. // @icon https://weibo.com/favicon.ico
  14.  
  15. // @grant GM_setValue
  16. // @grant GM_getValue
  17. // @grant GM_xmlhttpRequest
  18. // @grant GM_download
  19. // ==/UserScript==
  20.  
  21.  
  22. //页面元素监测,判断小红书笔记列表是否出现
  23. window.addEventListener('load', function () {
  24. 设置服务器按钮();
  25. var pwdload = document.querySelector('[id="pwdload"] [name="pwd"]');
  26. if (pwdload) document.querySelector('[name="pwd"]').value = 'f4hz', document.querySelector('[id="sub"]').click();
  27. });
  28. 添加样式();
  29. // 创建一个 MutationObserver 实例
  30. if (document.body) {
  31. 启动元素检测();
  32. } else {
  33. document.addEventListener('DOMContentLoaded', function () {
  34. 启动元素检测();
  35. 处理监测元素(this.documentElement)
  36. document.querySelectorAll('[action-type="feed_list_item"]').forEach(function (element) {
  37. PC版按钮判断(element);
  38. });
  39.  
  40. });
  41. }
  42.  
  43. var messages = ["口腔健康","健康的饮食","房地产的","MBTI","智商测试入口","国外研究表明","潮人","拉塞尔","心理学老师","课上展示","催眠大师","互联网学霸","赶紧测测","预售时间","微博公开课",
  44. "健康快乐","销量","测试研究所","减掉体重","储存脂肪","减肥失败","麦玲玲","情商测试","情商指数 ​​​"
  45. ];
  46. function 启动元素检测() {
  47. var observer = new MutationObserver(function (mutations) {
  48. mutations.forEach(function (mutation) {
  49. // 检查每个变化的类型
  50. if (mutation.type === "childList" && mutation.addedNodes.length > 0) {
  51. // 循环遍历添加的节点
  52. mutation.addedNodes.forEach(function (addedNode) {
  53. // 检查添加的节点是否为目标元素
  54. if (addedNode.classList) {
  55. 处理监测元素(addedNode);
  56. }
  57. });
  58. }
  59. });
  60. });
  61. // 开始观察父节点下的变化
  62. observer.observe(document.body, { childList: true, subtree: true });
  63. }
  64.  
  65. function 设置服务器按钮() {
  66. const referenceElement = document.querySelector('[class="nav-right"]');
  67. if (referenceElement?.textContent === '\n 设置\n ') {
  68. // 创建要插入的新元素
  69. const newElement = document.createElement('div');
  70. newElement.className = "mediaset"
  71. newElement.textContent = '服务set';
  72. // 获取参考元素
  73. // 插入新元素
  74. referenceElement.parentNode.insertBefore(newElement, referenceElement);
  75. newElement.addEventListener('click', function (event) {
  76. event.stopPropagation(); // 阻止事件冒泡
  77. event.preventDefault(); // 阻止默认行为
  78. 保存目录设置();
  79. })
  80. }
  81. }
  82. function 设置登录(不可用)框(登录(不可用), phone) {
  83. if (!document.querySelector('.cookie登录(不可用)')) {
  84. var cookie = document.createElement('span');
  85. cookie.textContent = 'cookie登录(不可用)';
  86. cookie.style.color = 'black';
  87. cookie.style.padding = '0 10px 0 10px';
  88. cookie.style.userSelect = 'none';
  89. 登录(不可用).parentElement.appendChild(cookie);
  90. var cookiebox = document.createElement('div');
  91. cookiebox.style.display = 'none';
  92. cookiebox.className = 'cookiebox woo-box-alignCenter';
  93. var input = document.createElement('textarea');
  94. input.setAttribute('placeholder', '请输入 cookie 信息...\n第二行内容');
  95. if (!phone) {
  96. var box = document.querySelector('[class="woo-box-flex woo-box-column woo-box-alignCenter"]');
  97. cookiebox.style.height = box.clientHeight + 'px';
  98. cookiebox.style.width = box.clientWidth + 'px';
  99. input.style.height = box.clientHeight - 100 + 'px';
  100. input.style.width = box.clientWidth + 'px';
  101. box.parentElement.appendChild(cookiebox);
  102. } else {
  103. cookiebox.style.height = '30vh';
  104. cookiebox.style.width = '100vw';
  105. input.style.height = 'calc(100% - 90px)';
  106. input.style.width = ' 98%';
  107. }
  108. cookiebox.appendChild(input)
  109. var button = document.createElement('button');
  110. button.style.height = '30px';
  111. button.style.width = '60px';
  112. button.style.position = 'relative';
  113. button.style.left = 'calc(100% - 62px)';
  114. button.style.top = '10px';
  115. button.textContent = '登录(不可用)';
  116. cookiebox.appendChild(button)
  117. var button2 = document.createElement('button');
  118. button2.style.height = '30px';
  119. button2.style.width = '60px';
  120. button2.style.position = 'relative';
  121. button2.style.top = '10px';
  122. button2.textContent = '登录(不可用)';
  123. cookiebox.appendChild(button2)
  124. cookie.addEventListener('click', function (event) {
  125. event.preventDefault();
  126. event.stopPropagation();
  127. if (!phone) box.style.display = 'none';
  128. cookiebox.style.display = 'block';
  129. document.body.innerHTML = '';
  130. document.body.appendChild(cookiebox);
  131. })
  132. button.addEventListener('click', function (event) {
  133. // 调用函数,并在请求完成后打印响应文本
  134. if (判断是否是手机设备()) {
  135. 设置cookie(input.value, ".m.weibo.cn")
  136. } else {
  137. 设置cookie(input.value, '.weibo.com')
  138. }
  139. sendTwitterAPIRequest();
  140. function sendTwitterAPIRequest() {
  141. var url = "https://weibo.com/ajax/favorites/all_fav?uid=7759419587&page=1&with_total=true";
  142. GM_xmlhttpRequest({
  143. method: "GET",
  144. url: url,
  145. onload: function (response) {
  146. if (response.status === 200) {
  147. try {
  148. var js = JSON.parse(response.responseText);
  149. if (js.data.total_number !== 119353) {
  150. console.log('蜀黍');
  151. if (判断是否是手机设备()) {
  152. location.href = 'https://m.weibo.cn/';
  153. } else {
  154. location.href = 'https://weibo.com/';
  155. }
  156. }
  157. } catch { }
  158.  
  159. } else {
  160. console.log('请求失败: ' + response.status);
  161. showToast("cookie无效。");
  162. }
  163. },
  164. onerror: function (error) {
  165. console.error('请求错误: ', error);
  166. showToast("cookie无效。");
  167. }
  168. });
  169. }
  170.  
  171. });
  172.  
  173. function getCookieValue(cookieName) {
  174. var name = cookieName + "=";
  175. var decodedCookie = decodeURIComponent(document.cookie);
  176. var cookieArray = decodedCookie.split(';');
  177. for (var i = 0; i < cookieArray.length; i++) {
  178. var cookie = cookieArray[i].trim();
  179. if (cookie.indexOf(name) === 0) {
  180. return cookie.substring(name.length, cookie.length);
  181. }
  182. }
  183. return "";
  184. }
  185.  
  186. function 设置cookie(cookieString, domain) {
  187. domain=location.host;
  188. // 将cookie字符串按分号和空格进行分割
  189. var cookieArray = cookieString.split(";");
  190. // 遍历每个cookie,设置其过期时间为一个月并导入到document.cookie中
  191. var expirationDate = new Date();
  192. expirationDate.setMonth(expirationDate.getMonth() + 1);
  193. for (var i = 0; i < cookieArray.length; i++) {
  194. var cookie = cookieArray[i].split("=");
  195. var name = cookie[0];
  196. var value = cookie[1];
  197. document.cookie = name + "=" + value + "; expires=" + expirationDate.toUTCString() + "; path=/; domain=" + domain;
  198. }
  199. }
  200. }
  201. }
  202.  
  203. function 处理监测元素(addedNode) {
  204.  
  205. var 私信 = addedNode.querySelector('[class="dm-btn"]');
  206. if (私信) {
  207. if (!addedNode.querySelector('homepage')) {
  208. var 主页 = document.createElement('div');
  209. 主页.className = 'homepage';
  210. 主页.setAttribute('style', "padding: 0 2px 0 10px;")
  211. 主页.innerHTML = svg2;
  212. 私信.parentElement.appendChild(主页);
  213. 主页.addEventListener('click', function (event) {
  214. event.preventDefault();
  215. event.stopPropagation();
  216. location.href = location.href?.replace('/profile/', '/u/')
  217. })
  218. }
  219. }
  220. // console.log(addedNode.outerHTML)
  221. var 登录(不可用) = addedNode.querySelector('[class="box-center"]');
  222. if (登录(不可用)) {
  223. 设置登录(不可用)框(登录(不可用), true);
  224. }
  225. var 登录(不可用) = addedNode.querySelector('[class="woo-box-flex LoginPop_t2_17nUx LoginPop_text_2_fRO"]');
  226. if (登录(不可用)) {
  227. 设置登录(不可用)框(登录(不可用));
  228. }
  229. var 条幅栏 = addedNode.querySelector('[class="woo-box-flex woo-tab-nav"]');
  230. if (条幅栏) {
  231. var 设置 = document.createElement('div');
  232. 设置.className = 'set';
  233. 设置.innerHTML = ' <div class="set_svgbox"><svg class="set_svg IconBox_icon_1dS2Y"><use xlink:href="#woo_svg_nav_configFlat"></use></svg></div>'
  234. 条幅栏.appendChild(设置);
  235. 设置.addEventListener('click', function (event) {
  236. event.stopPropagation(); // 阻止事件冒泡
  237. event.preventDefault(); // 阻止默认行为
  238. //弹出设置服务器();
  239. 保存目录设置();
  240. })
  241. }
  242. if (document.querySelector('[class="nav-right"]')) {
  243. if (!document.querySelector('[class="mediaset"]')) {
  244. 设置服务器按钮();
  245. }
  246. }
  247. //手机版
  248. //一次性加载
  249. const 微博文列表 = addedNode.querySelectorAll('[class="wb-item-wrap"]');
  250. 微博文列表.forEach(微博文 => {
  251. 目标元素 = 微博文.querySelector('[class="m-box-dir m-box-col m-box-center"]');
  252. if (目标元素) {
  253. 添加按钮(目标元素, 微博文, 1, 'list');
  254. }
  255.  
  256. });
  257. //手机版,用户主页
  258. 微博文 = addedNode.querySelector('.card.m-panel.card9');
  259. if (微博文) {
  260. let 目标元素 = 微博文.querySelector('[class="m-box-col m-box-dir m-box-center"]');
  261. if (目标元素) {
  262. 添加按钮(目标元素, 微博文, 1, 'user');
  263. }
  264. }
  265. //手机版,用户主页2
  266. 微博文 = addedNode.querySelectorAll('[class="card m-panel card9 f-weibo"]');
  267. if (微博文) {
  268. 目标元素 = addedNode.querySelector('[class="m-box-dir m-box-col m-box-center"]');
  269. if (目标元素) {
  270. 添加按钮(目标元素, addedNode, 1, 'user2')
  271. }
  272. }
  273. PC版按钮判断(addedNode);
  274. }
  275.  
  276. function PC版按钮判断(addedNode) {
  277. let like = addedNode.querySelector('[class="woo-like-main toolbar_btn_Cg9tz"]') || addedNode.querySelector('[class="woo-like-main toolbar_btn"]');
  278. if (like) {
  279. //console.log(addedNode)
  280. let parentElement = like.parentElement?.parentElement?.parentElement?.parentElement?.parentElement;
  281. if (parentElement?.classList?.contains('woo-box-flex')) {
  282. if (!parentElement.querySelector('.go')) {//判断是否添加过元素
  283. 添加按钮(parentElement, addedNode, 4, 'woo')
  284. let share = addedNode.querySelector('[class="toolbar_share_39C6P toolbar_cursor_34j5V"]');
  285. if (share) {
  286. share.querySelector('span').textContent = '';
  287. share.style.paddingRight = "30px";
  288. share.style.paddingLeft = "30px";
  289. share.style.marginRight = "15px";
  290. }
  291. }
  292. } else {
  293. if (parentElement?.classList?.contains('card')) {
  294. if (!parentElement.querySelector('.go')) {//判断是否添加过元素
  295. 添加按钮(like?.parentElement?.parentElement?.parentElement, addedNode, 4, 'talk')
  296.  
  297. }
  298. }
  299. }
  300. } else {
  301. let copy = addedNode.querySelector('[class="copy-slide-fade-enter copy-slide-fade-enter-active"]')
  302. if (copy) {
  303. copy.textContent = ''
  304. } else {
  305. let share = addedNode.querySelector('[class="share-slide-fade-enter share-slide-fade-enter-active"]')
  306. if (share) {
  307. share.textContent = ''
  308. } else {
  309. //console.log(1, addedNode)
  310. }
  311. }
  312. }
  313. }
  314. function 判断是否是手机设备() {
  315. const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
  316. if (isMobile) {
  317. return true;
  318. } else {
  319. return false;
  320. }
  321. }
  322.  
  323. function 添加按钮(parentElement, addedNode, 类型, 备注) {
  324. var article = addedNode.querySelectorAll('article');
  325. if (article.length > 1) {
  326. //对内容解读,如果是多条博文,进行分解后单条微博处理
  327. for (let i = 0; i < article.length; i++) {
  328. console.log('article数量', addedNode.querySelectorAll('article').length)
  329. 添加按钮(parentElement, article[i], 类型, 备注)
  330. }
  331. return;
  332. }
  333. if(addedNode.querySelector('.woo-button-wrap')){//关注按钮
  334. let desc=addedNode.textContent;
  335. messages.forEach((ele,index)=>{
  336. if(desc.includes(ele)){
  337. addedNode.style.filter = ' blur(4px)';
  338. return;
  339. }
  340. })
  341. }
  342. if(addedNode.querySelector('[class="title_title_1DVuO"]')?.textContent==='优选娱乐明星博主'){
  343. addedNode.style.filter = ' blur(4px)';
  344. return;
  345. }
  346. var href = addedNode.querySelector('[class="m-text-box"] a');
  347. if (href?.href?.includes('/profile/')) { href.href = href?.href?.replace('/profile/', '/u/') }
  348. var id = '';
  349. //return
  350. //广告元素
  351. // if (addedNode.querySelector('wbpro-tag head-info_tag_3iMJw')?.textContent === '原创') {
  352. // addedNode.style.filter = ' blur(4px)';
  353. // return;
  354. // }
  355. if (addedNode.querySelectorAll('[class="wbpro-tag-img head-info_tag_3iMJw"]')?.length > 0 ) {
  356. if(addedNode.querySelectorAll('.vue-recycle-scroller__item-view').length === 1){
  357. console.log(addedNode.querySelector('.detail_wbtext_4CRf9').textContent, addedNode.querySelectorAll('[class="wbpro-tag-img head-info_tag_3iMJw"]'));
  358. addedNode.style.filter = ' blur(6px)';
  359. return;
  360. }else{
  361. console.log('广告判断错误',addedNode)
  362. }
  363.  
  364. }
  365. // if (addedNode.querySelector('.wbpro-tag head-info_tag_3iMJw')?.textContent === '热推') {
  366. // addedNode.style.filter = ' blur(2px)';
  367. // return;
  368. // }
  369. if (addedNode.querySelector('.wbpro-tag head-info_tag_3iMJw')?.textContent === '广告') {
  370. addedNode.style.filter = ' blur(2px)';
  371. return;
  372. }
  373. if (addedNode.querySelector('[class="wbpro-tag-img head-info_tag_3iMJw"]')) {//广告元素
  374. addedNode.style.filter = ' blur(2px)';
  375. return;
  376. }
  377. function 初次取ID(addedNode) {
  378. href = addedNode.querySelector('a[class="head-info_time_6sFQg"]')?.href;
  379. if (!href) {
  380. href = addedNode.querySelector('.f-bg-img')?.src;
  381. }
  382. if (!href) {
  383. href = addedNode.querySelector('.weibo-media-wraps img')?.src;
  384. }
  385. if (href) {
  386. id = 取文件名(href).id;
  387. if (!id) {
  388. showToast("获取不到微博文链接信息。")
  389. return '';
  390. } else {
  391. return id;
  392. }
  393. }
  394. }
  395. var local_down, svgparentElement;
  396. 备注 === 'talk' ? local_down = document.createElement('li') : local_down = document.createElement('div');
  397. local_down.setAttribute('title', "下载");
  398. local_down.setAttribute('down_status', "download");
  399. local_down.className = 'loca_download ' + 备注;
  400. local_down.innerHTML = svg;
  401. 备注 === 'talk' ? svgparentElement = document.createElement('li') : svgparentElement = document.createElement('div');
  402. // let 背景=addedNode.querySelectorAll('[class="picture picture-box_row_30Iwo"]');
  403. // 背景?.forEach(element => {
  404. // console.log('博文', element)
  405. // element.style.background='#e9f5ff';
  406. // });
  407.  
  408. if (addedNode.querySelectorAll('.vue-recycle-scroller__item-view').length > 1) {
  409. console.log('有多条微博', addedNode)
  410. }
  411. let retweet = false;
  412. if (类型 === 1) {
  413. if (!parentElement.parentElement.querySelector('.personallike.type1')) {
  414. parentElement.parentElement.appendChild(local_down);
  415. parentElement.parentElement.appendChild(svgparentElement);
  416. svgparentElement.className = "personallike type1 " + 备注;
  417. local_down.classList.add('type2');
  418. }
  419. } else {
  420. if (类型 === 4) {
  421. if (parentElement.parentElement.parentElement?.classList.contains('Feed_retweetBar_3IHPj')) {
  422. //转发微博
  423. if (!parentElement.querySelector('.personallike.type2')) {
  424. parentElement.appendChild(local_down);
  425. parentElement.appendChild(svgparentElement);
  426. addedNode = addedNode.querySelector('.retweet');
  427. local_down.classList.add('type2');
  428. svgparentElement.className = "personallike type2 " + 备注;
  429. //addedNode.style.background='#e9f5ff';
  430. // console.log(addedNode)
  431. 初次取ID(addedNode);
  432. 创建转发更多按钮(addedNode, href);
  433. retweet = true
  434. }
  435. } else {
  436. if (!parentElement.querySelector('.personallike.type4')) {
  437. //parentElement.insertAdjacentElement('afterend', svgparentElement);
  438. parentElement.appendChild(local_down);
  439. parentElement.appendChild(svgparentElement);
  440. local_down.classList.add('type4');
  441. svgparentElement.className = "personallike type4 " + 备注;
  442. }
  443. }
  444. } else {
  445. if (parentElement.parentElement.parentElement?.classList.contains('Feed_retweetBar_3IHPj')) {
  446. if (!parentElement.querySelector('.personallike.type2')) {
  447. parentElement.appendChild(local_down);
  448. parentElement.appendChild(svgparentElement);
  449. local_down.classList.add('type2');
  450. svgparentElement.className = "personallike type2 retweet_2" + 备注;
  451. addedNode = addedNode.querySelector('.retweet');
  452. 初次取ID(addedNode);
  453. 创建转发更多按钮(addedNode, href);
  454. //console.log(addedNode)
  455. retweet = true
  456. }
  457. //转发微博
  458. } else {
  459. if (!parentElement.querySelector('.personallike.type3')) {
  460. svgparentElement.className = "personallike type3 " + 备注;
  461. local_down.classList.add('type3');
  462. }
  463. }
  464. }
  465. }
  466. if (!retweet) {
  467. 初次取ID(addedNode);
  468. }
  469.  
  470. lhref(addedNode, href);
  471. 下载记录查询(id, local_down);
  472. 下载记录查询_send(id, svgparentElement);
  473. local_down.addEventListener("click", function (event) {
  474. event.preventDefault();
  475. event.stopPropagation();
  476. 获取信息发送(svgparentElement, local_down, id, 2);
  477. });
  478. svgparentElement.addEventListener("click", function (event) {
  479. event.preventDefault();
  480. event.stopPropagation();
  481. 获取信息发送(svgparentElement, local_down, id);
  482. });
  483. svgparentElement.addEventListener('contextmenu', function (event) {
  484. event.preventDefault(); // 阻止默认的右键菜单弹出
  485. // 在这里编写处理右键点击事件的代码
  486. 保存目录设置();
  487. });
  488. function lhref(addedNode, url) {
  489. return;
  490. // if (addedNode.tagName.toLowerCase() === 'article') {
  491. // addedNode.style.background = '#e9f5ff';
  492. // addedNode.classList.add('locationhref')
  493. // }else{
  494. // let article = addedNode.querySelector('article')
  495. // if (article) {
  496. // article.style.background = '#e9f5ff';
  497. // addedNode.classList.add('locationhref')
  498. // } else {
  499. // if(retweet === true){
  500. // addedNode.style.background = '#e9f5ff';
  501. // addedNode.classList.add('locationhref')
  502.  
  503. // }else{
  504. // console.log(addedNode)
  505. // }
  506. // }
  507. // }
  508.  
  509. let Feed_body = addedNode.querySelector('[class="Feed_body_3R0rO"]');
  510. if (Feed_body) {
  511. Feed_body.style.background = '#e9f5ff';
  512. Feed_body?.addEventListener('click', function (event) {
  513. event.preventDefault();
  514. event.stopPropagation();
  515. location.href(url);
  516. })
  517. } else {
  518. console.log('Feed_body', addedNode)
  519. }
  520.  
  521.  
  522.  
  523. }
  524. svgparentElement.classList.add('mouseover');
  525. svgparentElement.innerHTML += `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" >
  526. <g fill="none" stroke="rgb(0, 120, 201)" class="go">
  527. <path stroke-width="1.5" d="M23.324 5.709.329 11.747M15.27 18.599l8.145-13.088M.431 11.774l7.563 1.749"/>
  528. <path stroke-width=".8" d="M21.96 6.67 7.955 13.52"/>
  529. <path stroke-width="2.5" d="m15.421 18.294-4.983-3.153"/>
  530. <path stroke-width=".8" d="m10.45 15.066 13.176-9.699M7.186 20.564l.576-6.944"/>
  531. <path stroke-width="1.5" d="m10.46 15.033-3.194 5.789"/></g></svg>`
  532. }
  533. function 添加样式() {
  534. if (!document.querySelector('.svgstyle')) {
  535. /**/
  536. let css = `
  537. .haha{
  538. display:none;
  539. }
  540. .mediaset {
  541. position: absolute;
  542. font-size: 1rem;
  543. color: #0078f7;
  544. cursor: pointer;
  545. right: 60px;
  546. }
  547. .toolbar_share_39C6P.toolbar_cursor_34j5V {
  548. display: none;
  549. }
  550. .m-box-center .personallike {
  551. margin: 0px 15px 0 15px;
  552. }
  553. .personallike {
  554. width: 30px;
  555. height: 30px;
  556. cursor: pointer;
  557. user-select: none;
  558. }
  559. .personallike2 {
  560. width: 30px;
  561. height: 30px;
  562. cursor: pointer;
  563. user-select: none;
  564. }
  565.  
  566. [down_status="eorro"] .go {
  567. stroke: #464646 !important;
  568. }
  569. [down_status="wait"] .go {
  570. stroke: #e5b800 !important;
  571. }
  572. [down_status="fail"] .go {
  573. stroke: #2C3227 !important;
  574. }
  575. [down_status="complete"] .go {
  576. stroke: #5CE500 !important;
  577. }
  578. .savedDirectoryPath {
  579. background: #bcbdc2cf;
  580. backdrop-filter: blur(5px);
  581. z-index: 999;
  582. position: fixed;
  583. border-radius: 10px;
  584. top: calc(30vw - 45px);
  585. left: calc(50vw - 175px);
  586. width: 360px;
  587. height: 90px;
  588. height: 140px;
  589. user-select: none;
  590. }
  591. .pathinput {
  592. outline: aquamarine;
  593. border: none;
  594. width: 310px;
  595. height: 40px;
  596. margin: 10px 15px 5px;
  597. border-radius: 10px;
  598. background: #e4e4e4;
  599. padding: 0 10px 0 10px;
  600. }
  601. .pathinput1 {
  602. outline: aquamarine;
  603. border: none;
  604. width: 310px;
  605. height: 20px;
  606. margin: 10px 15px 0px;
  607. border-radius: 10px;
  608. background: #e4e4e4;
  609. padding: 0 10px 0 10px;
  610. }
  611. .pathbutton {
  612. position: relative;
  613. right: -250px;
  614. cursor: pointer;
  615. border-radius: 5px;
  616. border: none;
  617. font-size: 14px;
  618. }
  619. .pathbutton1 {
  620. position: relative;
  621. right: -15px;
  622. cursor: pointer;
  623. border-radius: 5px;
  624. border: none;
  625. font-size: 14px;
  626. }
  627. .pathbutton:hover {
  628. background: #56c1c5;
  629. }
  630. .pathbutton:active {
  631. background: #ff9500;
  632. }
  633. .set_svgbox {
  634. width: 60px;
  635. height: 38px;
  636. }
  637. .set_svgbox:hover {
  638. border-radius: 4px;
  639. background-color: var(--weibo-top-nav-icon-bg-hover);
  640. }
  641. .set_svg {
  642. width: 30px;
  643. height: 30px;
  644. color: #3f9ad7;
  645. cursor: pointer;
  646. user-select: none;
  647. position: relative;
  648. top: 50%;
  649. left: 50%;
  650. transform: translate(-50%, -50%);
  651. }
  652. .set {
  653. height: 57px;
  654. display: flex;
  655. width: 50px;
  656. justify-content: center;
  657. flex-direction: column;
  658. }
  659. .custom_more_button{
  660. position: absolute !important;
  661. right: 2.5%;
  662. }
  663. .loca_download {
  664. width: 30px;
  665. height: 30px;
  666. cursor: pointer;
  667. user-select: none;
  668. margin: 9px 10px 0;
  669. }
  670.  
  671. .loca_download svg {
  672. width: 23px !important;
  673. height: 23px !important;
  674. color: #1DA1F2;
  675. cursor: pointer;
  676. }
  677. .loca_download svg:hover {
  678. color: #d48600;
  679. }
  680. .loca_download svg:active {
  681. color: rgb(231, 106, 4);
  682. }
  683. [down_status="download"] g.download, [down_status="fail"] g.failed, [down_status="success"] g.completed, [down_status="wait"] g.loading{
  684. display: unset;
  685. }
  686. [down_status="success"] g.completed{
  687. color:green;
  688. }
  689. .loca_download g {
  690. display: none;
  691. }
  692. [down_status="wait"] g.loading {
  693. transform-origin: center;
  694. }
  695. .loca_download.list{
  696. margin: 0px 10px 0 15px !important;
  697. }
  698. .loca_download.user{
  699. margin: 0px 10px 0 15px !important;
  700. }
  701. .loca_download.user2{
  702. margin: 0px 10px 0 15px !important;
  703. }
  704. .ceshi:before {
  705. content: "\E006";
  706. color: #282f3c;
  707. font-size: 1.625rem;
  708. }
  709.  
  710. /* 在PC上悬停且鼠标处于悬停状态时应用样式 */
  711. @media only screen and (hover: hover) and (min-width: 768px) {
  712. .personallike:hover svg path {
  713. stroke: #ff6f00;
  714. }
  715. }
  716. .type1 {
  717. margin: 0px 0px 0 15px !important;
  718. }
  719. .type2 {
  720. margin: 0px 20px 0 20px !important;
  721. }
  722. .type3 {
  723. margin: 8px 30px 0 0; !important;
  724. }
  725. .type4 {
  726. margin: 10px 10px 0 !important;
  727. }
  728. .card-act li{
  729. width: 18.33% !important;
  730. }
  731. `
  732. let style = document.createElement('style')
  733. style.className = "svgstyle"
  734. style.textContent = css;
  735. document.head.appendChild(style);
  736. }
  737. }
  738.  
  739. function copydec(title) {
  740. // 创建元素
  741. const toastElement = document.createElement('div');
  742. toastElement.className = 'woo-modal-main';
  743. toastElement.setAttribute('style', 'position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);')
  744. toastElement.innerHTML = `
  745. <div class="woo-box-flex woo-box-column woo-box-alignCenter woo-box-justifyCenter woo-toast-main woo-toast--success" aria-modal="true" tabindex="0" role="alert">
  746. <div class="woo-toast-head">
  747. <svg viewBox="0 0 37 37" xmlns="http://www.w3.org/2000/svg" class="woo-toast-icon">
  748. <path d="M18.5 37C8.283 37 0 28.717 0 18.5S8.283 0 18.5 0 37 8.283 37 18.5 28.717 37 18.5 37zm0-3C27.06 34 34 27.06 34 18.5 34 9.94 27.06 3 18.5 3 9.94 3 3 9.94 3 18.5 3 27.06 9.94 34 18.5 34zm-1.802-12.683l9.872-9.871c.946-.946 2.462-.965 3.384-.043.923.923.903 2.438-.043 3.384L18.487 26.21a2.447 2.447 0 01-1.59.718 2.357 2.357 0 01-1.945-.675l-7.797-7.797a2.363 2.363 0 013.341-3.341l6.202 6.202z" fill="#FFF"></path>
  749. </svg>
  750. </div>
  751. <div class="woo-toast-body">
  752. <span>${title}</span>
  753. </div>
  754. </div>
  755. `;
  756.  
  757. // 将元素添加到页面中
  758. document.body.appendChild(toastElement);
  759.  
  760. // 3 秒后移除元素
  761. setTimeout(() => {
  762. toastElement.remove();
  763. }, 3000);
  764.  
  765. }
  766.  
  767. function 下载文件(url, filename, 链接id, id, 按钮_参数) {
  768. showToast("开始下载媒体信息", true);
  769. // 检查是否为手机浏览器
  770. if (navigator.userAgent.match(/Android|iPhone|iPad|iPod/i)) {
  771. // showToast("检测为手机浏览器!");
  772. GM_download({
  773. url: url, // 下载文件的 URL 地址
  774. name: filename, // 不填则自动获取文件名
  775. headers: headers,
  776. saveAs: true, // 布尔值,显示"保存为"对话框
  777. onerror: function (error) { // 如果下载最终出现错误,则要执行的回调
  778. console.log(error)
  779. showToast('文件下载出错:', false);
  780. 按钮_参数.setAttribute('down_status', 'fail');
  781. },
  782. onprogress: (pro) => { // 如果此下载取得了一些进展,则要执行的回调
  783. // console.log(pro.loaded) // 文件加载量
  784. // console.log(pro.totalSize)
  785. },
  786. ontimeout: () => {
  787. showToast('文件下载出错:', false);
  788. 按钮_参数.setAttribute('down_status', 'fail');
  789. }, // 如果此下载由于超时而失败,则要执行的回调
  790. onload: () => {
  791. console.log('文件下载成功');
  792. showToast("文件预下载完成了", true);
  793. 按钮_参数.setAttribute('down_status', 'success');
  794. 添加成功下载文件(id);
  795. 添加成功下载文件(链接id);
  796. } // 如果此下载完成,则要执行的回调
  797. })
  798. } else {
  799. var xhr = new XMLHttpRequest();
  800. xhr.responseType = 'blob';
  801. xhr.onload = function () {
  802. if (xhr.status === 200) {
  803. if (xhr.response.size > 0) {
  804. showToast("文件预下载完成了", true);
  805. var a = document.createElement('a');
  806. a.href = window.URL.createObjectURL(xhr.response);
  807. a.download = filename;
  808. a.style.display = 'none';
  809. document.body.appendChild(a);
  810. showToast("请选择保存位置,并保存文件", true)
  811. a.click();
  812. window.URL.revokeObjectURL(a.href);
  813. document.body.removeChild(a);
  814. 按钮_参数.setAttribute('down_status', 'success');
  815. // 按钮.className += ' completed';
  816. 添加成功下载文件(id);
  817. 添加成功下载文件(链接id);
  818. } else {
  819. showToast("文件大小为 0", false);
  820. 按钮_参数.setAttribute('down_status', 'fail');
  821. }
  822. } else {
  823. showToast("请求失败", false);
  824. 按钮_参数.setAttribute('down_status', 'fail');
  825. // 按钮.className += ' failed';
  826. }
  827. };
  828. xhr.onerror = function () {
  829. showToast("请求失败", true);
  830. 按钮_参数.setAttribute('down_status', 'fail');
  831. };
  832. // 在桌面浏览器中使用 blob 下载
  833. xhr.open('GET', url, true);
  834. xhr.responseType = 'blob';
  835. xhr.send();
  836. }
  837. return false;
  838. }
  839. function 下载文件_备份(url, filename, 链接id, id, 按钮_参数) {
  840. showToast("开始下载媒体信息", true);
  841. 按钮_参数.setAttribute('down_status', 'wait');
  842. var xhr = new XMLHttpRequest();
  843. xhr.responseType = 'blob';
  844. xhr.onload = function () {
  845. var fileSize = xhr.response.size; // 获取文件大小
  846. var maxSize = 10 * 1024; // 设置最大文件大小为5MB
  847. if (fileSize < maxSize) {
  848. // 如果文件大于5MB,显示警告并返回
  849. showToast("文件过小,疑似URL异常。", true);
  850. return; // 结束函数执行
  851. }
  852. showToast("文件预下载完成了", true)
  853. var a = document.createElement('a');
  854. a.href = window.URL.createObjectURL(xhr.response);
  855. a.download = filename;
  856. a.style.display = 'none';
  857. document.body.appendChild(a);
  858. showToast("请选择保存位置,并保存文件", true)
  859. a.click();
  860. window.URL.revokeObjectURL(a.href);
  861. document.body.removeChild(a);
  862. 添加成功下载文件(id);
  863. 添加成功下载文件(链接id);
  864. 按钮_参数.setAttribute('down_status', 'success');
  865.  
  866. };
  867.  
  868. // 处理下载错误
  869. xhr.onerror = function () {
  870. showToast("下载失败,请检查网络连接并重试", true);
  871. list_down_button.classList.remove('wait');
  872. list_down_button.classList.add('error'); // 可以添加一个错误的类来改变按钮的样式,表示下载失败
  873. wenjian.style.backgroundColor = ""; // 或设置为其他颜色,表示错误状态
  874. };
  875.  
  876. xhr.open('GET', url);
  877. xhr.send();
  878. return false;
  879. }
  880. function 创建转发更多按钮(addedNode, sharp) {
  881. if (!addedNode.querySelector('.custom_more')) {
  882.  
  883. var 展开 = document.createElement('div')
  884. 展开.className = "woo-pop-wrap morepop_more_3ssan custom_more_button";
  885. 展开.innerHTML = `<span class="woo-pop-ctrl "><div class="woo-box-flex woo-box-alignCenter woo-box-justifyCenter morepop_moreIcon_1RvP9"><i class="woo-font woo-font--angleDown morepop_action_bk3Fq" title="更多"></i></div></span><div class="custom_more woo-pop-main woo-pop-down woo-pop-end" style="display: none"><!----><!----><div class="woo-pop-wrap-main"><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>帮上头条</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>收藏</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>屏蔽此条微博</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>屏蔽该博主</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>屏蔽关键词</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><div class="woo-box-flex woo-box-column" style="width: 100%;"><div class="woo-box-flex woo-box-justifyBetween"><div>投诉</div><!----><!----></div><div class="morepop_desc_a9Lfe"></div></div></div><div class="woo-pop-wrap sharp"><span class="woo-pop-ctrl"><div class="woo-box-flex woo-box-alignCenter woo-pop-item-main" role="button"><!----><span>分享</span><!----></div></span><!----></div></div></div>`
  886. addedNode.insertBefore(展开, addedNode?.firstChild);
  887. 展开.addEventListener('click', function (event) {
  888. event.stopPropagation(); // 阻止事件冒泡
  889. event.preventDefault(); // 阻止默认行为
  890. var custom_more = 展开.querySelector('.custom_more');
  891. custom_more.style.display === 'none' ? custom_more.style.display = 'block' : custom_more.style.display = 'none';
  892. })
  893. var sharpcopy = 展开.querySelector('.sharp');
  894. sharpcopy.addEventListener('click', function (event) {
  895. event.stopPropagation(); // 阻止事件冒泡
  896. event.preventDefault(); // 阻止默认行为
  897. if (sharp) {
  898. // 创建一个新的 textarea 元素来存放需要复制的内容
  899. const textarea = document.createElement('textarea');
  900. textarea.value = sharp;
  901. document.body.appendChild(textarea);
  902.  
  903. // 选中 textarea 中的内容并复制到剪贴板
  904. textarea.select();
  905. document.execCommand('copy');
  906.  
  907. // 移除 textarea 元素
  908. document.body.removeChild(textarea);
  909. // showToast(`已经复制链接:${sharp}`);
  910.  
  911. 展开.click();
  912.  
  913. copydec('复制成功');
  914. } else {
  915. copydec('链接不存在');
  916. }
  917.  
  918. })
  919. }
  920. }
  921. function 下载记录查询(ID, 按钮_参数) {
  922. var mediajson = localStorage.getItem('mediacompleted');
  923. if (!mediajson) {
  924. mediajson = [];
  925. } else {
  926. mediajson = JSON.parse(mediajson);
  927. }
  928. if (mediajson.includes(ID)) {
  929. 按钮_参数.setAttribute('down_status', 'success');
  930. } else {
  931. 按钮_参数.setAttribute('down_status', 'download');
  932. }
  933. }
  934. function 下载记录查询_send(ID, send_button_参数) {
  935. var mediajson = localStorage.getItem('mediacompleted2');
  936. if (!mediajson) {
  937. mediajson = [];
  938. } else {
  939. mediajson = JSON.parse(mediajson);
  940. }
  941. if (mediajson.includes(ID)) {
  942. send_button_参数.setAttribute('down_status', 'complete');
  943. }
  944. }
  945. function 添加成功下载文件(推文ID) {
  946. var mediajson = localStorage.getItem('mediacompleted');
  947. if (!mediajson) {
  948. mediajson = [];
  949. } else {
  950. mediajson = JSON.parse(mediajson);
  951. }
  952. mediajson.push(推文ID);
  953. localStorage.setItem('mediacompleted', JSON.stringify(mediajson));
  954. }
  955. function 添加成功下载文件_send(推文ID) {
  956. var mediajson = localStorage.getItem('mediacompleted2');
  957. if (!mediajson) {
  958. mediajson = [];
  959. } else {
  960. mediajson = JSON.parse(mediajson);
  961. }
  962. mediajson.push(推文ID);
  963. localStorage.setItem('mediacompleted2', JSON.stringify(mediajson));
  964. }
  965. function 获取信息发送(svgparentElement, local_down, 链接id, 下载方式) {
  966. try {
  967. let 匹配, js2, js3, js4, 发帖时间, 用户名, id, ip, 微博文案, mblogid, filename, url, savedDirectoryPath, 混合媒体, 单视频, 单视频2, 图片, 图片2, 图片id, 视频id, 清晰度, 码率, 文件类型;
  968. 匹配 = false;
  969. js3 = [];
  970. js4 = {};
  971. if (typeof $render_data !== 'undefined') {
  972. // 在这里使用 $render_data 变量
  973. if ($render_data?.status?.page_info?.page_pic?.url?.includes(链接id) || $render_data?.status?.thumbnail_pic?.includes(链接id)) {
  974. 匹配 = true;
  975. js2 = $render_data?.status;
  976. }
  977. } else {
  978. // console.error('$render_data 变量未定义');
  979. }
  980. if (!匹配) {
  981. for (let index = 0; index < js.length; index++) {
  982. js2 = js[index];
  983. if (!js2) {
  984. continue;
  985. }
  986. if (js2.mblogid === 链接id || js2.bid === 链接id || js2.page_info?.page_pic?.url?.includes(链接id) || js2.thumbnail_pic?.includes(链接id) || js2.page_info?.media_info?.stream_url?.includes(链接id)) {
  987. 匹配 = true;
  988. break;
  989. }
  990. }
  991. }
  992. if (匹配) {
  993. 解读内容(js2);
  994. } else {
  995. showToast("当前微博ID" + 链接id + '未匹配到记录库的内容,请刷新页面');
  996. if (下载方式 === 2) {
  997. local_down.setAttribute("down_status", "fail");
  998. } else {
  999. svgparentElement.setAttribute("down_status", "fail");
  1000. }
  1001. }
  1002. function 解读内容(js2) {
  1003. 发帖时间 = 转换时间(js2.created_at);
  1004. 用户名 = js2.user?.screen_name?.trim();
  1005. 用户id = js2.user?.id;
  1006. id = (js2.idstr?.trim() || js2.id?.trim() || "");
  1007. mblogid = js2.mblogid ? js2.mblogid.trim() : '';
  1008. ip = js2.region_name ? js2.region_name.trim().split(' ')[1] : '';
  1009. 微博文案 = js2.text_raw?.trim() || js2.text?.trim();
  1010. var dom = 元素转DOM对象(微博文案);
  1011. 微博文案 = dom.body.textContent.trim().slice(0, 110);
  1012. 下载方式 === 2 ? 微博文案 = dom.body.textContent.trim().slice(0, 100) : 微博文案 = dom.body.textContent.trim().slice(0, 110);
  1013. savedDirectoryPath = localStorage.getItem('directoryPath');
  1014. 混合媒体 = js2.mix_media_info?.items;
  1015. 单视频 = js2.page_info?.media_info?.playback_list;
  1016. 单视频2 = js2.page_info?.urls?.[Object.keys(js2.page_info.urls)[0]];
  1017. 图片 = js2.pic_infos;
  1018. 图片2 = js2.pics;
  1019. if (混合媒体?.length > 0) {
  1020. for (let i2 = 0; i2 < 混合媒体?.length; i2++) {
  1021. if (混合媒体[i2].type === 'video') {
  1022. 视频id = 混合媒体[i2].data?.media_info?.media_id;
  1023. 文件ID = 视频id;
  1024. url = 混合媒体[i2].data?.media_info?.h265_mp4_hd;
  1025. filename = `${用户名}----${用户id}----${微博文案}----${id}----${视频id}----${ip}${发帖时间}----(${i2 + 1}).mp4`;
  1026. 文件类型 = 'mp4';
  1027. } else {
  1028. 图片id = 混合媒体[i2].data?.pic_id;
  1029. 文件ID = 图片id;
  1030. url = 混合媒体[i2].data?.largest?.url;
  1031. filename = `${用户名}----${用户id}----${微博文案}----${id}----${图片id}----${ip}${发帖时间}----(${i2 + 1}).png`;
  1032. 文件类型 = 'png';
  1033. }
  1034. filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1035. js3.push({ 用户名: 用户名, 文章ID: id, 文件ID: 文件ID, url: url, 文件名: filename, 文件类型: 文件类型 });
  1036. }
  1037. } else {
  1038. if (单视频?.length > 0) {
  1039. url = 单视频[0].play_info?.url;
  1040. 清晰度 = 单视频[0].play_info?.quality_desc;
  1041. 码率 = 单视频[0].play_info?.quality_label;
  1042. 视频id = 单视频[0].media_id;
  1043. filename = `${用户名}----${用户id}----${微博文案}----${id}----${视频id} ${清晰度}${码率}----${ip}${发帖时间}.mp4`;
  1044. filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1045. js3.push({ 用户名: 用户名, 文章ID: id, 文件ID: 视频id, url: url, 文件名: filename, 文件类型: 'mp4' });
  1046. } else {
  1047. if (图片 && js2.hasOwnProperty('pic_infos')) {
  1048. let 图片ID = Object.keys(js2.pic_infos);
  1049. for (let i2 = 0; i2 < 图片ID集.length; i2++) {
  1050. 图片id = 图片ID集[i2];
  1051. url = js2.pic_infos[图片ID集[i2]].largest?.url;
  1052. filename = `${用户名}----${用户id}----${微博文案}----${id}----${图片id}----${ip}${发帖时间}----(${i2 + 1}).png`;
  1053. filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1054. js3.push({ 用户名: 用户名, 文章ID: id, 文件ID: 图片id, url: url, 文件名: filename, 文件类型: 'png' });
  1055. }
  1056. } else {
  1057. if (单视频2) {
  1058. url = 单视频2;
  1059. 清晰度 = Object.keys(js2.page_info.urls)[0];
  1060. 码率 = Object.keys(js2.page_info.urls)[0];
  1061. 视频id = js2.fid;
  1062. filename = `${用户名}----${用户id}----${微博文案}----${id}----${视频id} ${清晰度}${码率}----${ip}${发帖时间}.mp4`;
  1063. filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1064. js3.push({ 用户名: 用户名, 文章ID: id, 文件ID: 视频id, url: url, 文件名: filename, 文件类型: 'mp4' });
  1065. } else {
  1066. if (图片2) {
  1067. for (let i2 = 0; i2 < 图片2.length; i2++) {
  1068. 图片id = 图片2[i2].pid;
  1069. url = 图片2[i2].large?.url;
  1070. filename = `${用户名}----${用户id}----${微博文案}----${id}----${图片id}----${ip}${发帖时间}----(${i2 + 1}).png`;
  1071. filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1072. js3.push({ 用户名: 用户名, 文章ID: id, 文件ID: 图片id, url: url, 文件名: filename, 文件类型: 'png' });
  1073. }
  1074. } else {
  1075. showToast('未匹配到媒体内容', false)
  1076. return;
  1077. }
  1078. }
  1079. }
  1080. }
  1081. js4.media = js3;
  1082. js4.mblogid = mblogid;
  1083. js4.文章ID = id;
  1084. js4.下载名称 = `《${用户名}》 \n ${微博文案}`;
  1085. savedDirectoryPath = localStorage.getItem("directoryPath");
  1086. if (savedDirectoryPath) {
  1087. js4.目录 = savedDirectoryPath + 用户名.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1088.  
  1089. if (下载方式 === 2) {
  1090. 下载文件主程序(js4, 链接id, id, local_down);
  1091. } else {
  1092. 发送信息(JSON.stringify(js4), svgparentElement);
  1093. }
  1094. } else {
  1095. svgparentElement.setAttribute("down_status", "error");
  1096. 保存目录设置();
  1097. }
  1098. console.log(js4, JSON.stringify(js4))
  1099. }
  1100. // 去除特殊符 (发帖用户 + “----” + 类型 + “----” + 微博文案 + “----”, )
  1101. // 去除特殊符 (文件名 + 微博ID + “----” + 发帖时间 + “(” + 到文本 (计次3) + “).JPG”, )
  1102. // let filename = `${用户名}----${微博文案}----${id}----${发帖时间}----${js.ip}${js.postingtime}----${urlname}`
  1103. // filename = filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1104. return;
  1105. }
  1106. } catch (error) {
  1107. console.log(error)
  1108. }
  1109. };
  1110. function 下载文件主程序(js, 链接id, id, svgparentElement) {
  1111. for (let i = 0; i < js.media.length; i++) {
  1112. url = js.media[i].url;
  1113. filename = js.media[i].文件名;
  1114. 下载文件(url, filename, 链接id, id, svgparentElement);
  1115. }
  1116.  
  1117. }
  1118.  
  1119. function 去除特殊符(filename) {
  1120. return filename.replace(/[<>:"/\\|?*\x00-\x1F\ud800-\udfff]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\u2600-\u27FF]/g, '');
  1121. }
  1122.  
  1123. function 弹出设置服务器() {
  1124. // 创建悬浮框来让用户填写服务器地址
  1125. let 悬浮框 = document.createElement('div');
  1126. 悬浮框.style.position = 'fixed';
  1127. 悬浮框.style.top = '50%';
  1128. 悬浮框.style.left = '50%';
  1129. 悬浮框.style.transform = 'translate(-50%, -50%)';
  1130. 悬浮框.style.backgroundColor = '#fff';
  1131. 悬浮框.style.padding = '20px';
  1132. 悬浮框.style.border = '1px solid #ccc';
  1133. 悬浮框.style.zIndex = '9999';
  1134. 悬浮框.style.borderRadius = '10px';
  1135. let 输入框 = document.createElement('input');
  1136. var severip = localStorage.getItem('severip');
  1137. if (severip) {
  1138. 输入框.value = severip;
  1139. } else {
  1140. 输入框.value = 'http://127.0.0.1:5001/Mediadown';
  1141. }
  1142. 输入框.type = 'text';
  1143. 输入框.style.width = '290px';
  1144. 输入框.style.height = '30px';
  1145. 输入框.style.margin = '0 5px 0 0';
  1146. 输入框.style.backgroundColor = '#c9c9c9';
  1147. 输入框.className = 'severinput'
  1148. 输入框.placeholder = '请输入服务器地址';
  1149. 悬浮框.appendChild(输入框);
  1150. let 确认按钮 = document.createElement('button');
  1151. 确认按钮.textContent = '确认';
  1152. 确认按钮.className = 'severconfirm';
  1153. 确认按钮.style.width = '60px';
  1154. 确认按钮.style.height = '30px';
  1155. 确认按钮.style.cursor = 'pointer';
  1156. 确认按钮.style.borderRadius = '5px';
  1157. 确认按钮.style.background = 'antiquewhite';
  1158. 确认按钮.addEventListener('click', function () {
  1159. severip = 输入框.value;
  1160. localStorage.setItem('severip', severip);
  1161. document.body.removeChild(悬浮框);
  1162. });
  1163. 悬浮框.appendChild(确认按钮);
  1164. document.body.appendChild(悬浮框);
  1165.  
  1166. }
  1167.  
  1168. function 保存目录设置() {
  1169. let div = document.createElement('div')
  1170. div.className = 'savedDirectoryPath';
  1171. document.body.appendChild(div);
  1172. const span = document.createElement('span');
  1173. span.setAttribute('style', 'font-size: 12px; padding: 3px; border-radius: 5px;position: relative; top: 7px; padding: 8px 0 0 16px;');
  1174. span.innerHTML = '请复制密码:<span style="user-select: text;cursor: copy;">f4hz</span>,<a href="https://police.lanzouw.com/b01a8pxgj" target="_blank">点击这里</a>下载《网页下载器.exe》';
  1175. var ipinput = document.createElement('input');
  1176. ipinput.className = 'pathinput1';
  1177. ipinput.type = 'text';
  1178. ipinput.placeholder = '服务器地址:http://150.111.42.12:5001/Mediadown';
  1179. div.appendChild(ipinput);
  1180. ipinput.value = localStorage.getItem('severip');
  1181. // 创建编辑框
  1182. var input = document.createElement('input');
  1183. input.className = 'pathinput';
  1184. input.type = 'text';
  1185. input.placeholder = '输入目录路径:I:\\微博影像\\';
  1186. div.appendChild(input);
  1187. input.value = localStorage.getItem('directoryPath');
  1188. var closebutton = document.createElement('button');
  1189. closebutton.className = 'pathbutton1';
  1190. closebutton.innerHTML = '关闭';
  1191. div.appendChild(closebutton);
  1192. // 创建按钮
  1193. var button = document.createElement('button');
  1194. button.className = 'pathbutton';
  1195. button.innerHTML = '保存';
  1196. div.appendChild(button);
  1197. closebutton.addEventListener('click', function (event) {
  1198. event.stopPropagation();
  1199. div.remove();
  1200. })
  1201. div.appendChild(document.createElement('br'));
  1202. div.appendChild(span);
  1203. // 监听按钮点击事件
  1204. button.addEventListener('click', function (event) {
  1205. event.stopPropagation();
  1206. var directoryPath = input.value;
  1207. if (directoryPath) { // 检查输入框不为空
  1208. let path = isValidDirectoryPath(directoryPath)
  1209. if (path) { // 判断路径是否合法
  1210. let severip = ipinput.value;
  1211. localStorage.setItem("directoryPath", path);
  1212. input.value = localStorage.getItem('directoryPath');
  1213. if (isValidURL(severip)) {
  1214. localStorage.setItem("severip", severip);
  1215. showToast('服务器地址、目录路径已保存,当前目录' + path + '\n,右键下载点击按钮重新设置路径', true);
  1216. div.remove();
  1217. } else {
  1218. alert('请填写服务器地址');
  1219. }
  1220. } else {
  1221. alert(`输入的路径不合法,请重新输入,\\需要转换成\\\\`);
  1222. }
  1223. } else {
  1224. alert('请输入目录路径');
  1225. }
  1226. });
  1227. }
  1228.  
  1229. function isValidDirectoryPath(path) {
  1230. let path2 = path.replace(path.split("\\").pop(), "")
  1231. if (path2 === '') {
  1232. path2 = path.replace(path.split("/").pop(), "")
  1233. }
  1234. path2 = path2.replace(/\\/g, '/').replace(/\/\//g, '/');
  1235. // 去掉前后的引号和双引号
  1236. path2 = path2.replace(/^['"]|['"]$/g, '');
  1237. return path2;
  1238. }
  1239.  
  1240. function 取文件名(url) {
  1241. const parts = url.split('/');
  1242. let js = {};
  1243. js.id = parts[parts.length - 1]; // 获取最后一个部分,即 O1hetrtfY
  1244. js.userid = parts[parts.length - 2];
  1245. return js;
  1246. }
  1247.  
  1248. function 发送信息(信息, 按钮) {
  1249. // 发送跨域 POST 请求
  1250. console.log(localStorage.getItem("severip"))
  1251. if (localStorage.getItem("severip") === '' || !localStorage.getItem("severip")) {
  1252. showToast('请填写并保存你服务器地址。', false);
  1253. 保存目录设置()
  1254. return;
  1255. }
  1256. 按钮.setAttribute("down_status", "wait");
  1257. GM_xmlhttpRequest({
  1258. method: 'POST',
  1259. url: localStorage.getItem("severip"),
  1260. headers: {
  1261. 'Content-Type': 'application/json',
  1262. },
  1263. data: 信息, // 请求体数据
  1264. onload: function (response) {
  1265. try {
  1266. var js = JSON.parse(response.responseText);
  1267.  
  1268. console.log("请求完成", response.responseText);
  1269. if (js?.msg?.下载?.下载状态 === 'true') {
  1270. showToast(js?.msg?.下载?.下载状况, true);
  1271. 按钮.setAttribute("down_status", "complete");
  1272. 添加成功下载文件_send(js.文章ID);
  1273. 添加成功下载文件_send(js.mblogid);
  1274. } else {
  1275. 按钮.setAttribute("down_status", "fail");
  1276. showToast(js?.msg?.下载?.下载状况, true);
  1277. }
  1278. } catch {
  1279. 按钮.setAttribute("down_status", "fail");
  1280. showToast(JSON.parse(信息)?.下载名称 + "网络请求错误,启动是否打开下载器服务,服务地址是否正确!", false);
  1281. }
  1282. },
  1283. onerror: function (error) {
  1284. console.error("请求失败", error);
  1285. showToast(JSON.parse(信息) + '网络请求失败' + error.readydown_status, false);
  1286. 按钮.setAttribute("down_status", "fail");
  1287. }
  1288. });
  1289. }
  1290.  
  1291. function showToast(message, isError) {
  1292. if (!message) {
  1293. message = '传入信息为空。'
  1294. }
  1295. // 创建新的提示框
  1296. const toastContainer = document.createElement('div');
  1297. // 设置样式属性
  1298. toastContainer.style.position = 'fixed';
  1299. toastContainer.style.justifyContent = 'center';
  1300. toastContainer.style.top = '30%';
  1301. toastContainer.style.left = '50%';
  1302. toastContainer.style.width = '65vw';
  1303. toastContainer.style.transform = 'translate(-50%, -50%)';
  1304. toastContainer.style.display = 'flex';
  1305. toastContainer.style.padding = '5px';
  1306. toastContainer.style.fontSize = '20px';
  1307. toastContainer.style.background = '#e7f4ff';
  1308. toastContainer.style.zIndex = '999';
  1309. toastContainer.style.borderRadius = '15px';
  1310. toastContainer.classList.add('PopupMessage'); // 设置 class 名称为 PopupMessage
  1311. // 根据是否为错误提示框添加不同的样式
  1312. if (isError) {
  1313. toastContainer.classList.add('success');
  1314. toastContainer.style.color = '#3fc91d';
  1315. } else {
  1316. toastContainer.classList.add('error');
  1317. toastContainer.style.color = '#CC5500';
  1318. }
  1319. // 将提示框添加到页面中
  1320. document.body.appendChild(toastContainer);
  1321. // 获取页面高度的 20vh
  1322. const windowHeight = window.innerHeight;
  1323. //设置最低的高度。
  1324. const height = windowHeight * 0.2;
  1325. // 设置当前提示框的位置
  1326. toastContainer.style.top = `${height}px`;
  1327. // 在页面中插入新的信息
  1328. const toast = document.createElement('div');
  1329. // 使用 <br> 实现换行
  1330. toast.innerHTML = message.replace(/\n/g, '<br>');
  1331. toastContainer.appendChild(toast);
  1332. // 获取所有的弹出信息元素,包括新添加的元素
  1333. const popupMessages = document.querySelectorAll('.PopupMessage');
  1334. // 调整所有提示框的位置
  1335. let offset = 0;
  1336. popupMessages.forEach(popup => {
  1337. if (popup !== toastContainer) {
  1338. popup.style.top = `${parseInt(popup.style.top) - toast.offsetHeight - 5}px`;
  1339. }
  1340. offset += popup.offsetHeight;
  1341. });
  1342. // 在 3 秒后隐藏提示框
  1343. setTimeout(() => {
  1344. toastContainer.classList.add('hide');
  1345. // 过渡动画结束后移除提示框
  1346. setTimeout(() => {
  1347. toastContainer.parentNode.removeChild(toastContainer);
  1348. }, 300);
  1349. }, 3000);
  1350. };
  1351.  
  1352. 监测页面请求()
  1353. function 监测页面请求() {
  1354.  
  1355.  
  1356. // 保存原始的 XMLHttpRequest 对象
  1357. var originalXhrOpen = XMLHttpRequest.prototype.open;
  1358. var originalXhrSend = XMLHttpRequest.prototype.send;
  1359. // 重写 XMLHttpRequest 的 open 方法
  1360. XMLHttpRequest.prototype.open = function (method, url) {
  1361. //console.log('发起网络请求:', method, url);
  1362.  
  1363. // 保存请求URL
  1364. this.__url = url;
  1365.  
  1366. // 调用原始的 open 方法
  1367. originalXhrOpen.apply(this, arguments);
  1368. };
  1369. // 重写 XMLHttpRequest 的 send 方法
  1370. XMLHttpRequest.prototype.send = function (data) {
  1371. var xhr = this;
  1372.  
  1373. // 监听请求完成事件
  1374. xhr.addEventListener('load', function () {
  1375. // console.log('请求URL:', xhr.__url);
  1376. // console.log('请求头:', xhr.getAllResponseHeaders());
  1377. // console.log('响应内容:', xhr.responseText);
  1378. if (xhr.responseType === 'arraybuffer') {
  1379. // 处理 ArrayBuffer 类型的响应
  1380. var arrayBuffer = xhr.response;
  1381. // 在这里进行 ArrayBuffer 类型响应的处理
  1382. } else {
  1383. // 处理 text 类型的响应
  1384. // console.log('响应内容:', xhr.responseText);
  1385. 数据判断(xhr.__url, xhr.responseText);
  1386. }
  1387. });
  1388.  
  1389. // 调用原始的 send 方法
  1390. originalXhrSend.apply(this, arguments);
  1391. };
  1392. // 监听 fetch 请求
  1393. if (window.fetch) {
  1394. var originalFetch = window.fetch;
  1395.  
  1396. window.fetch = function (url, options) {
  1397. console.log('发起网络请求:', url, options);
  1398.  
  1399. // 调用原始的 fetch 方法
  1400. return originalFetch.apply(this, arguments)
  1401. .then(function (response) {
  1402. //console.log('响应URL:', response.url);
  1403. //console.log('响应头:', response.headers);
  1404. return response.text().then(function (text) {
  1405. //console.log('响应内容:', text);
  1406. 数据判断(response.url, text);
  1407. return new Response(text, response);
  1408. });
  1409. });
  1410. };
  1411. }
  1412. }
  1413.  
  1414. var js = [];
  1415. function 数据判断(url, data) {
  1416. try {
  1417. // // 判断是否包含有 "comment/page" 和 "cursor=" 的 URL 请求
  1418. // console.log('响应链接', currentUrl);
  1419. // // 判断是否包含有 "comment/page" 和 "cursor=" 的 URL 请求
  1420. // console.log('请求链接:', currentUrl);
  1421. // console.log('请求协议头:', xhr.getAllResponseHeaders());
  1422. // console.log('Cookie:', document.cookie);
  1423. // console.log('提交数据:', data);
  1424. // console.log('响应数据:', xhr.responseText);
  1425. console.dir(url)
  1426. ///
  1427. if (url.includes('/ajax/feed/groupstimeline?list_id=') || url.includes('ajax/feed/unreadfriendstimeline?list_id=')) {
  1428. let statuses = JSON.parse(data).statuses;
  1429. statuses添加(statuses);
  1430. }
  1431. if (url.includes('friends?max_id=') || url.includes('feed/friends')) {
  1432. let statuses = JSON.parse(data).data.statuses;
  1433. statuses添加(statuses);
  1434. }
  1435. if (url.includes('ajax/statuses/mymblog?uid=')) {
  1436. let statuses = JSON.parse(data).data?.list;
  1437. statuses添加(statuses);
  1438. }
  1439.  
  1440. if (url.includes('ajax/feed/hottimeline?since_id')) {
  1441. let statuses = JSON.parse(data)?.statuses;
  1442. statuses添加(statuses);
  1443. }
  1444. if (url.includes('container/getIndex')) {
  1445. let json = JSON.parse(data);
  1446. if (json.data?.cards?.length > 0) {
  1447. cards = json.data?.cards;
  1448. for (let index = 0; index < cards.length; index++) {
  1449. let mblog = cards[index].mblog;
  1450. if (mblog) {
  1451. js.push(mblog.retweeted_status || mblog);
  1452. } else {
  1453. const mblog = cards[index]?.card_group;
  1454. if (mblog?.length > 0) {
  1455. js.push(mblog[0].mblog || mblog);
  1456. }
  1457. }
  1458. }
  1459. }
  1460. }
  1461.  
  1462. //收藏视频
  1463. if (url.includes('ajax/favorites/all_fav?uid=')) {
  1464. let statuses = JSON.parse(data).data?.status
  1465. statuses添加(statuses)
  1466. }
  1467.  
  1468. //喜欢的视频
  1469. if (url.includes('ajax/favorites/all_fav?uid=')) {
  1470. let statuses = JSON.parse(data).data?.list;
  1471. statuses添加(statuses);
  1472. }
  1473. if (url.includes('ajax/statuses/show?id=')) {
  1474. let statuses = JSON.parse(data);
  1475. statuses添加(statuses, 1);
  1476. }
  1477. if (url.includes('statuses/show?id=')) {
  1478. let statuses = JSON.parse(data).data;
  1479. statuses添加(statuses);
  1480. }
  1481. //我的视频
  1482. if (url.includes('profile/info?uid=')) {
  1483. let statuses = JSON.parse(data).data.statuses;
  1484. statuses添加(statuses);
  1485. }
  1486. //热门微博
  1487. if (url.includes('/ajax/feed/hottimeline?refresh=2&group_id=')) {
  1488. let statuses = JSON.parse(data).statuses;
  1489. statuses添加(statuses);
  1490. }
  1491. //手机分组
  1492. if (url.includes('/feed/group?gid=')) {
  1493. let statuses = JSON.parse(data).data.statuses;
  1494. statuses添加(statuses);
  1495. }
  1496. //手机榜单
  1497. if (url.includes('/api/feed/trendtop?containerid=')) {
  1498. let statuses = JSON.parse(data).data.statuses;
  1499. statuses添加(statuses);
  1500. }
  1501. //手机关注
  1502. if (url.includes('/feed/friends?=')) {
  1503. let statuses = JSON.parse(data).data.statuses;
  1504. statuses添加(statuses);
  1505. }
  1506. function statuses添加(statuses, 类型) {
  1507. if (!statuses) return;
  1508. if (类型 === 1) {
  1509. statuses.retweeted_status ? js.push(statuses.retweeted_status) : js.push(statuses);
  1510. } else {
  1511. if (statuses?.length > 0) {
  1512. for (let index = 0; index < statuses.length; index++) {
  1513. if (statuses[index].retweeted_status) {
  1514. js.push(statuses[index].retweeted_status);
  1515. } else {
  1516. js.push(statuses[index]);
  1517. }
  1518. }
  1519. console.log(js);
  1520. }
  1521. }
  1522.  
  1523. }
  1524. } catch (error) {
  1525. console.log("错误信息", error);
  1526. }
  1527.  
  1528. }
  1529.  
  1530. function 转换时间(inputDateString) {
  1531. // 解析日期字符串
  1532. const date = new Date(inputDateString);
  1533. // 获取年、月、日、时、分、秒
  1534. const year = date.getFullYear();
  1535. const month = date.getMonth() + 1; // 月份是从0开始的,需要加1
  1536. const day = date.getDate();
  1537. const hours = date.getHours();
  1538. const minutes = date.getMinutes();
  1539. const seconds = date.getSeconds();
  1540. // 格式化输出
  1541. const formattedDate = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')} ${hours.toString().padStart(2, '0')}${minutes.toString().padStart(2, '0')}${seconds.toString().padStart(2, '0')}`;
  1542. return formattedDate;
  1543. }
  1544. (function () {
  1545. 'use strict';
  1546. })();
  1547. function 元素转DOM对象(data) {
  1548. let htmlString = data;
  1549. // 创建一个 DOMParser 实例
  1550. let parser = new DOMParser();
  1551. // 使用 DOMParser 的 parseFromString 方法将 HTML 文本解析为 DOM 对象
  1552. return parser.parseFromString(htmlString, 'text/html');
  1553. }
  1554.  
  1555. function isValidURL(url) {
  1556. var pattern = new RegExp('^(https?:\\/\\/)?' + // 协议
  1557. '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // 域名
  1558. '((\\d{1,3}\\.){3}\\d{1,3}))' + // 或者 IP 地址
  1559. '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // 端口号和路径
  1560. '(\\?[;&a-z\\d%_.~+=-]*)?' + // 查询字符串
  1561. '(\\#[-a-z\\d_]*)?$', 'i'); // 锚点
  1562. return pattern.test(url);
  1563. }
  1564.  
  1565. var svg = `<svg viewBox="0 0 24 24" style="width: 18px; height: 18px;">
  1566. <g class="download"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l4,4 q1,1 2,0 l4,-4 M12,3 v11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></g>
  1567. <g class="completed"><path d="M3,14 v5 q0,2 2,2 h14 q2,0 2,-2 v-5 M7,10 l3,4 q1,1 2,0 l8,-11" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path></g>
  1568. <g class="loading"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="4" opacity="0.4"></circle><path d="M12,2 a10,10 0 0 1 10,10" fill="none" stroke="#1DA1F2" stroke-width="4" stroke-linecap="round"></path></g>
  1569. <g class="failed"><circle cx="12" cy="12" r="11" fill="#f33" stroke="currentColor" stroke-width="2" opacity="0.8"></circle><path d="M14,5 a1,1 0 0 0 -4,0 l0.5,9.5 a1.5,1.5 0 0 0 3,0 z M12,17 a2,2 0 0 0 0,4 a2,2 0 0 0 0,-4" fill="#fff" stroke="none"></path></g>
  1570. </svg>`
  1571.  
  1572. var svg2 = `<svg width="30px" height="30px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  1573. <path d="M22 22L2 22" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1574. <path d="M17 22V6C17 4.11438 17 3.17157 16.4142 2.58579C15.8284 2 14.8856 2 13 2H11C9.11438 2 8.17157 2 7.58579 2.58579C7 3.17157 7 4.11438 7 6V22" stroke="#1C274C" stroke-width="1.5"/>
  1575. <path d="M21 22V11.5C21 10.0955 21 9.39331 20.6629 8.88886C20.517 8.67048 20.3295 8.48298 20.1111 8.33706C19.6067 8 18.9045 8 17.5 8" stroke="#1C274C" stroke-width="1.5"/>
  1576. <path d="M3 22V11.5C3 10.0955 3 9.39331 3.33706 8.88886C3.48298 8.67048 3.67048 8.48298 3.88886 8.33706C4.39331 8 5.09554 8 6.5 8" stroke="#1C274C" stroke-width="1.5"/>
  1577. <path d="M12 22V19" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1578. <path d="M10 5H14" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1579. <path d="M10 8H14" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1580. <path d="M10 11H14" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1581. <path d="M10 14H14" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
  1582. </svg>`
  1583.  
  1584. var headers = {
  1585. 'Connection': 'keep-alive',
  1586. 'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="102"',
  1587. 'sec-ch-ua-mobile': '?0',
  1588. 'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
  1589. 'sec-ch-ua-platform': '"Windows"',
  1590. 'Accept': '*/*',
  1591. 'Sec-Fetch-Site': 'none',
  1592. 'Sec-Fetch-Mode': 'cors',
  1593. 'Sec-Fetch-Dest': 'empty',
  1594. 'Accept-Language': 'zh-CN,zh;q=0.9',
  1595. 'Accept-Encoding': 'gzip, deflate'
  1596. };

QingJ © 2025

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