From ef265331278482ea31e4127250b27db6e91e42f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=87=E8=B6=A3=E4=BF=9D=E7=BD=97?= Date: Sun, 21 Apr 2024 23:34:23 +0800 Subject: [PATCH] Insert SyncButton on bilibili bangumi detail page to update progress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 插入一个手动同步的按钮,以提交追番进度到服务器 --- background/messages/bili.ts | 16 +++++++ components/biz/toy/index.tsx | 6 +-- contents/biliProgress.tsx | 90 ++++++++++++++++++++++++++++++++++++ contents/injectBili.ts | 37 ++++++++++++--- contents/read.ts | 2 - types/pageMessage.d.ts | 16 +++++++ utils/pageMessage.ts | 46 ++++++++++++++++++ 7 files changed, 199 insertions(+), 14 deletions(-) create mode 100644 contents/biliProgress.tsx create mode 100644 types/pageMessage.d.ts create mode 100644 utils/pageMessage.ts diff --git a/background/messages/bili.ts b/background/messages/bili.ts index 4e4034d..5f235d6 100644 --- a/background/messages/bili.ts +++ b/background/messages/bili.ts @@ -3,6 +3,7 @@ import type { PlasmoMessaging } from "@plasmohq/messaging"; const handler: PlasmoMessaging.MessageHandler = async (req, res) => { const { token, siteUrl } = await chrome.storage.local.get(["token", "siteUrl"]); + // 添加手办 if (req.body.action === "submitAddForm") { const { values } = req.body; @@ -32,6 +33,21 @@ const handler: PlasmoMessaging.MessageHandler = async (req, res) => { res.send(addReq); } + + // 更新追番进度 + if (req.body.action === "updateBangumiProgress") { + const { values } = req.body; + + const updateRequest = await fetch(`${siteUrl}/api/bangumi/update`, { + method: "POST", + body: JSON.stringify(values), + headers: { + "paul-token-code": token, + }, + }).then((res) => res.json()); + + res.send(updateRequest); + } } export default handler; diff --git a/components/biz/toy/index.tsx b/components/biz/toy/index.tsx index 244cc99..5d83d96 100644 --- a/components/biz/toy/index.tsx +++ b/components/biz/toy/index.tsx @@ -24,11 +24,7 @@ const getInfo = async () => { [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true }); if (tab && !tab.url.includes("chrome")) { - const a = await chrome.tabs.sendMessage(tab.id, { type: 'toolbox:getBiliToy' }); - - console.log('get toy:', a); - - return a; + return await chrome.tabs.sendMessage(tab.id, { type: 'toolbox:getBiliToy' }); } } diff --git a/contents/biliProgress.tsx b/contents/biliProgress.tsx new file mode 100644 index 0000000..3eb56f5 --- /dev/null +++ b/contents/biliProgress.tsx @@ -0,0 +1,90 @@ +import { useState } from "react"; +import type { PlasmoCSConfig, PlasmoGetInlineAnchor } from "plasmo"; +import { sendToBackground } from "@plasmohq/messaging"; +import { postPageMessage, waitPageMessage } from "~utils/pageMessage"; + +export const config: PlasmoCSConfig = { + matches: ["https://www.bilibili.com/bangumi/media/*"], +}; + +export const getInlineAnchor: PlasmoGetInlineAnchor = () => { + return document.querySelector(".bangumi-btn"); +} + +// Use this to optimize unmount lookups +// export const getShadowHostId = () => "plasmo-inline-example-unique-id" + +const SyncButton = () => { + const [status, setStatus] = useState(0); + + const onClick = () => { + postPageMessage({ type: "toolbox::getBiliProgress" }); + + waitPageMessage("toolbox::sendBiliProgress").then((res) => { + if (res.type !== "toolbox::sendBiliProgress") { + return; + } + + if (!res.value) { + setStatus(3); + return; + } + + console.log("Toolbox: 获得追番信息", res.value); + + sendToBackground({ + name: "bili", + body: { + action: "updateBangumiProgress", + values: res.value, + }, + }).then((res) => { + if (res.status === "Success") { + setStatus(1); + } + else { + setStatus(2); + } + }).catch((e) => { + if (e instanceof Error) { + setStatus(2); + } + }); + }); + } + + const text = (() => { + if (status === 0) { + return "同步追番进度"; + } + else if (status === 1) { + return "✔️ 同步成功"; + } + else if (status === 2) { + return "❌ 同步失败"; + } + else if (status === 3) { + return "❌ 没有追过此番"; + } + })(); + + return ( + + ); +} + +export default SyncButton; diff --git a/contents/injectBili.ts b/contents/injectBili.ts index 0918425..60fa6c6 100644 --- a/contents/injectBili.ts +++ b/contents/injectBili.ts @@ -1,4 +1,5 @@ import type { PlasmoCSConfig } from "plasmo"; +import { postPageMessage, receivePageMessage } from "~utils/pageMessage"; export const config: PlasmoCSConfig = { run_at: "document_start", @@ -6,8 +7,8 @@ export const config: PlasmoCSConfig = { world: "MAIN", }; -console.log("尝试获取当前追番进度"); - +// 番剧 ID +let seasonId; // 所有剧集(是个数组) // { @@ -43,6 +44,9 @@ let progress; // 进度(对应 section 接口里面所有剧集数组的索引) let progressIndex; +// 给接口使用的结果 +let result; + const open = XMLHttpRequest.prototype.open; const send = XMLHttpRequest.prototype.send; @@ -66,7 +70,9 @@ Object.defineProperty(XMLHttpRequest.prototype, "send", { sections = JSON.parse(this.response).result.main_section.episodes; } else if (this._paul_url.includes("season/user/status")) { - progress = JSON.parse(this.response).result.progress; + seasonId = new URL(this._paul_url).searchParams.get("season_id"); + + progress = JSON.parse(this.response).result.progress || { last_ep_id: -1 }; } }) } @@ -78,12 +84,29 @@ Object.defineProperty(XMLHttpRequest.prototype, "send", { const checkDataIsHandled = window.setInterval(() => { if (sections && progress) { - progressIndex = sections.findIndex( - (item) => item.id === progress.last_ep_id - ); + if (progress.last_ep_id !== -1) { + progressIndex = sections.findIndex( + (item) => item.id === progress.last_ep_id + ); - console.log("播放进度获取完成", progressIndex); + console.log("Toolbox: 追番进度获取完成", progressIndex); + + result = { + id: seasonId, + seem: progressIndex, + name: document.querySelector(".media-info-title-t").innerText, + }; + } else { + console.log("Toolbox: 追番进度获取失败,可能从未观看"); + } window.clearInterval(checkDataIsHandled); } }, 1000); + +receivePageMessage(() => { + postPageMessage({ + type: "toolbox::sendBiliProgress", + value: result, + }); +}, "toolbox::getBiliProgress"); diff --git a/contents/read.ts b/contents/read.ts index ff76850..171a96f 100644 --- a/contents/read.ts +++ b/contents/read.ts @@ -123,8 +123,6 @@ const getTags = () => { } chrome.runtime.onMessage.addListener((req, sender, send) => { - console.log(req); - if (req.type === "toolbox:getInfo") { send({ title: getTitle(), diff --git a/types/pageMessage.d.ts b/types/pageMessage.d.ts new file mode 100644 index 0000000..fbac349 --- /dev/null +++ b/types/pageMessage.d.ts @@ -0,0 +1,16 @@ +declare namespace PageMessage { + type Messages = GetBiliProgressMsg | SendBiliProgressMsg; + + interface GetBiliProgressMsg { + type: "toolbox::getBiliProgress", + } + + interface SendBiliProgressMsg { + type: "toolbox::sendBiliProgress", + value: { + id: number; + name: string; + seem: number; + }, + } +} diff --git a/utils/pageMessage.ts b/utils/pageMessage.ts new file mode 100644 index 0000000..af11b83 --- /dev/null +++ b/utils/pageMessage.ts @@ -0,0 +1,46 @@ +// 发送一条消息(二次封装类型) +export const postPageMessage = (data: PageMessage.Messages) => { + return window.postMessage(data); +}; + +// 接收一条消息 +export const receivePageMessage = ( + fn: (data: PageMessage.Messages) => void, + eventName?: PageMessage.Messages["type"] +) => { + const eventFn = (ev: MessageEvent) => { + if (!ev.data) { + return; + } + + if (eventName && ev.data.type === eventName) { + fn(ev.data); + } else if (!eventName && ev.data.type?.includes("toolbox::")) { + fn(ev.data); + } + }; + + window.addEventListener("message", eventFn); + + return () => { + window.removeEventListener("message", eventFn); + }; +}; + +// 等待一条消息的推送 +export const waitPageMessage = (eventName: PageMessage.Messages["type"]) => { + return new Promise((resolve) => { + const eventFn = (ev: MessageEvent) => { + if (!ev.data) { + return; + } + + if (eventName && ev.data.type === eventName) { + window.removeEventListener("message", eventFn); + resolve(ev.data); + } + }; + + window.addEventListener("message", eventFn); + }); +};