LZT BetterTV AC

Add BetterTV smilies to editor autocomplete

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name LZT BetterTV AC
// @namespace lzt-bettertv-ac
// @description Add BetterTV smilies to editor autocomplete
// @version 1.0.0
// @author Toil
// @homepageURL https://t.me/lzt_upgrade
// @icon https://cdn.lztup.net/brand/logo-mini.png
// @license MIT
// @match *://lolz.guru/*
// @match *://lolz.live/*
// @match *://zelenka.guru/*
// @match *://zelenka.market/*
// @match *://lzt.market/*
// @match *://lolz.market/*
// @supportURL https://t.me/lzt_upgrade
// ==/UserScript==
// Generated by LZT Upgrade extension bundler. Telegram: https://t.me/lzt_upgrade Github: https://github.com/lzt-upgrade

var __legacyDecorateClassTS = function(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1;i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};

// __style_helper__
function injectStyle(text, hash) {
  if (typeof document === "undefined") {
    return;
  }
  const style = document.createElement("style");
  style.id = `lztup_${hash}`;
  style.innerText = text;
  document.head.appendChild(style);
}

// lzt-bettertv-ac/style.css
injectStyle(".fe-ac-BetterTV{flex-direction:row;display:flex}.fe-ac-smilie-image.lztup-smilie{margin:0!important}", "fa4e12cb0f2f32d4");

// lzt-bettertv-ac/index.js
function registerBetterTVAC(froala) {
  new CustomEditorAutoCompleter(froala.$el, { insertMode: "html" }, froala);
}
if (typeof Lolzteam.ACProvider !== "function") {
  console.log("[BetterTVAC] FroalaEditor isn't loaded");
  return;
}

class BetterTVACProvider extends Lolzteam.ACProvider {
  constructor(froala) {
    super(froala, "BetterTV");
    this.froala = froala;
    this.apiUrl = "https://api.betterttv.net/3/";
    this.cdnUrl = "https://cdn.betterttv.net/";
    this.limit = 5;
    this.debounceTime = 300;
  }
  debounceShow(text) {
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }
    this.debounceTimer = setTimeout(async () => {
      let results = await this.searchSmilies(text[0] === ":" ? text.slice(1) : text);
      if (!results?.length) {
        return false;
      }
      this.state = {
        text,
        textNode: this.froala.selection.get().anchorNode
      };
      this.popup.html("");
      const prioritySmilies = $(".fe-ac-smilie > .fe-ac-smilie-result").toArray();
      for (const prioritySmilie of prioritySmilies) {
        $(prioritySmilie).appendTo(this.popup);
      }
      for (const result of results) {
        if (this.popup.find(".fe-ac-smilie-result").length >= this.limit) {
          continue;
        }
        $('<div class="fe-ac-smilie-result fe-ac-result"/>').append($("<img/>", {
          class: "fe-ac-smilie-image fr-draggable lztup-smilie",
          alt: result.name,
          title: result.name,
          src: result.image
        })).appendTo(this.popup);
      }
      this.debounceTimeout = null;
      this.showPopup();
    }, this.debounceTime);
  }
  async searchSmilies(text) {
    if (text.length < 3) {
      return [];
    }
    try {
      const res = await fetch(`${this.apiUrl}emotes/shared/search?query=${text}&offset=0&limit=${this.limit}`);
      const data = await res.json();
      return data.map((smilie) => ({
        aliases: [],
        image: `${this.cdnUrl}emote/${smilie.id}/1x.webp`,
        name: smilie.code,
        value: `:${smilie.code}:`
      }));
    } catch (err) {
      console.error(`[BetterTVAC] Failed to search BetterTV smilies by text: ${err.message}`);
    }
  }
  async trigger() {
    let text = this.getSelectedText(", ");
    let selectedNode = this.froala.selection.get().anchorNode;
    let previousSibling = selectedNode.previousSibling || selectedNode.parentNode.previousSibling;
    selectedNode = selectedNode?.cloneNode(true);
    previousSibling = previousSibling?.cloneNode(true);
    if (!text || text.indexOf("@") !== -1 || selectedNode.textContent.startsWith(text) && previousSibling && previousSibling?.textContent.length !== 0 && !previousSibling?.textContent.endsWith(" ")) {
      return false;
    }
    text = text?.trim();
    this.hide();
    this.debounceShow(text);
    return true;
  }
  insertResult() {
    if (!this.popup.find(".active").length) {
      this.hide();
      return false;
    }
    this.froala.selection.save();
    this.state.textNode.textContent = this.state.textNode.textContent.trimEnd().slice(0, -this.state.text.length);
    this.froala.selection.restore();
    this.froala.html.insert(this.popup.find(".active").html());
    $("#lzt-fe-eb-smilie").trigger("ac-picked-smilie");
    this.hide();
    return true;
  }
}

class CustomEditorAutoCompleter extends Lolzteam.EditorAutoCompleter {
  constructor(el, n, froala) {
    super(el, n, froala);
    this.froala = froala;
    this.providers = [new BetterTVACProvider(froala)];
    froala.events.on("keydown", this.onKeydown.bind(this), true);
    froala.events.on("keyup", this.onKeyup.bind(this), true);
    froala.events.on("focus", this.onFocus.bind(this), true);
  }
}
FroalaEditor.MODULES.smilieBetterTVAC = function(e) {
  return {
    _init: registerBetterTVAC(e)
  };
};