|
| 1 | +/** |
| 2 | + * @name Now Playing 推送 |
| 3 | + * @id splayer.now-playing-webhook |
| 4 | + * @version 1.0.0 |
| 5 | + * @author SPlayer |
| 6 | + * @type control |
| 7 | + * @apiLevel 2 |
| 8 | + * @description 切歌时把当前播放信息推送到 Webhook,支持 Discord 与通用 JSON。 |
| 9 | + * @homepage https://github.com/SPlayer-Dev/plugins |
| 10 | + * @updateUrl https://raw.githubusercontent.com/SPlayer-Dev/plugins/main/plugins/splayer.now-playing-webhook.js |
| 11 | + * @changelog 首个版本:切歌推送,支持 Discord / 通用 JSON、自定义模板。 |
| 12 | + */ |
| 13 | + |
| 14 | +splayer.register({ |
| 15 | + events: ["trackChange"], |
| 16 | + settings: [ |
| 17 | + { |
| 18 | + key: "webhook", |
| 19 | + type: "text", |
| 20 | + label: "Webhook 地址", |
| 21 | + placeholder: "https://discord.com/api/webhooks/...", |
| 22 | + default: "", |
| 23 | + }, |
| 24 | + { |
| 25 | + key: "format", |
| 26 | + type: "select", |
| 27 | + label: "推送格式", |
| 28 | + default: "discord", |
| 29 | + options: [ |
| 30 | + { label: "Discord Webhook", value: "discord" }, |
| 31 | + { label: "通用 JSON", value: "json" }, |
| 32 | + ], |
| 33 | + }, |
| 34 | + { |
| 35 | + key: "template", |
| 36 | + type: "text", |
| 37 | + label: "消息模板", |
| 38 | + description: "占位符:{title} {artists} {album}", |
| 39 | + default: "🎵 正在收听:{title} - {artists}", |
| 40 | + }, |
| 41 | + ], |
| 42 | +}); |
| 43 | + |
| 44 | +/** 用 track 字段填充模板占位符 */ |
| 45 | +const render = (tpl, track) => |
| 46 | + String(tpl || "").replace(/\{(title|artists|album)\}/g, (_, key) => String(track[key] || "")); |
| 47 | + |
| 48 | +/** 本地封面是 cover:// 协议,外部服务取不到,只放行 http(s) */ |
| 49 | +const httpCover = (cover) => |
| 50 | + typeof cover === "string" && /^https?:\/\//.test(cover) ? cover : ""; |
| 51 | + |
| 52 | +let lastKey = ""; |
| 53 | + |
| 54 | +splayer.player.on("trackChange", async ({ track }) => { |
| 55 | + if (!track) { |
| 56 | + lastKey = ""; |
| 57 | + return; |
| 58 | + } |
| 59 | + |
| 60 | + const webhook = String(splayer.getSetting("webhook") || "").trim(); |
| 61 | + if (!webhook) return; |
| 62 | + |
| 63 | + // 去重:同一首歌只推一次(启用补发的快照、重复事件都被过滤) |
| 64 | + const key = track.title + "|" + track.artists; |
| 65 | + if (key === lastKey) return; |
| 66 | + lastKey = key; |
| 67 | + |
| 68 | + const text = render(splayer.getSetting("template"), track); |
| 69 | + const cover = httpCover(track.cover); |
| 70 | + const format = splayer.getSetting("format") || "discord"; |
| 71 | + |
| 72 | + let body; |
| 73 | + if (format === "discord") { |
| 74 | + const embed = { title: track.title || "", description: track.artists || "" }; |
| 75 | + if (track.album) embed.footer = { text: track.album }; |
| 76 | + if (cover) embed.thumbnail = { url: cover }; |
| 77 | + body = { content: text, embeds: [embed] }; |
| 78 | + } else { |
| 79 | + body = { |
| 80 | + text, |
| 81 | + title: track.title || "", |
| 82 | + artists: track.artists || "", |
| 83 | + album: track.album || "", |
| 84 | + cover, |
| 85 | + duration: track.duration || 0, |
| 86 | + }; |
| 87 | + } |
| 88 | + |
| 89 | + try { |
| 90 | + await splayer.request(webhook, { |
| 91 | + method: "POST", |
| 92 | + headers: { "Content-Type": "application/json" }, |
| 93 | + body: JSON.stringify(body), |
| 94 | + }); |
| 95 | + splayer.log.info("Now Playing 已推送:" + track.title); |
| 96 | + } catch (err) { |
| 97 | + splayer.log.warn("Now Playing 推送失败:" + (err && err.message)); |
| 98 | + } |
| 99 | +}); |
0 commit comments