functions.ts
1 import { 2 ActionRowBuilder, 3 AnyComponentBuilder, 4 AttachmentBuilder, 5 BaseInteraction, 6 ButtonBuilder, 7 Client, 8 GuildMember, 9 TextChannel, 10 VoiceChannel 11 } from 'discord.js'; 12 import { emojis } from './configs.json'; 13 import { loops } from './maps'; 14 import { Langs, localizationBuilder, localizationsType } from '../langs/Manager'; 15 import { log4js } from 'amethystjs'; 16 import { stations } from '../cache/stations'; 17 import { stationType } from '../typings/firebase'; 18 19 20 export const inviteLink = (client: Client) => { 21 return `https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=2184464640&scope=bot%20applications.commands`; 22 }; 23 export const formatTime = (timeInSeconds: number, interaction: BaseInteraction): string => { 24 let seconds = 0; 25 let minutes = 0; 26 let hours = 0; 27 28 for (let i = 0; i < timeInSeconds; i++) { 29 seconds++; 30 if (seconds === 60) { 31 minutes++; 32 seconds = 0; 33 if (minutes === 60) { 34 hours++; 35 minutes = 0; 36 } 37 } 38 } 39 let res = ''; 40 const values: string[] = []; 41 [ 42 { x: hours, y: interaction.client.langs.getText(interaction, 'formatTime', 'hours') }, 43 { x: minutes, y: interaction.client.langs.getText(interaction, 'formatTime', 'minutes') }, 44 { x: seconds, y: interaction.client.langs.getText(interaction, 'formatTime', 'seconds') } 45 ] 46 .filter((x) => x.x > 0) 47 .forEach((x) => { 48 values.push(`${x.x} ${x.x === 1 ? x.y.substring(0, x.y.length - 1) : x.y}`); 49 }); 50 51 values.forEach((v, i) => { 52 res += `${v}`; 53 const next = values[i + 1]; 54 if (!next) return; 55 const dnext = values[i + 2]; 56 let sep = dnext ? ',' : ' ' + interaction.client.langs.getText(interaction, 'formatTime', 'joiner'); 57 res += sep + ' '; 58 }); 59 return res; 60 }; 61 export const isUserAlone = (channel: VoiceChannel) => { 62 return (channel?.members?.filter((x) => !x.user.bot)?.size ?? 0) === 1; 63 }; 64 export const checkForEnv = () => { 65 if (!process.env.token && !process.env.beta_token) { 66 throw new Error('Token or beta_token is missing in .env file'); 67 } 68 if (!process.env.botOwner) { 69 throw new Error('botOwner is missing in .env file'); 70 } 71 if (!process.env.panelChannel) { 72 throw new Error('panelChannel is missing in .env file'); 73 } 74 }; 75 export const boolEmojis = (b: boolean) => emojis[b ? 'online' : 'dnd']; 76 export const findEmoji = (txt: string) => { 77 const chars = "'" + 'abcdefghijklmnopqrstuvwxyz0123456798-_"()[]{}*.,?!:/;%ùø&éà@^\\|è~ '; 78 let uniques = []; 79 80 for (const c of txt) { 81 if (!chars.includes(c.toLowerCase())) uniques.push(c); 82 } 83 if (uniques.length === 0) return ''; 84 if (uniques.length === 1) return uniques[0]; 85 86 uniques = uniques.sort((a, b) => txt.indexOf(a) - txt.indexOf(b)).reverse(); 87 if (uniques.length === 2) return uniques[1]; 88 return uniques[0]; 89 }; 90 export const getLoopState = (guildId: string) => { 91 return loops.get(guildId) ?? false; 92 }; 93 export const setLoopState = (guildId: string, state: boolean) => { 94 return loops.set(guildId, state); 95 }; 96 export const row = <T extends AnyComponentBuilder = ButtonBuilder>(...components: T[]) => { 97 return new ActionRowBuilder({ 98 components: components 99 }) as ActionRowBuilder<T>; 100 }; 101 export const resizeStr = (str: string, size?: number) => { 102 const max = size ?? 100; 103 if (str.length <= max) return str; 104 return str.substring(0, size - 3) + '...'; 105 }; 106 export const isLofIManager = (member: GuildMember) => member.roles.cache.some(x => x.name === 'lofi') 107 export const autoDump = async(client: Client) => { 108 const now = new Date(); 109 const date = `${now.getFullYear()}/${now.getMonth()}/${now.getDate()}:${now.getHours()}:${now.getMinutes()}` 110 111 const file = new AttachmentBuilder('./dist/utils/configs.json') 112 .setName('configs.json') 113 .setDescription(`From ${date}`); 114 115 const channel = await client.channels.fetch(process.env.dumpChannel)?.catch(log4js.trace) as TextChannel 116 if (!channel) return 117 118 channel.send({ 119 content: `✅ | Dump config\nConfig file from ${date}`, 120 files: [file] 121 }).catch(log4js.trace) 122 } 123 export const setDumpClock = (client: Client) => { 124 const midnight = new Date(new Date().setHours(0, 0, 0, 0) + 86400000) 125 const diff = midnight.getTime() - Date.now() 126 127 setTimeout(() => { 128 autoDump(client) 129 130 setInterval(() => { 131 autoDump(client) 132 }, 86400000) 133 }, diff) 134 135 } 136 export const getRandomStation = () => { 137 const keys = Object.keys(stations); 138 if (keys.length === 0) return null; 139 140 const randomKey = keys[Math.floor(Math.random() * keys.length)]; 141 return stations[randomKey]; 142 } 143 export const convertTimestampToSeconds = (timestamp: string) => { 144 const parts = timestamp.split(':'); 145 const integers = parts.map(x => parseInt(x)) 146 147 if (parts.length === 3) { 148 return integers[0] * 3600 + integers[1] * 60 + integers[2]; 149 } 150 if (parts.length === 2) { 151 return integers[0] * 60 + integers[1]; 152 } 153 if (parts.length === 1) { 154 return integers[0]; 155 } 156 } 157 export const convertSecondsToTimestamp = (seconds: number) => { 158 const hours = Math.floor(seconds / 3600); 159 seconds %= 3600; 160 const minutes = Math.floor(seconds / 60); 161 seconds %= 60; 162 163 const parts: string[] = []; 164 if (hours > 0) parts.push(hours.toString().padStart(2, '0')); 165 parts.push(minutes.toString().padStart(2, '0')); 166 parts.push(seconds.toString().padStart(2, '0')); 167 168 return parts.join(':'); 169 } 170 export const resolveName = (station: stationType<false>) => `${station.authors.join(' x ')} - ${station.title} ${station.beats}`.trim(); 171 export const buildLocalizations = <Key extends keyof localizationsType<'commands'>>(command: Key): localizationBuilder<Key> => { 172 const langs = new Langs(); 173 return langs.buildLocalizations(command); 174 };