// ==UserScript== // @name 剧本杀活动通知生成器 // @namespace https://github.com/heiyexing // @version 2024-01-29 // @description 用于获取本周剧本杀活动信息并生成 Markdown 代码 // @author 炎熊 // @match https://yuque.antfin-inc.com/yuhmb7/pksdw8/** // @match https://yuque.antfin.com/yuhmb7/pksdw8/** // @icon https://www.google.com/s2/favicons?sz=64&domain=antfin-inc.com // @require https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.9/dayjs.min.js // @require https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.9/locale/zh-cn.min.js // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { "use strict"; console.log("脚本运行成功") function initStyle() { const style = document.createElement("style"); style.innerHTML = ` .murder-mystery-btn { position: fixed; bottom: 25px; right: 80px; width: 40px; height: 40px; background-color: #fff; border-radius: 50%; box-shadow: 0 0 10px rgba(0, 0, 0, .2); cursor: pointer; display: inline-flex; justify-content: center; align-items: center; z-index: 2; } .murder-mystery-btn img { width: 20px; } `; document.head.appendChild(style); return style; } function initBtn() { const btn = document.createElement("div"); btn.className = "murder-mystery-btn"; const logo = document.createElement("img"); logo.src = "https://mdn.alipayobjects.com/huamei_baaa7a/afts/img/A*f8MvQYdbHPoAAAAAAAAAAAAADqSCAQ/original"; btn.appendChild(logo); document.body.appendChild(btn); return btn; } function getTitleInfo(title) { const month = title.match(/\d+(?=\s*月)/)?.[0]; const date = title.match(/\d+(?=\s*日)/)?.[0]; const name = title.match(/(?<=《).*?(?=》)/)?.[0]; if (!month || !date || !name) { return null; } return { month: +month, date: +date, name, }; } function getRegExpStr(strList, regexp) { for (const str of strList) { const result = str.match(regexp); if (result) { return result[0].trim(); } } return ""; } function exeCommandCopyText(text) { try { const t = document.createElement("textarea"); t.nodeValue = text; t.value = text; document.body.appendChild(t); t.select(); document.execCommand("copy"); document.body.removeChild(t); return true; } catch (e) { console.log(e); return false; } } dayjs.locale(dayjs_locale_zh_cn); initStyle(); const btn = initBtn(); btn.addEventListener("click", async () => { if (!window.appData || !Array.isArray(window.appData?.book.toc)) { return; } const tocList = window.appData?.book.toc; const pathList = location.pathname.split("/"); if (pathList.length <= 0) { return; } const docUrl = pathList[pathList.length - 1]; const currentToc = tocList.find((item) => item.url === docUrl); if (!currentToc) { return; } const parentToc = tocList.find( (item) => item.uuid === currentToc.parent_uuid ); if (!parentToc) { return; } const targetTocList = tocList.filter( (item) => item.parent_uuid === parentToc.uuid ); const targetTimeRangeList = targetTocList .map((item) => { const titleInfo = getTitleInfo(item.title); if (!titleInfo) { return item; } return { ...item, ...titleInfo, dayjs: dayjs() .set("month", titleInfo.month - 1) .set("date", titleInfo.date), }; }) .filter((item) => { return item.dayjs.isSame(dayjs(), "week"); }) .sort((a, b) => a.dayjs - b.dayjs); const list = await Promise.all( targetTimeRangeList.map((item) => { return fetch( `${location.origin}/api/docs/${item.url}?book_id=${window.appData?.book.id}&include_contributors=true&include_like=true&include_hits=true&merge_dynamic_data=false` ) .then((res) => res.json()) .then((res) => { const content = res.data.content; const div = document.createElement("div"); div.style = "height: 0px; overflow: hidden;"; div.innerHTML = content; document.body.appendChild(div); const rowList = div.innerText.split("\n"); const tag = getRegExpStr(rowList, /(?<=类型\s*[::]\s*).+/)?.split(/[/||]/).join('/'); const level = getRegExpStr( rowList, /(?<=(难度|适合)\s*[::\s*]).+/ ); const dm = getRegExpStr(rowList, /(?<=(dm|DM)\s*[::]\s*).+/); let place = getRegExpStr(rowList, /(?<=(地点|场地)\s*[::]\s*).+/); if (/[Aa]\s?空间/.test(place)) { place = "A空间"; } if (/元空间/.test(place)) { place = "元空间"; } const persons = getRegExpStr(rowList, /(?<=(人数)\s*[::]\s*).+/) .split(/[,,\(\)()「」]/) .map((item) => item.replace(/(回复报名|注明男女|及人数)/, "")) .filter((item) => item.trim()) .join("·"); const week = getRegExpStr(rowList, /周[一二三四五六日]/) || `周${ ["日", "一", "二", "三", "四", "五", "六"][item.dayjs.day()] }`; const time = getRegExpStr(rowList, /\d{1,2}[::]\d{2}/); const [hour = "", minute = ""] = time.split(/[::]/); const duration = getRegExpStr( rowList, /(?<=(预计时.|时长)\s*[::]\s*).+/ ).replace(/(h|小时)/, "H"); return { ...item, tag, level, dm, week, hour, minute, place, persons, duration, }; }); }) ); const text = ` # 📢 剧本杀活动通知 --- ${list .map((item) => { return ` 🎬 《${item.name}》${item.tag}${item.level ? `/${item.level}` : ""} 🕙 ${item.month}.${item.date} ${item.week} ${item.hour}:${item.minute} 📍${ item.place } 💎 DM ${item.dm}【${item.persons}·${ item.duration }】[报名](https://yuque.antfin.com/yuhmb7/pksdw8/${item.url}?singleDoc#) --- `; }) .join("")} 🙋‍ [玩家报名须知](https://yuque.antfin.com/yuhmb7/pksdw8/igri3gwp127v3v32?singleDoc#),防跳车押金以报名页面为准! 🔜 加入钉群:14575023754,获取更多活动信息! `; exeCommandCopyText(text); alert("已将本周活动信息复制到剪贴板!"); }); })();