Compare commits
19 Commits
e5933aacc2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d3349231f3 | |||
| 5046fe91ba | |||
| 2df9279c1b | |||
| 60097b9a1d | |||
| efedea8c45 | |||
| fb3f659831 | |||
| fceefcc667 | |||
| f17cdb12c0 | |||
| 1b3b498723 | |||
| 6fabb20a2c | |||
| 53c496422e | |||
| 7ca4b47ba9 | |||
| bbfb3bfae1 | |||
| 81c1ce886b | |||
| 2cc35f659e | |||
| 52f12ffac7 | |||
| 53ac0f4b79 | |||
| de9767f0bf | |||
| 745e709bef |
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
data/*.db
|
||||||
|
config.json
|
||||||
|
.git
|
||||||
|
.env
|
||||||
30
Dockerfile
Normal file
30
Dockerfile
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# Use Node.js 20 LTS as the base image
|
||||||
|
FROM node:20-slim
|
||||||
|
|
||||||
|
# Install dependencies needed for better-sqlite3 (if prebuilt binaries fail)
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install --omit=dev
|
||||||
|
|
||||||
|
# Copy the rest of the application code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Create the data directory for the database
|
||||||
|
RUN mkdir -p data
|
||||||
|
|
||||||
|
# The bot uses config.json. In Docker, we'll likely mount this or use env vars,
|
||||||
|
# but for now, we ensure the structure is there.
|
||||||
|
|
||||||
|
# Command to run the bot
|
||||||
|
CMD [ "node", "main.js" ]
|
||||||
170
commands/receipts/receiptCommands.js
Normal file
170
commands/receipts/receiptCommands.js
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
category: 'utility',
|
||||||
|
global: true,
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('budget')
|
||||||
|
.setDescription('The thing')
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('set')
|
||||||
|
.setDescription('Set weekly budget')
|
||||||
|
.addIntegerOption(option =>
|
||||||
|
option.setName('amount')
|
||||||
|
.setRequired(true)
|
||||||
|
.setDescription('Amount as int'))
|
||||||
|
.addBooleanOption(option =>
|
||||||
|
option.setName('override')
|
||||||
|
.setRequired(false)
|
||||||
|
.setDescription('Override budget of current period'))
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('view')
|
||||||
|
.setDescription('View your grocery spendings for the current or previous week')
|
||||||
|
.addUserOption(option =>
|
||||||
|
option.setName('user')
|
||||||
|
.setRequired(false)
|
||||||
|
.setDescription('User to view budget for'))
|
||||||
|
.addBooleanOption(option =>
|
||||||
|
option
|
||||||
|
.setName('lastweek')
|
||||||
|
.setDescription('Show spendings from the previous budget cycle instead of the current one')
|
||||||
|
.setRequired(false)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('stats')
|
||||||
|
.setDescription('View detailed spending and savings statistics')
|
||||||
|
.addUserOption(option =>
|
||||||
|
option.setName('user')
|
||||||
|
.setRequired(false)
|
||||||
|
.setDescription('User to view stats for'))
|
||||||
|
),
|
||||||
|
async execute(interaction) {
|
||||||
|
console.log('budget command entrypoint');
|
||||||
|
let db = await interaction.client.localDB;
|
||||||
|
let targetUser = interaction.options.getUser('user') ?? interaction.user;
|
||||||
|
let discordId = interaction.member.id;
|
||||||
|
console.log(db, discordId);
|
||||||
|
let allowed = ['372115788498468864', '222457277708369928'].includes(discordId);
|
||||||
|
console.log(allowed);
|
||||||
|
if (!allowed) {
|
||||||
|
console.log('budget command denied');
|
||||||
|
await interaction.reply('This command may only be invoked by Miffy!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(`Switcching on sub ${interaction.options.getSubcommand()}`);
|
||||||
|
switch (interaction.options.getSubcommand()) {
|
||||||
|
case 'set':
|
||||||
|
console.log('budget command set');
|
||||||
|
let override = interaction.options.getBoolean('override') ?? false;
|
||||||
|
let budget = interaction.options.get('amount').value;
|
||||||
|
db.prepare(`INSERT OR REPLACE INTO bot_config (id, weekly_budget) VALUES (1, ?)`).run(budget);
|
||||||
|
if (override) {
|
||||||
|
db.prepare(`
|
||||||
|
UPDATE weekly_budgets
|
||||||
|
SET budget_amount = ?
|
||||||
|
WHERE id = (
|
||||||
|
SELECT id FROM weekly_budgets
|
||||||
|
WHERE date('now', 'localtime') BETWEEN start_date AND end_date
|
||||||
|
ORDER BY id DESC
|
||||||
|
LIMIT 1
|
||||||
|
)`).run(budget);
|
||||||
|
|
||||||
|
}
|
||||||
|
await interaction.reply(`Budget set for ${targetUser.username} to ${Number(budget).toFixed(2)}.`);
|
||||||
|
break;
|
||||||
|
case 'view':
|
||||||
|
const lastWeek = interaction.options.getBoolean('lastweek') ?? false;
|
||||||
|
const currentBudget = db.prepare(`
|
||||||
|
SELECT id, budget_amount, exchange_rate, start_date, end_date
|
||||||
|
FROM weekly_budgets
|
||||||
|
WHERE ${lastWeek ? "start_date < date('now', 'localtime')" : "date('now', 'localtime') BETWEEN start_date AND end_date"}
|
||||||
|
ORDER BY start_date DESC
|
||||||
|
LIMIT 1
|
||||||
|
`).get();
|
||||||
|
|
||||||
|
if (!currentBudget) {
|
||||||
|
await interaction.reply("No budget period found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userSpendings = db.prepare(`
|
||||||
|
SELECT amount, message_raw
|
||||||
|
FROM grocery_spendings
|
||||||
|
WHERE budget_id = ? AND discord_id = ?
|
||||||
|
`).all(currentBudget.id, targetUser.id);
|
||||||
|
|
||||||
|
const totalSpentEur = userSpendings.reduce((acc, s) => {
|
||||||
|
return acc + s.amount;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
const remainingEur = currentBudget.budget_amount - totalSpentEur;
|
||||||
|
const remainingSek = remainingEur * currentBudget.exchange_rate;
|
||||||
|
|
||||||
|
const todayTimestamp = Math.floor(Date.now() / 1000);
|
||||||
|
const endTimestamp = Math.floor(new Date(`${currentBudget.end_date}T23:59:59`).getTime() / 1000);
|
||||||
|
|
||||||
|
const budgetEmbed = new EmbedBuilder()
|
||||||
|
.setColor(remainingEur > 0 ? 0x00ff00 : 0xff0000)
|
||||||
|
.setTitle(`${targetUser.globalName ?? targetUser.username} Budget as of <t:${todayTimestamp}:F>`)
|
||||||
|
.setDescription(`Period: \`${currentBudget.start_date}\` to \`${currentBudget.end_date}\`\nReset <t:${endTimestamp}:R>`)
|
||||||
|
.addFields(
|
||||||
|
{ name: 'Spent', value: `${totalSpentEur.toFixed(2)} €\n${(totalSpentEur * currentBudget.exchange_rate).toFixed(2)} kr`, inline: true },
|
||||||
|
{ name: 'Remaining', value: `${remainingEur.toFixed(2)} €\n${remainingSek.toFixed(2)} kr`, inline: true },
|
||||||
|
)
|
||||||
|
.setFooter({ text: `Exchange rate this week: 1 € = ${currentBudget.exchange_rate.toFixed(2)} kr` })
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [budgetEmbed] });
|
||||||
|
break
|
||||||
|
case 'stats':
|
||||||
|
const allBudgets = db.prepare(`
|
||||||
|
SELECT id, budget_amount, exchange_rate, start_date, end_date
|
||||||
|
FROM weekly_budgets
|
||||||
|
ORDER BY start_date ASC
|
||||||
|
LIMIT 4
|
||||||
|
`).all();
|
||||||
|
|
||||||
|
let statsDescription = "";
|
||||||
|
let cumulativeSavingsEur = 0;
|
||||||
|
|
||||||
|
for (const budgetPeriod of allBudgets) {
|
||||||
|
const periodSpendings = db.prepare(`
|
||||||
|
SELECT amount
|
||||||
|
FROM grocery_spendings
|
||||||
|
WHERE budget_id = ? AND discord_id = ?
|
||||||
|
`).all(budgetPeriod.id, targetUser.id);
|
||||||
|
|
||||||
|
const totalSpentInPeriodEur = periodSpendings.reduce((acc, s) => acc + s.amount, 0);
|
||||||
|
const savedInPeriodEur = Number(budgetPeriod.budget_amount) - Number(totalSpentInPeriodEur);
|
||||||
|
cumulativeSavingsEur += savedInPeriodEur;
|
||||||
|
|
||||||
|
statsDescription += `**Period: ${budgetPeriod.start_date} - ${budgetPeriod.end_date}**\n`;
|
||||||
|
statsDescription += `Budget: ${budgetPeriod.budget_amount.toFixed(2)}€\n`;
|
||||||
|
statsDescription += `Spent: ${totalSpentInPeriodEur.toFixed(2)}€ (${(totalSpentInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`;
|
||||||
|
statsDescription += `Saved: ${savedInPeriodEur.toFixed(2)}€ (${(savedInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`;
|
||||||
|
statsDescription += `Cumulative: ${cumulativeSavingsEur.toFixed(2)}€\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allBudgets.length === 0) {
|
||||||
|
statsDescription = "No budget periods on record.";
|
||||||
|
}
|
||||||
|
|
||||||
|
const statsEmbed = new EmbedBuilder()
|
||||||
|
.setColor(0x0099ff)
|
||||||
|
.setTitle(`${targetUser.globalName ?? targetUser.username}'s Budget Statistics`)
|
||||||
|
.setDescription(statsDescription)
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [statsEmbed] });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
await interaction.reply(`Sub mismatch. Switching on ${interaction.options.getSubcommand()}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
category: 'utility',
|
|
||||||
global: true,
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName('budget')
|
|
||||||
.setDescription('The thing')
|
|
||||||
.addSubcommand(subcommand =>
|
|
||||||
subcommand
|
|
||||||
.setName('set')
|
|
||||||
.setDescription('Set weekly budget')
|
|
||||||
.addIntegerOption(option =>
|
|
||||||
option.setName('amount')
|
|
||||||
.setRequired(true)
|
|
||||||
.setDescription('Amount as int'))
|
|
||||||
)
|
|
||||||
.addSubcommand(subcommand =>
|
|
||||||
subcommand
|
|
||||||
.setName('show')
|
|
||||||
.setDescription('not implemented')
|
|
||||||
),
|
|
||||||
async execute(interaction) {
|
|
||||||
console.log('budget command entrypoint');
|
|
||||||
let db = await interaction.client.localDB;
|
|
||||||
let discordId = interaction.member.id;
|
|
||||||
console.log(db, discordId);
|
|
||||||
let allowed = ['372115788498468864', '222457277708369928'].includes(discordId);
|
|
||||||
console.log(allowed);
|
|
||||||
if (!allowed) {
|
|
||||||
console.log('budget command denied');
|
|
||||||
await interaction.reply('This command may only be invoked by Miffy!');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
console.log(`Switcching on sub ${interaction.options.getSubcommand()}`);
|
|
||||||
switch (interaction.options.getSubcommand()) {
|
|
||||||
case 'set':
|
|
||||||
console.log('budget command set');
|
|
||||||
let budget = interaction.options.get('amount').value
|
|
||||||
db.prepare(`INSERT OR REPLACE INTO bot_config (id, weekly_budget) VALUES (1, ?)`).run(budget);
|
|
||||||
await interaction.reply(`Budget set to ${budget}`);
|
|
||||||
break;
|
|
||||||
case 'show':
|
|
||||||
console.log('budget command show');
|
|
||||||
await interaction.reply('Not implemented');
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
await interaction.reply(`Sub mismatch. Switching on ${interaction.options.getSubcommand()}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
||||||
51
core/db.js
51
core/db.js
@@ -1,7 +1,7 @@
|
|||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const Database = require("better-sqlite3");
|
const Database = require("better-sqlite3");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const { open } = require('sqlite');
|
const { Umzug, JSONStorage } = require('umzug');
|
||||||
const filepath = "./data/minzbot.db";
|
const filepath = "./data/minzbot.db";
|
||||||
|
|
||||||
async function createDbConnection() {
|
async function createDbConnection() {
|
||||||
@@ -12,51 +12,22 @@ async function createDbConnection() {
|
|||||||
|
|
||||||
const db = new Database(filepath, { verbose: console.log });
|
const db = new Database(filepath, { verbose: console.log });
|
||||||
|
|
||||||
initDB(db);
|
await runMigrations(db);
|
||||||
|
|
||||||
console.log("[DATABASE] Connection with better-sqlite3 established");
|
console.log("[DATABASE] Connection with better-sqlite3 established");
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initDB(db) {
|
async function runMigrations(db) {
|
||||||
await db.exec(`
|
const umzug = new Umzug({
|
||||||
CREATE TABLE IF NOT EXISTS anniversaries (
|
migrations: { glob: 'migrations/*.js' },
|
||||||
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
context: db,
|
||||||
name VARCHAR(50) NOT NULL,
|
storage: new JSONStorage({ path: './data/migrations.json' }),
|
||||||
guild_id TEXT NOT NULL,
|
logger: console,
|
||||||
discord_id VARCHAR(50) NOT NULL,
|
});
|
||||||
last_anniversary_notification TEXT
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
await db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS lastfm (
|
|
||||||
discord_id TEXT PRIMARY KEY NOT NULL,
|
|
||||||
lastfm_name TEXT
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
await db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS bot_config (
|
|
||||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
||||||
weekly_budget REAL DEFAULT 0,
|
|
||||||
exchange_rate_eur_kr REAL DEFAULT 0,
|
|
||||||
last_budget_notification_date TEXT
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
await db.exec(`
|
|
||||||
CREATE TABLE IF NOT EXISTS grocery_budgets (
|
|
||||||
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
discord_id VARCHAR(50) NOT NULL,
|
|
||||||
budget_spent REAL,
|
|
||||||
total_spent REAL
|
|
||||||
);
|
|
||||||
`);
|
|
||||||
|
|
||||||
// Optional: Initialize the row if it doesn't exist yet
|
await umzug.up();
|
||||||
await db.exec(`
|
console.log('[DATABASE] Migrations applied successfully');
|
||||||
INSERT OR IGNORE INTO bot_config (id, weekly_budget, last_budget_notification_date)
|
|
||||||
VALUES (1, 0, NULL);
|
|
||||||
`);
|
|
||||||
console.log('[DATABASE] Created new DB table');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = createDbConnection;
|
module.exports = createDbConnection;
|
||||||
8
core/utils.js
Normal file
8
core/utils.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
formatDate (date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
docker-compose.yml
Normal file
10
docker-compose.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
services:
|
||||||
|
minzbot:
|
||||||
|
build: .
|
||||||
|
container_name: minzbot
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./config.json:/usr/src/app/config.json:ro
|
||||||
|
- ./data:/usr/src/app/data
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
@@ -5,20 +5,42 @@ module.exports = {
|
|||||||
async execute(message) {
|
async execute(message) {
|
||||||
if (message.author.bot) return;
|
if (message.author.bot) return;
|
||||||
|
|
||||||
if(message.channel.id === '1462060674766344370') {
|
const receiptsChannelId = process.env.NODE_ENV === 'development' ? '1468186493251227658' : '1462060674766344370';
|
||||||
|
if(message.channel.id === receiptsChannelId) {
|
||||||
|
const CURRENCY_MAP = {
|
||||||
|
"222457277708369928": "EUR", // Minz
|
||||||
|
"372115788498468864": "SEK", // Miffy
|
||||||
|
};
|
||||||
|
|
||||||
let reply = "";
|
let reply = "";
|
||||||
let db = await message.client.localDB;
|
let db = await message.client.localDB;
|
||||||
const receiptsChannel = message.channel;
|
const receiptsChannel = message.channel;
|
||||||
const authorId = message.author.id;
|
const authorId = message.author.id;
|
||||||
|
|
||||||
let budgets = await db.prepare(`SELECT * FROM grocery_budgets WHERE discord_id = ?`).get(authorId);
|
|
||||||
let weeklyBudget = await (await db.prepare(`SELECT weekly_budget FROM bot_config`).get()).weekly_budget;
|
const currentBudget = db.prepare(`
|
||||||
|
SELECT id, exchange_rate, budget_amount FROM weekly_budgets
|
||||||
console.log(weeklyBudget, budgets);
|
WHERE date('now', 'localtime') BETWEEN start_date AND end_date
|
||||||
if (budgets === undefined) {
|
ORDER BY created_at DESC
|
||||||
console.log(`No budget row in db for ${authorId}`);
|
LIMIT 1
|
||||||
db.prepare(`INSERT OR REPLACE INTO grocery_budgets (discord_id, budget_spent, total_spent) VALUES (?,0,0)`).run(authorId);
|
`).get();
|
||||||
|
|
||||||
|
if (message.content === "fuck") {
|
||||||
|
|
||||||
|
let lastSpend = db.prepare(`
|
||||||
|
SELECT id, amount, message_raw, created_at
|
||||||
|
FROM grocery_spendings
|
||||||
|
WHERE discord_id = ? AND budget_id = ?
|
||||||
|
ORDER BY created_at DESC, id DESC
|
||||||
|
LIMIT 1
|
||||||
|
`).get(authorId, currentBudget.id);
|
||||||
|
if (lastSpend) {
|
||||||
|
db.prepare(`DELETE FROM grocery_spendings WHERE id = ?`).run(lastSpend.id);
|
||||||
|
await message.reply(`Your last spending of ${lastSpend.amount.toFixed(2)}€ has been deleted.`);
|
||||||
|
} else {
|
||||||
|
await message.reply("You don't have any entries within the current budgeting period!");
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let matches = [];
|
let matches = [];
|
||||||
@@ -27,19 +49,56 @@ module.exports = {
|
|||||||
lines.forEach(line => {0
|
lines.forEach(line => {0
|
||||||
if (line.startsWith('-')) {
|
if (line.startsWith('-')) {
|
||||||
console.log(`Matching on line ${line}`);
|
console.log(`Matching on line ${line}`);
|
||||||
const regex = /-(?=[0-9])([0-9]*,?[0-9]*)/m;
|
const regex = /-(?=[0-9])([0-9]*[.,]?[0-9]*)/m;
|
||||||
let match = regex.exec(line)
|
let match = regex.exec(line)
|
||||||
console.log(match);
|
console.log(match);
|
||||||
additionalSpent = additionalSpent + parseFloat(match[1]);
|
if (match) {
|
||||||
|
additionalSpent = additionalSpent + parseFloat(match[1].replace(',', '.'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (additionalSpent > 0) {
|
|
||||||
db.prepare(`UPDATE grocery_budgets SET budget_spent = ?, total_spent = ? WHERE discord_id = ?`).run(budgets.budget_spent + additionalSpent, budgets.total_spent + additionalSpent, authorId);
|
|
||||||
let remainingBudget = weeklyBudget - (budgets.budget_spent + additionalSpent);
|
|
||||||
|
|
||||||
reply = `${message.author.globalName} spent ${additionalSpent} of their budget.\nThey have ${remainingBudget} remaining.`;
|
if (additionalSpent > 0) {
|
||||||
await receiptsChannel.send(reply);
|
|
||||||
|
|
||||||
|
const currency = CURRENCY_MAP[authorId] || "EUR"
|
||||||
|
switch (currency) {
|
||||||
|
case "SEK":
|
||||||
|
additionalSpent = additionalSpent / currentBudget.exchange_rate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
db.prepare(`
|
||||||
|
INSERT INTO grocery_spendings (
|
||||||
|
discord_id,
|
||||||
|
message_id,
|
||||||
|
message_raw,
|
||||||
|
amount,
|
||||||
|
budget_id
|
||||||
|
) VALUES (?, ?, ?, ?, ?)
|
||||||
|
`).run(
|
||||||
|
authorId,
|
||||||
|
message.id,
|
||||||
|
message.content,
|
||||||
|
additionalSpent,
|
||||||
|
currentBudget.id
|
||||||
|
);
|
||||||
|
|
||||||
|
const allSpendings = db.prepare(`
|
||||||
|
SELECT amount
|
||||||
|
FROM grocery_spendings
|
||||||
|
WHERE budget_id = ? AND discord_id = ?
|
||||||
|
`).all(currentBudget.id, authorId);
|
||||||
|
|
||||||
|
const totalSpent = allSpendings.reduce((acc, entry) => {
|
||||||
|
return acc + entry.amount;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
reply = `${message.author.globalName} spent ${additionalSpent.toFixed(2)}€ / ${(additionalSpent * currentBudget.exchange_rate).toFixed(2)} kr of their budget.\nThey have ${(currentBudget.budget_amount - totalSpent).toFixed(2)}€ / ${((currentBudget.budget_amount - totalSpent) * currentBudget.exchange_rate).toFixed(2)} kr remaining.`;
|
||||||
|
await message.reply(reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
61
migrations/00_initial_schema.js
Normal file
61
migrations/00_initial_schema.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
module.exports = {
|
||||||
|
up: async ({ context: db }) => {
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS anniversaries (
|
||||||
|
ID INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name VARCHAR(50) NOT NULL,
|
||||||
|
guild_id TEXT NOT NULL,
|
||||||
|
discord_id VARCHAR(50) NOT NULL,
|
||||||
|
last_anniversary_notification TEXT
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS lastfm (
|
||||||
|
discord_id TEXT PRIMARY KEY NOT NULL,
|
||||||
|
lastfm_name TEXT
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS bot_config (
|
||||||
|
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||||
|
weekly_budget REAL DEFAULT 0,
|
||||||
|
last_date_msg_receipts DATE NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS weekly_budgets (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
start_date DATE NOT NULL,
|
||||||
|
end_date DATE NOT NULL,
|
||||||
|
budget_amount DECIMAL(10, 2) NOT NULL,
|
||||||
|
exchange_rate DECIMAL(10, 6) NOT NULL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
CONSTRAINT date_check CHECK (end_date > start_date)
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
db.exec(`CREATE INDEX IF NOT EXISTS idx_budget_dates ON weekly_budgets (start_date, end_date);`);
|
||||||
|
db.exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS grocery_spendings (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
discord_id VARCHAR(50) NOT NULL,
|
||||||
|
message_id VARCHAR(50) NOT NULL,
|
||||||
|
message_raw TEXT DEFAULT "-",
|
||||||
|
amount DECIMAL(10, 2) NOT NULL,
|
||||||
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
budget_id INTEGER,
|
||||||
|
FOREIGN KEY (budget_id) REFERENCES weekly_budgets(id)
|
||||||
|
);
|
||||||
|
`);
|
||||||
|
db.exec(`
|
||||||
|
INSERT OR IGNORE INTO bot_config (id, weekly_budget)
|
||||||
|
VALUES (1, 10);
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
down: async ({ context: db }) => {
|
||||||
|
db.exec(`DROP TABLE IF EXISTS grocery_spendings;`);
|
||||||
|
db.exec(`DROP TABLE IF EXISTS weekly_budgets;`);
|
||||||
|
db.exec(`DROP TABLE IF EXISTS bot_config;`);
|
||||||
|
db.exec(`DROP TABLE IF EXISTS lastfm;`);
|
||||||
|
db.exec(`DROP TABLE IF EXISTS anniversaries;`);
|
||||||
|
}
|
||||||
|
};
|
||||||
589
package-lock.json
generated
589
package-lock.json
generated
@@ -14,7 +14,8 @@
|
|||||||
"discord.js": "^14.13.0",
|
"discord.js": "^14.13.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"spotify-web-api-node": "^5.0.2",
|
"spotify-web-api-node": "^5.0.2",
|
||||||
"sqlite": "^5.1.1"
|
"sqlite": "^5.1.1",
|
||||||
|
"umzug": "^3.8.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/builders": {
|
"node_modules/@discordjs/builders": {
|
||||||
@@ -99,6 +100,110 @@
|
|||||||
"node": ">=16.11.0"
|
"node": ">=16.11.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
|
"version": "2.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
|
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "2.0.5",
|
||||||
|
"run-parallel": "^1.1.9"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.stat": {
|
||||||
|
"version": "2.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||||
|
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@nodelib/fs.walk": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.scandir": "2.1.5",
|
||||||
|
"fastq": "^1.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rushstack/node-core-library": {
|
||||||
|
"version": "5.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.13.0.tgz",
|
||||||
|
"integrity": "sha512-IGVhy+JgUacAdCGXKUrRhwHMTzqhWwZUI+qEPcdzsb80heOw0QPbhhoVsoiMF7Klp8eYsp7hzpScMXmOa3Uhfg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "~8.13.0",
|
||||||
|
"ajv-draft-04": "~1.0.0",
|
||||||
|
"ajv-formats": "~3.0.1",
|
||||||
|
"fs-extra": "~11.3.0",
|
||||||
|
"import-lazy": "~4.0.0",
|
||||||
|
"jju": "~1.4.0",
|
||||||
|
"resolve": "~1.22.1",
|
||||||
|
"semver": "~7.5.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/node": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rushstack/node-core-library/node_modules/semver": {
|
||||||
|
"version": "7.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||||
|
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^6.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"semver": "bin/semver.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rushstack/terminal": {
|
||||||
|
"version": "0.15.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.15.2.tgz",
|
||||||
|
"integrity": "sha512-7Hmc0ysK5077R/IkLS9hYu0QuNafm+TbZbtYVzCMbeOdMjaRboLKrhryjwZSRJGJzu+TV1ON7qZHeqf58XfLpA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@rushstack/node-core-library": "5.13.0",
|
||||||
|
"supports-color": "~8.1.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@types/node": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@rushstack/ts-command-line": {
|
||||||
|
"version": "4.23.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.7.tgz",
|
||||||
|
"integrity": "sha512-Gr9cB7DGe6uz5vq2wdr89WbVDKz0UeuFEn5H2CfWDe7JvjFFaiV15gi6mqDBTbHhHCWS7w8mF1h3BnIfUndqdA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@rushstack/terminal": "0.15.2",
|
||||||
|
"@types/argparse": "1.0.38",
|
||||||
|
"argparse": "~1.0.9",
|
||||||
|
"string-argv": "~0.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@sapphire/async-queue": {
|
"node_modules/@sapphire/async-queue": {
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.0.tgz",
|
||||||
@@ -130,6 +235,12 @@
|
|||||||
"npm": ">=7.0.0"
|
"npm": ">=7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/argparse": {
|
||||||
|
"version": "1.0.38",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz",
|
||||||
|
"integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "20.8.10",
|
"version": "20.8.10",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz",
|
||||||
@@ -155,6 +266,62 @@
|
|||||||
"npm": ">=7.0.0"
|
"npm": ">=7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ajv": {
|
||||||
|
"version": "8.13.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz",
|
||||||
|
"integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.4.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ajv-draft-04": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"ajv": "^8.5.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"ajv": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ajv-formats": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "^8.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"ajv": "^8.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"ajv": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/argparse": {
|
||||||
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sprintf-js": "~1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
@@ -237,6 +404,18 @@
|
|||||||
"readable-stream": "^3.4.0"
|
"readable-stream": "^3.4.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/braces": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"fill-range": "^7.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/buffer": {
|
"node_modules/buffer": {
|
||||||
"version": "5.7.1",
|
"version": "5.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
|
||||||
@@ -433,6 +612,18 @@
|
|||||||
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
"url": "https://github.com/motdotla/dotenv?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/emittery": {
|
||||||
|
"version": "0.13.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
|
||||||
|
"integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/end-of-stream": {
|
"node_modules/end-of-stream": {
|
||||||
"version": "1.4.5",
|
"version": "1.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
@@ -475,17 +666,54 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-glob": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@nodelib/fs.stat": "^2.0.2",
|
||||||
|
"@nodelib/fs.walk": "^1.2.3",
|
||||||
|
"glob-parent": "^5.1.2",
|
||||||
|
"merge2": "^1.3.0",
|
||||||
|
"micromatch": "^4.0.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fast-safe-stringify": {
|
"node_modules/fast-safe-stringify": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||||
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
|
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fastq": {
|
||||||
|
"version": "1.20.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
|
||||||
|
"integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"reusify": "^1.0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/file-uri-to-path": {
|
"node_modules/file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fill-range": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"to-regex-range": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.6",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||||
@@ -533,6 +761,20 @@
|
|||||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fs-extra": {
|
||||||
|
"version": "11.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz",
|
||||||
|
"integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"graceful-fs": "^4.2.0",
|
||||||
|
"jsonfile": "^6.0.1",
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||||
@@ -565,6 +807,18 @@
|
|||||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/glob-parent": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gopd": {
|
"node_modules/gopd": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||||
@@ -576,6 +830,21 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/graceful-fs": {
|
||||||
|
"version": "4.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||||
|
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/has-flag": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/has-property-descriptors": {
|
"node_modules/has-property-descriptors": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||||
@@ -640,6 +909,15 @@
|
|||||||
],
|
],
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
|
"node_modules/import-lazy": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/inherits": {
|
"node_modules/inherits": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
@@ -651,6 +929,75 @@
|
|||||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/is-core-module": {
|
||||||
|
"version": "2.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
|
||||||
|
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-extglob": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-glob": {
|
||||||
|
"version": "4.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-extglob": "^2.1.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-number": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.12.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/jju": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/jsonfile": {
|
||||||
|
"version": "6.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||||
|
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"universalify": "^2.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"graceful-fs": "^4.1.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
@@ -677,6 +1024,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/magic-bytes.js/-/magic-bytes.js-1.5.0.tgz",
|
||||||
"integrity": "sha512-wJkXvutRbNWcc37tt5j1HyOK1nosspdh3dj6LUYYAvF6JYNqs53IfRvK9oEpcwiDA1NdoIi64yAMfdivPeVAyw=="
|
"integrity": "sha512-wJkXvutRbNWcc37tt5j1HyOK1nosspdh3dj6LUYYAvF6JYNqs53IfRvK9oEpcwiDA1NdoIi64yAMfdivPeVAyw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/merge2": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
|
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/methods": {
|
"node_modules/methods": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||||
@@ -685,6 +1041,19 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/micromatch": {
|
||||||
|
"version": "4.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||||
|
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"braces": "^3.0.3",
|
||||||
|
"picomatch": "^2.3.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/mime": {
|
"node_modules/mime": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
|
||||||
@@ -782,6 +1151,33 @@
|
|||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/path-parse": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/picomatch": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pony-cause": {
|
||||||
|
"version": "2.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/pony-cause/-/pony-cause-2.1.11.tgz",
|
||||||
|
"integrity": "sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==",
|
||||||
|
"license": "0BSD",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prebuild-install": {
|
"node_modules/prebuild-install": {
|
||||||
"version": "7.1.3",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
|
||||||
@@ -823,6 +1219,15 @@
|
|||||||
"once": "^1.3.1"
|
"once": "^1.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/punycode": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/qs": {
|
"node_modules/qs": {
|
||||||
"version": "6.12.0",
|
"version": "6.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz",
|
||||||
@@ -837,6 +1242,26 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/queue-microtask": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/rc": {
|
"node_modules/rc": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.8",
|
||||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||||
@@ -865,6 +1290,68 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/require-from-string": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/resolve": {
|
||||||
|
"version": "1.22.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
|
||||||
|
"integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-core-module": "^2.16.1",
|
||||||
|
"path-parse": "^1.0.7",
|
||||||
|
"supports-preserve-symlinks-flag": "^1.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"resolve": "bin/resolve"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/reusify": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"iojs": ">=1.0.0",
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/run-parallel": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "patreon",
|
||||||
|
"url": "https://www.patreon.com/feross"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "consulting",
|
||||||
|
"url": "https://feross.org/support"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"queue-microtask": "^1.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -984,6 +1471,12 @@
|
|||||||
"superagent": "^6.1.0"
|
"superagent": "^6.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sprintf-js": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/sqlite": {
|
"node_modules/sqlite": {
|
||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/sqlite/-/sqlite-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/sqlite/-/sqlite-5.1.1.tgz",
|
||||||
@@ -1005,6 +1498,15 @@
|
|||||||
"safe-buffer": "~5.2.0"
|
"safe-buffer": "~5.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/string-argv": {
|
||||||
|
"version": "0.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
|
||||||
|
"integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strip-json-comments": {
|
"node_modules/strip-json-comments": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||||
@@ -1036,6 +1538,33 @@
|
|||||||
"node": ">= 7.0.0"
|
"node": ">= 7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/supports-color": {
|
||||||
|
"version": "8.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||||
|
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"has-flag": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/supports-color?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/supports-preserve-symlinks-flag": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tar-fs": {
|
"node_modules/tar-fs": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||||
@@ -1064,6 +1593,18 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/to-regex-range": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-number": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ts-mixer": {
|
"node_modules/ts-mixer": {
|
||||||
"version": "6.0.3",
|
"version": "6.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.3.tgz",
|
||||||
@@ -1086,6 +1627,34 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/type-fest": {
|
||||||
|
"version": "4.41.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
|
||||||
|
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/umzug": {
|
||||||
|
"version": "3.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/umzug/-/umzug-3.8.2.tgz",
|
||||||
|
"integrity": "sha512-BEWEF8OJjTYVC56GjELeHl/1XjFejrD7aHzn+HldRJTx+pL1siBrKHZC8n4K/xL3bEzVA9o++qD1tK2CpZu4KA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@rushstack/ts-command-line": "^4.12.2",
|
||||||
|
"emittery": "^0.13.0",
|
||||||
|
"fast-glob": "^3.3.2",
|
||||||
|
"pony-cause": "^2.1.4",
|
||||||
|
"type-fest": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/undici": {
|
"node_modules/undici": {
|
||||||
"version": "5.22.1",
|
"version": "5.22.1",
|
||||||
"resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz",
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz",
|
||||||
@@ -1102,6 +1671,24 @@
|
|||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/universalify": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/uri-js": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|||||||
@@ -5,14 +5,16 @@
|
|||||||
"discord.js": "^14.13.0",
|
"discord.js": "^14.13.0",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"spotify-web-api-node": "^5.0.2",
|
"spotify-web-api-node": "^5.0.2",
|
||||||
"sqlite": "^5.1.1"
|
"sqlite": "^5.1.1",
|
||||||
|
"umzug": "^3.8.2"
|
||||||
},
|
},
|
||||||
"name": "minzbot",
|
"name": "minzbot",
|
||||||
"description": "Successor of the Discord.py implementation",
|
"description": "Successor of the Discord.py implementation",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"backup": "node scripts/backup.js"
|
||||||
},
|
},
|
||||||
"author": "Minz💕",
|
"author": "Minz💕",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
|
|||||||
25
scripts/backup.js
Normal file
25
scripts/backup.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const dbPath = path.join(__dirname, '../data/minzbot.db');
|
||||||
|
const backupDir = path.join(__dirname, '../data/backups');
|
||||||
|
|
||||||
|
if (!fs.existsSync(backupDir)) {
|
||||||
|
fs.mkdirSync(backupDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||||
|
const backupPath = path.join(backupDir, `${timestamp}_minzbot.db`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (fs.existsSync(dbPath)) {
|
||||||
|
fs.copyFileSync(dbPath, backupPath);
|
||||||
|
console.log(`Backup successful: ${backupPath}`);
|
||||||
|
} else {
|
||||||
|
console.error(`Database file not found at ${dbPath}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Backup failed:', error);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ module.exports = {
|
|||||||
animeList: ["K-On!", "Spice and Wolf", "Bakemonogatari", "Your Lie in April", "Noragami", "Puella Magi Madoka Magica", "Akame ga Kill!", "Steins;Gate", "\u3086\u308b\u30ad\u30e3\u30f3\u25b3"]
|
animeList: ["K-On!", "Spice and Wolf", "Bakemonogatari", "Your Lie in April", "Noragami", "Puella Magi Madoka Magica", "Akame ga Kill!", "Steins;Gate", "\u3086\u308b\u30ad\u30e3\u30f3\u25b3"]
|
||||||
},
|
},
|
||||||
async tick(client, timer) {
|
async tick(client, timer) {
|
||||||
|
return;
|
||||||
client.user.setActivity(timer.data.animeList[timer.data.statusIndex], { type: ActivityType.Watching });
|
client.user.setActivity(timer.data.animeList[timer.data.statusIndex], { type: ActivityType.Watching });
|
||||||
timer.data.statusIndex = (timer.data.statusIndex + 1) % timer.data.animeList.length
|
timer.data.statusIndex = (timer.data.statusIndex + 1) % timer.data.animeList.length
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,9 +8,6 @@ module.exports = {
|
|||||||
const keepMessageEmoteId = '1214140438265724980';
|
const keepMessageEmoteId = '1214140438265724980';
|
||||||
const channelConfigs = [
|
const channelConfigs = [
|
||||||
{ channelId: '1214134516247957504', keepTimeMinutes: 2, keepAttachment: true }, //toho-test/mnzbot-test
|
{ channelId: '1214134516247957504', keepTimeMinutes: 2, keepAttachment: true }, //toho-test/mnzbot-test
|
||||||
{ channelId: '1111054421091155978', keepTimeMinutes: 2880 }, //cotr/Spam
|
|
||||||
{ channelId: '1170190197384814762', keepTimeMinutes: 2880, keepAttachment: true }, //cotr/Red
|
|
||||||
{ channelId: '1101703550070947920', keepTimeMinutes: 2880, keepAttachment: true }, //cotr/Memes
|
|
||||||
];
|
];
|
||||||
function isMessageLocked(message) {
|
function isMessageLocked(message) {
|
||||||
for (const [id, reaction] of message.reactions.cache) {
|
for (const [id, reaction] of message.reactions.cache) {
|
||||||
|
|||||||
@@ -1,36 +1,103 @@
|
|||||||
|
const { formatDate } = require('../core/utils.js');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
timeout: 1000,
|
timeout: 10000,
|
||||||
immediate: false,
|
immediate: true,
|
||||||
name: 'Receipt Day Announcements',
|
name: 'Receipt Day Announcements',
|
||||||
data: {
|
data: {
|
||||||
channelId: '1462060674766344370',
|
channelId: process.env.NODE_ENV === 'development' ? '1468186493251227658' : '1462060674766344370',
|
||||||
targetHour: 0,
|
targetHour: 0,
|
||||||
targetMinute: 1
|
targetMinute: 1
|
||||||
},
|
},
|
||||||
async tick(client, timer) {
|
async tick(client, timer) {
|
||||||
|
|
||||||
|
//format date because isostring is utc duh
|
||||||
try {
|
try {
|
||||||
// 1. Send the message
|
const today = new Date();
|
||||||
const currentDate = new Date().toLocaleDateString('en-GB', {
|
const lastMonday = new Date(today);
|
||||||
weekday: 'long',
|
lastMonday.setDate(today.getDate() - ((today.getDay() === 0) ? 6 : today.getDay() - 1));
|
||||||
day: '2-digit',
|
const startDate = formatDate(lastMonday);
|
||||||
month: '2-digit',
|
|
||||||
year: 'numeric'
|
const nextSunday = new Date(lastMonday);
|
||||||
});
|
nextSunday.setDate(lastMonday.getDate() + 6);
|
||||||
|
const endDate = formatDate(nextSunday);
|
||||||
|
// 0 1 2 3 4 5 6
|
||||||
|
// S M T W T F S
|
||||||
|
let db = await client.localDB;
|
||||||
const channel = await client.channels.fetch(timer.data.channelId);
|
const channel = await client.channels.fetch(timer.data.channelId);
|
||||||
await channel.send(`${currentDate}`);
|
|
||||||
if (currentDate.startsWith('Sunday')) {
|
const config = await (await db.prepare(`SELECT weekly_budget, last_date_msg_receipts FROM bot_config`).get());
|
||||||
|
const existingBudget = db.prepare(`SELECT id FROM weekly_budgets WHERE start_date = ?`).get(startDate);
|
||||||
|
|
||||||
|
if (!existingBudget) {
|
||||||
|
await channel.send(`Format date last monday ${lastMonday} as startDate Format date next sunday ${nextSunday} as endDate`);
|
||||||
|
await channel.send(`\`\`\`SELECT id FROM weekly_budgets WHERE start_date = ${startDate}\`\`\`
|
||||||
|
${JSON.stringify(existingBudget)}`);
|
||||||
|
console.log(`No budget found for week starting ${startDate}.`);
|
||||||
const response = await fetch(`https://api.frankfurter.dev/v1/latest?amount=1&from=EUR&to=SEK`);
|
const response = await fetch(`https://api.frankfurter.dev/v1/latest?amount=1&from=EUR&to=SEK`);
|
||||||
|
|
||||||
|
|
||||||
if (!response.ok) await channel.send(`Failed to fetch exchange rate:\n${response.statusText}`);
|
if (!response.ok) await channel.send(`Failed to fetch exchange rate:\n${response.statusText}`);
|
||||||
let db = await client.localDB;
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
db.prepare(`UPDATE bot_config SET exchange_rate_eur_kr = ? WHERE id = 1`).run(data.rates.SEK);
|
//await channel.send(`Fetched new exchange rate:\n${JSON.stringify(data)}`);
|
||||||
let weeklyBudget = await (await db.prepare(`SELECT weekly_budget FROM bot_config`).get()).weekly_budget;
|
await channel.send(`Reset weekly budget to ${config.weekly_budget.toFixed(2)}€ / ${(config.weekly_budget * data.rates.SEK).toFixed(2)} kr`);
|
||||||
await channel.send(`Fetched new exchange rate:\n${JSON.stringify(data)}`);
|
|
||||||
db.prepare(`UPDATE grocery_budgets SET budget_spent = 0`).run();
|
|
||||||
await channel.send(`Reset weekly budget to ${weeklyBudget}EUR / ${weeklyBudget*data.rates.SEK}SEK`);
|
db.prepare(`
|
||||||
|
INSERT INTO weekly_budgets (start_date, end_date, budget_amount, exchange_rate)
|
||||||
|
VALUES (?, ?, ?, ?)
|
||||||
|
`).run(startDate, endDate, config.weekly_budget, data.rates.SEK);
|
||||||
|
|
||||||
|
await channel.send(`\`\`\`INSERT INTO weekly_budgets (start_date, end_date, budget_amount, exchange_rate)
|
||||||
|
VALUES (${startDate}, ${endDate}, ${config.weekly_budget}, ${data.rates.SEK})\`\`\``);
|
||||||
|
} else {
|
||||||
|
console.log(`budget found for week starting ${startDate}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const notification = db.prepare(`
|
||||||
|
SELECT EXISTS (
|
||||||
|
SELECT 1 FROM bot_config
|
||||||
|
WHERE date(last_date_msg_receipts, 'localtime') = date('now', 'localtime')
|
||||||
|
) as was_sent_today
|
||||||
|
`).get();
|
||||||
|
|
||||||
|
const debug = db.prepare(`
|
||||||
|
SELECT
|
||||||
|
date(last_date_msg_receipts, 'localtime') AS last_date,
|
||||||
|
datetime('now', 'localtime') AS current_time_full,
|
||||||
|
(date(last_date_msg_receipts, 'localtime') = date('now', 'localtime')) AS was_sent_today
|
||||||
|
FROM bot_config
|
||||||
|
LIMIT 1;
|
||||||
|
`).get();
|
||||||
|
|
||||||
|
|
||||||
|
if (!notification.was_sent_today) {
|
||||||
|
await channel.send(`\`\`\`SELECT
|
||||||
|
date(last_date_msg_receipts, 'localtime') AS last_date,
|
||||||
|
datetime('now', 'localtime') AS current_time_full,
|
||||||
|
(date(last_date_msg_receipts, 'localtime') = date('now', 'localtime')) AS was_sent_today
|
||||||
|
FROM bot_config
|
||||||
|
LIMIT 1;\`\`\`
|
||||||
|
|
||||||
|
${JSON.stringify(debug)}`);
|
||||||
|
const currentDate = new Date().toLocaleDateString('en-GB', {
|
||||||
|
weekday: 'long',
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric'
|
||||||
|
});
|
||||||
|
await channel.send(`${currentDate}`);
|
||||||
|
console.log("No notification today, sending...");
|
||||||
|
db.prepare(`
|
||||||
|
UPDATE bot_config
|
||||||
|
SET last_date_msg_receipts = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = 1
|
||||||
|
`).run();
|
||||||
|
} else {
|
||||||
|
console.log("Notification already sent");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[TIMER] Error:', error);
|
console.error('[TIMER] Error:', error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -58,7 +125,7 @@ module.exports = {
|
|||||||
}, delay);
|
}, delay);
|
||||||
|
|
||||||
const channel = await client.channels.fetch(timer.data.channelId);
|
const channel = await client.channels.fetch(timer.data.channelId);
|
||||||
if (channel) await channel.send(`Next message scheduled for: ${next.toLocaleString()} with ms delta of ${delay} / ${delay/3600000}`);
|
//if (channel) await channel.send(`Next message scheduled for: ${next.toLocaleString()} with ms delta of ${delay} / ${delay/3600000}`);
|
||||||
console.log(`[TIMER] Next message scheduled for: ${next.toLocaleString()}`);
|
console.log(`[TIMER] Next message scheduled for: ${next.toLocaleString()}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user