UNPKG

twitch-emote

Version:

splice twitch emotes from a message string

123 lines (96 loc) 3.13 kB
import { access, mkdir } from 'fs/promises' import { join } from 'path' import { readJson, writeJson } from './fs_json' import { getSetting } from './settings' import { ChannelIdentifier, EmoteData } from './types' import { isChannelThrow, uniqueArr } from './util' const Dir = (fname?: string) => join(getSetting('cacheDir'), fname || '') export interface FsResponse<T> { data: T timestamp: number } export async function ensureCacheFolder() { try { await access(Dir()) } catch (e) { await mkdir(Dir()) } } export async function loadCacheRaw<T = {}>(fileName: string): Promise<T | null> { await ensureCacheFolder() try { await access(Dir(fileName)) } catch (e) { return null } return await readJson(Dir(fileName)) } export async function loadCache<T = []>(fileName: string, def: T): Promise<FsResponse<T>> { let file = await loadCacheRaw<FsResponse<T>>(fileName) if (!file) { return { data: def, timestamp: 0 } } return file } async function writeCache(fileName: string, data: any) { await ensureCacheFolder() await writeJson(Dir(fileName), { data, timestamp: Date.now() }) } export async function loadChannelList() { const data = await loadCache<string[]>(`channels`, []) return data.data } export async function saveChannelList(channels: string[]) { return await writeCache('channels', uniqueArr(channels)) } export async function loadGlobalCache(): Promise<FsResponse<EmoteData[]>> { return loadCache(`global`, []) } export async function loadChannelCache(channel: string): Promise<FsResponse<EmoteData[]>> { isChannelThrow(channel) return loadCache(`channel.${channel}`, []) } export async function loadIdentifierCache( channel: string ): Promise<FsResponse<ChannelIdentifier | null>> { return loadCache(`identifier.${channel}`, null) } export async function saveGlobalCache(cache: EmoteData[]) { await writeCache(`global`, cache) } export async function saveChannelCache( channel: string, emotes: EmoteData[], identifier: ChannelIdentifier ) { isChannelThrow(channel) await writeCache(`channel.${channel}`, emotes) await writeCache(`identifier.${channel}`, identifier) let channels = await loadChannelList() if (!channels.includes(channel)) { channels.push(channel) await saveChannelList(channels) } } export interface AllChannelData { emotes: FsResponse<EmoteData[]> identifier: FsResponse<ChannelIdentifier | null> } export interface AllChannelDataCollection { [channel: string]: AllChannelData } export async function loadChannels(): Promise<AllChannelDataCollection | null> { const channels = await loadChannelList() let foundData: AllChannelDataCollection = {} if (!channels.length) { return null } else { for (const chan of uniqueArr(channels)) { foundData[chan] = { emotes: await loadChannelCache(chan), identifier: await loadIdentifierCache(chan), } } return foundData } }