Get Twitch Emotes

整合twitch表情

当前为 2024-09-23 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Get Twitch Emotes
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  整合twitch表情
// @author       Lee-7723
// @match        https://www.twitch.tv/*
// @icon         https://static.twitchcdn.net/assets/favicon-16-52e571ffea063af7a7f4.png
// @grant        none

// ==/UserScript==

'use strict';

function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

var body = document.getElementsByTagName('body')[0];
var emote_dict = new Object();
var old_href = document.location.href;
// var emote_btn;
// var all_emotes = new Array();
// var emotes;

let css = document.createElement('style');
css.innerHTML = `
#emote_url_box {
    position: absolute;
    top: 5rem; left: 25%;
    padding: 10px;
    z-index: 9999;
    height: 70%;
    width: 50%;
    min-height: 30rem;
    min-width: 50rem;
    resize: both;
    overflow: scroll;
    background-color: var(--color-background-alt);
    border-radius: 10px;
    border: 1.6px solid var(--color-background-pill);
    box-shadow: 4px 4px 10px #000a;
}
#emote_url_text {
    height: calc(100% - 8.5rem); width: 100%;
    resize: none;
    padding: 12px;
    background-color: var(--color-background-input);
    color: var(--color-text-input);
    overflow: scroll;
    display: flex;
}
#emote_url_box > p:last-of-type {
    margin-top: 0.5rem;
    position: relative;
}
#emote_tool_header {
    display: flex;
    justify-content: space-between;
    margin-bottom: 0.5rem;
    font-weight: bold;
}
#emote_url_close_btn, #emote_url_preview_btn, #emote_download_json_btn {
    position: relative;
    right: 8px;
    bottom: 0rem;
    border-radius: 6px;
    margin: 0 0.5rem;
    padding: 1rem;
    float: right;
}
#emote_url_preview {
    height: calc(100% - 8.5rem); width: 100%;
    resize: none;
    padding: 12px;
    background-color: var(--color-background-input);
    color: var(--color-text-input);
    border: 1px solid rgb(118, 118, 118);
    border-radius: 2px;
    overflow-y: scroll;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}
.emote_preview {
    margin: 5px 5px 1px;
    border: 2px solid #FFF;
    border-radius: 4px;
    width: 112px; height: 112px;">
    <p style="text-align: center; margin-bottom: 3px
}

`;
body.appendChild(css)

async function get_emote_picker_button() {//监视获取聊天区的表情按钮
    'use strict';
    let emote_btn;
    for (var i = 0; !emote_btn; i) {
        await sleep(1000);
        emote_btn = document.querySelectorAll('button[data-a-target="emote-picker-button"]')[0];
        //console.log(emote_btn)
    }
    return emote_btn;
}


get_emote_after_button()
async function get_emote_after_button() {//加载出表情按钮之后
    let emote_btn = await get_emote_picker_button();
    // console.log(emote_btn);
    emote_btn.onclick = function () { output() }//给聊天区的表情按钮添加功能,指向output()
}


async function get_emotes() {//获取表情名img_alt,及表情链接img_srcset
    let emotes_grid;
    while (!emotes_grid) {
        console.log('fetching emotes')
        await sleep(1000);
        var emote_grid_header = document.getElementsByClassName('emote-grid-section__header-title');
        if (emote_grid_header.length == 1) emotes_grid = emote_grid_header[0].parentElement;
        else emotes_grid = emote_grid_header[1].parentElement;
    };

    let emote_imgs = emotes_grid.getElementsByTagName("img");
    let emote_dict = new Object();
    for (let j of emote_imgs) {
        emote_dict[j.alt] = j.src.replace('1.0', '3.0');
    }
    console.log(emote_dict);
    return emote_dict
}


