143 lines
5.2 KiB
TypeScript
143 lines
5.2 KiB
TypeScript
import axios from "axios";
|
|
import { GuildEmoji } from "discord.js";
|
|
import JSON5 from 'json5';
|
|
import { BRIDGED_EMOJIS, logger } from "..";
|
|
import { client } from "./client";
|
|
|
|
const EMOJI_DICT_URL = 'https://raw.githubusercontent.com/revoltchat/revite/master/src/assets/emojis.ts';
|
|
const EMOJI_URL_BASE = 'https://dl.insrt.uk/projects/revolt/emotes/';
|
|
const EMOJI_SERVERS = process.env.EMOJI_SERVERS?.split(',') || [];
|
|
|
|
async function fetchEmojiList(): Promise<Record<string, string>> {
|
|
const file: string = (await axios.get(EMOJI_DICT_URL)).data;
|
|
const start = file.indexOf('...{') + 3;
|
|
const end = file.indexOf('},') + 1;
|
|
|
|
return JSON5.parse(file.substring(start, end).trim());
|
|
}
|
|
|
|
const emojiUpdate = async () => {
|
|
try {
|
|
if (!EMOJI_SERVERS.length) return logger.info('$EMOJI_SERVERS not set, not bridging emojis.');
|
|
|
|
if (!client.readyAt) await new Promise(r => client.once('ready', r));
|
|
logger.info('Updating bridged emojis. Due to Discord rate limits, this can take a few hours to complete.');
|
|
|
|
const emojis = await fetchEmojiList();
|
|
logger.info(`Downloaded emoji list: ${Object.keys(emojis).length} emojis.`);
|
|
|
|
const servers = await Promise.all(EMOJI_SERVERS.map(id => client.guilds.fetch(id)));
|
|
await Promise.all(servers.map(server => server.emojis.fetch())); // Make sure all emojis are cached
|
|
|
|
const findFreeServer = (animated: boolean) => servers.find(
|
|
server => server.emojis.cache
|
|
.filter(e => e.animated == animated)
|
|
.size < 50
|
|
);
|
|
|
|
// Remove unknown emojis from servers
|
|
for (const server of servers) {
|
|
for (const emoji of server.emojis.cache) {
|
|
const dbEmoji = await BRIDGED_EMOJIS.findOne({
|
|
emojiid: emoji[1].id,
|
|
});
|
|
|
|
if (!dbEmoji) {
|
|
try {
|
|
logger.info('Found unknown emoji; deleting.');
|
|
await emoji[1].delete('Unknown emoji');
|
|
} catch(e) {
|
|
logger.warn('Failed to delete emoji: ' + e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const emoji of Object.entries(emojis)) {
|
|
const dbEmoji = await BRIDGED_EMOJIS.findOne({
|
|
$or: [
|
|
{ name: emoji[0] },
|
|
{ originalFileUrl: emoji[1] },
|
|
],
|
|
});
|
|
|
|
if (!dbEmoji) {
|
|
// Upload to Discord
|
|
logger.debug('Uploading emoji: ' + emoji[1]);
|
|
|
|
const fileurl = EMOJI_URL_BASE + emoji[1].replace('custom:', '');
|
|
const server = findFreeServer(emoji[1].endsWith('.gif'));
|
|
|
|
if (!server) {
|
|
logger.warn('Could not find a server with free emoji slots for ' + emoji[1]);
|
|
continue;
|
|
}
|
|
|
|
let e: GuildEmoji;
|
|
try {
|
|
e = await server.emojis.create(fileurl, emoji[0], { reason: 'Bridged Emoji' });
|
|
} catch(e) {
|
|
logger.warn(emoji[0] + ': Failed to upload emoji: ' + e);
|
|
continue;
|
|
}
|
|
|
|
await BRIDGED_EMOJIS.insert({
|
|
animated: e.animated || false,
|
|
emojiid: e.id,
|
|
name: emoji[0],
|
|
originalFileUrl: fileurl,
|
|
server: e.guild.id,
|
|
});
|
|
}
|
|
else {
|
|
// Double check if emoji exists
|
|
let exists = false;
|
|
for (const server of servers) {
|
|
if (server.emojis.cache.find(e => e.id == dbEmoji.emojiid)) {
|
|
exists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!exists) {
|
|
logger.info(`Emoji ${emoji[0]} does not exist; reuploading.`);
|
|
await BRIDGED_EMOJIS.remove({ emojiid: dbEmoji.emojiid });
|
|
|
|
const fileurl = EMOJI_URL_BASE + emoji[1].replace('custom:', '');
|
|
const server = findFreeServer(emoji[1].endsWith('.gif'));
|
|
|
|
if (!server) {
|
|
logger.warn('Could not find a server with free emoji slots for ' + emoji[1]);
|
|
continue;
|
|
}
|
|
|
|
let e: GuildEmoji;
|
|
try {
|
|
e = await server.emojis.create(fileurl, emoji[0], { reason: 'Bridged Emoji' });
|
|
} catch(e) {
|
|
logger.warn(emoji[0] + ': Failed to upload emoji: ' + e);
|
|
continue;
|
|
}
|
|
|
|
await BRIDGED_EMOJIS.insert({
|
|
animated: e.animated || false,
|
|
emojiid: e.id,
|
|
name: emoji[0],
|
|
originalFileUrl: fileurl,
|
|
server: e.guild.id,
|
|
});
|
|
}
|
|
}
|
|
};
|
|
|
|
logger.done('Emoji update finished.');
|
|
} catch(e) {
|
|
logger.error('Updating bridged emojis failed');
|
|
console.error(e);
|
|
}
|
|
};
|
|
|
|
emojiUpdate();
|
|
setInterval(emojiUpdate, 1000 * 60 * 60 * 6); // Every 6h
|
|
|
|
export { fetchEmojiList }
|