Equicord/src/equicordplugins/moreStickers/lineEmojis.ts
2025-04-09 08:23:40 -04:00

138 lines
3.8 KiB
TypeScript

/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { LineEmoji, LineEmojiPack, Sticker, StickerPack } from "./types";
import { corsFetch } from "./utils";
export interface StickerCategory {
title: string;
id: number;
packs: {
title: string;
id: string;
img: string;
}[];
}
/**
* Get ID of sticker pack from a URL
*
* @param url The URL to get the ID from.
* @returns {string} The ID.
* @throws {Error} If the URL is invalid.
*/
export function getIdFromUrl(url: string): string {
const re = /^https:\/\/store\.line\.me\/emojishop\/product\/([a-z0-9]+)\/.*$/;
const match = re.exec(url);
if (match === null) {
throw new Error("Invalid URL");
}
return match[1];
}
/**
* Convert LineEmojiPack id to StickerPack id
*
* @param id The id to convert.
* @returns {string} The converted id.
*/
function toStickerPackId(id: string): string {
return "MoreStickers:Line:Emoji-Pack:" + id;
}
/**
* Convert LineEmoji id to Sticker id
*
* @param stickerId The id to convert.
* @param lineEmojiPackId The id of the LineEmojiPack.
* @returns {string} The converted id.
*/
function toStickerId(stickerId: string, lineEmojiPackId: string): string {
return "MoreStickers:Line-Emoji:" + lineEmojiPackId + ":" + stickerId;
}
/**
* Convert LineEmoji to Sticker
*
* @param {LineEmoji} s The LineEmoji to convert.
* @return {Sticker} The sticker.
*/
export function convertSticker(s: LineEmoji): Sticker {
return {
id: toStickerId(s.id, s.stickerPackId),
image: s.animationUrl || s.staticUrl,
title: s.id,
stickerPackId: toStickerPackId(s.stickerPackId),
isAnimated: !!s.animationUrl
};
}
/**
* Convert LineEmojiPack to StickerPack
*
* @param {LineEmojiPack} sp The LineEmojiPack to convert.
* @return {StickerPack} The sticker pack.
*/
export function convert(sp: LineEmojiPack): StickerPack {
return {
id: toStickerPackId(sp.id),
title: sp.title,
author: sp.author,
logo: convertSticker(sp.mainImage),
stickers: sp.stickers.map(convertSticker)
};
}
/**
* Get stickers from given HTML
*
* @param {string} html The HTML.
* @return {Promise<LineEmojiPack>} The sticker pack.
*/
export function parseHtml(html: string): LineEmojiPack {
const doc = new DOMParser().parseFromString(html, "text/html");
const mainImage = JSON.parse((doc.querySelector("[ref=mainImage]") as HTMLElement)?.dataset?.preview ?? "null") as LineEmoji;
const { id } = mainImage;
const stickers =
[...doc.querySelectorAll(".FnStickerPreviewItem")]
.map(x => JSON.parse((x as HTMLElement).dataset.preview ?? "null"))
.filter(x => x !== null)
.map(x => ({ ...x, stickerPackId: id })) as LineEmoji[];
const stickerPack = {
title: doc.querySelector("[data-test=emoji-name-title]")?.textContent ?? "null",
author: {
name: doc.querySelector("[data-test=emoji-author]")?.textContent ?? "null",
url: "https://store.line.me/" + (doc.querySelector("[data-test=emoji-author]")?.getAttribute("href") ?? "null")
},
id,
mainImage,
stickers
} as LineEmojiPack;
return stickerPack;
}
export function isLineEmojiPackHtml(html: string): boolean {
return html.includes("data-test=\"emoji-name-title\"");
}
/**
* Get stickers from LINE
*
* @param {string} id The id of the sticker pack.
* @return {Promise<LineEmojiPack>} The sticker pack.
*/
export async function getStickerPackById(id: string, region = "en"): Promise<LineEmojiPack> {
const res = await corsFetch(`https://store.line.me/emojishop/product/${id}/${region}`);
const html = await res.text();
return parseHtml(html);
}