// ==UserScript== // @license MIT // @name AIGC春联 // @namespace http://tampermonkey.net/ // @version 2024-01-26 // @description A AIGC couplet // @author Sincenir // @match *://*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=undefined. // @grant GM_addStyle // @require https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js // @downloadURL none // ==/UserScript== (function() { 'use strict'; GM_addStyle(` @keyframes couplet-top { 0% { width: 0%; padding: 16px 0px; } 100% { width: 186px; padding: 16px 32px; } } @keyframes couplet { 0% { height: 0px; padding: 0px 24px; } 100% { height: 294px; padding: 32px 24px; } } @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes hide { 0% { opacity: 1; } 30% { opacity: 0; } 100% { opacity: 0; } } .couplet-container { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; font-family: "楷体", "宋体", "Microsoft YaHei", sans-serif; font-size: 32px; font-weight: 700; color: #fec401; z-index: 1000000000; } .top { position: absolute; top: 5%; left: 50%; transform: translateX(-50%); width: 200px; height: auto; padding: 16px 24px; background-color: #ca3a2a; text-align: center; overflow: hidden; white-space: nowrap; animation: couplet-top 1s ease-in-out; box-shadow: 0 0 0 6px #ff664d; border-radius: 8px; } .top::before { content: ""; position: absolute; top: 10px; left: 16px; right: 16px; bottom: 10px; border: 4px solid #f3dab8; border-radius: 8px; } .couplet-all { position: absolute; top: 50%; transform: translateY(-50%); width: auto; height: 300px; padding: 32px 24px; background-color: #ca3a2a; writing-mode: vertical-rl; text-align: center; overflow: hidden; white-space: nowrap; animation: couplet 1s ease-in-out; box-shadow: 0 0 0 6px #ff664d; border-radius: 8px; } .couplet-all::before { content: ""; position: absolute; top: 16px; left: 10px; right: 10px; bottom: 16px; border: 4px solid #f3dab8; border-radius: 8px; } .couplet-up { right: 5%; } .couplet-down { left: 5%; } .couplet-fu { width: 100%; height: 100%; display: flex; justify-content: center; align-items: center; animation: spin 1s ease; } .hide { animation: hide 3s ease-in-out; }`) const showTime = 10000; const getWebsocketUrl = () => { var apiKey = "fefa35b37578cc17d1b59f4f26a3e0c0"; var apiSecret = "OTdhMTY0MjdjZGY1MjlmZDEyY2U4NjM2"; var url = "wss://spark-api.xf-yun.com/v3.1/chat"; var host = location.host; var date = new Date().toGMTString(); var algorithm = "hmac-sha256"; var headers = "host date request-line"; var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v3.1/chat HTTP/1.1`; var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret); var signature = CryptoJS.enc.Base64.stringify(signatureSha); var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`; var authorization = btoa(authorizationOrigin); url = `${url}?authorization=${authorization}&date=${date}&host=${host}`; return url; }; const send = async () => { return new Promise((resolve, reject) => { const url = getWebsocketUrl(); const instance = new WebSocket(url); instance.onopen = async () => { const prompt = "你是一个春联专家。我希望你给我一个春联,春联分为上下联和横批。请给我一个春联。要求:上下联字数为 7;主题为 龙年;横批中不要出现龙;上联、下联、横批之间用逗号隔开;不要换行;对联中间不要出现标点符号;"; const params = { header: { app_id: "69ae0231", uid: "jayliang", }, parameter: { chat: { domain: "generalv3", temperature: 0.5, max_tokens: 1024, }, }, payload: { message: { text: [{ role: "user", content: prompt }], }, }, }; instance.send(JSON.stringify(params)); }; let str = ""; instance.onmessage = (msg) => { const data = JSON.parse(msg.data); const status = data.payload.choices.status; const content = data.payload.choices.text[0].content; str = str + content; if (status === 2) { resolve(str.split(",").map((s) => s.slice(3, -1))); } }; setTimeout(() => { reject(); }, 5000); }); }; function createCoupletContainer() { const container = document.createElement("div"); container.className = "couplet-container"; return container; } function createTop(str) { const topEl = document.createElement("div"); topEl.innerHTML = str; topEl.className = "top"; return topEl; } function createUp(str) { const upEl = document.createElement("div"); upEl.className = "couplet-all couplet-up"; upEl.innerHTML = str; return upEl; } function createDown(str) { const down = document.createElement("div"); down.className = "couplet-all couplet-down"; down.innerHTML = str; return down; } function createFu() { const fu = document.createElement("div"); fu.className = "couplet-fu"; fu.innerHTML = ''; return fu; } const coupletContainer = createCoupletContainer(); send() .then((r) => { console.log(r) const top = createTop(r[2]); const up = createUp(r[0]); const down = createDown(r[1]); const fu = createFu(); coupletContainer.append(top); coupletContainer.append(up); coupletContainer.append(down); coupletContainer.append(fu); document.body.append(coupletContainer); }) .catch((r) => { const top = createTop("龍行龘龘"); const up = createUp("鯤鵬展翅華夏騰飛"); const down = createDown("龍鳳呈祥陽春錦繡"); const fu = createFu(); coupletContainer.append(top); coupletContainer.append(up); coupletContainer.append(down); coupletContainer.append(fu); document.body.append(coupletContainer); }).finally(() => { setTimeout(() => { document.querySelector(".couplet-container").className = "couplet-container hide"; setTimeout(() => { document.querySelector(".couplet-container").remove(); }, 1000); }, showTime); }); document.addEventListener("keydown", (e) => { if (e.key !== "Escape") return; document.querySelector(".couplet-container").className = "couplet-container hide"; setTimeout(() => { document.querySelector(".couplet-container").remove(); }, 1000); }); })();