mirror of
https://github.com/toast-ts/Daggerbot-TS.git
synced 2024-11-17 16:30:58 -05:00
Compare commits
No commits in common. "fcfd11431a5ef56ddf420e56011771df2a37e126" and "6912392130ed0d69d46a5c02eeda258ec10b96b0" have entirely different histories.
fcfd11431a
...
6912392130
@ -41,16 +41,18 @@ export default class TClient extends Discord.Client {
|
|||||||
public tags: TagSystemSvc = new TagSystemSvc();
|
public tags: TagSystemSvc = new TagSystemSvc();
|
||||||
public ytChannels: YouTubeChannelsSvc = new YouTubeChannelsSvc();
|
public ytChannels: YouTubeChannelsSvc = new YouTubeChannelsSvc();
|
||||||
public repeatedMessages: IRepeatedMessages = {};
|
public repeatedMessages: IRepeatedMessages = {};
|
||||||
|
public statsGraph: number = -120;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super({
|
super({
|
||||||
intents: [
|
intents: [
|
||||||
Discord.GatewayIntentBits.Guilds, Discord.GatewayIntentBits.GuildMembers,
|
Discord.GatewayIntentBits.Guilds, Discord.GatewayIntentBits.GuildMembers,
|
||||||
Discord.GatewayIntentBits.GuildModeration, Discord.GatewayIntentBits.GuildInvites,
|
Discord.GatewayIntentBits.GuildModeration, Discord.GatewayIntentBits.GuildInvites,
|
||||||
Discord.GatewayIntentBits.GuildPresences, Discord.GatewayIntentBits.MessageContent,
|
Discord.GatewayIntentBits.GuildMessageReactions, Discord.GatewayIntentBits.GuildPresences,
|
||||||
Discord.GatewayIntentBits.GuildMessages, Discord.GatewayIntentBits.DirectMessages
|
Discord.GatewayIntentBits.MessageContent, Discord.GatewayIntentBits.GuildMessages,
|
||||||
|
Discord.GatewayIntentBits.DirectMessages
|
||||||
], partials: [
|
], partials: [
|
||||||
Discord.Partials.Channel, Discord.Partials.Message
|
Discord.Partials.Channel, Discord.Partials.Reaction, Discord.Partials.Message
|
||||||
], allowedMentions: {users:[], roles:[]}
|
], allowedMentions: {users:[], roles:[]}
|
||||||
})
|
})
|
||||||
this.config = ConfigHelper.loadConfig() as Config;
|
this.config = ConfigHelper.loadConfig() as Config;
|
||||||
|
@ -20,6 +20,7 @@ const channels = {
|
|||||||
activePlayers: '739084625862852715',
|
activePlayers: '739084625862852715',
|
||||||
announcements: '1084864116776251463',
|
announcements: '1084864116776251463',
|
||||||
mainMpChat: '468835769092669461',
|
mainMpChat: '468835769092669461',
|
||||||
|
mfMpChat: '1149238561934151690',
|
||||||
serverInfo: '543494084363288637',
|
serverInfo: '543494084363288637',
|
||||||
}
|
}
|
||||||
export default class MP {
|
export default class MP {
|
||||||
@ -31,7 +32,7 @@ export default class MP {
|
|||||||
static async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) {
|
static async run(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>) {
|
||||||
if (client.config.botSwitches.mpSys === false) return interaction.reply({embeds: [mpModuleDisabled(client)]});
|
if (client.config.botSwitches.mpSys === false) return interaction.reply({embeds: [mpModuleDisabled(client)]});
|
||||||
if (client.uptime < refreshTimerSecs) return interaction.reply('MPModule isn\'t initialized yet, please wait a moment and try again.');
|
if (client.uptime < refreshTimerSecs) return interaction.reply('MPModule isn\'t initialized yet, please wait a moment and try again.');
|
||||||
if ([channels.mainMpChat, client.config.dcServer.channels.multifarm_chat].includes(interaction.channelId) && !MessageTool.isStaff(interaction.member) && ['status', 'players'].includes(interaction.options.getSubcommand())) return interaction.reply(`Please use <#${channels.activePlayers}> for \`/mp status/players\` commands to prevent clutter in this channel.`).then(()=>setTimeout(()=>interaction.deleteReply(), 6000));
|
if ([channels.mainMpChat, channels.mfMpChat].includes(interaction.channelId) && !MessageTool.isStaff(interaction.member) && ['status', 'players'].includes(interaction.options.getSubcommand())) return interaction.reply(`Please use <#${channels.activePlayers}> for \`/mp status/players\` commands to prevent clutter in this channel.`).then(()=>setTimeout(()=>interaction.deleteReply(), 6000));
|
||||||
const choiceSelector = interaction.options.getString('server');
|
const choiceSelector = interaction.options.getString('server');
|
||||||
({
|
({
|
||||||
players: async()=>{
|
players: async()=>{
|
||||||
@ -39,7 +40,7 @@ export default class MP {
|
|||||||
if (!DSS) return console.log('Endpoint failed - players');
|
if (!DSS) return console.log('Endpoint failed - players');
|
||||||
|
|
||||||
const PDArr = await client.MPServer.fetchPlayerData(choiceSelector);
|
const PDArr = await client.MPServer.fetchPlayerData(choiceSelector);
|
||||||
const canvas = await new CanvasBuilder().generateGraph(PDArr.slice(-120), 'players');
|
const canvas = await new CanvasBuilder().generateGraph(PDArr.slice(client.statsGraph), 'players');
|
||||||
const players:string[] = [];
|
const players:string[] = [];
|
||||||
let embedColor:Discord.ColorResolvable;
|
let embedColor:Discord.ColorResolvable;
|
||||||
switch (true){
|
switch (true){
|
||||||
|
@ -2,6 +2,7 @@ import {createClient, ErrorReply} from 'redis';
|
|||||||
import Logger from '../helpers/Logger.js';
|
import Logger from '../helpers/Logger.js';
|
||||||
import TSClient from '../helpers/TSClient.js';
|
import TSClient from '../helpers/TSClient.js';
|
||||||
|
|
||||||
|
let Prefix = 'Cache';
|
||||||
const RedisClient = createClient({
|
const RedisClient = createClient({
|
||||||
url: (await TSClient()).redis_uri,
|
url: (await TSClient()).redis_uri,
|
||||||
database: 0,
|
database: 0,
|
||||||
@ -10,32 +11,35 @@ const RedisClient = createClient({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export default class CacheServer {
|
export default class CacheServer {
|
||||||
protected static prefix = 'Cache';
|
|
||||||
protected static eventManager() {
|
protected static eventManager() {
|
||||||
RedisClient
|
RedisClient
|
||||||
.on('connect', ()=>Logger.console('log', this.prefix, 'Connection to Redis has been established'))
|
.on('connect', ()=>Logger.console('log', Prefix, 'Connection to Redis has been established'))
|
||||||
.on('error', (err:ErrorReply)=>{
|
.on('error', (err:ErrorReply)=>{
|
||||||
Logger.console('error', this.prefix, `Encountered an error in Redis: ${err.message}`)
|
Logger.console('error', Prefix, `Encountered an error in Redis: ${err.message}`)
|
||||||
setTimeout(async()=>{
|
setTimeout(async()=>{
|
||||||
if (!RedisClient.isReady) {
|
if (!RedisClient.isReady) {
|
||||||
Logger.console('log', this.prefix, 'Client is zombified, starting a fresh connection...');
|
Logger.console('log', Prefix, 'Client is zombified, starting a fresh connection...');
|
||||||
RedisClient.quit();
|
RedisClient.quit();
|
||||||
await RedisClient.connect();
|
await RedisClient.connect();
|
||||||
}
|
}
|
||||||
}, 1500)
|
}, 1500)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
public static async get(key:any, jsonMode:boolean):Promise<any> {
|
public static async get(key:any) {
|
||||||
let cachedResult:any;
|
const cachedResult = await RedisClient.get(key);
|
||||||
if (jsonMode) cachedResult = await RedisClient.json.get(key);
|
if (cachedResult) return JSON.parse(cachedResult);
|
||||||
else {
|
else return null
|
||||||
cachedResult = await RedisClient.get(key);
|
|
||||||
if (cachedResult) cachedResult = JSON.parse(cachedResult);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public static async set(key:any, value:any, jsonMode:boolean):Promise<any> {
|
public static async set(key:any, value:any) {
|
||||||
if (jsonMode) return await RedisClient.json.set(key, '.', value);
|
return await RedisClient.set(key, JSON.stringify(value));
|
||||||
else return await RedisClient.set(key, JSON.stringify(value));
|
}
|
||||||
|
public static async getJSON(key:any) {
|
||||||
|
const cachedResult = await RedisClient.json.get(key);
|
||||||
|
if (cachedResult) return cachedResult;
|
||||||
|
else return null
|
||||||
|
}
|
||||||
|
public static async setJSON(key:any, value:any) {
|
||||||
|
return await RedisClient.json.set(key, '.', value);
|
||||||
}
|
}
|
||||||
public static async expiry(key:any, time:number) {
|
public static async expiry(key:any, time:number) {
|
||||||
return await RedisClient.expire(key, time); // NOTE: time is in seconds, not milliseconds -- you know what you did wrong
|
return await RedisClient.expire(key, time); // NOTE: time is in seconds, not milliseconds -- you know what you did wrong
|
||||||
@ -48,8 +52,7 @@ export default class CacheServer {
|
|||||||
RedisClient.connect();
|
RedisClient.connect();
|
||||||
this.eventManager();
|
this.eventManager();
|
||||||
} catch {
|
} catch {
|
||||||
console.error('Cannot initialize RedisClient -- is Redis running?');
|
console.error('Cannot initialize RedisClient -- is Redis running?')
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
src/events/messageReactionAdd.ts
Normal file
11
src/events/messageReactionAdd.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import Discord from 'discord.js';
|
||||||
|
import TClient from '../client.js';
|
||||||
|
export default class MessageReactionAdd {
|
||||||
|
static run(client:TClient, reaction:Discord.MessageReaction, user:Discord.User){
|
||||||
|
if (!client.config.botSwitches.logs) return;
|
||||||
|
if (reaction.message.guildId != client.config.dcServer.id || reaction.message.partial) return;
|
||||||
|
const ReactedFirst = reaction.users.cache.first();
|
||||||
|
if (ReactedFirst.id != user.id) return;
|
||||||
|
if (reaction.emoji.name === '🖕') return (client.channels.cache.get(client.config.dcServer.channels.logs) as Discord.TextChannel).send({embeds:[new client.embed().setColor(client.config.embedColorYellow).setTimestamp().setAuthor({name: `Author: ${ReactedFirst.username} (${ReactedFirst.id})`, iconURL: ReactedFirst.displayAvatarURL()}).setTitle('Message reaction').setDescription(`<@${ReactedFirst.id}>\nAdded a reaction to the message.\n**Emoji**\n${reaction.emoji.name}\n**Channel**\n<#${reaction.message.channelId}>`).setFooter({text: 'Possibly this member, bot fetches who reacted first.'})], components: [new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents(new Discord.ButtonBuilder().setStyle(5).setURL(`${reaction.message.url}`).setLabel('Jump to message'))]});
|
||||||
|
}
|
||||||
|
}
|
8
src/events/messageReactionRemove.ts
Normal file
8
src/events/messageReactionRemove.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import Discord from 'discord.js';
|
||||||
|
import TClient from '../client.js';
|
||||||
|
export default class MessageReactionRemove {
|
||||||
|
static run(client:TClient, reaction:Discord.MessageReaction, user:Discord.User){
|
||||||
|
if (!client.config.botSwitches.logs || reaction.message.guildId != client.config.dcServer.id || reaction.message.partial) return;
|
||||||
|
if (reaction.emoji.name === '🖕') return (client.channels.cache.get(client.config.dcServer.channels.logs) as Discord.TextChannel).send({embeds:[new client.embed().setColor(client.config.embedColorRed).setTimestamp().setAuthor({name: `Author: ${user.username} (${user.id})`, iconURL: user.displayAvatarURL()}).setTitle('Message reaction').setDescription(`<@${user.id}>\nRemoved a reaction from the message.\n**Emoji**\n${reaction.emoji.name}\n**Channel**\n<#${reaction.message.channelId}>`)]})
|
||||||
|
}
|
||||||
|
}
|
@ -109,12 +109,12 @@ export class MPServerSvc {
|
|||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
async findInCache(): Promise<IServer[]> {
|
async findInCache(): Promise<IServer[]> {
|
||||||
const cachedResult = await CacheServer.get(cacheKey, true);
|
const cachedResult = await CacheServer.getJSON(cacheKey);
|
||||||
let result;
|
let result;
|
||||||
if (cachedResult) result = cachedResult;
|
if (cachedResult) result = cachedResult;
|
||||||
else {
|
else {
|
||||||
result = await this.model.findAll();
|
result = await this.model.findAll();
|
||||||
CacheServer.set(cacheKey, result, true).then(()=>CacheServer.expiry(cacheKey, 1800));
|
CacheServer.setJSON(cacheKey, result).then(()=>CacheServer.expiry(cacheKey, 1800));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -124,12 +124,12 @@ export class PunishmentsSvc {
|
|||||||
}
|
}
|
||||||
async findInCache():Promise<any> {
|
async findInCache():Promise<any> {
|
||||||
const cacheKey = 'punishments';
|
const cacheKey = 'punishments';
|
||||||
const cachedResult = await CacheServer.get(cacheKey, true);
|
const cachedResult = await CacheServer.getJSON(cacheKey);
|
||||||
let result;
|
let result;
|
||||||
if (cachedResult) result = cachedResult;
|
if (cachedResult) result = cachedResult;
|
||||||
else {
|
else {
|
||||||
result = await this.model.findAll();
|
result = await this.model.findAll();
|
||||||
CacheServer.set(cacheKey, result, true).then(()=>CacheServer.expiry(cacheKey, 20));
|
CacheServer.setJSON(cacheKey, result).then(()=>CacheServer.expiry(cacheKey, 20));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -88,12 +88,12 @@ export class TagSystemSvc {
|
|||||||
}
|
}
|
||||||
async findInCache(): Promise<Tags[]> {
|
async findInCache(): Promise<Tags[]> {
|
||||||
const cacheKey = 'tags';
|
const cacheKey = 'tags';
|
||||||
const cachedResult = await CacheServer.get(cacheKey, true);
|
const cachedResult = await CacheServer.getJSON(cacheKey);
|
||||||
let result;
|
let result;
|
||||||
if (cachedResult) result = cachedResult;
|
if (cachedResult) result = cachedResult;
|
||||||
else {
|
else {
|
||||||
result = await this.model.findAll();
|
result = await this.model.findAll();
|
||||||
CacheServer.set(cacheKey, result, true).then(()=>CacheServer.expiry(cacheKey, 240));
|
CacheServer.setJSON(cacheKey, result).then(()=>CacheServer.expiry(cacheKey, 240));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ let refreshIntrvlTxt:string = `Refreshes every ${refreshTimerSecs/1000} seconds.
|
|||||||
|
|
||||||
export default async(client:TClient)=>{
|
export default async(client:TClient)=>{
|
||||||
const message = await (client.channels.resolve(isBotInDevMode ? '1091300529696673792' : '543494084363288637') as Discord.TextChannel).messages.fetch(isBotInDevMode ? '1104563309451161742' : '1149141188079779900');
|
const message = await (client.channels.resolve(isBotInDevMode ? '1091300529696673792' : '543494084363288637') as Discord.TextChannel).messages.fetch(isBotInDevMode ? '1104563309451161742' : '1149141188079779900');
|
||||||
if (!client.config.botSwitches.mpSys) return message.edit({content: null, embeds: [mpModuleDisabled(client)]});
|
if (client.config.botSwitches.mpSys === false) return message.edit({content: null, embeds: [mpModuleDisabled(client)]});
|
||||||
|
|
||||||
async function newServerEntry(server:IServer) {
|
async function newServerEntry(server:IServer) {
|
||||||
const serverData = await requestServerData(client, server);
|
const serverData = await requestServerData(client, server);
|
||||||
|
@ -9,42 +9,42 @@ export default async(client:TClient)=>{
|
|||||||
let Data:any;
|
let Data:any;
|
||||||
const cacheExpiry:number = 7200; // Invalidate cache after sitting in Redis for 2 hours
|
const cacheExpiry:number = 7200; // Invalidate cache after sitting in Redis for 2 hours
|
||||||
|
|
||||||
|
let YTChannelID:string;
|
||||||
|
let YTChannelName:string;
|
||||||
|
let DiscordChannelID:string;
|
||||||
|
let DiscordRoleID:string;
|
||||||
|
|
||||||
const YTDB = await client.ytChannels.getChannels();
|
const YTDB = await client.ytChannels.getChannels();
|
||||||
for (const channel of YTDB) {
|
for (const channel of YTDB) {
|
||||||
let YTChannelID:string;
|
|
||||||
let YTChannelName:string;
|
|
||||||
let DiscordChannelID:string;
|
|
||||||
let DiscordRoleID:string;
|
|
||||||
|
|
||||||
YTChannelID = channel.dataValues.ytchannel;
|
YTChannelID = channel.dataValues.ytchannel;
|
||||||
DiscordChannelID = channel.dataValues.dcchannel;
|
DiscordChannelID = channel.dataValues.dcchannel;
|
||||||
DiscordRoleID = channel.dataValues.dcrole;
|
DiscordRoleID = channel.dataValues.dcrole;
|
||||||
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Undici.request(`https://youtube.googleapis.com/youtube/v3/activities?part=snippet&channelId=${YTChannelID}&maxResults=2&key=${(await TSClient()).youtube}`, {
|
await Undici.request(`https://youtube.googleapis.com/youtube/v3/activities?part=snippet&channelId=${YTChannelID}&maxResults=2&key=${(await TSClient()).youtube}`, {
|
||||||
signal: AbortSignal.timeout(10000),
|
signal: AbortSignal.timeout(10000),
|
||||||
headers: {'User-Agent':`${client.user.username} - YTModule/undici`},
|
headers: {'User-Agent':`${client.user.username} - YTModule/undici`},
|
||||||
}).then(async resp=>Data = await resp.body.json());
|
}).then(async resp=>Data = await resp.body.json());
|
||||||
YTChannelName = Data.items[0].snippet.channelTitle;
|
YTChannelName = Data.items[0].snippet.channelTitle;
|
||||||
} catch {
|
} catch {
|
||||||
Logger.console('log', 'YTModule', `Failed to get video data for "${YTChannelName}" from YouTube API`);
|
Logger.console('log', 'YTModule', `Failed to get video data for "${YTChannelName}" from YouTube API`);
|
||||||
}
|
|
||||||
if (!Data) return;
|
|
||||||
|
|
||||||
const getVideoId = (index:number)=>Data.items[index].snippet.thumbnails.default.url.split('/')[4];
|
|
||||||
const videoUrl = `https://www.youtube.com/watch?v=${getVideoId(0)}`;
|
|
||||||
const cacheKey = `YTCache:${YTChannelID}`;
|
|
||||||
const cachedVideoId = await CacheServer.get(cacheKey, false);
|
|
||||||
if (!cachedVideoId) {
|
|
||||||
await CacheServer.set(cacheKey, getVideoId(0), false).then(async()=>await CacheServer.expiry(cacheKey, cacheExpiry));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (getVideoId(1) === cachedVideoId) {
|
|
||||||
await CacheServer.delete(cacheKey).then(async()=>await CacheServer.set(cacheKey, getVideoId(0), false).then(async()=>await CacheServer.expiry(cacheKey, cacheExpiry)));
|
|
||||||
|
|
||||||
(client.channels.resolve(DiscordChannelID) as TextChannel).send({
|
|
||||||
content: `${MessageTool.formatMention(DiscordRoleID, 'role')}\n**${YTChannelName}** just uploaded a video!\n${videoUrl}`, allowedMentions: {parse: ['roles']},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
if (!Data) return;
|
||||||
|
|
||||||
|
const getVideoId = (index:number)=>Data.items[index].snippet.thumbnails.default.url.split('/')[4];
|
||||||
|
const videoUrl = `https://www.youtube.com/watch?v=${getVideoId(0)}`;
|
||||||
|
const cacheKey = `YTCache:${YTChannelID}`;
|
||||||
|
const cachedVideoId = await CacheServer.get(cacheKey);
|
||||||
|
if (!cachedVideoId) {
|
||||||
|
await CacheServer.set(cacheKey, getVideoId(0)).then(async()=>await CacheServer.expiry(cacheKey, cacheExpiry));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (getVideoId(1) === cachedVideoId) {
|
||||||
|
await CacheServer.delete(cacheKey).then(async()=>await CacheServer.set(cacheKey, getVideoId(0)).then(async()=>await CacheServer.expiry(cacheKey, cacheExpiry)));
|
||||||
|
|
||||||
|
(client.channels.resolve(DiscordChannelID) as TextChannel).send({
|
||||||
|
content: `${MessageTool.formatMention(DiscordRoleID, 'role')}\n**${YTChannelName}** just uploaded a video!\n${videoUrl}`, allowedMentions: {parse: ['roles']},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user