async function output() {
    emote_dict = await get_emotes();//等待获取表情完成
    let emote_json = JSON.stringify(emote_dict);
    var button_class_name = document.querySelectorAll('.chat-input__buttons-container > div:last-of-type button')[1].className;
    let emote_grid_header = document.querySelectorAll('.emote-grid-section__header-title')
    if (emote_grid_header.length == 1) emote_grid_header = emote_grid_header[0];//未登录状态表情区只有一个分类
    else emote_grid_header = emote_grid_header[1];//登录状态选择表情区第二个分类
    console.log(emote_grid_header)



    let log_button = document.createElement('div');
    log_button.className = "Layout-sc-nxg1ff-0 jreOmo";
    log_button.id = 'emote_url_pop_box';
    log_button.innerHTML = `<div class="Layout-sc-nxg1ff-0 emWtQg">
    <div style="display: inherit;">
        <button id='emote_url_pop' class="${emote_grid_header.lastChild.getElementsByTagName('button')[0].className}">
            <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="currentcolor">
            <path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 9h-4V3H9v6H5l7 7 7-7zm-8 2V5h2v6h1.17L12 13.17 9.83 11H11zm-6 7h14v2H5z"/></svg>
        </button>
    </div>
    </div>`;
    if (!document.querySelector('#emote_url_pop')) emote_grid_header.insertBefore(log_button, emote_grid_header.children[1]);
    document.getElementById('emote_url_pop').onclick = () => {
        body.append(output_box);
    };


    var output_box = document.createElement("div")
    output_box.id = "emote_url_box";

    var output_text = document.createElement("textarea")
    output_text.id = "emote_url_text";

    var output_author = document.createElement("p")
    output_author.innerHTML = `script by Lee-7723`;

    var output_close_btn = document.createElement("button")
    output_close_btn.className = button_class_name;
    output_close_btn.id = "emote_url_close_btn";
    output_close_btn.onclick = function () { close_emote_box() };
    output_close_btn.innerHTML = '关闭';

    var preview_btn = document.createElement("button")
    preview_btn.className = button_class_name;
    preview_btn.id = "emote_url_preview_btn";
    preview_btn.onclick = function () { preview_emote_box() };
    preview_btn.innerHTML = '预览';

    var download_json_btn = document.createElement("a")
    download_json_btn.className = button_class_name;
    download_json_btn.id = "emote_download_json_btn";
    download_json_btn.href = `data:text/json;charset=utf-8,${encodeURIComponent(JSON.stringify(emote_dict))}`;
    download_json_btn.download = 'emotes.json';
    download_json_btn.innerHTML = '下载json';

    var usage = document.createElement("div");
    usage.id = 'emote_tool_header';
    usage.innerHTML = `
    <p>下载emote.json,将文件放在下载器相同路径下</p>
    <div id="drag_to_move" style="width: 2rem; cursor: move"><svg class="icon" style="width: 100%;height: 100%;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="944"><path d="M1013.333333 486.4l-153.6-153.6c-10.666667-10.666667-27.733333-2.133333-27.733333 10.666667v132.266666H544V189.866667h132.266667c14.933333 0 21.333333-17.066667 10.666666-27.733334L533.333333 8.533333c-12.8-12.8-32-12.8-44.8 0l-153.6 153.6c-10.666667 10.666667-2.133333 27.733333 10.666667 27.733334h132.266667v285.866666L192 477.866667v-132.266667c0-14.933333-17.066667-21.333333-27.733333-10.666667L10.666667 488.533333c-12.8 12.8-12.8 32 0 44.8l153.6 153.6c10.666667 10.666667 27.733333 2.133333 27.733333-10.666666v-132.266667h285.866667v285.866667h-132.266667c-14.933333 0-21.333333 17.066667-10.666667 27.733333l153.6 153.6c12.8 12.8 32 12.8 44.8 0l153.6-153.6c10.666667-10.666667 2.133333-27.733333-10.666666-27.733333h-132.266667V544H832v132.266667c0 14.933333 17.066667 21.333333 27.733333 10.666666l153.6-153.6c10.666667-12.8 10.666667-34.133333 0-46.933333z" fill="currentColor" p-id="945"></path></svg></div>
    `;

    output_text.value = emote_json;
    output_box.append(usage, output_text, output_author, output_close_btn, preview_btn, download_json_btn);
    dragElement(output_box, output_box.querySelector('#drag_to_move'));
}

function close_emote_box() {
    document.getElementById('emote_url_box').remove();
    document.getElementById('emote_url_pop_box').remove();
};

function preview_emote_box() {
    document.getElementById('emote_url_text').style.display = 'none';
    var preview_box = document.createElement("div");
    preview_box.id = "emote_url_preview";

    for (let j in emote_dict) {
        var pics = document.createElement("a");
        var pic_img = `<img src=${emote_dict[j]} alt=${j} class='emote_preview'>${j}</p>`;
        pics.innerHTML = pic_img;
        pics.href = emote_dict[j];
        pics.target = 'view emote';
        pics.download = j;
        pics.style.cssText = 'width: 122px; overflow: hidden;';
        preview_box.appendChild(pics);
    };

    document.getElementById('emote_url_box').insertBefore(preview_box, document.getElementById('emote_url_box').getElementsByTagName('p')[1]);
    document.getElementById("emote_url_preview_btn").innerHTML = '返回';
    document.querySelector("#emote_tool_header > p").innerHTML = '下列表情点击可跳转,可以手动保存';
    document.getElementById("emote_url_preview_btn").onclick = function () { return_emote_url_box() };
};

function return_emote_url_box() {
    document.getElementById('emote_url_text').style.display = 'flex';
    document.getElementById('emote_url_preview').style.display = 'none';
    document.getElementById("emote_url_preview_btn").innerHTML = '预览';
    document.querySelector("#emote_tool_header > p").innerHTML = '下载emote.json,将文件放在下载器相同路径下';
    document.getElementById("emote_url_preview_btn").onclick = function () { return_emote_preview_box() };
};

function return_emote_preview_box() {
    document.getElementById('emote_url_text').style.display = 'none';
    document.getElementById('emote_url_preview').style.display = 'flex';
    document.getElementById("emote_url_preview_btn").innerHTML = '返回';
    document.querySelector("#emote_tool_header > p").innerHTML = '下列表情点击可跳转,可以手动保存';
    document.getElementById("emote_url_preview_btn").onclick = function () { return_emote_url_box() };
};

window.onload = () => {
    var observer = new MutationObserver(
        function (mutation) {
            if (old_href != document.location.href) {
                old_href = document.location.href;
                get_emote_after_button();
            }
        }
    );
    observer.observe(body, { childList: true, subtree: true });
};

function dragElement(elmnt, mvelmnt) {
    var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
    mvelmnt.onmousedown = dragMouseDown;

    function dragMouseDown(e) {
      e = e || window.event;
      e.preventDefault();
      // get the mouse cursor position at startup:
      pos3 = e.clientX;
      pos4 = e.clientY;
      document.onmouseup = closeDragElement;
      // call a function whenever the cursor moves:
      document.onmousemove = elementDrag;
    };

    function elementDrag(e) {
      e = e || window.event;
      e.preventDefault();
      // calculate the new cursor position:
      pos1 = pos3 - e.clientX;
      pos2 = pos4 - e.clientY;
      pos3 = e.clientX;
      pos4 = e.clientY;
      // set the element's new position:
      elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
      elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
    };

    function closeDragElement() {
      // stop moving when mouse button is released:
      document.onmouseup = null;
      document.onmousemove = null;
    };
  }