您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
标记网页上的所有番号, 在相关网站快速方便的进行搜索
当前为
// ==UserScript== // @name 根据番号快速搜索 // @namespace https://github.com/qxinGitHub/searchAV // @version 0.24.3 // @description 标记网页上的所有番号, 在相关网站快速方便的进行搜索 // @author iqxin // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAAXNSR0IArs4c6QAABLdJREFUWEftmG2IVGUUx3//O6MZapIftJTeKAqDiqiPGllZSdqHXsw3KmNnpm1LzYqgAleoMAJLw2xmdtsKqS3BkIy0QDSS6FNIkAgRilhUkPjGprtzTzx3d2fv3L0z986upB+6X+855/6e5znnf55zZWYTOY8fOUBJJ85HxoDtf8BRHM2odtAM0cF0fC6oMnicpoUjEjYKrqpr04DWxTjOsNQ8Chg3AWNiQHoR++RTZCybtYx/RgqbGtA6mej3sVziRaCZqj9h0O79xga109csaCpAK3KDiW7g+mY/ELL/WcZCFfipmRiJgFZinsFHwMXNBK5je1SwSHl2po3VENBKzDWjG3FRQkCXY8chsBvX0NY4LrFQeb5KA1kX0Dq5zip8DVweE8gHDkis5Qxb1cbJQRvbyASyLDHxPHBNLIRxQD53qpUjSZCxgE4+/BKfSDwSE+CU4FlydDSSEmsn61/KCok1wPhoHIP3vRwtSXIUD1jkbhNbYwIPy6FgMWWeE8wyY3emwFthGHuP+SY2x6TJUXnMVwt7G+3iMED3QSuzBXgw4tgjn6V6MgAfEtIOJpvPLgg0cZ887lALf9fYlGkzC8BrNNOgnMmTbw6wzFVuJ6K5V+9ILA1g/ZQ5pF5mqY3D9SCH72CRxSY+BLJD28RxwX0q8N2wXEoB6HysyEyDLyNHfXpAdj5PDVgp8aYIKjD8/KBe7gpXa7Vq0wLW2g2t3ViTKdCeGtAv8xnGwzU5BB9k8iwLLgdF5iGuGHzve1won2cQl2EcNo93PJ+e0O4fosB2V61+iS+AeTWxjY2ZAk+nByyxA7gnArg+k2elFbnaFFTd1CT9Cr2vFk6lxNuCFRHfnV6ee88OYH8BuTycdhYBt3t55qcGrJToEjxe4yC2eDkWBMnewWQqNX15UqBzMAPYL2MpcKzqn+HooOz4DU4nPWCRdonVEYdYfRsETtLBwG4jl9gY9gDXhmML2pTn3dSAFt9FegQLlGf7iGWmzKNmdNbIF5yS8YAKQc+PfYbr4CamWCYQandk4We3xjA3ejtOJdT9EuMgbonE3K8Kt6uVP1MDOsNKkdckXoo4+WZs8PKsCjf4GkDjR8FsFYZycODisU5iOeBFJOb1TIGXGxVc/GWhzAwzvgGmR5x7DVZ7OdbWQJaZis8EQgUR5F1/i3tV4oWY2eWgKsxWKwebBgx2scQawSvRVQPuLrhNWQp6gr/qHs0mplsmyLk5MTH6XLdSnvVJclX/wtrFOOvlU+D+OkF6gV2CbjJ8Tx99ZMnSxywTi4GZdSa+wXB7VGFBo/zrP4UGfxbMFYzHDsTNSSsd4ftEyOShqZNp5rMN49YRQiS5NYRMBAy22c3EleCWk4vJpyQA994NVa4YnEjXVPKAc13IVICDBFbmRrMgsW9LCeoK6lsZrfzOL/401rnO0QxkU4BV0E1M8bM8Jp9FiCuBSQMfdUDHMA66mcar0BWe3IJBqknIEQGmOdP6nSHQxljhjjvu/xwwJOB1IcPD1DkBTAG5VyeZo1X0nDPARpAmPs7kWJIo1KPJtbS+A/36DYmVQedxF44KD+kpfj0vAKvK4P7pjGW8cvxRe+MZaHVpV3wu7P4FjSUI5qMsu14AAAAASUVORK5CYII= // @license MIT // @match *://**/* // @require https://update.greasyfork.org/scripts/447533/1214813/findAndReplaceDOMText%20v%20046.js // @require https://update.greasyfork.org/scripts/452219/1099124/MD5%20%E5%87%BD%E6%95%B0.js // @require https://update.greasyfork.org/scripts/452792/1214814/av%E7%95%AA%E5%8F%B7%E7%89%B9%E5%BE%81%28tag%29%E5%AF%B9%E7%85%A7%E8%A1%A8.js // @exclude *://steamcommunity.com/* // @exclude *://meta.appinn.net/* // @exclude *://v2ex.com/* // @exclude *://www.v2ex.com/* // @exclude *://greasyfork.org/* // @exclude *://bilibili.com/* // @exclude *.bilibili.com/* // @exclude *://www.douyin.com/* // @exclude *.1688.com/* // @exclude *.taobao.com/* // @exclude *.tmall.com/* // @exclude *.jd.com/* // @exclude *.smzdm.com/* // @exclude *.zhihu.com/* // @exclude *://weibo.com/* // @exclude *.qq.com/* // @exclude *.live.com/* // @exclude *.windows.com/* // @exclude *.mi.com/* // @exclude *docs.google.com/* // @exclude *baike.baidu.com/* // @exclude *.wikipedia.org/* // @exclude *://*.amazon.tld/* // @exclude *.flightradar24.com/* // @exclude *.obsidian.md/* // @exclude *.runoob.com/* // @exclude https://www.baidu.com/s?* // @exclude https://www.google.com/search* // @exclude https://www.bing.com/search* // @exclude https://www.so.com/s* // @exclude https://regex101.com/ // @exclude https://discord.com/* // @exclude https://web.telegram.org/* // @exclude https://www.flipkart.com/* // @exclude *.themoviedb.org/* // @exclude *.youku.com/* // @exclude *.cn/* // @exclude *mall* // @exclude *shop* // @exclude /.*(?<!jav)store.*/ // @exclude *buy* // @exclude *tools* // @exclude *translate* // @exclude */releases // @exclude */releases/* // @exclude *:5244* // @exclude *:8080* // @connect * // @connect javbus.com // @connect javdb.com // @connect fc2hub.com // @connect dmm.co.jp // @connect 1pondo.tv // @connect caribbeancom.com // @connect tokyo-hot.com // @connect mgstage.com // @connect r18.com // @connect prestige-av.com // @connect javspyl.tk // @connect fc2.com // @connect heydouga.com // @connect heyzo.com // @connect translate.google.com.hk // @connect fanyi.baidu.com // @connect self // @connect localhost // @grant GM_addStyle // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_registerMenuCommand // @grant GM_openInTab // @run-at document-idle // ==/UserScript== (function() { 'use strict'; if(window.location.href.search(/detail|product/gi)>0 && window.location.href.search(/attackers\.net|www\.dmm\.co\.jp|www\.mgstage\.com/i)<0){ console.log("sav: 当前网址不匹配: " + window.location.href); return; } window.qxin = {}; // 给引用脚本传参 var timerGetInfo; // 延时获取信息 var timerMouseLeave; // 鼠标离开番号。鼠标进入菜单时的定时器, 超时不进入, 菜单消失 var timerMouseLeaveMenu; // 鼠标离开菜单 // var timerImgLoading; // 图片加载后 重新定位的定时器。 加载成功后, 清除该定时器 var avInfo = {}; // 临时存储相关信息 var avInfoID = ""; // 临时存储avID var localInfo = {}; // 从本地获取到的番号信息, 只在判断是否本地存在和存储信息时使用 var Imgscall = 1.0; // 图片默认放大倍数, 在图片上滚动鼠标滚轮使用。 var javdbTime = []; // 记录访问javdb的时间, 如果短时间内多次访问就限制访问, 默认是5分钟内限制为10次访问。 var divTarget; // 鼠标当前经过的番号节点 var imgErrorSVG = "data:image/svg+xml,%3Csvg class='icon' viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M304.128 456.192c48.64 0 88.064-39.424 88.064-88.064s-39.424-88.064-88.064-88.064-88.064 39.424-88.064 88.064 39.424 88.064 88.064 88.064zm0-116.224c15.36 0 28.16 12.288 28.16 28.16s-12.288 28.16-28.16 28.16-28.16-12.288-28.16-28.16 12.288-28.16 28.16-28.16z' fill='%23999'/%3E%3Cpath d='M887.296 159.744H136.704C96.768 159.744 64 192 64 232.448v559.104c0 39.936 32.256 72.704 72.704 72.704h198.144L500.224 688.64l-36.352-222.72 162.304-130.56-61.44 143.872 92.672 214.016-105.472 171.008h335.36C927.232 864.256 960 832 960 791.552V232.448c0-39.936-32.256-72.704-72.704-72.704zm-138.752 71.68v.512H857.6c16.384 0 30.208 13.312 30.208 30.208v399.872L673.28 408.064l75.264-176.64zM304.64 792.064H165.888c-16.384 0-30.208-13.312-30.208-30.208v-9.728l138.752-164.352 104.96 124.416-74.752 79.872zm81.92-355.84l37.376 228.864-.512.512-142.848-169.984c-3.072-3.584-9.216-3.584-12.288 0L135.68 652.8V262.144c0-16.384 13.312-30.208 30.208-30.208h474.624L386.56 436.224zm501.248 325.632c0 16.896-13.312 30.208-29.696 30.208H680.96l57.344-93.184-87.552-202.24 7.168-7.68 229.888 272.896z' fill='%23999'/%3E%3C/svg%3E"; var cid = {}; // 用于预告视频的链接转换 var localVideoList = []; // 获取本地 jellyfin/emby 中所有的视频名称 var allHTML = document.querySelector("body"); // 获取网页 // 取出本地的信息 localInfo = GM_getValue("avInfo2"); if(!localInfo){ GM_setValue("avInfo2",{}); localInfo = {}; } // 初始化 setting // setting: 相关设置选项 var setting = GM_getValue("_setting"); if(!setting || JSON.stringify(setting) == "{}"){ setting = { "list":[ ["JavDB 搜索","https://javdb.com/search?q=%s&f=all"], ["JavLib 搜索","http://www.javlibrary.com/cn/vl_searchbyid.php?keyword=%s"], ["JavMenu 搜索","https://javmenu.com/search?wd=%s"], ["missav 在线","https://missav.ai/search/%s"] ], "list_wuma":[ ["JavMenu 搜索","https://javmenu.com/search?wd=%s"], ["btsow 下载","https://btsow.com/search/%s"] ] } GM_setValue("_setting",setting); } // 更新 if(setting.version && setting.version != 2){ setting.version = 2; setting.selectLength = 0; setting.list_wuma = [ ["JavMenu 搜索","https://javmenu.com/search?wd=%s"], ["btsow 下载","https://btsow.com/search/%s"] ]; GM_setValue("_setting",setting); } // setting2 放一些隐藏的变量, 本身这些变量就不允许用户修改, 例: version, javdbTime var setting2 = GM_getValue("_setting2"); if(!setting2){ setting2 = { "version":2, "javdbTime":[] } if(setting.javdbTime){ setting2.javdbTime = setting.javdbTime; } GM_setValue("_setting2",setting2); } if(setting2.javdbTime && Array.isArray(setting2.javdbTime)){ javdbTime = setting2.javdbTime } // 自定义获取信息的地址, 避免网络不通顺 var javbusLink = setting.javbus? setting.javbus: "https://www.javbus.com/" var javDBLink = setting.javdb? setting.javdb: "https://javdb.com/" // 磁链复制功能在引用脚本中还有一部分 window.qxin.CopyMagnet = setting.magnetCopy? true:false; window.qxin.includeIDinLinks = setting.includeIDinLinks ?? false; // 测试用 var debug = setting.debug?setting.debug:false // debug = true; // 打开一些console.log提示 if (debug) { console.clear(); console.log("sav已开启debug模式:"); console.log("老司机共浏览了" + Object.keys(localInfo).length + "个番号!"); } if(debug) {var searchTimes = 0; var avIDTimes=0}; // 计数, 查看有多少番号。searchTimes: 通过正则搜索到的次数。 avIDTimes:最后的实际匹配的番号数量 // 一般发行番号: 从javbus获取信息 // var oRegExp = /[a-zA-Z]{2,6}[-\s]?\d{2,5}/gi; // ; --------------------------------------------------------普通番号,带横杠----------------------------------------------------------------- |--------------------------------------------------------------普通番号, 不带横杠------------------------------------------------------------------------------------------------- |-------------字母特别的番号-------------------------|---------字母超长的番号---------------------- | 东京热 n k |加勒比(-)、一本道(_)、 MuraMura(_): 月日年 | 带前缀 carib|1pondo 的加勒比, 一本道 | 带后缀的 -1pon|-carib|-paco 加勒比 一本道 paco |Mesubuta メス豚 (也可能是一本道的变种) || HEYZO var oRegExp = /(?<!\w|\/|www\.|=|col-|\d-|>|Jukujo-)(?!heyzo|SHINKI|JPNXXX|carib|vps)[a-zA-Z]{2,6}-\d{2,5}(?:-c|_c|-4k)?(?!\d|[A-Za-z]{2,}|-\d|\.com|\.\d)|(?<!\w|\/|\\|\.|【|-|#|@|=|www\.)(?!heyzo|SHINKI|JPNXXX|carib|and|vps|dvd)[a-zA-Z]{2,6}\s{0,2}\d{3,4}(?:-c|_c)?(?!\w|-|\.|\/|×|%|%|@|\s?天| 于| 发表| 發表|歳| 歲|小时|分|系列| Min| day|ml| time|cm| ppi|\.com)|(?<!\w)(?:PARATHD|3DSVR|STARSBD)[-\s]?\d{3,4}(?!\w)|(?<!\w)(?:HIMEMIX|CASMANI|MGSSLND)[-\s]?\d{3}(?!\w)|(?<!\w)(?:k|n)[01]\d{3}(?!\w|-)|(?<!\w|\d-|\/)[01]\d{5}[-_](?:1)?\d{2,3}(?!\w|-\d)|(?<!\w)(?:carib|1pondo)[-_]\d{6}[-_]\d{2,3}(?!\w)|(?<!\w|\d-)\d{6}[-_]\d{2,3}(?:-1pon|-carib|-paco)(?!\w)|(?<!\w|\d-)\d{6}_(?:1)?\d{3}_0[12](?!\w|-\d)|HEYZO[_-\s]?(?:hd_)?\d{4}/gi; // 省略字母, 连续数字的番号 例: abc-001、002、003 var oRegExp2 = /(?<=(?<!\w|\d-)([a-zA-Z]{2,6})(?:[\s,,、-]?(?!2022|2021|2020|2019)\d{3,4})+(?!\d)[\s,、,和跟]{0,2})\d{3,4}(?!\w|%|%|人|年|歳|万|の|発)/gmi // 一些素人、无码番号: 从javdb获取信息 // ;--------- mgstage 字母 + 数字 + 字母 -----------------------|--------- FC2 ----------------| HEYDOUGA | T28 | TMA 5位,6位,3位(没匹配) | 1000girl 数字 + 字母 |MUGEN Entertainmen: MKD-S MKBD-S | 素人 | 北池袋盗撮倶楽部 | japornXXX: JPNXXX | xxx-av | crazyasia | PEWORLD | 10Musume 6位数字_01 |熟女俱乐部 var oRegExp_wuma = /(?<!\w|-|\/)\d{3}[a-zA-Z]{2,5}[-\s]?\d{3,4}(?!\w|-|.torrent|年)|(?<!\w|\/)FC2[^\d]{0,5}\d{6,7}|HEYDOUGA[_-\s]?\d{4}-\d{3,5}|(?<!\w)T28-\d{3}|(?<!\w)T-2\d{4,5}(?!\w|-)|(?<!\w|-|\/)[01]\d{5}-[a-zA-Z]{2,7}(?!\w|-)|(?<!\w)MK(?:B)?D-S\d{2,3}(?!\w|-)|(?:SHINKI|KITAIKE)[-\s]?\d{3}(?!\w|-)|JPNXXX[-\s]?\d{5}(?!\w|-)|xxx-av[-\s]\d{4,5}(?!\w|-)|(?<!\w)crazyasia\d{5}(?!\w|-)|(?<!\w)PEWORLD\d{5}(?!\w|-)|(?<!\w)[01]\d{5}[-_]?_01(?=-10mu)?|Jukujo-Club-\d{3}/gi; // 省略写的fc2番号 例: fc2-123456 567890 var oRegExp_wuma2 = /(?<=(FC2[^\d]{0,5})(?:[\s,、-]?\d{6,7})+[\s,、]?)\d{6,7}/gmi // 排除在此的番号, 与下面的 Exclude 不同的是: 这个还会判断后面跟的数字, 能够精确排除。 // | 排除非 fx-0xx | 数字部分全是0 | | 一些国家简称 + 两位数字 sr是黑鸟侦察机 |卡西欧 |细胞相关 |csgo皮肤 |致钛硬盘 | 瑞昱芯片 | soc | ns530刀片 var oRegExp_Exclude_ID = /^(?:fx-?([^0]\d{2}|\d{4})|[a-zA-Z]+-?0{2,6}$|pg-13|crc-32|ea211|fs[\s-]?140|trc-20|erc-20|rs[\s-]?(232|422|485)|(sg|ae|kr|tw|ph|vn|kh|ru|uk|ua|tr|th|fr|in|de|sr)[\s-]\d{2}|(gm|ga)-\d{4}|cd[\s-]?\d{2,4}|seed[\s-]?\d{3}$|pc005|moc-\d{5}|wd-40|rtd[\s-]?\d{4}|cm\d{4}|rk\d{4})|ns[\s-]?\d{3,4}/i // 排除在此的关键词。 个别与番号同名的也被排除, 例如 Top-10 这种 var oRegExp_Exclude_en = /^(?:about|ac|actg|aes|again|agm|ah|aim|all|ak|akko|apex|aptx|au|ax|avhd|avx|bej|bgm|chrome|bd|bm|build|(?:fc|p)?[blp]ga|by|bzk|cc|ccie|cctv|cea|ckg|class|cny|covid|cpu|code|debian|df|ds|dw|dx|ea|er|ecma|eia|emui|eof|ep|error|ez|fc|file|flash|flyme|fps|for|fork|from|fuck|fx|gbx|get|github|glm|gnz|gp|groupr|gt|gts|gtx|guest|hao|hd|her|hdr|hk|https?|hp|IEEE|il|ilc|ilce|imx|index|intel|inteli|ip|ipad|is|ISBN|iso|issue|issues|it|jav|javdb|joy|jp|jr|jsr|jt|jukujo|just|kc|keccak|kv[bd]|Kirin|lancet|line|linux|lk|lolrng|lpl|lt|lumia|lg|macos|math|md|mh|miui|mipc|mnvr|mm|mnvr|model|mv|mvp|ms|nas|nature|nc|next|ngff|note|number|ok|only|os|osx|pa|page|pch|phl|ppv|pmw|png|qbz|qsz|raid|rfc|ripemd|rmb|rng|rog|row|rtx|rush|rx|sale|scp|scte|sdm|sdr|server|sha|shp|sonnet|spent|sql|sn|snh|Socket|ssd|status|steam|su|swipe|tcp|the|to|top|than|thread|ts|type|uh|uhd|under|us|usa|usc|utf|utc|via|video|vkffsc|vol|vr|vs|vv|web|win|with|width|wikis|wta|xdr|xfx|xiaomi|yah)$/i // 在没有横杠的情况下, 会排除在此的关键词 例: 识别 tv-001 但是会排除 tv001 var oRegExp_Special_en = /^(?:ace|akb|api|am|anime|at|be|best|bt|bl|cp|crc|exynos|dl|dp|dq|gb|girl|jd|ha|has|hc|hours|iq|in|mk|mini|mhz|mx|no|open|of|over|part|pd|pdd|porn|pt|sb|sex|tv|tb|ty|ver|vip|zd|zip)$/i // 在没有横杠的情况下, 会排除在此的数字 var oRegExp_Special_num = /^(?:007|101|110|115|123|128|256|360|365|370|404|512|520|911|996|\d{1,2}00|19[789]\d|20[012]\d|720|1080|1024|2048|[056789]\d{3}|(\d)\1{2,3})$/ // 排除符合条件的无码番号 var oRegExp_Exclude_wuma = /^(?:512gb)/i // 可能是素人、无码番号, 如果在javbus获取不到信息, 会继续从javdb中查找. 2022-10-23 v0.19.3注: 可能会被弃用 var oRegExp_SuRen = /ANAN|ARA|BEAF|BKKJ|BSKC|BSKJ|CCDV|CUTE|DAVC|DCV|DDH|ECSN|ENE|ERKR|EROFC|FKNP|FLC|FTHT|GANA|GESB|GRQR|GRMO|GRMR|HABJ|HHL|HMDN|HMDNC|HMT|HOMEV|IMGN|IND|INSF|INSTC|JAC|JNT|JPNXXX|KING|KNB|LBJ|LOG|LUXU|MAAN|MCHT|MFC|MIUM|MKGF|MONA|NAEN|NMCH|NTK|NTR|OPCYN|OREC|ORECO|PAK|POK|pow|PPZ|PRGO|REIW|RKD|SCOH|SGK|SHE|SHINKI|SIRO|SIROR|SIMM|SQB|SROM|SSDV|SSK|STCV|STH|SUKE|TEN|TKOL|TKPR|WITH|\d{6}|(?:k|n)\d{4}/i // 磁力链接 var oRegExp_Magnet = /magnet:\?xt=urn:btih:[0-9a-fA-F]{40}|(?<!\w|\/|\||=)[0-9a-fA-F]{40}(?!\w|-)/ig // 特别的className,在这些class中不识别番号。 /name|auth|user|code/i; pstatus:javbus修改帖子的用户名; TbwUpd:谷歌搜索页面链接 window.qxin.RE_Exclude_className = /(?<!file)name|auth|user|(?<!home)code|^pstatus$|(?<!_tl_|ql-)editor|time|sav-id|sidebar|menu|TbwUpd/gi; // 相关网站匹配规则 switch(window.location.hostname){ case "www.dmm.co.jp": console.log("当前匹配网站: www.dmm.co.jp"); oRegExp = /[a-zA-Z]{2,6}\d{3,4}/gi; break; case "attackers.net": console.log("当前匹配网站: attackers.net"); oRegExp = /(?<=dvd)[a-zA-Z]{2,5}\d{3,4}/gi; break; case "www.mgstage.com": window.qxin.RE_Exclude_className = /(?<!file)name|auth|user|(?<!home)code|^pstatus$|(?<!_tl_|ql-)editor|time|sav-id|sidebar|TbwUpd/gi; break; case "www.javlibrary.com": case "www.d67b.com": window.qxin.javlibrary = true; break; } // 用于预告视频的链接转换, 预览图片的获取 if(!setting.dontGetVideo){ cid = { abp: ["118abp"], abw:["118abw"], aczd:["h_019aczd"], aed: ["aed"], aege:["1aege"], akdl: ["1akdl"], ako: ["ako"], ambi:["h_237ambi"], anb: ["anb"], apaa: ["apaa"], apns: ["apns"], aran: ["aran"], arbb:["h_092arbb"], atid:["atid"], avop:["avop","h_455avop00"], awd: ["awd"], bank: ["h_1495bank"], bdsr:["57bdsr"], bfd: ["24bfd"], bfkb: ["h_1285bfkb"], bkynb: ["1bkynb"], clot: ["h_237clot"], dandy: ["1dandy"], davk:["55davk"], dldss: ["1dldss"], docp:["118docp"], dori:["h_491dori"], drpt: ["1drpt"], dtvr: ["24dtvr"], dv: ["53dv"], dvaj: ["53dvaj"], dvdes: ["1dvdes"], ekdv: ["ekdv"], emth:["h_1638emth"], erofc:["erofc"], fbos:["fbos"], fera: ["h_086fera"], fgan: ["h_1440fgan"], fir:["118fir"], fneo: ["h_491fneo"], fone: ["h_491fone"], fsdss: ["1fsdss"], fset: ["1fset"], fsre:["h_491fsre"], fsvr: ["h_955fsvr"], ftht: ["1ftht"], fuga: ["h_086fuga"], gar:["1gar"], gas: ["71gas"], gets:["118gets"], gnab:["118gnab"], gnax:["gnax","h_1345gnax"], gone: ["h_1133gone"], gs:["140gs"], gvg: ["13gvg"], haru: ["h_687haru"], havd: ["1havd"], hbad:["1hbad"], hez:["59hez"], hgot:["84hgot"], hkd: ["hkd"], hmnf:["h_172hmnf"], hoks: ["hoks"], honb:["h_1133honb"], hz: ["h_113hz"], hzgb: ["h_1100hzgb"], hzgd:["h_1100hzgd"], ienf:["1ienf"], instc:["instc"], jbs:["118jbs"], jrze: ["h_086jrze"], jsop:["jsop"], jukf: ["h_227jukf"], keed:["h_086keed"], kmhr:["1kmhr"], kmhrs:["1kmhrs"], kri:["h_286kri"], ktra: ["h_094ktra"], lbdd:["n_1515lbdd"], lol: ["12lol"], macb:["h_687macb"], mas:["118mas"], mct: ["118mct"], mds: ["84mds"], meko: ["h_1160meko"], mesu: ["h_086mesu"], mist:["1mist"], mogi: ["1mogi"], moko: ["h_254moko"], mond:["18mond"], mtall: ["1mtall"], mxgs:["h_068mxgs"], natr:["h_067natr00"], neo:["433neo"], nhdta:["1nhdta"], nhdtb: ["1nhdtb"], npv:["118npv"], nxgs: ["h_254nxgs"], nyh:["1nyh"], ofku: ["h_254ofku"], omhd: ["omhd"], onez:["h_1674onez"], pako:["h_1133pako"], piyo: ["1piyo"], ppt: ["118ppt"], pydvr: ["h_1321pydvr00"], pym: ["h_283pym"], rct: ["1rct"], rctd: ["1rctd"], rdt:["118rdt"], rebd: ["h_346rebd"], sait:["55sait"], san:["h_796san00"], scpx: ["84scpx"], scr:["12scr"], sdab: ["1sdab"], sdam:["1sdam"], sdde: ["1sdde"], sdjs: ["1sdjs"], sdmf: ["1sdmf"], sdmm: ["1sdmm"], sdmu: ["1sdmu"], sdmua: ["1sdmua"], sdnm: ["1sdnm"], sdnt:["1sdnt"], sdth: ["1sdth"], sga:["118sga"], shh: ["1shh"], shic:["h_839shic"], shind: ["h_1560shind"], shn: ["1shn"], silkc: ["1silkc"], skmj: ["h_1324skmj"], sprd:["18sprd"], spro: ["h_1594spro"], spz: ["h_254spz"], star: ["1star"], stars: ["1stars"], stcv: ["h_1616stcv"], stko:["1stko"], sun: ["1sun"], svdvd: ["1svdvd"], svmgm:["1svmgm"], sw: ["1sw"], t28: ["55t28"], tmhp: ["h_452tmhp"], tmvi: ["h_452tmvi"], udak: ["h_254udak"], umd: ["125umd"], vrtm:["h_910vrtm"], wo: ["1wo"], wps:["118wps"], xrw:["84xrw"], yst:["540yst"], zeaa: ["h_086zeaa"], zex: ["h_720zex"], // 多个 // h_139doks571 36doks00567 doks:["h_139doks","36doks"], arso: ["h_1378arso","1arso"], // gvh-476, gvh-017 gvh:["gvh","13gvh"], // 末尾补零 bf:["bf00"], // 末尾截断 // n_1445thni088 thnib:["n_1445thni"], // 2024-07-09 elo:["767elo"], mcsr:["57mcsr"], nacr:["h_237nacr"], senn:["1senn"], btha:["5433btha"], tem:["118tem"], kbi:["118kbi"], har:["118har"], fadss:["1fadss"], beaf:["h_1615beaf"], giro:["118giro"], hodv:["41hodv"], nhvr:["1nhvr"], msfh:["1msfh"], kire:["1msfh"], okax:["84okax"], gesu:["49gesu"], ntr:["1ntr"], stsk:["h_1605stsk"], csct:["55csct"], bgn:["118bgn"], enki:["84enki"], kirm:["h_1540kirm"], aidv:["41aidv"], good:["118good"], sply:["1sply"], ysn:["h_127ysn"], abf:["118abf"], mdtm:["h_585mdtm"], mane:["1mane"], start:["1start"], brk:["143brk"], seven:["1seven"], ypaa:["h_086ypaa"], }; // cid_pic ={ // brk:["7brk"], // } } // 对动态添加的dom进行检测 var observerTarget = document.querySelector('body'); // 选择目标节点 var observerConfig = {childList: true, characterData: true ,subtree:true,}; // 配置观察选项 var observer = new window.MutationObserver(function(mutations) { // 创建观察者对象 // console.log("观察者数量"); // console.log(mutations.length); mutations.forEach(function(mutation) { if(mutation.target.innerText?.length<5){ // console.log(mutation.target.innerText); if(debug)console.log("内容为空"); } else if(checkParentClass(mutation.target)){ if(debug){console.log("存在不合适的父元素")} }else{ observer.disconnect(); // 关闭对 dom 的监听 // if(debug){console.log("开始判断正则")} if(mutation.target.innerText?.search(oRegExp)>-1){ // console.log("普通番号"); findAndReplaceDOMTextFun(mutation.target) } if(mutation.target.innerText.search(oRegExp2)>-1){ // console.log("连续番号"); findAndReplaceDOMTextFun2(mutation.target) } if(mutation.target.innerText.search(oRegExp_wuma)>-1){ // console.log("无码番号"); findAndReplaceDOMTextFun_Wuma(mutation.target) } if(mutation.target.innerText.search(oRegExp_wuma2)>-1){ // console.log("连续无码番号"); findAndReplaceDOMTextFun_Wuma2(mutation.target) } observer.observe(observerTarget, observerConfig); // 开启对 dom 的监听 } }) }); addStyle() // 比对本地 jellyfin/emby 视频, if(setting.jellyfinHost && setting.jellyfinApiKey && setting.LocalVideoSearch){ setTimeout(() => { localVideo_search(); }, 500); } // 延时执行, 解决javbus论坛通过搜索进入的帖子无发弹出工具栏的问题 setTimeout(findAVID,300); // 磁链 // 如果设置中有qbit的网址和下载地址, 则认为启用了下载功能 if(!(setting.dontMagnetDiscern || setting.dontCopyMagnet )&& setting.qBitHost && setting.qBitDownload){ window.qxin.QBit = qBit; } // 滑词搜索 if(setting.selectLength && setting.selectLength>0){ document.onmouseup = selectSearch } // 切换页面 暂停预览视频播放 if(setting.dontClearMenu){ document.addEventListener("visibilitychange",visibilitychangeFun); // 切换页面 暂停预览视频播放 } // function findAVID(){ if(debug){console.time("正则查询用时");} observer.disconnect(); // 关闭对 dom 的监听 findAndReplaceDOMTextFun_Wuma2(allHTML); //// 查找连续的 fc2 番号。 例: fc2-123456 567890 findAndReplaceDOMTextFun_Wuma(allHTML); // 查找fc2、素人、无码等番号 (无菜单,点击后会跳转到javdb进行搜索) findAndReplaceDOMTextFun2(allHTML); // 省略字母, 连续数字的番号 例: abc-001、002、003 findAndReplaceDOMTextFun(allHTML); // 查找普通番号 (与上面的顺序不能变,否则会导致 2函数 失效) observer.observe(observerTarget, observerConfig); // 开启对 dom 的监听 if(debug) {console.timeEnd("正则查询用时"); console.log("本页面通过正则匹配的有: " + searchTimes + " . 实际的番号数量: " + avIDTimes);} if(!(setting.dontMagnetDiscern || setting.dontCopyMagnet )){ // 磁链 findAndReplaceDOMTextFunMagnet(); } } // 查找番号, 匹配最基础的番号 function findAndReplaceDOMTextFun(element){ findAndReplaceDOMText(element, { find:oRegExp, preset: 'prose', // 仅搜索文本元素(不搜索样式、脚本、对象等),开启会会默认启用下面(NON_INLINE_PROSE)的这个功能, 强制隔断上下文。 forceContext: findAndReplaceDOMText.NON_INLINE_PROSE, //调用内置的元素判断, 强制隔断上下文 replace: function(portion,match) { // 当番号介于两个HTML元素之中, 只作用最后一个 if(portion.isEnd){ var otext = match[0]; }else{ return ""; } if(debug) {searchTimes++;}; // 检查番号, 如果存在特殊英文或者数字,则退出 if(IDcheck(otext)){return otext}; // 添加事件和样式 var avID = formatAVID(otext) // 判断3位数字写成2位的 if(avID.match(/-\d{2}$/) && localInfo[avID] && localInfo[avID].noInfo){ let avID2 = avID.replace("-","-0"); if(localInfo[avID2]){ avID = avID2; } } var odiv = addEventAndStyle(localInfo[avID],avID) // 添加事件和样式 if(debug){avIDTimes++; console.log(avIDTimes + "番号: " + avID,otext);otext = "["+avIDTimes +"]" + otext;} return displayMode(odiv,otext); } }); } // 省略字母, 连续数字的番号 例: abc-001、002、003 function findAndReplaceDOMTextFun2(element){ findAndReplaceDOMText(element,{ find: oRegExp2, preset: "prose", forceContext:findAndReplaceDOMText.NON_INLINE_PROSE, replace: function(portion,match){ var avID = match[1] + " " +match[0] // 视为无横杠番号 // 检查番号, 如果存在特殊英文或者数字,则退出 if(IDcheck(avID)){return match[0]}; if(debug) {searchTimes++;} // 添加事件和样式 avID = formatAVID(avID) var odiv = addEventAndStyle(localInfo[avID],avID) // 添加事件和样式 if(debug){avIDTimes++; console.log(avIDTimes + "省略字母,连续数字的番号: " + avID, portion.text);portion.text = "[*"+avIDTimes +"]" + portion.text} return displayMode(odiv,portion.text); } }) } // 查找番号, 匹配fc2、MGSTAGE(259LUXU等)、一本道、东京热、HEYZO等 // 只有一个功能就是跳转到 javdb 进行搜索, 没有菜单, 也没有其他任何功能 // 关于heyzo, 如果是后面跟横杠会触发上面的基础查找, 只有中间没有横杠或者有下划线的情况才会匹配这个。 function findAndReplaceDOMTextFun_Wuma(element){ findAndReplaceDOMText(element, { find:oRegExp_wuma, preset: 'prose', // 仅搜索文本元素(不搜索样式、脚本、对象等),开启会会默认启用下面(NON_INLINE_PROSE)的这个功能, 强制隔断上下文。 forceContext: findAndReplaceDOMText.NON_INLINE_PROSE, //调用内置的元素判断, 强制隔断上下文 replace: function(portion,match) { // 当番号介于两个HTML元素之中, 只作用最后一个 if(portion.isEnd){ var otext = match[0]; }else{ return ""; } // 检查番号是否合法 if(IDcheckWuma(otext)){return otext}; // 添加事件和样式 var avID = formatWuma(otext); // 格式化番号 // 123abc-456 数字字母-数字 if(avID.match(/\d{3}[a-zA-Z]{2,5}[-\s]?\d{3,4}/)){ avID = avID.slice(3); avID = formatAVID(avID) } var odiv = addEventAndStyle(localInfo[avID],avID) // 添加事件和样式 if(debug) {searchTimes++;avIDTimes++; console.log(avIDTimes + "无码番号: " + avID, otext); otext = "[!"+avIDTimes +"]" + otext;} odiv.dataset.av_wuma = avID; return displayMode(odiv,otext); } }); } // 查找番号, 连续的 fc2 番号。 例: fc2-123456 567890 function findAndReplaceDOMTextFun_Wuma2(element){ findAndReplaceDOMText(element, { find:oRegExp_wuma2, preset: 'prose', // 仅搜索文本元素(不搜索样式、脚本、对象等),开启会会默认启用下面(NON_INLINE_PROSE)的这个功能, 强制隔断上下文。 forceContext: findAndReplaceDOMText.NON_INLINE_PROSE, //调用内置的元素判断, 强制隔断上下文 replace: function(portion,match) { // 当番号介于两个HTML元素之中, 只作用最后一个 if(portion.isEnd){ var otext = match[0]; }else{ return ""; } var avID = match[1] + otext; avID = formatWuma(avID); // 格式化 fc2 番号 // 复制上方的。 fc2 番号是否合法: FC2-012345 和 FC2PPV-012345 搜索结果不一样 if(avID.match(/fc2/i) && localInfo[avID] && localInfo[avID].noInfo ){ let avID2; if(avID.match(/ppv/i)){ avID2 = avID.replace("FC2PPV","FC2"); }else{ avID2 = avID.replace("FC2","FC2PPV"); } if(localInfo[avID2] && !localInfo[avID2].noInfo){ avID = avID2; } } var odiv = addEventAndStyle(localInfo[avID],avID) // 添加事件和样式 if(debug) {searchTimes++;avIDTimes++; console.log(avIDTimes + "连续Fc2番号: " + avID,otext); otext = "[**"+avIDTimes +"]" + otext;} odiv.dataset.av_wuma = avID; return displayMode(odiv,otext); } }); } // 点击磁力链接, 可以复制到剪贴板 function findAndReplaceDOMTextFunMagnet(){ if(debug){console.log("开始查找磁力链接");}; observer.disconnect(); // 关闭对 dom 的监听 findAndReplaceDOMText(allHTML, { find:oRegExp_Magnet, preset: 'prose', // 仅搜索文本元素(不搜索样式、脚本、对象等),开启会会默认启用下面(NON_INLINE_PROSE)的这个功能, 强制隔断上下文。 forceContext: findAndReplaceDOMText.NON_INLINE_PROSE, //调用内置的元素判断, 强制隔断上下文 replace: function(portion,match) { // 当番号介于两个HTML元素之中, 只作用最后一个 if(portion.isEnd){ var otext = match[0]; }else{ return ""; } if(debug){console.log("发现磁力链接: " + otext);}; var magnet = otext if(magnet.indexOf("magnet")<0){ magnet = "magnet:?xt=urn:btih:" + magnet; } var odiv = document.createElement('savmagnet'); if(setting.magnetCopy){ odiv.addEventListener("click",function(){ GM_setClipboard(magnet); if(setting.qBitHost && setting.qBitDownload){ qBit(magnet); } }); odiv.title = "点击复制磁力链接"; } else { otext = "<a href='" +magnet+ "' style='text-decoration:underline;'>" +otext+ "</a>"; } odiv.innerHTML = otext; odiv.style.textDecoration = "underline #D9B412" return odiv; } }); observer.observe(observerTarget, observerConfig); // 开启对 dom 的监听 } // 添加页面番号样式 , 传入的参数是番号, 用来判断番号是否在本地存在 function addEventAndStyle(isExist,avID){ // 添加事件 var odiv = document.createElement('savdiv'); odiv.addEventListener("click",savIDClick); // 点击番号复制 if(setting.clickToMenu){ odiv.addEventListener("click",savIDMouseEnter); // 点击鼠标 开启菜单 }else{ odiv.addEventListener("mouseenter",savIDMouseEnter); // 鼠标滑过 开启菜单 } odiv.addEventListener("mouseleave",savIDMouseLeave); // 鼠标离开 关闭菜单 if(isExist){ // 添加浏览次数 if(isExist.visited){ odiv.dataset.visited = isExist.visited; } else { odiv.dataset.visited = 1; } // 添加class 在本地是否存在, (通过添加 class 来改变颜色) if(isExist.noInfo){ odiv.classList.add("sav-id", "infoNonExistent"); }else{ odiv.classList.add("sav-id", "infoExistent"); } }else { odiv.dataset.visited = 0; odiv.classList.add("sav-id", "infoFirst"); } odiv.dataset.av = avID; return odiv; } // 番号后面添加图标, 不作用于番号 function displayMode(odiv,otext){ if(setting.addSearchButton){ odiv.innerHTML = setting.searchButtonIcon?setting.searchButtonIcon:"✈"; var divWrap = document.createElement("savdiv"); divWrap.innerHTML = otext; divWrap.appendChild(odiv); return divWrap; }else{ odiv.innerHTML = otext; return odiv; } } // 创建搜索基本菜单(搜索按钮) function createPattenr(id,id_wuma){ let aPattern = `<avdivbutton>` // 添加 相关页面 按钮 if(!setting.close_Related_Page){ aPattern += `<avdiv class='savlink relatedPage RPdisabled'><a href='' target='_blank' referrerpolicy='same-origin'>JavBus 页面</a></avdiv>`; } // 添加特定搜索 if(id.match(/fc2/i)){ var basiceSearch = `https://fc2hub.com/search?kw=${id_wuma}`; aPattern += `<avdiv class='savlink'><a href='${basiceSearch}' target='_blank' referrerpolicy='same-origin'>fc2hub 搜索</a></avdiv><avdiv class='savlink'><a href='${javDBLink}search?q=${id_wuma}&f=all' target='_blank' referrerpolicy='same-origin'>JavDB 搜索</a></avdiv>`; var savList = setting.list_wuma; }else if(id_wuma){ var basiceSearch = `${javDBLink}search?q=${id_wuma}&f=all`; aPattern += `<avdiv class='savlink'><a href='${basiceSearch}' target='_blank' referrerpolicy='same-origin'>JavDB 搜索</a></avdiv>` ; var savList = setting.list_wuma; } else{ var basiceSearch = javbusLink + "search/" + id; aPattern += "<avdiv class='savlink'>" + "<a href='" + basiceSearch +"' target='_blank' referrerpolicy='same-origin'>JavBus 搜索</a>" +"</avdiv>" ; var savList = setting.list; } if(savList){ for(let i=0; i<savList.length;i++){ aPattern += "<avdiv class='savlink'>" + "<a href='" + savList[i][1].replace("%s", id) +" 'target='_blank' referrerpolicy='same-origin'>" + savList[i][0] + "</a>" + "</avdiv>" } } // 添加通用搜索按钮 if(setting.list_all && setting.list_all.length>0){ var savListAll = setting.list_all; for(let i=0; i<savListAll.length;i++){ aPattern += "<avdiv class='savlink'>" + "<a href='" + savListAll[i][1].replace("%s", id) +" 'target='_blank' referrerpolicy='same-origin'>" + savListAll[i][0] + "</a>" + "</avdiv>" } } // 添加色花堂搜索 if(setting.sehuatang){ aPattern += `<avdiv class='savlink savsehuatang' data-avid=${id}> 色花堂 </avdiv>` sehuatang_getFormHash(); } // 添加jellyfin按钮 if(setting.jellyfinHost && setting.jellyfinApiKey){ if(setting.emby){ aPattern += "<avdiv class='savlink jellyfin'> Emby </avdiv>" }else{ aPattern += "<avdiv class='savlink jellyfin'> Jellyfin </avdiv>" } } // 添加额外按钮 if(debug){ let debugSearchList = [ [ "dmm", "https://www.dmm.co.jp/search/?redirect=1&enc=UTF-8&category=&searchstr=%s&commit.x=11&commit.y=14" ], [ "google", "https://www.google.com/search?q=%s&ie=utf-8&oe=utf-8" ] ]; for(let i=0; i<debugSearchList.length;i++){ aPattern += "<avdiv class='savlink'>" + "<a href='" + debugSearchList[i][1].replace("%s", id) +" 'target='_blank' referrerpolicy='same-origin'>" + debugSearchList[i][0] + "</a>" + "</avdiv>" } } if(debug || setting.addOtherButton){aPattern += "<avdiv class='savlink savSetting'>设置</avdiv><avdiv class='savlink savCopyID' data-av='"+ id +"'>" + id + "</avdiv>"}; if(setting.dontClearMenu || setting.addOtherButton){aPattern += "<avdiv class='savlink savCloseMenu'> 关闭 </avdiv>"}; aPattern += `</avdivbutton>` var odiv = document.createElement("avdiv") if(localInfo[id]){ odiv.classList.add("sav-menu","idExistent"); odiv.dataset.visited = localInfo[id].visited?localInfo[id].visited:1; }else{ odiv.classList.add("sav-menu","idNonExistent"); odiv.dataset.visited = 0; } odiv.addEventListener("mouseenter",savMenuMouseEnter) odiv.addEventListener("mouseleave",savMenuMouseLeave) odiv.addEventListener("click",savMenuClick) // 鼠标在图片上点击和滚轮放大缩小图片 if(!setting.dontImgBig){ odiv.addEventListener("wheel",savImgWheel) }; odiv.dataset.av = id; odiv.innerHTML=aPattern; return odiv; } // 点击番号复制 function savIDClick(e){ if(!document.querySelector(".sav-menu")){ e.preventDefault(); return false; } var avid = e.target.dataset.av if(avid){ GM_setClipboard(avid); if(debug) console.log("粘贴成功: ", avid); } e.preventDefault(); return false; } // 鼠标经过番号 function savIDMouseEnter(e){ // 进入番号, 如果之前存在菜单, 就判断是否是现在番号的菜单, 如果是, 退出; 否则删掉菜单, 重新获取 if(divTarget && e.target.dataset.av==divTarget.dataset.av){ clearTimeout(timerMouseLeaveMenu) return }else if (divTarget){ clearTimeout(timerMouseLeaveMenu) let odiv = document.querySelector(".sav-menu"); odiv.parentNode.removeChild(odiv); } // observer.disconnect(); if(e.buttons != 0) return; // 如果是按键的情况下划过番号, 则不触发 divTarget = e.target; clearTimeout(timerMouseLeave); clearTimeout(timerGetInfo); avmouseenter(e); } // 鼠标离开番号 function savIDMouseLeave(e){ observer.observe(observerTarget, observerConfig); timerMouseLeave = setTimeout(function(){ avInfo = {}; avInfoID = ""; savMenuMouseLeave(); removeLoading(); clearTimeout(timerGetInfo); },50) } // 鼠标进入菜单 function savMenuMouseEnter(e){ observer.disconnect(); clearTimeout(timerMouseLeave); } // 鼠标离开菜单 function savMenuMouseLeave(e){ timerMouseLeaveMenu = setTimeout(function(){ var odiv = document.querySelector(".sav-menu"); if(odiv){ if(setting.dontClearMenu){ console.log("移除"); } else { // odiv.parentNode.removeChild(odiv); odiv.classList.add("savCloseAnim") setTimeout(function(){ if(odiv){ odiv.parentNode.removeChild(odiv); } },100) } Imgscall = 1.0; divTarget = null; } avInfo = {}; avInfoID = ""; clearTimeout(timerGetInfo); // clearInterval(timerImgLoading); // 重置位置的定时器 observer.observe(observerTarget, observerConfig); },10); } // 鼠标滑过 显示菜单 function avmouseenter(e){ if(document.querySelector(".sav-menu")){ return; // 防止出现菜单后重复触发, 尤其是margin上移两像素后 } var wuma = e.target.dataset.av_wuma; var avid = e.target.dataset.av; if(e.target.classList.contains("infoFirst")){ // e.target.classList.remove("infoFirst"); // e.target.classList.add("infoExistent"); let allDoms = document.querySelectorAll(`savdiv.infoFirst[data-av='${avid}']`) for( let i=0; i<allDoms.length; i++){ allDoms[i].classList.remove("infoFirst"); allDoms[i].classList.add("infoExistent"); } } var avdiv = document.querySelector(".sav-menu") if(avdiv){ avdiv.parentNode.removeChild(avdiv) } var oPosition = e.target.getBoundingClientRect() var odiv = createPattenr(avid,wuma); // e.target.appendChild(odiv); // 信息加载时的动画 if(!setting.closeLoadingAnimation && (setting.infoReload || !localInfo[avid])){ addLoading(odiv) } var posRight =630 - (document.documentElement.clientWidth-divTarget.getBoundingClientRect().x); if(posRight<15){ posRight = 15 } odiv.style.transformOrigin = posRight + "px 5px"; document.body.appendChild(odiv); odiv.style.left = oPosition.x + "px"; odiv.style.top = oPosition.y + oPosition.height - 2 + "px"; // return; // 停止一切信息获取 if(localInfo[avid]){ avInfo = localInfo[avid]; avInfoID = avid; timerGetInfo = setTimeout(() => { if(wuma){ if(setting.infoReload){ getInfo_wuma(avid); }else{ getInfo_local(avid) } }else{ if(setting.infoReload){ getInfo(avid); }else{ getInfo_local(avid) } } }, 100); } else{ timerGetInfo = setTimeout(() => { if(wuma){ getInfo_wuma(avid); }else{ getInfo(avid); } }, 300); } var otherInfo = document.createElement('avdivsInfo'); otherInfo.innerHTML=addOtherInfo(avid); odiv.appendChild(otherInfo); e.target.parentNode.title = ""; e.target.parentNode.parentNode.title = ""; settingPostion(); //重置位置 if(setting.emby){ getEmby(avid); }else{ getJellyfin(avid); } } // 点击事件, 图片放大缩小, debug中复制番号 function savMenuClick(e){ // 测试使用 if(e.target.classList.contains("savCopyID")){ GM_setClipboard(e.target.dataset.av) } else if(e.target.classList.contains("savCloseMenu")){ var odiv = document.querySelector(".sav-menu"); odiv.classList.add("savCloseAnim") setTimeout(function(){ odiv.parentNode.removeChild(odiv); },100) Imgscall = 1.0; avInfo = {}; avInfoID = ""; divTarget = null; clearTimeout(timerGetInfo); return; } else if(e.target.classList.contains("savSetting")){ savBoxEdit(); return; } else if(e.target.classList.contains("jellyfin")){ if(e.target.classList.contains("noJellyfin")){ console.log(e.target.dataset.avid); GM_setClipboard(e.target.dataset.avid); } // console.log(e.target.dataset.url); if(debug)console.log(e.target.dataset.url); GM_openInTab(e.target.dataset.url,{active: true, insert: true,setParent:true}); return; } else if(e.target.classList.contains("savsehuatang")){ // 防止多次点击导致重复发送请求 e.target.classList.remove("savsehuatang"); sehuatang(e.target.dataset.avid); return; } else if(e.target.classList.contains("savVideoClose")){ let videoDiv = document.querySelector("avdivVideo"); if(videoDiv){ videoDiv.classList.add("savCloseAnim2"); setTimeout(()=>{ videoDiv.parentNode.removeChild(videoDiv); },200) } return; } // 图片放大缩小 if(!setting.dontImgBig){ // odiv.addEventListener("click",savMenuClick) if(e.target.tagName == "IMG"){ if( e.target.classList.contains("imageBig")){ e.target.classList.remove("imageBig"); Imgscall = 1.0 e.target.style = ""; } else { Imgscall = 1.3 // 重置大小 e.target.classList.add("imageBig"); } } else { var oImg = document.querySelector(".sav-menu").querySelector("img"); if(oImg){ oImg.classList.remove("imageBig"); Imgscall = 1.0 oImg.style = ""; } } }; } // 滚动图片放大缩小 function savImgWheel(e){ if(e.target.tagName == "IMG"){ if(e.wheelDelta>0){ e.target.classList.add("imageBig"); // 点击后可以恢复 Imgscall += 0.15 e.target.style.transform = "scale(" + Imgscall +")" } else if(e.wheelDelta<0){ if(Imgscall>1){ Imgscall -= 0.15; if(Imgscall<1){Imgscall=1}; // 偶尔会继续减小, 明明已经小于1还是会执行到这 e.target.style.transform = "scale(" + Imgscall +")"; if(Imgscall==1){ // 缩放到1就去掉class, 之前是缩放到1后继续滚动一次才会去掉class e.target.classList.remove("imageBig"); e.target.style = ""; }; }else{ e.target.classList.remove("imageBig"); e.target.style = ""; } } } e.preventDefault(); return false; } // 鼠标选中 划词搜索 function selectSearch(e){ if(e.button !=0) return; // 排除非左键点击 if(document.activeElement.tagName.toUpperCase() == "INPUT" || document.activeElement.tagName.toUpperCase() == "TEXTAREA") return; // 排除inpu和textarea内的文本 if(document.querySelector(".sav-menu")) return; //如果已经存在菜单, 退出 var selectText = window.getSelection().toString().trim(); if (selectText.length > setting.selectLength) return; //如果复制的文字过长,退出。避免复制网址时自己弹出。 selectText = selectText.replace(/[^a-zA-Z0-9-]/g,""); //去掉一些莫名其妙的符号。网友分享的番号总是各种各样 var avid = selectText.match(/[a-z|A-Z]{2,8}-?\d{2,6}/i); if(!avid) return; //如果没搜索到,退出 observer.disconnect(); // 关闭dom变动的监听 avid = formatAVID(avid[0]); var odiv = createPattenr(avid); var divClientRect = odiv.getBoundingClientRect() var divWidth = divClientRect.right - divClientRect.left; odiv.style.left = e.pageX - divWidth/2 + "px"; odiv.style.top = e.pageY + "px"; odiv.style.position = "absolute"; if(localInfo[avid]){ avInfo = {}; avInfo = localInfo[avid]; avInfoID = avid; timerGetInfo = setTimeout(() => { if(setting.infoReload){ getInfo(avid); }else{ getInfo_local(avid) } }, 500); } else{ timerGetInfo = setTimeout(() => { getInfo(avid,true); }, 300); } document.body.appendChild(odiv); } // 调整距离底部的距离,以防越界 function settingPostion(image){ if(debug){console.log("正在重置位置");}; // if(image && image.complete){ // if(debug){console.log("图片加载情况: " + image.complete)}; // clearInterval(timerImgLoading); // } var odiv = document.querySelector(".sav-menu"); if(!odiv) return; var oClient = odiv.getBoundingClientRect() var oTop = oClient.top; // 距离顶部举例 var oHeight = oClient.height; //自身高度 // var oWidth = oClient.Width; // 自身宽度 var winHeight = document.documentElement.clientHeight; //可视窗口高度 var winWidth = document.documentElement.clientWidth; //可视窗口宽度 let loadingContainerHeight = document.querySelector(".savLoadingContainer")?8:0; if(oTop + oHeight - loadingContainerHeight > winHeight){ // 越出了屏幕底边 odiv.style.position = "fixed"; odiv.style.top = winHeight-oHeight + 2*loadingContainerHeight - 16 +"px"; var posBottom =oHeight - (document.documentElement.clientHeight-divTarget.getBoundingClientRect().y) +30; if(posBottom<5){ posBottom = 5 } odiv.style.transformOrigin = odiv.style.transformOrigin.replace(/\s.+px/,` ${posBottom}px`) } if(oClient.x<0){ //左边 odiv.style.position = "fixed"; odiv.style.left = 0; }else if(winWidth-oClient.x<600){ // 越出了屏幕右边 odiv.style.position = "fixed"; odiv.style.right = "4px"; odiv.style.left = ""; } } // 获取番号相关的信息, 添加图片,调用其他函数添加信息 function getInfo(avID,oFirstBrowse){ if(debug){console.log("从javbus获取信息中 getInfo: " + avID);} if(setting.getInfoFromJavDB){ console.log("直接从javdb获取信息") getInfo_wuma_javdb1(avID); return; } console.log("javbus获取信息"); if(setting.dontGetInfo){ getInfo_end_error(`<avdiv>已经设置为禁止获取番号信息</avdiv>`,avID); return; }; GM_xmlhttpRequest({ method: 'get', url: javbusLink + avID, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", timeout: 3000, // 应对2023-12月 出现的javbus 无法访问的问题 onload: function (data) { // noReferrer(); // 针对防盗链问题 javbusloading(); if(data.status==403 || data.status==522){ if(setting.getInfoFailToJavDB??true){ getInfo_wuma_javdb1(avID); } else{ getInfo_end(avID,data); } return; }else if(data.status==404){ // javbus 对于番号中002简写成02的会识别错误, 只认准确的番号。 一些网友分享的番号会简写, 此处做个判断。不能全部补全, 因为以前的番号确实有两位数字的, 补全后javbus不识别。 if( avID.length - avID.indexOf("-") ==3){ // 将错误番号存储到本地 localInfo[avID] = {}; localInfo[avID].title = "番号可能存在问题"; localInfo[avID].noInfo = true; GM_setValue("avInfo2",localInfo); setTimeout(() => { var avdivinfo = document.querySelector("avdivsinfo"); avdivinfo.parentNode.removeChild(avdivinfo); }, 300); // 重新获取信息 getInfo(avID.replace("-","-0"),true); let relatedPage = document.querySelector(".relatedPage a"); if(relatedPage){ relatedPage.href = relatedPage.href.replace("-","-0"); } } else if(avID.match(oRegExp_SuRen) || (setting.getInfoFailToJavDB??true) ){ getInfo_wuma_javdb1(avID); } else { getInfo_end(avID,data); } return; } var parser=new DOMParser(); var htmlDoc=parser.parseFromString(data.responseText, "text/html"); // 标题 avInfo.title = htmlDoc.title.replace(avID,"").replace(" - JavBus",""); // 获取演员名字 var starNameList = htmlDoc.querySelectorAll(".star-name"); var starName = []; for(let i=0;i<starNameList.length;i++){ starName.push(starNameList[i].querySelector("a").innerHTML); } avInfo.starName = starName; // 获取标签 var tagList = htmlDoc.querySelectorAll("input[name='gr_sel']"); var tags = ""; for(let i=0;i<tagList.length;i++){ tags += tagList[i].nextSibling.innerHTML + " "; } avInfo.tags = tags; // 其他: 发行日期和系列 此处的“发行日期”必须是繁体, 因为是匹配的具体的字。 var other = htmlDoc.querySelectorAll(".header"); for(let i=0;i<other.length;i++){ if(other[i].innerHTML=="發行日期:"){ avInfo.date = other[i].parentNode.innerText.replace("發行日期","日期"); } if(other[i].innerHTML=="系列:"){ avInfo.series = other[i].parentNode.innerText; avInfo.seriesLink = other[i].nextElementSibling.href; } } // 封面 var image = htmlDoc.querySelector(".bigImage img"); if(image){ changeRelatedPage(javbusLink + avID, "JavBus 页面"); var imgSrc = image.src; if(imgSrc.search("pics.dmm.co.jp")<0){ // var imgNum = imgSrc.search(/(imgs|pics)/i); imgSrc = imgSrc.slice(imgSrc.search(/(imgs|pics)/i)); image.src = javbusLink + imgSrc; } // console.log(image.src) image.removeAttribute("title"); //鼠标经过的时候会触发离开事件,所以删掉 } // console.log(image); // 链接 avInfo.link = javbusLink + avID; // 视频链接部分 let avIDsplit = avID.toLowerCase().split("-"); if(debug){ console.log(avIDsplit) console.log(cid[avIDsplit[0]]) } if(!setting.dontGetVideo && !cid[avIDsplit[0]]){ let videoURL = htmlDoc.querySelector("#sample-waterfall a")?.href; if(videoURL?.includes("dmm.co.jp")){ videoURL = videoURL.match(/(?<=.*video\/).*?(?=\/)/) // 1bkynb00008 let corp_finish = videoURL[0].slice(0,-avIDsplit[1].length); corp_finish = corp_finish.replace("00",""); if(corp_finish.length != avIDsplit[0].length){ // 只作用2015年以后的番号, 防止污染cid if(avInfo.date && new Date(avInfo.date)>new Date("1/1/2015")){ let setting2 = GM_getValue("_setting2"); setting2.cid_user = setting2.cid_user ?? {}; setting2.cid_user[avIDsplit[0]] = [corp_finish,avID]; // cid_user[bkynb] = 1bkynb00 if(debug) console.log("更新用户规则 cid: ",corp_finish,avID ); GM_setValue("_setting2",setting2); } } } } // 如果不是从javbus访问, 则调用dmm的图片 // if (window.location.href.indexOf(javbusLink)>-1){ // if(debug)console.log("从javbus访问, 默认用javbus的图片"); // }else{ // image.src = getPic_dmm(avID) // } getInfo_end(avID,data,image); }, // 2023-12-20左右, javbus无法访问, 临时使用javdb ontimeout(data){ if(setting.getInfoFailToJavDB??true){ getInfo_wuma_javdb1(avID); } else{ getInfo_end(avID,data); } } }); } // 通过 dmm 获取图片 function getPic_dmm(avID){ // https://pics.dmm.co.jp/mono/movie/adult/1start036/1start036pl.jpg let imgSrc_dmm = "https://pics.dmm.co.jp/mono/movie/adult/" let cid_user = GM_getValue("_setting2").cid_user ?? {}; // 提取番号中的英文和数字 const movieIdSplit = avID.toLowerCase().split("-"); const corp = movieIdSplit[0]; // 番号中的英文 const idNum = movieIdSplit[1]; // 返回中的数字 let urlPart = ""; // 是否需要特殊处理 if (cid[corp]) { if(debug) console.log("图片加载: 在默认URL规则中: ",cid[corp]) // if (cid[corp].length>1){ // console.log("多个") // 此处只会处理第2个及之后的, 第一个依旧会判断是否含0, 请求两遍 // for(let i=0;i<=cid_user.length;i++){ // urlPart = cid[corp][i] + idNum; // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.p576}.mp4`); // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.old720}.mp4`); // } // } urlPart = cid[corp][0] + idNum; } else if (cid_user[corp]){ if(debug) console.log("图片加载: 在用户学习URL规则中: ",cid_user[corp]); urlPart = cid_user[corp][0].replace("00","") + idNum; // corp = cid_user[corp][0] } else { if(debug) console.log("图片加载: URL规则,默认"); urlPart = corp + idNum; } imgSrc_dmm += urlPart + "/" + urlPart + "pl.jpg" return imgSrc_dmm } // 无码信息获取 function getInfo_wuma(avID){ if(debug){console.log("从网络获取信息中 getInfo_wuma: " + avID);} if(avID.match(/fc2/i)){ if(setting.dontGetInfoFc2){ getInfo_end_error(`<avdiv>已经设置为禁止获取 FC2 信息</avdiv>`,avID); return }; getInfo_fc2(avID); // getInfo_fc2_market(avID); }else{ getInfo_wuma_javdb1(avID); } } // 无码信息获取 - fc2 function getInfo_fc2_market(avID){ if(debug){console.log("从fc2hub获取信息中 getInfo_fc2_market: " + avID);} let IDnum = avID.slice(4) let link = `https://adult.contents.fc2.com/article/${IDnum}/` console.log(link) GM_xmlhttpRequest({ method: 'get', // https://contents.fc2.com/article/3107706/ url: link, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", onload: function (data) { console.log(data); let parser=new DOMParser(); let htmlDoc=parser.parseFromString(data.responseText, "text/html"); console.log(htmlDoc) let info = htmlDoc.querySelector(".items_article_headerInfo"); // 标题 let title = htmlDoc.title.replace("PPV-","").replace(avID,"").trim(); // 番号的链接 // let link = link; // 获取名字 // 获取标签 let tags = info.querySelector(".items_article_TagArea div").innerText // 获取日期 let d = info.querySelector(".items_article_Releasedate").innerText.slice(7).replaceAll("/","-"); // 获取图片 let img = htmlDoc.querySelector(".items_article_SampleImages a").href; // 获取视频 let video = htmlDoc.querySelector(".fc2-video-container video"); console.log(video); if(video){ console.log(video); var videoURL = video.src; var img2 = video.poster; } console.log(link) console.log(title) console.log(tags) console.log(d) console.log(img) console.log(img2) console.log(videoURL) } }); } function getInfo_fc2(avID){ if(debug){console.log("从fc2hub获取信息中 getInfo_fc2: " + avID);} let url = 'https://fc2hub.com/search?kw=' + avID; GM_xmlhttpRequest({ method: 'get', url: url, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", onload: function (data) { console.log(data); if(data.status == 500){ data.status = 404 getInfo_end(avID,data,false) return } if(data.finalUrl && data.finalUrl != url){ getInfo_fc2_openPage(avID,data.finalUrl) } else { data.status = 404 getInfo_end(avID,data,false) return } } }); } function getInfo_fc2_openPage(avID,link){ if(debug){console.log("从fc2hub获取信息中 getInfo_fc2_openPage: " + link);} fc2loading(); GM_xmlhttpRequest({ method: 'get', url: link, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", onload: function (data) { let parser=new DOMParser(); let htmlDoc=parser.parseFromString(data.responseText, "text/html"); var iframe = htmlDoc.querySelector("iframe.lazy") // 视频 avInfo.fc2Video = iframe.dataset.src // return // 番号的链接 avInfo.link = link.match(/http.*id\d{5,7}/)[0]; // 标题 avInfo.title = htmlDoc.querySelector(".fc2-title"); if(!avInfo.title){ data.status = 404 getInfo_end(avID,data,false) return } avInfo.title = avInfo.title.innerText //标签 avInfo.tags = htmlDoc.body.querySelector("meta[name~='keywords']")?.content.replaceAll(", "," "); // 日期 avInfo.date = "日期: " + htmlDoc.body.querySelector("meta[property~='videos:published_time']")?.content.slice(0,10); // 图片 let imgSrc; let img = htmlDoc.querySelector(".col-xl-4 .card-body .row a") if(img){ imgSrc = img.href; avInfo.imgSrc2 = htmlDoc.querySelector(".des img")?.src; } // 加载缩略图 if(setting.fc2Thumbnail){ imgSrc = imgSrc.replace("https://","https://contents-thumbnail2.fc2.com/w500/"); } let image = document.createElement("img"); image.src = imgSrc; changeRelatedPage(link, "fc2hub 页面"); getInfo_end(avID,data,image); } }); } // 从javdb获取信息 - 1.获取链接 function getInfo_wuma_javdb1(avID){ if(debug){console.log("从javdb获取信息中 getInfo_wuma_javdb1: " + avID);} if(setting.dontGetInfoWuma){ getInfo_end_error(`<avdiv>已经设置为禁止从 JavDB 获取信息</avdiv>`,avID); return }; // 从javdb加一些限制, 防止ip被禁用。 目前是5分钟内限制10个。 if(setting.closeJavdbLimit){ console.log("已经关闭对javdb的访问限制, 有封IP的风险"); }else{ var oTime = new Date().getTime(); if(javdbTime.length<10){ javdbTime.push(oTime); setting2.javdbTime = javdbTime; GM_setValue("_setting2",setting2); }else{ javdbTime = GM_getValue("_setting2").javdbTime; if(oTime-javdbTime[0]>300000){ if(debug){console.log("javdb时间保护机制: 正在更新");}; javdbTime.shift(); javdbTime.push(oTime) setting2.javdbTime = javdbTime; GM_setValue("_setting2",setting2); } else { if(debug){console.log("触发保护机制, 停止获取信息")}; getInfo_end_error(`<avdiv>提示: <br>由于短时间内过多访问 JavDB, 触发了脚本的自动保护机制 <br>目前已经限制脚本从 JavDB 获取信息, 稍后会自动恢复<br>该消息仅供参考,依旧有被封IP的风险</avdiv>`,avID); return; } } } GM_xmlhttpRequest({ method: 'get', url: javDBLink + 'search?q=' + avID , headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", onload: function (data) { noReferrer(); // 针对防盗链问题 var parser=new DOMParser(); var htmlDoc=parser.parseFromString(data.responseText, "text/html"); // console.log("data.status:"); var searchResult = htmlDoc.querySelectorAll(".movie-list .item") var REavID = new RegExp(avID.replace(/-|_/,"[_-]"),"i") // 没有搜索结果 if(!searchResult.length){ // console.log(htmlDoc); // 测试了一上午, ip被禁止访问了。。。 if(!htmlDoc.querySelector("title")){ console.log("ip被ban") if(htmlDoc.body.innerText.indexOf("copyright")>-1){ getInfo_end_error(`疑似使用的是日本代理,导致javdb拒绝了您的访问。 网站返回信息:</br></br> ${htmlDoc.querySelector("body").innerHTML}`,avID); }else{ // setting.dontGetInfoWuma = true; GM_setValue("_setting",setting); getInfo_end_error(`疑似IP地址被封。 网站返回信息:</br></br> ${htmlDoc.querySelector("body").innerHTML}`,avID); } return; } data.status = 404 getInfo_end(avID,data,false) return } // 有搜索结果, 但是没有该番号 var fuzzyID = false; if(searchResult[0].innerText.search(REavID)<0){ fuzzyID = fuzzyMatch(avID,searchResult[0].innerText); if(!fuzzyID){ data.status = 404 getInfo_end(avID,data,false) return } } var avLink = searchResult[0].querySelector("a").href; avLink = javDBLink.slice(0,-1) + avLink.slice(avLink.search(/\/v\//i)); changeRelatedPage(avLink, "JavDB 页面") getInfo_wuma_javdb2(avID,avLink) } }); } // 从javdb获取信息 - 2.具体内容 function getInfo_wuma_javdb2(avID,link){ if(debug){console.log("从javdb获取信息中 getInfo_wuma_javdb2: " + avID);} javdbloading() GM_xmlhttpRequest({ method: 'get', url: link, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: "", onload: function (data) { noReferrer(); // 针对防盗链问题 var parser=new DOMParser(); var htmlDoc=parser.parseFromString(data.responseText, "text/html"); // console.log("真实番号地址"); // console.log(htmlDoc); // 标题 avInfo.title = htmlDoc.title.replace(avID,"").slice(0,-16).trim(); // 番号的链接 avInfo.link = link; // 获取相关信息, 匹配的具体的字。 var other = htmlDoc.querySelectorAll(".panel-block"); for(let i=0;i<other.length;i++){ if(other[i].innerHTML.search("日期:")>-1){ avInfo.date = other[i].innerText.trim(); } if(other[i].innerHTML.search("系列")>-1){ avInfo.series = other[i].innerText.trim(); avInfo.seriesLink = other[i].querySelector("a").href; avInfo.seriesLink = avInfo.seriesLink.replace(/https:\/\/.*?\//,setting.javDBLink??"https://javdb.com/"); } if(other[i].innerHTML.search("類別")>-1){ avInfo.tags = other[i].lastElementChild.innerText.trim().replaceAll(", "," "); } if(other[i].innerHTML.search("演員")>-1){ var starNameList = other[i].querySelectorAll("a") var starName = []; for(let i=0;i<starNameList.length;i++){ if(starNameList[i].nextElementSibling.classList.contains("female")){ starName.push(starNameList[i].innerText); } } } } avInfo.starName = starName; // 封面 var image = htmlDoc.querySelector(".video-meta-panel img"); image.removeAttribute("title"); //鼠标经过的时候会触发离开事件,所以删掉 // 预览视频相关 if(!setting.dontGetVideo){ let videoURL = htmlDoc.querySelector("video source")?.src; if(videoURL?.includes("mp4")){ avInfo.video = videoURL; javdbVideoTest(videoURL,avID); } } getInfo_end(avID,data,image); } }); } // javdb网页中自带的视频链接判断是否有效 async function javdbVideoTest(link,avID){ await GetMess(link) .then((res) =>{ if(res.status == 200){ if(debug)console.log("javdb中的链接正常") return link; }else{ if(debug)console.error("javdb中的链接有误 X") let videoButton = document.querySelector(".avimg-preview-button"); if(videoButton){ videoButton.parentNode.removeChild(videoButton); localInfo[avID].video = false; GM_setValue("avInfo2",localInfo); } return false } }) } // 将获取到的信息进行展示和保存 function getInfo_end(avID,data,image){ // removeLoading() if(debug){console.log("从网络获取信息结束 end: " + avID, avInfo);} let errorDiv = document.querySelector("avdiverror"); if(errorDiv){ errorDiv.parentNode.removeChild(errorDiv); } // 标题翻译 if(data.status==403){ avInfo.title = "403错误, javBus 拒绝了您的访问!"; }else if(data.status==404){ getInfo_end_error(`脚本没有匹配到 ${avID} 相关页面, 请使用上方搜索进行查找`,avID) avInfo.noInfo = true; if(divTarget){ divTarget.classList.remove("infoExistent"); divTarget.classList.add("infoNonExistent"); } }else if(setting.dontTransTitle){ if(debug){console.log("禁止翻译标题 ✖ ✖ ✖ : ", avInfo.title);} }else if(!avInfo.titleTrans || avInfo.titleTrans.search("没有找到")>-1){ // 如果本地存在翻译, 就不再重复翻译 // 删除标题之后的演员名字 let title = avInfo.title; let starName = avInfo.starName; if(starName && starName.length ==1 && title.indexOf(starName[0])>-1){ let oLength = title.length-title.indexOf(starName[0]); if( oLength == starName[0].length){ title = title.slice(0,(oLength+1)*-1) } } // 删除标题中的番号(这是第二次删除, getInfo中还有一次) title = title.replace(avID,""); // 删除奇奇怪怪的标点 let biaodian = /[\※\☆\★\♥️\●\▲\♡]|[\s\……\——\-\】\』\}\、\|\;\‘\’\:\“\”\》\,\。\、\_\]\;\'\'\:\"\"\,\.\/\~]*$/g title = title.replace(biaodian,"") avInfo.title = title; if(setting.baiduAppid && setting.baiduKey){ baiduTrans(avID,title); } else{ googleTrans(avID,title); } } if(avInfo.tags && !setting.dontTransTags){ avInfo.tags= translateTag(avInfo.tags) } localInfo[avID] = {}; // 重置,防止在一个页面重复划过番号导致系列、发行日期等重复显示。 if(avInfo.noInfo){ localInfo[avID].noInfo = true; }else{ localInfo[avID].title = avInfo.title localInfo[avID].titleTrans = avInfo.titleTrans; localInfo[avID].starName = avInfo.starName; localInfo[avID].date = avInfo.date?.replace(/\n\s*/g," ") localInfo[avID].series = avInfo.series?.replace(/\n\s*/g," ").replace("系列: ",""); localInfo[avID].seriesLink = avInfo.seriesLink; localInfo[avID].tags = avInfo.tags if(image){ localInfo[avID].image = image.src; } localInfo[avID].link = avInfo.link localInfo[avID].visited = localInfo[avID].visited? localInfo[avID].visited+1:1; localInfo[avID].tips = avInfo.tips; localInfo[avID].correctID = avInfo.correctID; localInfo[avID].video = avInfo.video; localInfo[avID].fc2Video = avInfo.fc2Video; } localInfo[avID].getInfo_Time = new Date().getTime(); if(debug) console.log("保存相关信息: localInfo[avID] : ", localInfo[avID]); GM_setValue("avInfo2",localInfo); if(!document.querySelector(".sav-menu")){return}; // 判断是否重复加载图片 // if(document.querySelector(".avimg")){return}; // console.log("获取到的所有信息: "); // console.log(avInfo); // console.log("------------------"); var otherInfo = document.querySelector("avdivsInfo"); if(!otherInfo){ otherInfo = document.createElement('avdivsInfo'); } otherInfo.innerHTML = addOtherInfo(avID); if(image){ let imageDiv = document.createElement('avdivimg'); image.classList.add("avimg"); // image.setAttribute("referrerpolicy","same-origin"); imageDiv.appendChild(image) otherInfo.appendChild(imageDiv); image.onload = function(){ if(debug)console.log("getInfo_end: 图片加载完成"); removeLoading(); settingPostion(); } image.onerror = ()=>{ if(debug)console.log("javbus图片加载失败"); if(avInfo.imgSrc2){ image.src = avInfo.imgSrc2; localInfo[avID].image = avInfo.imgSrc2; GM_setValue("avInfo2",localInfo); }else{ // image.classList.add('savImgError'); // image.src = imgErrorSVG; image.src = getPic_dmm(avID); localInfo[avID].image = image.src; GM_setValue("avInfo2",localInfo); } } settingPostion() }else{ removeLoading(); } document.querySelector(".sav-menu").appendChild(otherInfo); if(localInfo[avID].fc2Video){ getVideoURLFC2(); }else{ getVideo(avID); } } function getInfo_end_error(errorText,avID){ if(debug){console.log("getInfo_end_error : ", errorText);} let errorInfo = document.createElement('avdivError'); errorInfo.innerHTML = errorText ; document.querySelector(".sav-menu").appendChild(errorInfo); removeLoading(); // 如果获取错误, 会不进入end函数; 错误会导致重新获取, 获取不到会继续保持错误, 然后不断循环 // 存在一种情况一个新浏览的番号, 没有获取到任何信息, 直接来到这里, 会导致localInfo[avID]是 undefined if(localInfo[avID]){ localInfo[avID].getInfo_Time = new Date().getTime(); } GM_setValue("avInfo2",localInfo); } // 从本地加载信息 function getInfo_local(avID){ if(debug){console.log("从本地加载信息 local: " ,avID, localInfo[avID]);} if(!document.querySelector(".sav-menu")){return}; // 判断是否重复加载图片 if(document.querySelector(".avimg")){return}; noReferrer(); if(localInfo[avID].noInfo){ getInfo_end_error(`脚本没有匹配到 ${avID} 相关页面, 请使用上方搜索进行查找`,avID) localInfo[avID].visited = localInfo[avID].visited? localInfo[avID].visited+1:1; GM_setValue("avInfo2",localInfo); reloadGetInfo(avID); return; } // 浏览过的番号,从本地加载链接。 信息只获取一次, 避免被网站拉黑IP if(localInfo[avID].link){ if(localInfo[avID].link.indexOf(javDBLink)>-1){ changeRelatedPage(localInfo[avID].link,"JavDB 页面",avID); }else if(localInfo[avID].link.indexOf(javbusLink)>-1){ changeRelatedPage(localInfo[avID].link,"JavBus 页面",avID); }else if(localInfo[avID].link.indexOf("fc2hub")>-1){ changeRelatedPage(localInfo[avID].link,"fc2Hub 页面",avID); } } let imgDiv = document.createElement("avdivimg"); let image = document.createElement("img"); if(localInfo[avID].image){ // 2022-10-12 0.18.0 之后将只保存网址, 之前的版本是保存的img节点 image.src = localInfo[avID].image.match(/https.*\.(jpg|jpeg|gif|png)/)[0]; image.classList.add("avimg"); image.setAttribute("referrerpolicy","same-origin"); imgDiv.appendChild(image); } else { // image.innerHTML = "没有在本地找到图片信息" if(debug){console.log("由于本地没有图片, 重新从网络中获取信息: ", avID)} reloadGetInfo(avID) return; } var otherInfo = document.querySelector('avdivsInfo'); otherInfo.appendChild(imgDiv); document.querySelector(".sav-menu").appendChild(otherInfo); localInfo[avID].visited = localInfo[avID].visited? localInfo[avID].visited+1:1; GM_setValue("avInfo2",localInfo); image.onload = function(){ if(debug){console.log("getInfo_local: 图片加载完成")} settingPostion() } image.onerror = ()=>{ image.classList.add('savImgError'); image.src = imgErrorSVG; // 图片无法加载, 视为网站更换了网址, 重新获取 reloadGetInfo(avID) } if(localInfo[avID].fc2Video){ getVideoURLFC2(); }else{ getVideo(avID); } } function changeRelatedPage(link,txt,avID){ // if(avInfo.correctID || localInfo[avID]?.correctID){ // return; // } let relatedPageButton = document.querySelector(".relatedPage"); let relatedPage = relatedPageButton?.querySelector("a"); if(relatedPage){ relatedPage.href = link; relatedPage.innerHTML = txt; } relatedPageButton?.classList.remove("RPdisabled") } // 重新获取信息, 通常是在本地信息不完整的情况下会调用该函数。例:noInfo为true, 或者缺少图片 function reloadGetInfo(avID){ if(debug){console.log("重新获取信息 reloadGetInfo: ",avID)}; avInfo = {}; let nowTime = new Date().getTime(); if(!localInfo[avID].getInfo_Time || nowTime-localInfo[avID].getInfo_Time > 43200000){ if(avID.match(oRegExp)){ getInfo(avID) }else if(avID.match(/fc2/i)){ getInfo_fc2(avID) } else { getInfo_wuma_javdb1(avID) } }else{ if(debug){console.log("重新获取信息 reloadGetInfo: 距离上次更新信息时间不足12小时, 将不会重新获取信息。")}; } } // 在菜单中添加番号相关的信息(标题,演员等) function addOtherInfo(avID){ if(localInfo[avID] && localInfo[avID].noInfo){return ""}; // 如果没有信息就直接返回 var actors = "" var str = ""; if(avInfo.titleTrans){ str += "<avdiv class='sav-title' id='searchAVMenuTitle'>标题: " + avInfo.titleTrans + "</avdiv>" }else if(avInfo.title){ str += "<avdiv class='sav-title' id='searchAVMenuTitle'>标题: " + avInfo.title + "</avdiv>" } if(avInfo.starName && avInfo.starName.length>0){ // let actorsSearchURL = "https://www.javbus.com/searchstar/%s" let actorsSearchURL = setting.actorsSearchURL?setting.actorsSearchURL:"https://www.javbus.com/searchstar/%s"; for(var i=0;i<avInfo.starName.length;i++){ actors += "<a class='sav-actors-"+ i + "' target='_blank' title='' href='" + actorsSearchURL.replace("%s",avInfo.starName[i]) + "'>"+ avInfo.starName[i] + "</a>, "; getJellyfin_Actor(avInfo.starName[i],i) } actors = actors.slice(0,actors.length-2); str += "<avdiv class='sav-actors'>演员: " + actors + "</avdiv>" } if(avInfo.tags && avInfo.tags.length>0){ str += "<avdiv class='avInfoTags'>标签: " + avInfo.tags + "</avdiv>" } if(avInfo.seriesLink){ str += `<avdiv class='avInfoSeries'>系列: <a target='_blank' href='${avInfo.seriesLink}' >${localInfo[avID].series}</a></avdiv>` }else if(avInfo.series){ // 2022-10-15 0.18.2 存储的series中, 不再含有汉字 “系列: ”, 此处的replace是与之前的版本兼容 str += "<avdiv class='avInfoSeries'>系列: " + avInfo.series.replace("系列: ","") + "</avdiv>" } if(avInfo.date){ str += "<avdiv>" + avInfo.date + "</avdiv>" } if(avInfo.tips){ str += "<avdiv>提示: " + avInfo.tips + "</avdiv>" } str += "" return str; } // 添加信息加载时的动画 function addLoading(odiv){ var savLoading = document.createElement('avdiv'); savLoading.classList.add("savLoadingContainer"); var savhr = '<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" version="1.1">' + '<linearGradient xmlns="http://www.w3.org/2000/svg" id="grad4" x1="0%" y1="50%" x2="100%" y2="50%">' + '<stop class="stop1" offset="30%" />' + '<stop class="stop2" offset="50%" />' + '<stop class="stop3" offset="70%" />' + '</linearGradient>' + '<rect xmlns="http://www.w3.org/2000/svg" width="600" height="5" style="fill:url(#grad4)"/> ' + '</svg>' savLoading.innerHTML='<avdiv class="savLoading">' + savhr +savhr + '</avdiv>'; odiv.appendChild(savLoading); } function javbusloading(){ var stop2 = document.querySelector(".stop2"); if(stop2){ stop2.classList.toggle("javbusloading") } } function javdbloading(){ var stop2 = document.querySelector(".stop2"); if(stop2){ stop2.classList.remove("javbusloading") stop2.classList.toggle("javdbloading") } } function fc2loading(){ var stop2 = document.querySelector(".stop2"); if(stop2){ stop2.classList.toggle("fc2loading") } } // 移除信息加载时的动画 function removeLoading(){ // return; var loading = document.querySelector(".savLoadingContainer"); if(loading){ loading.style.height = "0px"; loading.style.marginTop = "0px"; setTimeout(()=>{ loading.parentNode?.removeChild(loading); },200) } } // 格式化番号, 添加中间的横杠 function formatAVID(otext){ otext = otext.replace(/\s+|-c|_c|-4k|carib[-_]|1pondo[-_]|-1pon|-paco|-carib|hd_/ig,""); if(otext.match((/^[a-z|A-Z]{2,8}\d{2,5}$/i))){ var oindex = otext.search(/\d/); if(oindex>0){ otext = otext.slice(0,oindex) + "-" + otext.slice(oindex) } } return otext.toUpperCase(); } // 格式化无码番号 function formatWuma(otext){ otext = otext.replace(/\s+|carib[-_]|1pondo[-_]|-1pon|-paco|-carib|hd_/ig,""); // 不再分 "FC2PPV-" 和 "FC2-" 统一为 "FC2-" if(otext.match(/fc2/i)){ var oindex = otext.search(/(?<!fc)\d/i); // if(otext.match(/ppv/i)){ // otext = "FC2PPV-" + otext.slice(oindex) // }else{ otext = "FC2-" + otext.slice(oindex) // } return otext.toUpperCase(); } // heyzo if(otext.match(/heyzo/i)){ var oindex = otext.search(/\d/i); return "HEYZO-" + otext.slice(oindex) } // 东京热 n1234 返回小写 if(otext.match(/(?:k|n)\d{4}/i)){ return otext.toLowerCase(); } // 返回大写 MKD-S\d{2,3}(?!\w|-)|(?:SHINKI|KITAIKE)[-\s]?\d{3}(?!\w|-)|JPNXXX[-\s]?\d{5}(?!\w|-)|xxx-av[-\s]\d{4,5}(?!\w|-)|(?<!\w)crazyasia\d{5}(?!\w|-)|(?<!\w)PEWORLD\d{5}(?!\w|-)|(?<!\w)MKBD-S\d{2,3}|(?<!\w)\d{6}[-_]?_01(?=-10mu)/gi; if(otext.match(/t28|t-|MKD-S|SHINKI|KITAIKE|JPNXXX|xxx-av|crazyasia|PEWORLD|MKBD-S/i)){ return otext.toUpperCase(); } // heydouga if(otext.match(/HEYDOUGA/i)){ return "heydouga-" + otext.slice(otext.search(/\d/i)) } return otext; } // 检查番号是否需要排除 function IDcheck(otext){ var oOnlyText = otext.replace(/[^a-zA-Z]/gi,""); // 番号中的英文 var oOnlyNum = otext.replace(/[^0-9]/ig,""); // 番号中的数字 // if(debug) console.table([{name:"完整番号",value:otext},{name:"英文",value:oOnlyText},{name:"数字",value:oOnlyNum},{name:"是否有横杠",value:oNoHyphen},{name:"是否排除",value:oExclude},{name:"占位",value:"占位"}]); // 排除 特别的番号 if(otext.match(oRegExp_Exclude_ID)){ if(debug) {console.log(searchTimes-avIDTimes,` 特别的番号,略过: ${otext} `);} return true; } // 包含关键词的情况下 if(oOnlyText.match(oRegExp_Exclude_en)){ if(debug) {console.log(searchTimes-avIDTimes,` 存在排除词 ${oOnlyText} ,略过 ${otext} `);} return true; } if(otext.match((/^[a-z|A-Z]{2,8}\s?\d{2,5}$/i))){ // 没有横杠的情况下, 含有需要排除的数字 if(oOnlyNum.match(oRegExp_Special_num)){ if(debug) {console.log(searchTimes-avIDTimes,` 无横杠,且存在需要排除的数字 ${oOnlyNum},略过 ${otext} `)}; return true; } // 没有横杠的情况下, 并且含有关键词 if(oOnlyText.match(oRegExp_Special_en)){ if(debug) {console.log(searchTimes-avIDTimes,` 无横杠,且有关键词 ${oOnlyText},略过 ${otext} `)} ; return true; } } return false; } // 检查番号是否需要排除 无码 function IDcheckWuma(otext){ if(otext.match(/\d{3}[a-zA-Z]{2,5}[-\s]?\d{3,4}/i)){ if(otext.replace(/[^a-zA-Z]/gi,"").match(/^cm$/i)){ return true; } } if(otext.match(oRegExp_Exclude_wuma)){ if(debug) {console.log(searchTimes-avIDTimes,` 存在无码排除词,略过: ${otext} `);} return true; } return false; } // 动态添加的元素, 检查所有父元素的class是否是排除项 function checkParentClass(startDom){ if(startDom.classList && startDom.classList.length && startDom.className.match(window.qxin.RE_Exclude_className)){ if(debug)console.log("checkParentClass: 父元素存在相关class, 已排除: ",startDom.className); return true; } if(startDom.parentElement && "body" !== startDom.parentElement.nodeName){ return checkParentClass(startDom.parentElement) } else { return false } } // 模糊匹配 function fuzzyMatch(avID,title){ if(debug){console.log("进入模糊匹配, 标题: ",title)} let onlyText = avID.replace(/[^a-zA-Z]/gi,""); // 番号中的英文 let onlyNum = avID.replace(/[^0-9]/ig,""); // 番号中的数字 // 数字都是错误的情况下, 直接返回 if(title.indexOf(onlyNum)<0){ console.log("数字错误"); return false; } let searchIDLength = onlyText.length; // 紧邻两个字符错位的情况 for(let i =1;i<onlyText.length-1; i++ ){ let newID = onlyText.slice(0,i) + onlyText.charAt(i+1) + onlyText.charAt(i) if(i+2<onlyText.length){ newID += onlyText.slice(i+2) } if(title.indexOf(newID)>-1){ let wrongId1 = newID.slice(0,i) +"<b><u>" + newID.slice(i,i+2) +"</u></b>"+ newID.slice(i+2); let wrongId2 = avID.slice(0,i) +"<b><u>" + avID.slice(i,i+2) +"</u></b>"+ avID.slice(i+2); avInfo.tips = `这是 ${wrongId1}-${onlyNum} 的搜索结果, 如果继续搜索 ${wrongId2}, 请使用上方按钮` avInfo.correctID = `${newID}-${onlyNum}` return true } } // 单个字符错误的情况 let titleID = title.match(/\w{2,6}(?=-)/); if(!titleID || searchIDLength<3 || titleID[0].length != searchIDLength){ return } let title_ID = titleID[0]; let rightNum = 1; // 共同的次数 let wrongNum ; if(title_ID.length == searchIDLength){ // 第一个字符就错的情况, 直接返回 if(onlyText.charAt(0)!=title_ID.charAt(0)){ // console.log("第 1 个字符出现错误"); return false } for(let i =1;i<searchIDLength; i++ ){ if(onlyText.charAt(i)==title_ID.charAt(i)){ rightNum++; } else { wrongNum = i // console.log(`第 ${i} 个字符出现错误。`) } } if(rightNum==searchIDLength-1){ let wrongId1 = title_ID.slice(0,wrongNum) +"<b><u>" + title_ID.charAt(wrongNum) +"</u></b>"+ title_ID.slice(wrongNum+1); let wrongId2 = avID.slice(0,wrongNum) +"<b><u>" + avID.charAt(wrongNum) +"</u></b>"+ avID.slice(wrongNum+1); avInfo.tips = `这是 ${wrongId1}-${onlyNum} 的搜索结果, 如果继续搜索 ${wrongId2}, 请使用上方按钮` avInfo.correctID = `${title_ID}-${onlyNum}`; return true } } return false; } // 谷歌翻译 function googleTrans(avID,transText) { if(debug){console.log("谷歌翻译 googleTrans: ",transText);} var translate_url = ""; var googleTransApi = "https://translate.google.com.hk/translate_a/single?client=gtx&dt=t&dj=1&sl=auto&tl=zh-CN&hl=zh-CN&q="; translate_url = googleTransApi + encodeURIComponent(transText); GM_xmlhttpRequest({ method: "GET", url: translate_url, onload: function (r) { setTimeout(function () { // 如果返回结果不对 console.log(r.responseText) if(r.responseText.indexOf("sentences")<0){ console.log("谷歌翻译失败: ",r.responseText); return; } var data = JSON.parse(r.responseText); var trans = ""; for (var i = 0; i < data.sentences.length; i++) { var getransCont = data.sentences[i]; trans += getransCont.trans; } trans_end(avID,trans) }, 100); }, onerror: function (e) { console.error(e); console.log("谷歌翻译失败"); } }); } // 百度翻译 function baiduTrans(avID,transText) { if(debug){console.log("百度翻译 baiduTrans: ",transText);} var appid = setting.baiduAppid; var key = setting.baiduKey; var salt = (new Date).getTime(); // var query = 'apple'; // 多个query可以用\n连接 如 query='apple\norange\nbanana\npear' // var from = 'jp'; // var to = 'zh'; var str1 = appid + transText + salt +key; var sign = MD5(str1); var translate_url = "http://api.fanyi.baidu.com/api/trans/vip/translate?q="+ encodeURIComponent(transText) +"&from=jp&to=zh&appid="+appid+"&salt="+salt+"&sign="+sign; GM_xmlhttpRequest({ method: "GET", url: translate_url, onload: function (r) { console.log(r) if(r.responseText.indexOf("error_code")>0){ console.log("百度翻译失败:",r.responseText) return; } var data = JSON.parse(r.responseText); trans_end(avID,data.trans_result[0].dst) }, onerror: function (e) { console.error(e); console.log("百度翻译失败"); } }); } // 翻译结束 function trans_end(avID,result){ if(debug){console.log("翻译结束 trans_end: ",result)} localInfo[avID].titleTrans = result; GM_setValue("avInfo2",localInfo); if(document.querySelector("#searchAVMenuTitle")){ document.querySelector("#searchAVMenuTitle").innerHTML = "标题: (译)" + result; } } // 防盗链 function noReferrer(){ // 相关代码地址 https://greasyfork.org/zh-CN/scripts/376884 // 名称: 显示防盗链图片 for Inoreader // 作者: maboloshi var meta = document.createElement('meta'); meta.name = "referrer"; meta.content = "no-referrer"; // meta.content = "same-origin"; document.getElementsByTagName('head')[0].appendChild(meta); } // 预览视频 项目名称: "JAVBUS影片预告" 作者:"bigwolf99" 相关代码: https://sleazyfork.org/zh-CN/scripts/450740 async function getVideo(avID) { if(setting.dontGetVideo) return; if(avInfo.noInfo) return; if(debug) console.log("getVideo 开始"); let videoURL; if(!localInfo[avID].video){ videoURL = await queryVideoURL(avID); if(debug)console.log("最终url: ", videoURL); if(videoURL){ localInfo = GM_getValue("avInfo2") localInfo[avID].video = videoURL; GM_setValue("avInfo2",localInfo); }else{ if(debug)console.log("未获取到视频链接: ", videoURL); return; } }else{ // videoURL = localInfo[avID].video; // 大概从 2024-12-03 左右, dmm.co.jp 域名的预览视频, 非日本IP会出现 403 拒绝访问的问题 videoURL = localInfo[avID].video.replace("dmm.co.jp", "dmm.com"); localInfo[avID].video = videoURL; GM_setValue("avInfo2",localInfo); if(debug)console.log("本地存在视频链接: ", videoURL) } let avimg = document.querySelector(".avimg") if(avimg){ let videoButton = document.createElement("savdiv"); videoButton.classList.add("avimg-preview-button"); avimg.parentNode.insertBefore(videoButton,avimg); videoButton.addEventListener("click",addVideoDiv(videoURL, avID)); } return videoURL; } // 获取播放地址 async function queryDMMVideoURL(avID, host = "cc3001.dmm.com") { // if (movieInfo.isUncensored) // return Promise.reject("DMM server not support uncensored movie."); //see https://www.javbus.com/forum/forum.php?mod=viewthread&tid=63374 //see https://bit.ly/3wXLj6T let infix = "litevideo/freepv"; //1500kbps = _dmb_w || 3000kbps = _mhb_w || vrlite // 1080p:hhb 720p:hmb 576p:mhb let quality ={ "p1080":"hhb", "p720":"hmb", "p576":"mhb", "old720":"_dmb_w", } // vr 影片 // if (avID.search("VR-")) { // postfix = "vrlite"; // infix = "vrsample"; // url = `https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPartAdd00}/${urlPartAdd00}${postfix}.mp4` // } // 提取番号中的英文和数字 const movieIdSplit = avID.toLowerCase().split("-"); const corp = movieIdSplit[0]; // 番号中的英文 const idNum = movieIdSplit[1]; // 返回中的数字 let urlPart; let cid_user = GM_getValue("_setting2").cid_user ?? {}; var urls = []; // 是否需要特殊处理 if (cid[corp]) { if(debug) console.log("视频加载: 在默认URL规则中: ",cid[corp]) if (cid[corp].length>1){ console.log("多个") // 此处只会处理第2个及之后的, 第一个依旧会判断是否含0, 请求两遍 for(let i=1;i<=cid_user.length;i++){ urlPart = cid[corp][i] + idNum; urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.p576}.mp4`); urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.old720}.mp4`); } } urlPart = cid[corp][0] + idNum; // corp = cid[corp][0] } else if (cid_user[corp]){ if(debug) console.log("视频加载: 在用户学习URL规则中: ",cid_user[corp]); urlPart = cid_user[corp][0] + idNum; // corp = cid_user[corp][0] } else { if(debug) console.log("视频加载: URL规则,默认添加00"); urlPart = corp + "00" + idNum; } // https:// cc3001.dmm.co.jp / litevideo/freepv / s / ssn / ssni00378 / ssni00378 _dmb_w .mp4 // `https:// ${host} / ${infix} / ${urlPart[0]} / ${urlPart.substring(0,3)} / ${urlPart} / ${urlPart} ${postfix}.mp4`; // var videoURL = `https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${postfix}.mp4`; let urlPartAdd00 = replace00(urlPart); // 根据番号发布时间 访问不同的网址 // if(avInfo.date && new Date(avInfo.date)>new Date("1/1/2024")){ // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.p576}.mp4`); // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPartAdd00}/${urlPartAdd00}${quality.p576}.mp4`); // }else if(avInfo.date && new Date(avInfo.date)>new Date("8/29/2023")){ urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.p576}.mp4`); urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPartAdd00}/${urlPartAdd00}${quality.p576}.mp4`); // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.old720}.mp4`); // urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPartAdd00}/${urlPartAdd00}${quality.old720}.mp4`); }else{ urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPart}/${urlPart}${quality.old720}.mp4`); urls.push(`https://${host}/${infix}/${urlPart[0]}/${urlPart.substring(0,3)}/${urlPartAdd00}/${urlPartAdd00}${quality.old720}.mp4`); } var urlListGetMess = []; for(let i=0;i<urls.length;i++){ let p = GetMess(urls[i]) urlListGetMess.push(p) } return Promise.any(urlListGetMess) .then(res=>{ if(debug)console.log(res); return res.finalUrl; }) .catch(e=>{ if(debug)console.log(e); return queryJavSpylVideoURL(avID) .then(res=>{ let resJSON = JSON.parse(res.response) if(resJSON?.info?.url){ return "https://" + resJSON.info.url } return false }) .catch(()=>{return false}) }) } async function queryJavSpylVideoURL(avID) { if(debug)console.log("通过javspyl获取链接中:"); let javspylURL = "https://api.javspyl.eu.org/api/"; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url:javspylURL, method :"POST", headers: { origin: "https://api.javspyl.eu.org", "Content-Type": "application/x-www-form-urlencoded", }, data: `ID=${avID}`, onload:function(xhr){ resolve(xhr); }, onerror:function(xhr){ resolve(xhr); } }); })} // 用来替换番号中的 00 , 预览视频使用 function replace00(urlPart){ if(urlPart.search(/00\d{3,4}/)>0){ return urlPart.replace("00",""); } else { let oindex = urlPart.search(/[a-z]\d/i) +1; return urlPart.slice(0,oindex) + "00" + urlPart.slice(oindex) } } // 其他番号的播放地址 async function queryVideoURL(avID){ let link = ""; if(avID.match(/[01]\d{5}\-(?:1)?\d{2,3}/i)){ if(debug) {console.log("加勒比: ", avID);} link = `http://smovie.caribbeancom.com/sample/movies/${avID}/480p.mp4` }else if(avID.match(/[01]\d{5}\_(?:1)?\d{2,3}/i)){ if(debug) {console.log("一本道: ", avID);} link = `http://smovie.1pondo.tv/sample/movies/${avID}/480p.mp4` }else if(avID.match(/HEYZO/i)){ if(debug) {console.log("HEYZO: ", avID);} link = `https://www.heyzo.com/contents/3000/${avID.slice(6)}/heyzo_hd_${avID.slice(6)}_sample.mp4` }else if(avID.match(/HEYDOUGA/i)){ if(debug) {console.log("HEYDOUGA视频无法解析: ",avID)} return false; // heydouga-4037-445 let avIDSplit = avID.split("-"); link = `https://hls-mediaac.heydouga.com/sample/${avIDSplit[1]}/${avIDSplit[2]}/mb.m3u8`; }else if(avID.match(/(?:k|n)\d{4}/i)){ // 东京热 n1234 link = `https://my.cdn.tokyo-hot.com/media/samples/${avID}.mp4`; }else if(avID.search(/^[A-Z]{2,7}-\d{2,6}$/i>-1)){ return await queryDMMVideoURL(avID) }else{ if(debug) {console.log("该视频目前无法解析视频: ",avID);} return false; } return await GetMess(link) .then((res) =>{ if(res.status == 200){ return link; }else{ return false } }) .catch((e) =>{ return false; }) } function GetMess(link){ if(debug)console.log("GetMess请求: ", link); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url:link, method :"HEAD", headers: { }, fetch:link, onload:function(xhr){ if(xhr.status ==200){ resolve(xhr); } else{ reject(xhr) } }, onerror:function(xhr){ resolve(xhr); } }); }) } // 添加视频 function addVideoDiv(videoURL, avID){ return function(){ let videoDiv = document.createElement("avdivVideo"); videoDiv.innerHTML = ` <video class="avVideo" poster="${localInfo[avID].image}" controls autoplay loop > <source src="${videoURL}" type="video/mp4"> </video> <avidv class="savVideoClose"> X </avdiv> ` let imgDiv = document.querySelector("avdivimg"); imgDiv.appendChild(videoDiv) let videoSelect = document.querySelector(".avVideo"); if(videoSelect){ videoSelect.volume = setting.videoVolume??0.2; } } } // fc2 预览视频 function getVideoURLFC2(avID) { if(setting.dontGetVideo) return; if(debug) console.log("getVideoURLFC2 开始"); let videoButton = document.createElement("savdiv"); videoButton.classList.add("avimg-preview-button"); let avimg = document.querySelector(".avimg") avimg.parentNode.insertBefore(videoButton,avimg); videoButton.addEventListener("click",addVideoDivFc2(avInfo.fc2Video)); return } // 添加fc2视频 function addVideoDivFc2(videoURL){ return function(){ let videoDiv = document.createElement("avdivVideo"); videoDiv.innerHTML = ` <iframe src="${videoURL}"></iframe> <avidv class="savVideoClose"> X </avdiv> ` let imgDiv = document.querySelector("avdivimg"); imgDiv.appendChild(videoDiv) } } // 切换页面 暂停预览视频播放 function visibilitychangeFun(e){ if(e.target.hidden){ document.querySelector("avdiv .avVideo")?.pause(); document.querySelector(".main-video")?.pause(); // FC2 }else{ document.querySelector("avdiv .avVideo")?.play(); // document.querySelector(".main-video")?.play(); // FC2 仅自动暂停, 不会自动播放 } } // 获取色花堂的formhash function sehuatang_getFormHash(){ let setting2 = GM_getValue("_setting2"); let sehuatang_getTime = setting2.sehuatang_getTime; let nowTime = new Date().getTime(); let sehuatangURL = setting.sehuatangURL?setting.sehuatangURL.replace(/\/$/,""):"https://www.sehuatang.org"; // 不确定这个值会不会变动, 12小时获取一次 if(!sehuatang_getTime || nowTime-sehuatang_getTime > 43200000 || setting2.sehuatang_url != sehuatangURL){ GM_xmlhttpRequest({ method:"get", url:sehuatangURL, onload:function(data){ // console.log(data); var parser=new DOMParser(); let htmlDoc=parser.parseFromString(data.responseText, "text/html"); let odom = htmlDoc.querySelector('input[name="formhash"]'); // console.log(odom); if(!odom) return; let formhash_value = odom.value; // console.log(formhash_value); let setting2 = GM_getValue("_setting2"); setting2.sehuatang_formhash = formhash_value; setting2.sehuatang_getTime = nowTime; setting2.sehuatang_url = sehuatangURL; GM_setValue("_setting2",setting2); } }) if(debug){console.log(`重新获取色花堂的formhash`)}; }else{ if(debug){console.log(`没有重新获取色花堂的formhash`)} } } // 色花堂搜索 function sehuatang(avID){ let formhash = GM_getValue("_setting2").sehuatang_formhash; let sehuatangURL = setting.sehuatangURL?setting.sehuatangURL.replace(/\/$/,""):"https://www.sehuatang.org"; if(formhash){ GM_xmlhttpRequest({ method: "post", url: sehuatangURL+"/search.php?mod=forum", data: `formhash=${formhash}&srchtxt=${avID}&searchsubmit=yes`, headers: { "Content-Type": "application/x-www-form-urlencoded", "Origin":sehuatangURL, "Referer":sehuatangURL }, onload: function(data){ // console.log(data); // console.log(data.finalUrl); if(data.finalUrl){ window.open(data.finalUrl); }else{ GM_setClipboard(avID) window.open(`${sehuatangURL}/search.php`); } }, onerror : function(err){ console.log('error') console.log(err) } }); }else{ GM_setClipboard(avID) window.open(`${sehuatangURL}/search.php`); } } // 查看本地 jellyfin 中是否存在 function getJellyfin(avID){ if(setting.jellyfinHost && setting.jellyfinApiKey){ if(debug){console.log("查询本地jellyfin: getJellyfin");}; } else { if(debug){console.log("退出jellfin函数, 其中host和apiKey: ", setting.jellyfinHost , setting.jellyfinApiKey)} return; } GM_xmlhttpRequest({ method: 'get', url: setting.jellyfinHost + "emby/Search/Hints?searchTerm=" + avID, headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Emby-Token":setting.jellyfinApiKey }, data: "", timeout: 1000, onload: function (r) { var div_jellyfin = document.querySelector(".jellyfin"); if(!div_jellyfin){return}; // ApiKey输入错误的情况下, 会出现401错误, 身份验证错误 if(r.status == 401){ console.log("jellyfin: 身份验证错误, 请检查设置中的 ApiKey 是否设置正确"); div_jellyfin.classList.add("errJellyfin") return; } var data = JSON.parse(r.responseText); if(data.SearchHints[0]){ if(debug){console.log("jellyfin中的标题: ", data.SearchHints[0].Name)}; div_jellyfin.dataset.url = setting.jellyfinHost + "web/index.html#!/details?id=" + data.SearchHints[0].Id; div_jellyfin.classList.add("yesJellyfin"); } else { div_jellyfin.dataset.url = setting.jellyfinHost + "web/index.html#!/search.html"; div_jellyfin.dataset.avid = avID; div_jellyfin.classList.add("noJellyfin"); } }, ontimeout(data){ console.log("jellyfin访问超时") console.log(data) document.querySelector(".jellyfin")?.classList.add("errJellyfin") } }); } function getEmby(avID){ if(setting.jellyfinHost && setting.jellyfinApiKey){ if(debug){console.log("查询本地 Emby : getEmby");}; } else { if(debug){console.log("退出 Emby 函数, 其中host和apiKey: ", setting.jellyfinHost , setting.jellyfinApiKey)} return; } GM_xmlhttpRequest({ method: "GET", // url: // setting.jellyfinHost+"emby/Users/"+setting.jellyfinApiKey+"/Items?api_key="+setting.jellyfinApiKey+ // "&Recursive=true&IncludeItemTypes=Movie&SearchTerm="+avID, url: setting.jellyfinHost+"emby/Items?api_key="+setting.jellyfinApiKey+"&Recursive=true&IncludeItemTypes=Movie&SearchTerm="+avID, headers: { accept: "application/json", }, onload: function (r) { var data = JSON.parse(r.responseText); // console.log(data) var div_jellyfin = document.querySelector(".jellyfin"); if(!div_jellyfin){return}; if(data.Items[0]){ div_jellyfin.dataset.url = ` ${setting.jellyfinHost}web/index.html#!/item?id=${data.Items[0].Id}&serverId=${data.Items[0].ServerId} `; div_jellyfin.classList.add("yesJellyfin"); } else { div_jellyfin.dataset.url = setting.jellyfinHost + "web/index.html#!/list/list.html?type=search"; div_jellyfin.dataset.avid = avID; div_jellyfin.classList.add("noJellyfin"); } } }); } // 查看本地 jellyfin 演员 function getJellyfin_Actor(name,index){ if(debug){console.log("jellyfin/emby 演员查询: ", index, name);}; GM_xmlhttpRequest({ method: 'get', url: setting.jellyfinHost + "Persons?searchTerm=" + name, headers: { "Content-Type": "application/x-www-form-urlencoded", "X-Emby-Token":setting.jellyfinApiKey }, data: '', onload: function (r) { if(!r || r?.status != 200){return}; var data = JSON.parse(r.responseText); // TotalRecordCount 查询到的数量 if(data.TotalRecordCount){ var div_actor = document.querySelector(".sav-actors-"+ index) if(div_actor){ var div_jellyfin = document.createElement("avspan"); if(setting.emby){ var jellyfin_ico = '<svg role="img" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M469.333333 85.333333L256 298.666667l42.666667 42.666666-213.333334 213.333334 213.333334 213.333333 42.666666-42.666667 213.333334 213.333334 213.333333-213.333334-42.666667-42.666666 213.333334-213.333334-213.333334-213.333333-42.666666 42.666667-213.333334-213.333334m-42.666666 277.333334l256 149.333333-256 149.333333v-298.666666z" fill="#05b010" p-id="1934"></path></svg>' div_jellyfin.innerHTML = "<a class='actor-jellyfin' target='_blank' title='' href= '"+ setting.jellyfinHost + "web/index.html#!/item?id=" + data.Items[0].Id + "&serverId="+ data.Items[0].ServerId +"'>"+ jellyfin_ico + "</a>"; }else{ var jellyfin_ico = '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="30%" style="stop-color:#AA5CC3;stop-opacity:1" /><stop offset="100%" style="stop-color:#00A4DC;stop-opacity:1" /></linearGradient><path style="fill:url(#grad3)" d="M12 .002C8.826.002-1.398 18.537.16 21.666c1.56 3.129 22.14 3.094 23.682 0C25.384 18.573 15.177 0 12 0zm7.76 18.949c-1.008 2.028-14.493 2.05-15.514 0C3.224 16.9 9.92 4.755 12.003 4.755c2.081 0 8.77 12.166 7.759 14.196zM12 9.198c-1.054 0-4.446 6.15-3.93 7.189.518 1.04 7.348 1.027 7.86 0 .511-1.027-2.874-7.19-3.93-7.19z"/></svg>' div_jellyfin.innerHTML = "<a class='actor-jellyfin' target='_blank' title='' href= '"+ setting.jellyfinHost + "web/index.html#!/details?id=" + data.Items[0].Id + "&serverId="+ data.Items[0].ServerId +"'>"+ jellyfin_ico + "</a>"; } // 插入到演员dom的后面 var div_parent = div_actor.parentNode; if(div_parent.lastChild == div_actor){ div_parent.appendChild(div_jellyfin); }else{ div_parent.insertBefore(div_jellyfin,div_actor.nextSibling); } } }else{ if(debug){console.log("jellyfin 中没搜到相关演员: ",name)} } } }); } // 搜索本地 jellyf/emby 视频, 返回所有所有的 movie 分类视频的名称列表 function localVideo_search(){ // actor_search() // console.log("localVideo_search") let url; if(setting.emby){ url = setting.jellyfinHost+"emby/Items?Recursive=true&IsMovie=true&IsFolder=false&api_key=" + setting.jellyfinApiKey; }else{ url = setting.jellyfinHost + "Items?recursive=true&filters=IsNotFolder&includeItemTypes=Movie&api_key=" + setting.jellyfinApiKey; } GM_xmlhttpRequest({ method: "GET", url: url, headers: { accept: "application/json" }, onload: (r) => { // console.log(r) if(r.status != 200){ console.log("搜索本地jellyf视频有误, 返回结果: "); console.log(r); return; } var data = JSON.parse(r.responseText); // console.log(data); if(r.status == 200 && data.Items?.length>0){ localVideoList = data.Items; localVideo_addStyle(); } }, }); } function localVideo_comparison(avID){ let reg = new RegExp(avID,"i") return localVideoList.find(value=>{ return value.Name?.search(reg)>-1 }) } function actor_search(){ // const fetch = require('node-fetch'); // Jellyfin API端点和身份验证令牌 const baseUrl = setting.jellyfinHost + 'api/'; const apiKey = setting.jellyfinApiKey; // // 构建API请求 // const endpoint = baseUrl + 'Persons'; // const headers = { // 'X-Emby-Token': apiKey, // }; var url = setting.jellyfinHost + "api/Persons&api_key=" + setting.jellyfinApiKey; url = "http://192.168.31.6:8096/Persons?IsMovie=true&api_key=e4c35ab15f9347a0916fe049de870e61" GM_xmlhttpRequest({ method: "GET", url: url, headers: { accept: "application/json" }, onload: (r) => { // console.log(r) var data = JSON.parse(r.responseText); // console.log(data); if(r.status == 200 && data.Items?.length>0){ // localVideoList = data.Items; // localVideo_addStyle(); console.log(data) data.Items.forEach(actor=>{ console.log(actor.Name) }) } }, }); // 发起API请求 // fetch(endpoint, { headers }) // .then(response => { // if (response.ok) { // return response.json(); // } else { // throw new Error('Failed to fetch actors. Status code: ' + response.status); // } // }) // .then(actors => { // // 打印演员信息 // actors.forEach(actor => { // console.log(actor.Name); // }); // }) // .catch(error => { // console.error('Error:', error.message); // }); } // 对本地视频(jellyfin/emby)已有的番号添加额外样式 function localVideo_addStyle(){ let avdivs = document.querySelectorAll('.sav-id'); for(let i=0;i<avdivs.length;i++){ // 判断本地有没有相关视频 let localVideoExist = localVideo_comparison(avdivs[i].dataset.av); if(localVideoExist){ if(setting.LocalVideoSearchExtraButton){ let exDiv = document.createElement("savdiv"); let url; if(setting.emby){ exDiv.innerHTML = '<svg role="img" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" ><path d="M469.333333 85.333333L256 298.666667l42.666667 42.666666-213.333334 213.333334 213.333334 213.333333 42.666666-42.666667 213.333334 213.333334 213.333333-213.333334-42.666667-42.666666 213.333334-213.333334-213.333334-213.333333-42.666666 42.666667-213.333334-213.333334m-42.666666 277.333334l256 149.333333-256 149.333333v-298.666666z" fill="#05b010" p-id="1934"></path></svg>' url = ` ${setting.jellyfinHost}web/index.html#!/item?id=${localVideoExist.Id}&serverId=${localVideoExist.ServerId} ` }else{ exDiv.innerHTML = '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <linearGradient id="grad3" x1="0%" y1="0%" x2="100%" y2="100%"><stop offset="30%" style="stop-color:#AA5CC3;stop-opacity:1" /><stop offset="100%" style="stop-color:#00A4DC;stop-opacity:1" /></linearGradient><path style="fill:url(#grad3)" d="M12 .002C8.826.002-1.398 18.537.16 21.666c1.56 3.129 22.14 3.094 23.682 0C25.384 18.573 15.177 0 12 0zm7.76 18.949c-1.008 2.028-14.493 2.05-15.514 0C3.224 16.9 9.92 4.755 12.003 4.755c2.081 0 8.77 12.166 7.759 14.196zM12 9.198c-1.054 0-4.446 6.15-3.93 7.189.518 1.04 7.348 1.027 7.86 0 .511-1.027-2.874-7.19-3.93-7.19z"/></svg>' url = setting.jellyfinHost + "web/index.html#!/details?id=" + localVideoExist.Id;; } exDiv.classList.add("jellyfin_openPage"); exDiv.addEventListener("click",function(e){ GM_openInTab(url,{active: true, insert: true,setParent:true}); e.preventDefault(); return; }) appendChild_Afterend(exDiv,avdivs[i]); } // 番号上添加相关标识 avdivs[i].classList.remove("infoFirst","infoExistent","infoNonExistent"); avdivs[i].classList.add("infoLocalVideoExistent"); } avdivs[i].classList.add("infoLocalVideoSearched"); } } // 插入到给定元素的后面 function appendChild_Afterend(obj,oTarget){ if (oTarget.nextSibling) { oTarget.parentNode.insertBefore(obj, oTarget.nextSibling); } else { oTarget.parentNode.appendChild(obj); }; } // 调用qbit下载 function qBit(torrent){ if(debug){console.log("正在调用磁力下载, ",torrent);}; // 弹窗询问是否下载 let download_check = setting.qBitNoPopup ? setting.qBitNoPopup : window.confirm ("是否调用 qBittorrent 下载磁链: \n" + torrent); if (!download_check){ if(debug){console.log("取消qbit 下载",download_check, setting.qBitNoPopup)} return } var qbi_host = setting.qBitHost var download = setting.qBitDownload; GM_xmlhttpRequest({ method: 'POST', url: qbi_host + 'api/v2/torrents/add', headers: { "Content-Type": "application/x-www-form-urlencoded" }, timeout:1000, data:"urls=" + torrent + "&autoTMM=false&savepath=" + download + "&cookie=&rename=&category=&paused=false&contentLayout=Original&dlLimit=NaN&upLimit=NaN" , onload: function (response) { console.log("qBittorrent 返回消息: " ,response); if(response.statusText){ if(setting.qBitNoPopup && response.statusText.indexOf("OK")>-1){ return; } let confirm_r = window.confirm ("qBittorrent 返回消息: \n" + response.statusText + "\n 确定打开 qBit, 取消关闭弹窗"); if(confirm_r){ window.open(setting.qBitHost, "_blank") } } else { alert("网址可能存在问题, 网站返回消息: \n" + response.statusText); } }, ontimeout: function (response) { console.log(response) alert("调用 qBittorrent 出现超时 \n请检查是否已经打开相关软件"); }, onerror: function (response) { console.log(response) alert("调用 qBittorrent 发生错误"); }, }) } // 菜单 // 菜单编辑 function savBoxEdit(){ var editbox = document.createElement("div"); editbox.id = "sav-editCodeBox"; editbox.style.cssText = "position:fixed;" + "z-index:99999;" + "top:50%;left:50%;" + "transform:translate(-50%,-50%);" + "background:#ccc;" + "border-radius:4px;" + "padding:10px 20px;" ; var innerH = " "+ "<p>搜索词用 %s 代替 <br>格式是 JSON ,修改时注意中英文标点符号 尤其有无逗号 <br>点击“供测试使用”按钮后, 会增加额外选项, 能影响脚本功能 <br><u><a href='https://github.com/qxinGitHub/searchAV'>Github</a></u>上有具体使用说明, 也可以去<u><a href='https://greasyfork.org/zh-CN/scripts/423350/feedback'>greasyfork论坛求助</a></u> </p>" + "<textarea wrap='off' cols='66' rows='20' style='overflow:auto;border-radius:4px;'>" + JSON.stringify( GM_getValue("_setting"),false,4) + "</textarea>" + "<br>" + "<p>老司机共浏览了" + Object.keys(localInfo).length + "个番号!</p>" + "<button id='savDebug' >供测试使用</button> " + "<button id='savClearSetting' >清空设置</button> " + "<button id='savHistory' >清空浏览历史</button> " + "<button id='savEditBoxCloase' >关闭</button> " + "<button id='savEditBoxSave' >保存</button>" + ""; editbox.innerHTML = innerH; editbox.querySelector("#savDebug").addEventListener("click",savDebug) editbox.querySelector("#savClearSetting").addEventListener("click",clearSetting) editbox.querySelector("#savHistory").addEventListener("click",clearHistory) editbox.querySelector("#savEditBoxCloase").addEventListener("click",savBoxClose) editbox.querySelector("#savEditBoxSave").addEventListener("click",savBoxSave) document.body.appendChild(editbox); } // 菜单保存 function savBoxSave(){ var codevalue = savBoxGetValue(); if(codevalue){ GM_setValue("_setting",codevalue); setTimeout(function(){ window.location.reload(); },300); } } // 关闭菜单 function savBoxClose(){ var box = document.querySelector("#sav-editCodeBox"); if(box){ box.parentNode.removeChild(box); } } // 开启debug, 会加入额外的信息 function savDebug(){ // 如果是想自定义搜索列表和颜色, 去设置里点击“测试”,然后“保存”, 不要改动此处 var debug_setting = { "debug":false, // 会在番号上额外添加一些信息, 不建议开启 "selectLength":0, // 选中搜索的字符长度。超过该长度的会忽略掉, 设置0可以关闭划词搜索。 // 设置更大的数字,例如16,可以应对一些超长的番号。实际使用中颇多的问题。 "javbus":"https://www.javbus.com/", // 自定义javbus网站地址 "https://www.javsee.bid/" "javdb":"https://javdb.com/", // 自定义javdb网站地址 "https://javdb004.com/" "sehuatangURL":"https://www.sehuatang.net", // 自定义色花堂网址 "actorsSearchURL":"https://www.javbus.com/searchstar/%s", // 自定义演员搜索地址, 搜索词用 %s 代替 "addSearchButton":false, // 在番号后面添加一个图标, 鼠标滑过作用于图标, 而不是番号 "searchButtonIcon":"✈", // 番号后面的图标样式 "clickToMenu":false, // 鼠标点击番号才会出现菜单 "dontClearMenu": false, // 鼠标移出后,菜单不会消失(测试时找问题使用, 开启会影响脚本使用) "includeIDinLinks":true, // 番号本身是个链接的情况下是否识别 "dontImgBig": false, // 图片点击放大, 包括滚动放大 "dontGetInfo":false, // 获取番号的相关信息(从javbus获取), "getInfoFromJavDB":false, // 直接从 JavDB 获取信息, 不使用Javbus "dontGetInfoFc2":false, // 获取fc2的相关信息(从javmenu获取) "dontGetInfoWuma":false, // 获取无码番号的信息, 大量访问会导致javdb禁止你的ip访问一到两个星期。 "getInfoFailToJavDB":true, // 从javbus获取不到信息时, 会从javdb尝试获取。有被javDB封IP的风险 "dontMagnetDiscern":false, // 将磁链转为链接 "magnetCopy":false, // 磁链不转化链接,点击磁链复制到剪贴板 // "avLinkMagnet":false, // 链接是磁链的番号是否添加复制功能 "dontTransTitle":false, // 翻译标题 "dontTransTags":false, // 翻译标签 "dontGetVideo":false, // 关闭视频预览 "videoVolume":0.2, // 视频播放音量,取值0-1, 对fc2的预览视频无效 "fc2Thumbnail":false, // fc2 的预览图是否用缩略图, 用低画质换取快速加载图片 "infoReload": false, // 浏览过的番号将不会重复获取信息, 避免IP地址被网站拉黑。 "closeJavdbLimit":false, // 禁止在短时间内多次访问javdb。 设为 true 可以关闭限制, 容易封IP "closeLoadingAnimation":false, // 关闭信息加载时的动画 "close_Related_Page":false, // 关闭相关页面的按钮(第一个按钮) "addOtherButton":false, // 添加3个额外的按钮: 1,设置按钮; 2,番号按钮,点击复制; 3,关闭按钮 "sehuatang":false, // 添加色花堂的搜索按钮 "emby":false, // 将 Jellyfin 替换成 Emby, 如果使用 emby, 必须改为true "jellyfinHost":"http://localhost:8096/", // 本地的jellyfin/emby的地址 "jellyfinApiKey":"", // 外部程序需要密钥才能和jellyfin/emby通信。 “设置 - 控制台 - API密钥” 点击加号生成一个 "LocalVideoSearch":false, // 如果在本地有相关视频, 显示样式为 “infoLocalVideoStyle”, 该样式的优先级最高 "LocalVideoSearchExtraButton": false, // 如果在本地有相关视频, 会直接在番号后面显示跳转按钮 "qBitHost":"http://localhost:8080/", //本地 qbit 的地址 "qBitDownload":"", // 在qbit中才下载地址,注意双斜杠: D:\\_下载\\qBittorrent "qBitNoPopup":false, // qbit 弹窗询问是否调用qbit下载 "baiduAppid":"", // 百度翻译的 APP ID "baiduKey":"", // 百度翻译的 密钥 "linkStyle":{ // 没浏览的番号 "color":"green", // 颜色 名称:green 十六进制:#00FF00 RGB:rgb(0,255,0) "text-decoration":"underline green", //下划线 "font-weight":"normal", // 加粗: normal、bold、lighter "text-shadow":"rgb(177 177 177 / 70%) 1px 1px", // 字体阴影 }, "visitStyle":{ // 已经浏览过的番号 "color":"chocolate", // 颜色 "text-decoration":"underline dotted chocolate", // 下划线 "font-weight":"normal", // 加粗 "text-shadow":"rgb(177 177 177 / 65%) 1px 1px", // 字体阴影 }, "noExistStyle":{ // 已经浏览过, 但是没有获取到信息的番号 "color":"red", // 颜色 "text-decoration":"underline dotted red", // 下划线 }, "infoLocalVideoStyle":{ //本地视频(jellyfin/emby)已有的番号 "color":"#00ADB0", // 颜色 "text-decoration":"underline dotted #00ADB0", // 下划线 }, "list":[], // 普通番号的搜索列表, 建议直接将搜索加在 "list_all" "list_wuma":[], // 素人番号的搜索列表, 建议直接将搜索加在 "list_all" "list_all":[] // 它俩共同的搜索, 会同时加在上面两个列表的后面, 建议使用这个。 } Object.assign(debug_setting,savBoxGetValue()); document.querySelector("#sav-editCodeBox textarea").value = JSON.stringify(debug_setting,false,4) } // 返回设置选择的json格式 function savBoxGetValue(){ var codevalue = document.querySelector("#sav-editCodeBox textarea").value; if(codevalue.length ==0){ codevalue = "{}" } var return_value ; try{ return_value = JSON.parse(codevalue) }catch(err){ alert("保存失败,请按照下方提示修改后重新保存\n"+err); } return return_value; } // 清空设置 function clearSetting(){ GM_deleteValue("_setting"); GM_deleteValue("_setting2"); localInfo = {}; savBoxClose(); location.reload(); } // 清除浏览历史 function clearHistory(){ GM_setValue("avInfo2",{}); localInfo = {} savBoxClose() location.reload(); } GM_registerMenuCommand("自定义搜索", savBoxEdit) // 添加样式 function addStyle(){ var styleText = ""; var styleAVID = ""; if(setting.linkStyle){ styleAVID += ".infoFirst{" for(let key in setting.linkStyle){ styleAVID += key + ":" + setting.linkStyle[key] + ";" } styleAVID += "}" }else { styleAVID += ".infoFirst{text-decoration:underline green;}" } if(setting.visitStyle){ styleAVID += ".infoExistent{" for(let key in setting.visitStyle){ styleAVID += key + ":" + setting.visitStyle[key] + ";" } styleAVID += "}" }else { styleAVID += ".infoExistent{text-decoration:underline dotted #66ccff;}" } if(setting.noExistStyle){ styleAVID += ".infoNonExistent{" for(let key in setting.noExistStyle){ styleAVID += key + ":" + setting.noExistStyle[key] + ";" } styleAVID += "}" }else { styleAVID += ".infoNonExistent{text-decoration:underline dotted red;}" } if(setting.infoLocalVideoStyle){ styleAVID += ".infoLocalVideoExistent{" for(let key in setting.infoLocalVideoStyle){ styleAVID += key + ":" + setting.infoLocalVideoStyle[key] + ";" } styleAVID += "}" }else { styleAVID += ".infoLocalVideoExistent{text-decoration:underline dotted #598987;}" } styleText = ` .sav-menu{ font-family: Microsoft YaHei,sans-serif; position:fixed; display: block; text-align: left; color: #000; background:rgba(255,255,255,.8); backdrop-filter: blur(5px); border-radius: 4px; padding:6px 12px 10px 9px; /* margin-top: -2px; */ z-index: 99999; font-size: 14px; max-width: 600px; box-shadow: 4px 4px 12px #ccc, -1px -1px 5px #eee; border-top: 2px solid #fff; border-left: 2px solid #fff; transform:scale(1); transition:0.2s; transition-timing-function: ease-out; animation: savOpenAnim 0.15s; } .savCloseAnim{ animation: savCloseAnim 0.15s; } @keyframes savOpenAnim { 0% { transform:scale(0.5); background:rgba(255,255,255,.1); } 100% { transform:scale(1); background:rgba(255,255,255,.8); } } @keyframes savCloseAnim { 0% { opacity: 1; transform:scale(1); } 100% { opacity: 0; transform:scale(0.5); } } /* 链接相关 */ .savlink{ margin: 4px 4px 4px 4px; border-radius: 4px; padding: 3px 5px; background: #fff; display: inline-block; transition: 0.2s; transition-timing-function: ease-out; box-shadow: -2px -2px 4px rgb(240 240 240), 2px 2px 4px rgb(70 70 70 / 50%); cursor: pointer; user-select: none; } .savlink:not(.RPdisabled):hover{ background: aliceblue; box-shadow: -2px -2px 6px rgb(255 255 255 / 50%), 1px 1px 2px rgb(70 70 70 / 50%), inset -2px -2px 6px rgb(255 255 255 / 50%),inset 2px 2px 6px rgb(100 100 100 / 50%); } .sav-menu .savlink a{ color:#459df5; text-decoration:none; transition:0.4s; } .sav-menu .savlink:not(.RPdisabled):hover a { color: #039cff; text-shadow: 0 0 #7cfb80; } avdivsinfo a, avdivsinfo a:visited, avdivsinfo a:link{ color: #000; transition:0.2s; } avdivsinfo a:hover{ color: #850000; } /* 相关页面按钮 */ .relatedPage.RPdisabled{ cursor:default; } .relatedPage.RPdisabled a{ cursor:default; pointer-events:none; text-decoration:line-through; color:#333; } avdivsinfo{ text-indent: -2.5em; line-height: normal; } avdivsinfo avdiv{ display:block; margin-bottom: 5px; text-shadow: 0 0 #d9d9d9; transition: 0.2s; padding-left: 2.5em; } avdivsinfo .avInfoTags, avdivsinfo .avInfoSeries{ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } avdiverror{ display:block; margin-top: 10px; padding-left: 10px; } avdiverror avdiv{ display:block; margin-bottom: 5px; transition: 0.2s; } avdiv .avimg{ height: 400px; max-width: 100%; max-height: 500px; cursor: pointer; box-shadow: -2px -2px 4px rgb(230 230 230), 2px 2px 2px rgb(70 70 70 / 50%); border-top: 1px solid #fff; border-left: 1px solid #fff; border-radius: 4px; transform-origin: center 80%; transition:0.2s; transition-timing-function: ease-out; } /* .avimg-preview-button:hover + .avimg, avdiv .avimg:hover{ scale:1.01; box-shadow: -2px -2px 4px rgb(160 160 160), 4px 4px 4px rgb(70 70 70 / 60%); } */ avdiv .imageBig{ max-height: 600px; transform: scale(1.3); border-radius: 10px; border-top: 2px solid #fff; border-left: 2px solid #fff; box-shadow: -2px -2px 4px rgb(160 160 160), 4px 4px 4px rgb(70 70 70 / 60%); } avdiv .imageBig:hover{ box-shadow: -4px -4px 8px rgb(160 160 160), 6px 6px 8px rgb(70 70 70 / 60%); } savdiv.sav-id{ transition: 0.5s; } savdiv.sav-id, savmagnet { cursor: pointer; } .jellyfin_openPage svg{ cursor:pointer; width:1em; scale:0.9; vertical-align:text-bottom; } u:has(savdiv){ text-decoration: none; } .yesJellyfin{ color:#459df5 } .noJellyfin{ text-decoration:line-through; } .errJellyfin{ cursor:default; pointer-events:none; text-decoration:line-through; color:#333; } avspan svg { height: 14px; position: relative; top: 0.1em; opacity:0.8; transition:0.2s; display: inline-block; vertical-align: baseline; } avspan svg:hover { opacity:1; } avdiv.sav-menu .avimg.savImgError{ height: 400px; width: 600px; } /* 动画: 横线加载时的动画 */ @keyframes sav-loading-animation { from{ transform: translate(0, 0); } to{ transform: translate(50%, 0); } } .savLoadingContainer { display:block; overflow: hidden; width: 100%; transition:0.1s; height: 3px; margin-top: 5px; } .savLoading { display: block; font-size: 0; height: 100%; width: 200%; position: relative; transition:0.2s; animation: sav-loading-animation 3s linear infinite; } .savLoading svg { border: none; height: 100%; width: 50%; position: absolute; } .savLoading svg:last-child { left: -50%; } .stop1, .stop3{ stop-color:#fff0; } .stop2{ stop-color:#6dc4ed; transition: 1s; } .stop2.javbusloading{ stop-color:#71d99b; } .stop2.javdbloading{ stop-color:#cccc00; } .stop2.fc2loading{ stop-color:#F8A01C; } /* 预览视频 */ avdivimg{ position: relative; display: block; text-indent: initial; user-select: none; } .avimg-preview-button{ width: 40px; height: 40px; border-radius: 40px; background:#00e7ff00; opacity: 0.8; position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; z-index:1; transition:0.4s; animation: savOpenAnim2 0.15s; } @keyframes huerotate{ 0%{ filter:hue-rotate(0deg); } 100%{ filter:hue-rotate(360deg); } } .avimg-preview-button:hover{ opacity: 1; background:#00e7ff; } .avimg-preview-button:after { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M448 255c0-106-86-192-192-192S64 150 64 256s86 192 192 192 192-86 192-192z' fill='' fill-opacity='0.8' stroke='none'/%3E%3Cpath fill='white' d='M216.32 334.44l114.45-69.14a10.89 10.89 0 000-18.6l-114.45-69.14a10.78 10.78 0 00-16.32 9.31v138.26a10.78 10.78 0 0016.32 9.31z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: 50%; background-size: 48px 48px; content: ""; display: block; position: absolute; top: 0; bottom: 0; left: 0; right: 0; /* border: 2px solid; border-image:linear-gradient(45deg,gold,deeppink)1; */ } .savCloseAnim2, avdivimg:has(avdivVideo) .avimg-preview-button, avdivimg:has(.imageBig) .avimg-preview-button{ animation: savCloseAnim2 0.15s; animation-fill-mode: forwards; } avdivVideo{ position: absolute; top: 0; bottom: 0; left: 0; right: 0; animation: savOpenAnim2 0.15s; } avdivimg video{ width: 100%; height: 100%; object-fit: contain; background: #fff9; backdrop-filter: blur(5px); border-radius:4px; } .savVideoClose { position: absolute; right: 0; top: 0; padding: 7px 10px 7px 97%; border-radius: 4px; cursor: pointer; transition:0.4s; } iframe + .savVideoClose{ color:#fff; } .savVideoClose:hover { color:red; background: #fff8; } avdivvideo iframe{ width:100%; height:100%; border: none; } @keyframes savOpenAnim2 { 0% { opacity: 0; transform:scale(0); } 100% { opacity: 1; transform:scale(1); } } @keyframes savCloseAnim2 { 0% { opacity: 1; transform:scale(1); } 100% { opacity: 0; transform:scale(0); } } /* 对其他网站的一些更改 */ .fc2-embed-video-player.opt_logo .fc2-video-player .fc2-video-metadata{ display:none !important; } .fc2-video-player-logo{ display:none !important; } `; styleText += styleAVID; GM_addStyle(styleText); } })();