diff --git a/.env.example b/.env.example index 3ff53e9..4fccad3 100644 --- a/.env.example +++ b/.env.example @@ -13,23 +13,24 @@ BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 BOT_ENV=4 BOT_ADMINS=147392775707426816,887272961504071690 +BOT_LOGLEVEL=info ABOUT_FUNDING= ABOUT_REPO= -DATA_DIR= +DATA_DIR=./.temp -DB_HOST= -DB_PORT= -DB_NAME= +DB_HOST=127.0.0.1 +DB_PORT=3301 +DB_NAME=carddrop DB_AUTH_USER= DB_AUTH_PASS= DB_SYNC= DB_LOGGING= -DB_DATA_LOCATION=~/.docker +DB_DATA_LOCATION=./.temp/database DB_CARD_FILE=:memory: -EXPRESS_PORT=3303 +EXPRESS_PORT=3302 GDRIVESYNC_AUTO=true \ No newline at end of file diff --git a/.forgejo/workflows/production.yml b/.forgejo/workflows/production.yml index ba028b4..79906d1 100644 --- a/.forgejo/workflows/production.yml +++ b/.forgejo/workflows/production.yml @@ -53,12 +53,13 @@ jobs: DATA_DIR: ${{ secrets.PROD_DATA_DIR }} GDRIVESYNC_AUTO: ${{ vars.PROD_GDRIVESYNC_AUTO }} EXPRESS_PORT: ${{ secrets.PROD_EXPRESS_PORT }} + BOT_LOGLEVEL: ${{ vars.PROD_BOT_LOGLEVEL }} with: host: ${{ secrets.PROD_SSH_HOST }} username: ${{ secrets.PROD_SSH_USER }} key: ${{ secrets.PROD_SSH_KEY }} port: ${{ secrets.PROD_SSH_PORT }} - envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT + envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT,BOT_LOGLEVEL script: | source .sshrc \ && cd /home/vylpes/apps/card-drop/card-drop_prod \ diff --git a/.forgejo/workflows/stage.yml b/.forgejo/workflows/stage.yml index d0d0215..ce9b78f 100644 --- a/.forgejo/workflows/stage.yml +++ b/.forgejo/workflows/stage.yml @@ -53,12 +53,13 @@ jobs: DATA_DIR: ${{ secrets.STAGE_DATA_DIR }} GDRIVESYNC_AUTO: ${{ vars.STAGE_GDRIVESYNC_AUTO }} EXPRESS_PORT: ${{ secrets.STAGE_EXPRESS_PORT }} + BOT_LOGLEVEL: ${{ vars.STAGE_BOT_LOGLEVEL }} with: host: ${{ secrets.STAGE_SSH_HOST }} username: ${{ secrets.STAGE_SSH_USER }} key: ${{ secrets.STAGE_SSH_KEY }} port: ${{ secrets.STAGE_SSH_PORT }} - envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT + envs: DB_NAME,DB_AUTH_USER,DB_AUTH_PASS,DB_HOST,DB_PORT,DB_ROOT_HOST,DB_SYNC,DB_LOGGING,DB_DATA_LOCATION,BOT_TOKEN,BOT_VER,BOT_AUTHOR,BOT_OWNERID,BOT_CLIENTID,ABOUT_FUNDING,ABOUT_REPO,BOT_ENV,BOT_ADMINS,DATA_DIR,GDRIVESYNC_AUTO,SERVER_PATH,EXPRESS_PORT,BOT_LOGLEVEL script: | source .sshrc \ && cd /home/vylpes/apps/card-drop/card-drop_stage \ diff --git a/package-lock.json b/package-lock.json index 7f521cb..a2bd7db 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1906,9 +1906,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.12.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.8.tgz", + "integrity": "sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w==", "dependencies": { "undici-types": "~5.26.4" } @@ -6831,11 +6831,11 @@ } }, "node_modules/jest-mock-extended": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.6.tgz", - "integrity": "sha512-DJuEoFzio0loqdX8NIwkbE9dgIXNzaj//pefOQxGkoivohpxbSQeNHCAiXkDNA/fmM4EIJDoZnSibP4w3dUJ9g==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/jest-mock-extended/-/jest-mock-extended-3.0.7.tgz", + "integrity": "sha512-7lsKdLFcW9B9l5NzZ66S/yTQ9k8rFtnwYdCNuRU/81fqDWicNDVhitTSPnrGmNeNm0xyw0JHexEOShrIKRCIRQ==", "dependencies": { - "ts-essentials": "^9.4.2" + "ts-essentials": "^10.0.0" }, "peerDependencies": { "jest": "^24.0.0 || ^25.0.0 || ^26.0.0 || ^27.0.0 || ^28.0.0 || ^29.0.0", @@ -10870,11 +10870,11 @@ } }, "node_modules/ts-essentials": { - "version": "9.4.2", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.4.2.tgz", - "integrity": "sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-10.0.0.tgz", + "integrity": "sha512-77FHNJEyysF9+1s4G6eejuA1lxw7uMchT3ZPy3CIbh7GIunffpshtM8pTe5G6N5dpOzNevqRHew859ceLWVBfw==", "peerDependencies": { - "typescript": ">=4.1.0" + "typescript": ">=4.5.0" }, "peerDependenciesMeta": { "typescript": { diff --git a/src/bot.ts b/src/bot.ts index f75bbff..41ec193 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -58,12 +58,4 @@ if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO }); } -client.start(); - -const timerHelper = new TimerHelper(); - -const id = timerHelper.AddTimer('* * * * * *', 'Europe/London', GiveCurrency); - -console.log(`Timer Created: ${id}`); - -timerHelper.StartAllTimers(); \ No newline at end of file +client.start(); \ No newline at end of file diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts index 6c45900..9d29f7b 100644 --- a/src/buttonEvents/Claim.ts +++ b/src/buttonEvents/Claim.ts @@ -7,6 +7,7 @@ import AppLogger from "../client/appLogger"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import { readFileSync } from "fs"; import path from "path"; +import User from "../database/entities/app/User"; export default class Claim extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -41,6 +42,17 @@ export default class Claim extends ButtonEvent { await inventory.Save(Inventory, inventory); + let user = await User.FetchOneById(User, userId) || new User(userId, 300); + + AppLogger.LogSilly("Button/Claim", `${user.Id} has ${user.Currency} currency`); + + if (!user.RemoveCurrency(10)) { + await interaction.reply(`Not enough currency! You need 10 currency, you have ${user.Currency}`); + return; + } + + await user.Save(User, user); + const claim = new eClaim(claimId); claim.SetInventory(inventory); diff --git a/src/client/client.ts b/src/client/client.ts index c694950..2dd9a29 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -14,6 +14,8 @@ import Webhooks from "../webhooks"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; import { SeriesMetadata } from "../contracts/SeriesMetadata"; import AppLogger from "./appLogger"; +import TimerHelper from "../helpers/TimerHelper"; +import GiveCurrency from "../timers/GiveCurrency"; export class CoreClient extends Client { private static _commandItems: ICommandItem[]; @@ -23,6 +25,7 @@ export class CoreClient extends Client { private _events: Events; private _util: Util; private _webhooks: Webhooks; + private _timerHelper: TimerHelper; public static ClaimId: string; public static Environment: Environment; @@ -59,6 +62,7 @@ export class CoreClient extends Client { this._events = new Events(); this._util = new Util(); this._webhooks = new Webhooks(); + this._timerHelper = new TimerHelper(); AppLogger.LogInfo("Client", `Environment: ${CoreClient.Environment}`); @@ -72,7 +76,12 @@ export class CoreClient extends Client { } await AppDataSource.initialize() - .then(() => AppLogger.LogInfo("Client", "App Data Source Initialised")) + .then(() => { + AppLogger.LogInfo("Client", "App Data Source Initialised"); + + const timerId = this._timerHelper.AddTimer("*/30 * * * * *", "Europe/London", GiveCurrency, false); + this._timerHelper.StartTimer(timerId); + }) .catch(err => { AppLogger.LogError("Client", "App Data Source Initialisation Failed"); AppLogger.LogError("Client", err); diff --git a/src/contracts/AppBaseEntity.ts b/src/contracts/AppBaseEntity.ts index b9ca565..3eb9684 100644 --- a/src/contracts/AppBaseEntity.ts +++ b/src/contracts/AppBaseEntity.ts @@ -27,6 +27,12 @@ export default class AppBaseEntity { await repository.save(entity); } + public static async SaveAll(target: EntityTarget, entities: DeepPartial[]): Promise { + const repository = AppDataSource.getRepository(target); + + await repository.save(entities); + } + public static async Remove(target: EntityTarget, entity: T): Promise { const repository = AppDataSource.getRepository(target); diff --git a/src/database/entities/app/User.ts b/src/database/entities/app/User.ts index c954aea..a909552 100644 --- a/src/database/entities/app/User.ts +++ b/src/database/entities/app/User.ts @@ -13,7 +13,15 @@ export default class User extends AppBaseEntity { @Column() Currency: number; - public UpdateCurrency(currency: number) { - this.Currency = currency; + public AddCurrency(amount: number) { + this.Currency += amount; + } + + public RemoveCurrency(amount: number): boolean { + if (this.Currency < amount) return false; + + this.Currency -= amount; + + return true; } } \ No newline at end of file diff --git a/src/helpers/TimerHelper.ts b/src/helpers/TimerHelper.ts index 3d3f7e9..c5b1071 100644 --- a/src/helpers/TimerHelper.ts +++ b/src/helpers/TimerHelper.ts @@ -5,6 +5,8 @@ interface Timer { id: string; job: CronJob; context: Map; + onTick: ((context: Map) => void) | ((context: Map) => Promise); + runOnStart: boolean; } export default class TimerHelper { @@ -17,7 +19,8 @@ export default class TimerHelper { public AddTimer( cronTime: string, timeZone: string, - onTick: ((context: Map) => void) | ((context: Map) => Promise)): string { + onTick: ((context: Map) => void) | ((context: Map) => Promise), + runOnStart: boolean = false): string { const context = new Map(); const job = new CronJob( @@ -36,13 +39,15 @@ export default class TimerHelper { id, job, context, + onTick, + runOnStart, }); return id; } public StartAllTimers() { - this._timers.forEach(timer => timer.job.start()); + this._timers.forEach(timer => this.StartJob(timer)); } public StopAllTimers() { @@ -54,7 +59,7 @@ export default class TimerHelper { if (!timer) return; - timer.job.start(); + this.StartJob(timer); } public StopTimer(id: string) { @@ -64,4 +69,12 @@ export default class TimerHelper { timer.job.stop(); } + + private StartJob(timer: Timer) { + timer.job.start(); + + if (timer.runOnStart) { + timer.onTick(timer.context); + } + } } \ No newline at end of file diff --git a/src/registry.ts b/src/registry.ts index bb68685..eee78f4 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -52,4 +52,8 @@ export default class Registry { CoreClient.RegisterButtonEvent("series", new SeriesEvent()); CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent()); } + + public static RegisterTimers() { + + } } \ No newline at end of file diff --git a/src/timers/GiveCurrency.ts b/src/timers/GiveCurrency.ts index d9e40fa..9a0d28a 100644 --- a/src/timers/GiveCurrency.ts +++ b/src/timers/GiveCurrency.ts @@ -1,9 +1,16 @@ -export default function GiveCurrency(context: Map) { - let calledTimes = context.get('times') as number; +import AppLogger from "../client/appLogger"; +import User from "../database/entities/app/User"; - if (!calledTimes) calledTimes = 1; +export default async function GiveCurrency(context: Map) { + AppLogger.LogInfo("Timers/GiveCurrency", "Giving currency to every known user"); - console.log(`This has been called ${calledTimes} times!`); + const users = await User.FetchAll(User); - context.set('times', calledTimes + 1); + for (const user of users) { + user.AddCurrency(5); + } + + User.SaveAll(User, users); + + AppLogger.LogInfo("Timers/GiveCurrency", `Successfully gave +5 currency to ${users.length} users`); } \ No newline at end of file