您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Find new unwatched episode from your disired Telegram channel/group/peer... and show a link to it in front of each anime on your MAL CURRENTLY WATCHING page.
// ==UserScript== // @name Telegram new episode finder for MAL watching list page and anime list // @namespace https://github.com/kingofnull/mal-tg-episode-finder // @version 2.00 // @description Find new unwatched episode from your disired Telegram channel/group/peer... and show a link to it in front of each anime on your MAL CURRENTLY WATCHING page. // @author KingOfNull // @homepage https://github.com/kingofnull/mal-tg-episode-finder // @match https://myanimelist.net/animelist/*?*status=1* // @match https://myanimelist.net/anime/*/* // @icon https://www.google.com/s2/favicons?domain=myanimelist.net // @grant GM_addStyle // @license MIT // ==/UserScript== function addScript(src) { return new Promise((resolve, reject) => { const s = document.createElement('script'); s.setAttribute('src', src); s.addEventListener('load', resolve); s.addEventListener('error', reject); document.body.appendChild(s); }); } async function initTgClient(){ //you can use mine or generate your own one const apiId = 1799740; // put your api id here [for example 123456789] const apiHash = "645175d3249752aa32bce7b4659cfd94"; // put your api hash here [for example '123456abcfghe'] const session = localStorage.getItem('TgStrSession') ?? ""; const {TelegramClient} = gramjs; const { StringSession } = gramjs.sessions; const client = new TelegramClient(new StringSession(session), apiId, apiHash, { connectionRetries: 3, }); //await client.connect(); await client.start({ phoneNumber: async () => prompt("Please enter your number: "), password: async () => prompt("Please enter your password: "), phoneCode: async () => prompt("Please enter the code you received: "), onError: (err) => console.log(err), }); client.session.setDC(4, 'kws4.web.telegram.org', 443);//wss://kws4.web.telegram.org/apiws localStorage.setItem('TgStrSession',client.session.save()); return client; } function getPeerIds(){ //find your peerId using @username_to_id_bot in telegram let peerId=localStorage.getItem("TgSearchPeerId"); if(!peerId){ peerId=prompt("Enter your search target peerId:"); localStorage.setItem("TgSearchPeerId",peerId); } let peerIds=peerId.split(",").map(p=>p*1); return peerIds; } async function findNewEp(client,name,ep,peerId,withOutLeadingZero){ const {Api} = gramjs; let nextEpStr=(ep*1+1).toString(); if(!withOutLeadingZero){ nextEpStr=nextEpStr.padStart(2,'0'); } let searchTerm=`"${name} ${nextEpStr}"`; console.log("search for:",searchTerm); const result = await client.invoke( new Api.messages.Search({ peer: peerId, q: searchTerm, filter: new Api.InputMessagesFilterDocument({}), limit:10, }) ); if(result.count<1){ console.warn("not found"); if(!withOutLeadingZero){ return await findNewEp(client,name,ep,peerId,true); } return null; } let message=result.messages.at(0); let fname=message.media.document.attributes.at().fileName; console.log(result.count,fname); // prints the result /* const linkResult = await client.invoke( new Api.channels.ExportMessageLink({ channel: peerId, id: message.id, thread: true, }) ); let link=linkResult.link; */ let link=`tg://privatepost?channel=${message.peerId.channelId}&post=${message.id}`; console.log(link); return {link,fname}; } function initRenamer($title){ const orgName= $title.text(); const renameKey="acname-"+orgName; const customName=localStorage.getItem(renameKey); if(customName){ $title.text(customName); } $title.siblings(".rename-btn").remove(); $("<a>",{class:'rename-btn'}).text("Rename").insertAfter($title).click(e=> { let newname=prompt("Enter new name:",$title.text()); if(newname===""){ localStorage.removeItem(renameKey); $title.text(orgName); }else if(newname!==null){ localStorage.setItem(renameKey,newname); $title.text(newname); } }); return $title.text(); } async function searchAllPeers(client,title,curEp){ let data; for(let pId of getPeerIds()){ try{ data=await findNewEp(client,title,curEp,pId); }catch(e){ console.error('FindNewEp Failed,PID:',pId,e); } if(data){ break; } } return data; } (async ()=> { await addScript('https://cdn.jsdelivr.net/gh/kingofnull/gramjs-browser-build@69e9b471e30bb6da54577f911c953e1bf646b98b/gramjs.js'); //-----------------------------------watching list page handler------------------------------------------// if(/https:\/\/myanimelist.net\/animelist\/[^\/]/i.test(document.URL)){ GM_addStyle(` .new-ep-link{ background: #a70000; color: white !important; padding: 5px 7px; border-radius: 7px; display:inline-block; padding:5px; margin-left: 0.5em; } .list-table .list-table-data .data a.new-ep-link:hover { color: #a70000 !important; background: white !important; } .rename-btn{ background: #009688; padding: 0.2em 0.4em; border-radius: 0.5em; color: white !important; position: relative; /* top: -10px; */ cursor: pointer; margin-left: 0.5em; } .list-table .list-table-data .data a.rename-btn:hover { background: #ffffff !important; color: #009688 !important; } `); let client=await initTgClient(); for(let r of $("td.title a.link").get()){ let $r=$(r); //let title=$r.text(); let title=initRenamer($r); let curEp=$r.parents("tr").find("td.progress a.link").text(); if(!Number(curEp)){ curEp="0"; } title=initRenamer($r); console.log(title,":",curEp); let data=await searchAllPeers(client,title,curEp); if(data){ $("<a>",{href:data.link,class:'new-ep-link',target:"tgLinksWin"}) .text("New Ep ! : "+data.fname) .appendTo($r.parents("td")); } } client.disconnect(); } //-------------------------------- Anime page handler------------------------------------------// if(/https:\/\/myanimelist.net\/anime\/\d+\/[^\/]/i.test(document.URL)){ GM_addStyle(` .new-ep-link{ background: #a70000; color: white !important; padding: 5px 7px; border-radius: 7px; display:inline-block; padding:5px; margin: 0.5em 0; } a.new-ep-link:hover { color: #a70000 !important; background: white !important; } .rename-btn { background: #009688; padding: 0.2em 0.4em; border-radius: 0.5em; color: white !important; position: relative; top: -7px; cursor: pointer; margin: 1em 0.5em; } a.new-ep-link, a.rename-btn { font-size: 10px !important; font-family: monospace !important; } `); async function findAndShowLink(){ $('#next-ep-link').remove(); let client=await initTgClient(); let $r=$(".title-name").first(); let title=initRenamer($r); let curEp=$("#myinfo_watchedeps").val(); if(!Number(curEp)){ curEp="0"; } console.log(title,":",curEp); let data=await searchAllPeers(client,title,curEp); if(data){ $("<a>",{href:data.link,class:'new-ep-link',target:"tgLinksWin", id:'next-ep-link'}) .text("New Ep ! : "+data.fname) .appendTo($r.parent()); } client.disconnect(); } $(".js-btn-count").on("click", ()=>findAndShowLink()); $("#myinfo_watchedeps").on('change blure',e=>fetchDlLink()); findAndShowLink(); } })();