Greasy Fork

AIGC春联

A AIGC couplet

目前为 2024-01-26 提交的版本。查看 最新版本


// ==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
// ==/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 =
            '<svg t="1706247528897" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2446" width="200" height="200"><path d="M457.665918 982.912037L41.187933 566.334082c-29.891243-29.891243-29.891243-78.776921 0-108.468222L457.665918 41.387875c29.891243-29.891243 78.67695-29.891243 108.468222 0L982.712096 457.86586c29.891243 29.891243 29.891243 78.776921 0 108.468222L566.334082 983.012008c-29.891243 29.791272-78.776921 29.791272-108.668164-0.099971z m0 0" fill="#CA3A2A" p-id="2447"></path><path d="M512.049985 1024c-24.392854 0-48.885678-9.297276-67.48023-27.891829L28.09177 579.630186c-37.189105-37.189105-37.189105-97.671385 0-134.86049L444.569755 28.09177c37.189105-37.189105 97.671385-37.189105 134.86049 0l416.477985 416.477985c37.189105 37.189105 37.189105 97.671385 0 134.86049L579.430245 996.108171c-18.594552 18.594552-42.987406 27.891829-67.38026 27.891829z m0-986.510983c-14.895636 0-29.791272 5.698331-41.187933 16.995021L54.384067 470.962023c-22.693352 22.693352-22.693352 59.582544 0 82.175925L470.862052 969.715904c22.693352 22.693352 59.582544 22.693352 82.175925 0l416.477985-416.477985c22.693352-22.693352 22.693352-59.582544 0-82.175925L553.037977 54.484038c-11.29669-11.396661-26.192326-16.995021-40.987992-16.995021z m0 0" fill="#CA3A2A" p-id="2448"></path><path d="M864.346773 475.060822L549.039149 159.653227c-9.79713-9.8971-22.993264-15.295519-36.989164-15.295519s-27.092063 5.398418-36.989163 15.295519L159.553256 475.060822c-20.394025 20.394025-20.394025 53.684272 0 74.178268L475.060822 864.746656c10.097042 10.197013 23.693059 15.295519 36.989163 15.295519 13.396075 0 26.892121-5.098506 36.989164-15.295519l315.307624-315.707507c9.8971-9.79713 15.295519-22.993264 15.295519-36.989164s-5.398418-27.192034-15.295519-36.989163z m-12.996192 45.486674l-330.903056 330.903056c-4.398711 4.598653-12.096456 4.598653-16.695109 0l-331.003026-330.903056c-4.598653-4.498682-4.598653-12.096456 0-16.695109l331.003026-331.003026c2.999121-2.999121 6.498096-3.399004 8.39754-3.399005 1.899444 0 5.398418 0.399883 8.39754 3.399005l330.903056 331.003026c2.999121 2.999121 3.399004 6.498096 3.399004 8.39754-0.199941 1.799473-0.599824 5.298448-3.498975 8.297569z m0 0" fill="#F3DAB8" p-id="2449"></path><path d="M668.60412 596.425266H562.835107c-7.297862 0-13.9959-4.298741-16.995021-10.896808-2.999121-6.598067-1.899444-14.395782 2.899151-19.894171L670.203651 425.875232c6.798008-7.797716 18.494582-8.597481 26.292297-1.799473 7.797716 6.698038 8.597481 18.494582 1.899444 26.292297l-94.672264 108.968076h64.980963c10.197013 0 18.594552 8.39754 18.594552 18.594552 0.099971 10.197013-8.297569 18.494582-18.694523 18.494582z m-33.190276 51.584887l-28.09177-33.990042" fill="#FEC401" p-id="2450"></path><path d="M635.413844 666.604706c-5.298448 0-10.696866-2.299326-14.295812-6.698038l-27.991799-33.890071c-6.498096-7.897686-5.498389-19.69423 2.399297-26.192327s19.69423-5.498389 26.192326 2.399297l27.991799 33.890072c6.498096 7.897686 5.498389 19.69423-2.399297 26.192326-3.598946 2.899151-7.697745 4.298741-11.896514 4.298741z m-22.793323-135.060432c-10.197013 0-18.594552-8.39754-18.594552-18.594552V376.189788c0-10.197013 8.39754-18.594552 18.594552-18.594552 10.197013 0 18.594552 8.39754 18.594553 18.594552v136.759934c0 10.197013-8.39754 18.594552-18.594553 18.594552z m0 0" fill="#FEC401" p-id="2451"></path><path d="M582.829249 504.052328c-4.998536 0-9.997071-1.999414-13.695987-6.098213l-32.690423-35.589573c-6.99795-7.597774-6.398126-19.294347 1.199649-26.292298 7.597774-6.99795 19.294347-6.398126 26.292297 1.199649l32.690422 35.589573c6.99795 7.597774 6.398126 19.294347-1.199648 26.292298-3.598946 3.199063-8.197598 4.898565-12.59631 4.898564z m-94.772234 162.552378H351.896905c-10.197013 0-18.594552-8.39754-18.594552-18.594553 0-10.197013 8.39754-18.594552 18.594552-18.594552h136.16011c10.197013 0 18.594552 8.39754 18.594552 18.594552 0 10.197013-8.297569 18.594552-18.594552 18.594553z m-19.294348-48.485796h-97.571414c-12.196427 0-22.093527-9.8971-22.093528-22.093527V549.838914c0-12.196427 9.8971-22.093527 22.093528-22.093527h97.571414c12.196427 0 22.093527 9.8971 22.093527 22.093527v46.186469c0.099971 12.196427-9.8971 22.093527-22.093527 22.093527zM386.28683 580.829835h67.48023v-15.895343h-67.48023V580.829835z m84.175339-75.577858h-100.970419c-26.69218 0-48.485795-21.693644-48.485795-48.485795v-49.18559c0-26.69218 21.793615-48.485795 48.485795-48.485796h100.970419c26.69218 0 48.485795 21.793615 48.485795 48.485796V456.866152c0 26.69218-21.693644 48.385824-48.485795 48.385825zM369.591721 396.383872c-6.198184 0-11.29669 5.098506-11.29669 11.29669V456.866152c0 6.198184 5.098506 11.29669 11.29669 11.296691h100.970419c6.198184 0 11.29669-5.098506 11.29669-11.296691v-49.18559c0-6.198184-5.098506-11.29669-11.29669-11.29669h-100.970419z m0 0" fill="#FEC401" p-id="2452"></path><path d="M482.858538 450.767939H356.695499c-10.197013 0-18.594552-8.39754-18.594552-18.594552 0-10.197013 8.39754-18.594552 18.594552-18.594553H482.858538c10.197013 0 18.594552 8.39754 18.594552 18.594553 0 10.197013-8.39754 18.594552-18.594552 18.594552z m0 0" fill="#FEC401" p-id="2453"></path><path d="M419.677048 496.354584c-10.197013 0-18.594552-8.39754-18.594553-18.594553v-92.972762c0-10.197013 8.39754-18.594552 18.594553-18.594552 10.197013 0 18.594552 8.39754 18.594552 18.594552v92.972762c0 10.197013-8.197598 18.594552-18.594552 18.594553z m0 0" fill="#FEC401" p-id="2454"></path><path d="M512.049985 1024c-24.392854 0-48.885678-9.297276-67.48023-27.891829L28.09177 579.630186c-37.189105-37.189105-37.189105-97.671385 0-134.86049L444.569755 28.09177c37.189105-37.189105 97.671385-37.189105 134.86049 0l416.477985 416.477985c37.189105 37.189105 37.189105 97.671385 0 134.86049L579.430245 996.108171c-18.594552 18.594552-42.987406 27.891829-67.38026 27.891829z m0-986.510983c-14.895636 0-29.791272 5.698331-41.187933 16.995021L54.384067 470.962023c-22.693352 22.693352-22.693352 59.582544 0 82.175925L470.862052 969.715904c22.693352 22.693352 59.582544 22.693352 82.175925 0l416.477985-416.477985c22.693352-22.693352 22.693352-59.582544 0-82.175925L553.037977 54.484038c-11.29669-11.396661-26.192326-16.995021-40.987992-16.995021z m0 0" fill="#FF664D" p-id="2455"></path></svg>';
        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);
    });
})();