-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
346 additions
and
84 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import colors from 'colors' | ||
import { EventEmitter } from 'events' | ||
import { randomUUID } from 'crypto' | ||
import cronParser, { type CronExpression } from 'cron-parser' | ||
import { core } from '@/app' | ||
|
||
/** | ||
* Configuration object for defining recurring cron jobs. | ||
*/ | ||
export interface CronsConfigurations<Metadata = undefined> { | ||
/** | ||
* Identifier for the Cron job. | ||
*/ | ||
name: string | ||
/** | ||
* Cron argument, e.g., "* * * * * *" for every second. | ||
*/ | ||
cron: string | ||
/** | ||
* Function to be executed when the cron job is triggered. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/method-signature-style | ||
exec(cron: CronsConfigurations<Metadata>, interval: CronExpression): any | ||
/** | ||
* Metadata for the cron job, for specific information. | ||
*/ | ||
metadata?: Metadata | ||
/** | ||
* Indicates whether the cron job should run only once. | ||
*/ | ||
once?: boolean | ||
} | ||
|
||
/** | ||
* Configuration object for defining a unique cron job to run only once. | ||
*/ | ||
export interface UniqueCron<MetaArgs> { | ||
/** | ||
* Identifier for the unique cron job. | ||
*/ | ||
name: string | ||
/** | ||
* Cron argument, e.g., "* * * * * *" for every second. | ||
*/ | ||
cron: string | ||
/** | ||
* Function to be executed when the unique cron job is triggered. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/method-signature-style | ||
exec(cron: UniqueCron<MetaArgs>): any | ||
/** | ||
* Metadata for the unique cron job, for specific information. | ||
*/ | ||
metadata?: MetaArgs | ||
} | ||
|
||
/** | ||
* Extended configuration interface for cron jobs, including a UUID. | ||
*/ | ||
export interface CronsConfigurationsSystem<Metadata> extends CronsConfigurations<Metadata> { | ||
uuid: string | ||
} | ||
|
||
/** | ||
* Class representing a collection of cron jobs. | ||
*/ | ||
export class Crons<Metadata> { | ||
/** | ||
* Array containing all defined cron jobs. | ||
*/ | ||
public static all: Array<CronsConfigurationsSystem<InstanceType<typeof Crons>['data']['metadata']>> = [] | ||
/** | ||
* EventEmitter used for managing cron job events. | ||
*/ | ||
public static set = new EventEmitter() | ||
public static timeouts = new Map() | ||
|
||
/** | ||
* Starts the specified cron job. | ||
* @param cron - Configuration for the cron job. | ||
*/ | ||
public static start (cron: CronsConfigurationsSystem<InstanceType<typeof Crons>['data']['metadata']>): void { | ||
const interval = cronParser.parseExpression(cron.cron) | ||
const nextScheduledTime = interval.next().getTime() | ||
const currentTime = Date.now() | ||
const delay = nextScheduledTime - currentTime | ||
|
||
// Updates the interval and schedules the next execution | ||
this.timeouts.set(cron.uuid, setTimeout(() => { | ||
Crons.set.emit(cron.uuid, cron, interval) | ||
if (!(cron.once ?? false)) Crons.start(cron) | ||
}, delay)) | ||
} | ||
|
||
/** | ||
* Configures unique cron jobs that run only once. | ||
* @return Returns the setTimeout ID, which can be used for cancellation. | ||
*/ | ||
public static once<MetaArgs>(cron: UniqueCron<MetaArgs>): NodeJS.Timeout { | ||
const interval = cronParser.parseExpression(cron.cron) | ||
const nextScheduledTime = interval.next().getTime() | ||
const currentTime = Date.now() | ||
const delay = nextScheduledTime - currentTime | ||
|
||
// Schedules the unique cron job and logs success | ||
console.log(`| ${colors.green('Unique Cron')} - ${colors.blue(cron.name)} added successfully.`) | ||
|
||
return setTimeout(() => { | ||
cron.exec(cron) | ||
}, delay) | ||
} | ||
|
||
/** | ||
* Updates or adds a cron job. | ||
* @param cron - Configuration for the cron job. | ||
*/ | ||
public static post (cron: CronsConfigurationsSystem<InstanceType<typeof Crons>['data']['metadata']>): void { | ||
if ((cron?.uuid).length > 0) { | ||
const index = Crons.all.findIndex(c => c.uuid === cron.uuid) | ||
if (index !== -1) { | ||
if (cron === Crons.all[index]) return | ||
Crons.all[index] = cron | ||
console.log(`${colors.green('Crons')} - ${colors.blue(cron.name)} | updated successfully.`) | ||
} | ||
} else { | ||
// Generates a new UUID if not provided | ||
const newcron = { | ||
...cron, | ||
uuid: randomUUID().replaceAll('-', '') | ||
} | ||
newcron.once = cron.once ?? false | ||
Crons.all.push(newcron) | ||
console.log(`${colors.green('Crons')} - ${colors.blue(cron.name)} | added successfully.`) | ||
} | ||
} | ||
|
||
/** | ||
* Generates a cron expression for a specific date. | ||
* @param date - Expiration date. | ||
* @returns Returns the cron expression. | ||
*/ | ||
public static date (date: Date): string { | ||
const seconds = date.getSeconds() | ||
const minutes = date.getMinutes() | ||
const hours = date.getHours() | ||
const dayOfMonth = date.getDate() | ||
let month = date.getMonth() + 1 // Months start from zero in JavaScript | ||
if (month === 13) { | ||
month = 12 | ||
} | ||
return `${seconds} ${minutes} ${hours} ${dayOfMonth} ${month} *` | ||
} | ||
|
||
/** | ||
* Constructor for the Crons class. | ||
* @param data - Configuration for the cron job. | ||
*/ | ||
constructor (public data: CronsConfigurations<Metadata>) { | ||
core.log(`${colors.green('Schedules')} - ${colors.blue(data.name)} | configured successfully.`) | ||
|
||
const cron = { | ||
...data, | ||
uuid: randomUUID().replaceAll('-', '') | ||
} | ||
cron.once = data.once ?? false | ||
Crons.all.push(cron as CronsConfigurationsSystem<InstanceType<typeof Crons>['data']['metadata']>) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { core } from '@/app' | ||
import { Crons } from '@/classes/Crons' | ||
import { PaymentBot } from '@/classes/PaymentBot' | ||
Check failure on line 3 in src/crons/authUpdate.ts GitHub Actions / build (18.x)
|
||
import getSettings from '@/functions/getSettings' | ||
import internalDB from '@/settings/settings.json' | ||
Check failure on line 5 in src/crons/authUpdate.ts GitHub Actions / build (18.x)
|
||
|
||
new Crons({ | ||
name: 'Auth - Start', | ||
cron: '* * * * * *', | ||
once: true, | ||
async exec (cron, interval) { | ||
if (interval === undefined) return | ||
await authUpdate() | ||
} | ||
}) | ||
|
||
new Crons({ | ||
name: 'Auth', | ||
cron: '0 */1 * ? * *', | ||
once: false, | ||
async exec (cron, interval) { | ||
if (interval === undefined) return | ||
await authUpdate() | ||
} | ||
}) | ||
|
||
async function authUpdate (): Promise<void> { | ||
const { Auth } = getSettings() | ||
Check failure on line 28 in src/crons/authUpdate.ts GitHub Actions / build (18.x)
|
||
if (Auth?.email === undefined || Auth.password === undefined || Auth.uuid === undefined) { core.warn('Sistema de autenticação não configurado'); return } | ||
const PaymentAuth = new PaymentBot({ url: internalDB.API }) | ||
|
||
await PaymentAuth.login({ email: Auth.email, password: Auth.password }) | ||
await PaymentAuth.validate({ uuid: Auth.uuid }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { ActivityType, type PresenceStatusData } from 'discord.js' | ||
import { client, db } from '@/app' | ||
import axios from 'axios' | ||
import { Crons } from '@/classes/Crons' | ||
|
||
new Crons({ | ||
name: 'statusPresence', | ||
cron: '*/30 * * * * *', | ||
once: false, | ||
async exec (cron, interval) { | ||
if (interval === undefined) return | ||
const guilds = client.guilds.cache | ||
|
||
for (const guild of guilds.values()) { | ||
const enabled = await db.system.get(`${guild.id}.status.systemStatus`) | ||
if (enabled !== undefined && enabled === false) return | ||
|
||
const type = (await db.system.get(`${guild.id}.status.systemStatusType`)) as PresenceStatusData | ||
const typeStatus = await db.system.get(`${guild.id}.status.systemStatusMinecraft`) | ||
|
||
if (typeStatus !== undefined && typeStatus === true) { | ||
const ip = await db.guilds.get(`${guild.id}.minecraft.ip`) | ||
await mineStatus(ip, type) | ||
} else if (typeStatus === undefined || typeStatus === false) { | ||
const messages = await db.messages.get(`${guild.id}.system.status.messages`) | ||
|
||
if (messages?.[0] !== undefined) { | ||
let currentMessage = await db.messages.get(`${guild.id}.system.status.currentMessage`) | ||
|
||
if (currentMessage >= messages?.length || currentMessage === undefined) { | ||
currentMessage = 0 | ||
await db.messages.set(`${guild.id}.system.status.currentMessage`, 0) | ||
} | ||
|
||
const newStatus = messages[currentMessage] | ||
client?.user?.setPresence({ | ||
activities: [{ name: newStatus, type: ActivityType.Playing }], | ||
status: type | ||
}) | ||
await db.messages.add(`${guild.id}.system.status.currentMessage`, 1) | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
|
||
async function mineStatus (ip: string, type: PresenceStatusData): Promise<void> { | ||
try { | ||
const res = await axios.get(`https://api.mcsrvstat.us/3/${ip}`) | ||
const formatRes = `${ip} | Status: ${ | ||
res.data.online === true | ||
? `Online | Players: ${res.data.players.online ?? 0}/${res.data.players.max ?? 0}` | ||
: 'Offline' | ||
}` | ||
|
||
client?.user?.setPresence({ | ||
activities: [{ name: formatRes, type: ActivityType.Playing }], | ||
status: `${type ?? 'online'}` | ||
}) | ||
} catch (err) { | ||
console.error(err) | ||
client?.user?.setPresence({ | ||
activities: [{ name: 'API Error', type: ActivityType.Playing }], | ||
status: 'idle' | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.