migrate from pg to sequelize

This commit is contained in:
Rene Kievits
2024-09-14 02:20:30 +02:00
parent 5ed26bd488
commit 9fd47761b0
26 changed files with 1205 additions and 745 deletions

3
.gitignore vendored
View File

@@ -1,3 +1,6 @@
.env
node_modules/
package-lock.json
src/database/config/
src/database/migrations/
src/database/seeders/

59
eslint.config.mjs Normal file
View File

@@ -0,0 +1,59 @@
import globals from 'globals'
import pluginJs from '@eslint/js'
export default [
{
files: ['eslint.config.mjs'],
languageOptions: {
sourceType: 'module',
ecmaVersion: 2021,
},
rules: {
'semi': ['error', 'never'],
'quotes': ['error', 'single'],
'indent': ['error', 2],
'linebreak-style': ['error', 'unix'],
'comma-dangle': ['error', 'always-multiline'],
'no-unused-vars': ['error', {
vars: 'all',
args: 'after-used',
ignoreRestSiblings: true,
caughtErrors: 'none',
argsIgnorePattern: '_',
}],
},
},
{
files: ['**/*.js'],
languageOptions: {
sourceType: 'commonjs',
ecmaVersion: 2021,
},
rules: {
'semi': ['error', 'never'],
'quotes': ['error', 'single'],
'indent': ['error', 2],
'linebreak-style': ['error', 'unix'],
'comma-dangle': ['error', {
arrays: 'always-multiline',
objects: 'always-multiline',
imports: 'always-multiline',
exports: 'always-multiline',
functions: 'never',
}],
'no-unused-vars': ['error', {
vars: 'all',
args: 'after-used',
ignoreRestSiblings: true,
caughtErrors: 'none',
argsIgnorePattern: '_',
}],
},
},
{
languageOptions: {
globals: globals.browser,
},
},
pluginJs.configs.recommended,
]

View File

@@ -9,5 +9,12 @@
},
"scripts": {
"test": "jest"
},
"devDependencies": {
"@eslint/js": "^9.10.0",
"eslint": "^9.10.0",
"globals": "^15.9.0",
"sequelize-auto": "^0.8.8",
"sequelize-cli": "^6.6.2"
}
}

View File

@@ -1,100 +1,111 @@
const { getClient } = require('./database')
const {
birthday: Birthday,
discorduser: DiscordUser,
} = require('./models')
const CreateBirthday = async (user, birthday) => {
try {
const client = getClient()
const userResult = await client.query(`
SELECT * FROM discorduser
WHERE name = $1;`,
[user]
)
const CreateBirthday = async (userName, birthdayDate) => {
try {
const [user, _] = await DiscordUser.findOrCreate({
where: { name: userName },
defaults: { name: userName },
})
if (userResult.rows.length === 0) {
await client.query(`
INSERT INTO discorduser (name)
VALUES ($1);`,
[user]
)
}
const formattedBirthday = new Date(
birthdayDate.split('.').reverse().join('-')
).toISOString().slice(0, 10)
const res = await client.query(`
INSERT INTO birthday (date, discorduser)
VALUES ($1, $2);`,
[new Date(birthday.split('.').reverse().join('-')).toISOString().slice(0, 10), user]
)
const birthday = await Birthday.create({
date: formattedBirthday,
discorduser: user.name,
})
return res.rowCount > 0
} catch (error) {
console.error('Error creating birthday entry:', error)
return false
}
return birthday !== null
} catch (error) {
console.error('Error creating birthday entry:', error)
return false
}
}
const ReadBirthday = async (user) => {
try {
const client = getClient()
if (user) {
const res = await client.query(`
SELECT * FROM birthday
WHERE discorduser = $1;`,
[user]
)
return res.rows
} else {
const res = await client.query(`
SELECT * FROM birthday`,
)
return res.rows
}
} catch (error) {
console.error('Error reading birthday table:', error)
return []
}
const ReadBirthday = async (userName) => {
try {
if (userName) {
const user = await DiscordUser.findOne({
where: {
name: userName,
},
})
if (user) {
const birthdays = await Birthday.findAll({
where: {
discorduser: user.name,
},
})
return birthdays
} else return []
} else {
const birthdays = await Birthday.findAll()
return birthdays
}
} catch (error) {
console.error('Error reading birthday table:', error)
return []
}
}
const UpdateBirthday = async (user, birthday) => {
try {
const client = getClient()
const UpdateBirthday = async (userName, birthdayDate) => {
try {
const user = await DiscordUser.findOne({
where: {
name: userName,
},
})
if (!birthday) return false
await client.query(`
UPDATE birthday
SET birthday = $2
WHERE discorduser = $1;`,
[user, birthday]
)
return true
} catch (error) {
console.error('Error updating birthday table:', error)
return false
}
if (user) {
const [updated] = await Birthday.update(
{
date: new Date(
birthdayDate.split('.').reverse().join('-')
).toISOString().slice(0, 10),
},
{
where: {
discorduser: user.name,
},
}
)
return updated > 0
} else return false
} catch (error) {
console.error('Error updating birthday table:', error)
return false
}
}
const DeleteBirthday = async (user) => {
try {
const client = getClient()
const DeleteBirthday = async (userName) => {
try {
const user = await DiscordUser.findOne({
where: {
name: userName,
},
})
if (!user) return false
await client.query(`
DELETE FROM birthday
WHERE discorduser = $1;`,
[user]
)
return true
} catch (error) {
console.error('Error deleting birthday table:', error)
return false
}
if (user) {
const deleted = await Birthday.destroy({
where: {
discorduser: user.name,
},
})
return deleted > 0
} else return false
} catch (error) {
console.error('Error deleting birthday table:', error)
return false
}
}
module.exports = {
CreateBirthday,
ReadBirthday,
UpdateBirthday,
DeleteBirthday,
CreateBirthday,
ReadBirthday,
UpdateBirthday,
DeleteBirthday,
}

View File

@@ -1,99 +1,99 @@
const { getClient } = require('./database')
const {
blacklist: Blacklist,
discorduser: DiscordUser,
} = require('./models')
const CreateBlacklist = async (reportedUser, reason, reportedByUser) => {
try {
const client = getClient()
try {
const existingBlacklist = await Blacklist.findOne({
where: {
name: reportedUser,
},
})
const alreadyReportedResult = await client.query(
"SELECT name FROM blacklist WHERE name = $1",
[reportedUser]
)
if (existingBlacklist) return existingBlacklist
if (alreadyReportedResult.rows.length === 1)
return alreadyReportedResult.rows[0]
const [reportingUser] = await DiscordUser.findOrCreate({
where: {
name: reportedByUser,
},
defaults: {
name: reportedByUser,
},
})
const userResult = await client.query(
"SELECT * FROM discorduser WHERE name = $1",
[reportedByUser]
)
const blacklistEntry = await Blacklist.create({
name: reportedUser,
reason,
reportedby: reportingUser.name,
})
if (userResult.rows.length === 0)
await client.query(
"INSERT INTO discorduser (name) VALUES ($1)",
[reportedByUser]
)
await client.query(
"INSERT INTO blacklist (name, reason, reportedby) VALUES ($1, $2, $3)",
[reportedUser, reason, reportedByUser]
)
return true
} catch (error) {
console.error('Error creating blacklist entry:', error)
return false
}
return blacklistEntry !== null
} catch (error) {
console.error('Error creating blacklist entry:', error)
return false
}
}
const ReadBlacklist = async (user) => {
try {
const client = getClient()
if (user) {
const res = await client.query(
"SELECT * FROM blacklist WHERE name=$1",
[user]
)
return res.rows[0] || false
} else {
const res = await client.query(
"SELECT * FROM blacklist"
)
return res.rows
}
} catch (error) {
console.error('Error reading blacklist table:', error)
return []
}
const ReadBlacklist = async (userName) => {
try {
if (userName) {
const blacklistEntry = await Blacklist.findOne({
where: {
name: userName,
},
})
return blacklistEntry || false
} else {
const allBlacklistEntries = await Blacklist.findAll()
return allBlacklistEntries
}
} catch (error) {
console.error('Error reading blacklist table:', error)
return []
}
}
const UpdateBlacklist = async (reportedUser, reason) => {
try {
const client = getClient()
try {
if (!reportedUser) return false
if (!reportedUser) return false
const [updated] = await Blacklist.update(
{ reason },
{
where: {
name: reportedUser,
},
}
)
await client.query(
"UPDATE blacklist SET reason = $2 WHERE name = $1",
[reportedUser, reason]
)
return true
} catch (error) {
console.error('Error updating blacklist table:', error)
return false
}
return updated > 0
} catch (error) {
console.error('Error updating blacklist table:', error)
return false
}
}
const DeleteBlacklist = async (user) => {
try {
const client = getClient()
const DeleteBlacklist = async (userName) => {
try {
if (!userName) return false
if (!user) return false
const deleted = await Blacklist.destroy({
where: {
name: userName,
},
})
await client.query(
"DELETE FROM blacklist WHERE name = $1",
[user]
)
return true
} catch (error) {
console.error('Error deleting blacklist table:', error)
return false
}
return deleted > 0
} catch (error) {
console.error('Error deleting blacklist table:', error)
return false
}
}
module.exports = {
CreateBlacklist,
ReadBlacklist,
UpdateBlacklist,
DeleteBlacklist,
CreateBlacklist,
ReadBlacklist,
UpdateBlacklist,
DeleteBlacklist,
}

View File

@@ -1,32 +0,0 @@
const { Client } = require('pg')
let client = null
const createClient = (config) => {
client = new Client(config);
return client;
};
const connectDatabase = async (client) => {
try {
await client.connect()
console.log('Database connected')
} catch (error) {
console.error('Database connection error:', error)
throw new Error('Connection failed');
}
}
const getClient = () => {
if (!client) {
throw new Error('Client has not been initialized. Call createClient first.');
}
return client;
};
module.exports = {
createClient,
connectDatabase,
getClient,
}

View File

@@ -1,13 +1,13 @@
const { getClient } = require('./database')
const {
event_schedule: EventTimes,
event_role_view: EventRoleView,
event_roles: EventRoles,
} = require('./models')
const ReadEvents = async () => {
try {
const client = getClient()
const res = await client.query(
"SELECT * FROM event_times"
)
return res.rows
const events = await EventTimes.findAll()
return events
} catch (error) {
console.error('Error reading event entries:', error)
return false
@@ -16,34 +16,30 @@ const ReadEvents = async () => {
const GetEventRole = async () => {
try {
const client = getClient()
const res = await client.query(
"SELECT * FROM event_role_view"
)
const eventRoles = await EventRoleView.findAll()
const rolesEventMap = new Map()
res.rows.forEach(row => rolesEventMap.set(row.event_name, row.role))
eventRoles.forEach(row => rolesEventMap.set(row.event_name, row.role))
return rolesEventMap
} catch (error) {
console.error(error)
console.error('Error fetching event roles:', error)
return false
}
}
const GetIconRole = async () => {
try {
const client = getClient()
const eventIcons = await EventRoles.findAll({
attributes: ['role', 'icon_name'],
})
const rolesIconMap = new Map()
const res = await client.query(
"SELECT role, icon_name FROM event_roles"
)
const rolesEventMap = new Map()
res.rows.forEach(row => rolesEventMap.set(row.icon_name, row.role))
eventIcons.forEach(row => rolesIconMap.set(row.icon_name, row.role))
return rolesEventMap
return rolesIconMap
} catch (error) {
console.error(error)
console.error('Error fetching icon roles:', error)
return false
}
}

View File

@@ -0,0 +1,37 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('birthday', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
date: {
type: DataTypes.DATEONLY,
allowNull: false,
},
discorduser: {
type: DataTypes.STRING(100),
allowNull: false,
references: {
model: 'discorduser',
key: 'name',
},
},
}, {
sequelize,
tableName: 'birthday',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'birthday_pkey',
unique: true,
fields: [
{ name: 'id' },
],
},
],
})
}

View File

@@ -0,0 +1,36 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('blacklist', {
name: {
type: DataTypes.STRING(100),
allowNull: false,
primaryKey: true,
},
reason: {
type: DataTypes.TEXT,
allowNull: false,
},
reportedby: {
type: DataTypes.STRING(100),
allowNull: true,
references: {
model: 'discorduser',
key: 'name',
},
},
}, {
sequelize,
tableName: 'blacklist',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'blacklist_pkey',
unique: true,
fields: [
{ name: 'name' },
],
},
],
})
}

View File

@@ -0,0 +1,24 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('discorduser', {
name: {
type: DataTypes.STRING(100),
allowNull: false,
primaryKey: true,
},
}, {
sequelize,
tableName: 'discorduser',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'discorduser_pkey',
unique: true,
fields: [
{ name: 'name' },
],
},
],
})
}

View File

@@ -0,0 +1,37 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('event', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING(255),
allowNull: false,
unique: 'event_name_key',
},
}, {
sequelize,
tableName: 'event',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'event_name_key',
unique: true,
fields: [
{ name: 'name' },
],
},
{
name: 'event_pkey',
unique: true,
fields: [
{ name: 'id' },
],
},
],
})
}

View File

@@ -0,0 +1,41 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('event_roles', {
event_id: {
type: DataTypes.INTEGER,
allowNull: true,
references: {
model: 'event',
key: 'id',
},
},
role: {
type: DataTypes.STRING(50),
allowNull: false,
},
icon_name: {
type: DataTypes.STRING(50),
allowNull: true,
},
role_id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
}, {
sequelize,
tableName: 'event_roles',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'event_roles_pkey',
unique: true,
fields: [
{ name: 'role_id' },
],
},
],
})
}

View File

@@ -0,0 +1,45 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('event_schedule', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
event_id: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: 'event',
key: 'id',
},
},
day_of_week: {
type: DataTypes.STRING(9),
allowNull: true,
},
start_time: {
type: DataTypes.TIME,
allowNull: true,
},
end_time: {
type: DataTypes.TIME,
allowNull: true,
},
}, {
sequelize,
tableName: 'event_schedule',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'event_schedule_pkey',
unique: true,
fields: [
{ name: 'id' },
],
},
],
})
}

View File

@@ -0,0 +1,43 @@
'use strict'
const fs = require('fs')
const path = require('path')
const Sequelize = require('sequelize')
const process = require('process')
const basename = path.basename(__filename)
const env = process.env.NODE_ENV || 'development'
const config = require(__dirname + '/../config/config.json')[env]
const db = {}
let sequelize
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config)
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config)
}
fs
.readdirSync(__dirname)
.filter(file => {
return (
file.indexOf('.') !== 0 &&
file !== basename &&
file.slice(-3) === '.js' &&
file.indexOf('.test.js') === -1
)
})
.forEach(file => {
const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes)
db[model.name] = model
})
Object.keys(db).forEach(modelName => {
if (db[modelName].associate) {
db[modelName].associate(db)
}
})
db.sequelize = sequelize
db.Sequelize = Sequelize
module.exports = db

View File

@@ -0,0 +1,49 @@
var DataTypes = require('sequelize').DataTypes
var _birthday = require('./birthday')
var _blacklist = require('./blacklist')
var _discorduser = require('./discorduser')
var _event = require('./event')
var _event_roles = require('./event_roles')
var _event_schedule = require('./event_schedule')
var _static = require('./static')
var _static_members = require('./static_members')
function initModels(sequelize) {
var birthday = _birthday(sequelize, DataTypes)
var blacklist = _blacklist(sequelize, DataTypes)
var discorduser = _discorduser(sequelize, DataTypes)
var event = _event(sequelize, DataTypes)
var event_roles = _event_roles(sequelize, DataTypes)
var event_schedule = _event_schedule(sequelize, DataTypes)
var static = _static(sequelize, DataTypes)
var static_members = _static_members(sequelize, DataTypes)
discorduser.belongsToMany(static, { as: 'static_id_statics', through: static_members, foreignKey: 'username', otherKey: 'static_id' })
static.belongsToMany(discorduser, { as: 'username_discordusers', through: static_members, foreignKey: 'static_id', otherKey: 'username' })
birthday.belongsTo(discorduser, { as: 'discorduser_discorduser', foreignKey: 'discorduser'})
discorduser.hasMany(birthday, { as: 'birthdays', foreignKey: 'discorduser'})
blacklist.belongsTo(discorduser, { as: 'reportedby_discorduser', foreignKey: 'reportedby'})
discorduser.hasMany(blacklist, { as: 'blacklists', foreignKey: 'reportedby'})
static_members.belongsTo(discorduser, { as: 'username_discorduser', foreignKey: 'username'})
discorduser.hasMany(static_members, { as: 'static_members', foreignKey: 'username'})
event_roles.belongsTo(event, { as: 'event', foreignKey: 'event_id'})
event.hasMany(event_roles, { as: 'event_roles', foreignKey: 'event_id'})
event_schedule.belongsTo(event, { as: 'event', foreignKey: 'event_id'})
event.hasMany(event_schedule, { as: 'event_schedules', foreignKey: 'event_id'})
static_members.belongsTo(static, { as: 'static', foreignKey: 'static_id'})
static.hasMany(static_members, { as: 'static_members', foreignKey: 'static_id'})
return {
birthday,
blacklist,
discorduser,
event,
event_roles,
event_schedule,
static,
static_members,
}
}
module.exports = initModels
module.exports.initModels = initModels
module.exports.default = initModels

View File

@@ -0,0 +1,49 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('static', {
id: {
autoIncrement: true,
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
},
name: {
type: DataTypes.STRING(12),
allowNull: false,
unique: 'unique_name',
},
creator: {
type: DataTypes.STRING(255),
allowNull: false,
},
size: {
type: DataTypes.INTEGER,
allowNull: true,
},
time: {
type: DataTypes.DATE,
allowNull: true,
},
}, {
sequelize,
tableName: 'static',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'static_pkey',
unique: true,
fields: [
{ name: 'id' },
],
},
{
name: 'unique_name',
unique: true,
fields: [
{ name: 'name' },
],
},
],
})
}

View File

@@ -0,0 +1,38 @@
const Sequelize = require('sequelize')
module.exports = function(sequelize, DataTypes) {
return sequelize.define('static_members', {
static_id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
references: {
model: 'static',
key: 'id',
},
},
username: {
type: DataTypes.STRING(100),
allowNull: false,
primaryKey: true,
references: {
model: 'discorduser',
key: 'name',
},
},
}, {
sequelize,
tableName: 'static_members',
schema: 'public',
timestamps: false,
indexes: [
{
name: 'static_members_pkey',
unique: true,
fields: [
{ name: 'static_id' },
{ name: 'username' },
],
},
],
})
}

View File

@@ -1,61 +1,81 @@
const { getClient } = require('./database')
const {
static: Static,
static_members: StaticMembers,
discorduser: DiscordUser,
} = require('./models')
const CreateStatic = async (name, creator, members, size) => {
try {
const client = getClient()
try {
const staticEntry = await Static.create({
name,
creator,
size,
})
const result = await client.query(
"INSERT INTO static (name, creator, size) VALUES ($1, $2, $3) RETURNING id",
[name, creator, size]
)
const staticId = staticEntry.id
const staticId = result.rows[0].id
await Promise.all(
members.map(async member => {
const [user] = await DiscordUser.findOrCreate({
where: {
name: member,
},
defaults: {
name: member,
},
})
for (const member of members) {
await client.query(
"INSERT INTO static_members (static_id, member) VALUES ($1, $2)",
[staticId, member]
)
}
await StaticMembers.create({
static_id: staticId,
member: user.name,
})
})
)
return true
} catch (error) {
console.error('Error creating static entry:', error)
return false
}
return true
} catch (error) {
console.error('Error creating static entry:', error)
return false
}
}
const ReadStatic = async (name) => {
try {
const client = getClient()
const res = await client.query(
"SELECT * FROM static WHERE name = $1",
[name]
)
return res.rows
} catch (error) {
console.error('Error reading static entry:', error)
return false
}
try {
const staticEntry = await Static.findOne({
where: { name },
})
return staticEntry || false
} catch (error) {
console.error('Error reading static entry:', error)
return false
}
}
const DeleteStatic = async (name) => {
try {
const client = getClient()
try {
const staticEntry = await Static.findOne({
where: { name },
})
await client.query(
"DELETE FROM static WHERE name = $1",
[name]
)
} catch (error) {
console.error('Error deleting static entry:', error)
return false
}
if (!staticEntry) return false
await StaticMembers.destroy({
where: {
static_id: staticEntry.id,
},
})
await staticEntry.destroy()
return true
} catch (error) {
console.error('Error deleting static entry:', error)
return false
}
}
module.exports = {
CreateStatic,
ReadStatic,
DeleteStatic,
CreateStatic,
ReadStatic,
DeleteStatic,
}

View File

@@ -3,23 +3,23 @@ require('dotenv').config()
const { REST } = require('@discordjs/rest')
const { SlashCommandBuilder } = require('@discordjs/builders')
const {
initReactionPerRole,
messageReactionAdd,
messageReactionRemove,
initReactionPerRole,
messageReactionAdd,
messageReactionRemove,
} = require('../features/reactionPerRole')
const {
handleBlacklistAdd,
handleBlacklistCheck,
handleBlacklistShow,
updateGlobalMessage,
handleBlacklistAdd,
handleBlacklistCheck,
handleBlacklistShow,
updateGlobalMessage,
} = require('../features/blacklist')
const {
handleBirthdayAdd,
handleBirthdayUpdate,
handleBirthdayCheck,
handleBirthdayDelete,
handleBirthdayAdd,
handleBirthdayUpdate,
handleBirthdayCheck,
handleBirthdayDelete,
} = require('../features/birthday')
const { startBirthdayCheckCron } = require('../tasks/checkBirthday')
@@ -28,179 +28,179 @@ const { startEventCheckCron } = require('../tasks/eventReminder')
const rest = new REST({ version: '10' }).setToken(process.env.BOT_TOKEN)
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMessageReactions,
],
partials: [
Partials.Channel,
]
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMessageReactions,
],
partials: [
Partials.Channel,
],
})
client.on('interactionCreate', async interaction => {
if (!interaction.isCommand()) return
if (!interaction.isCommand()) return
switch (interaction.commandName) {
case 'blacklist':
const reportedUser = interaction.options.getString('player')
const reason = interaction.options.getString('reason')
const reportedByUser = interaction.user.username
switch (interaction.commandName) {
case 'blacklist':
const reportedUser = interaction.options.getString('player')
const reason = interaction.options.getString('reason')
const reportedByUser = interaction.user.username
const res = await handleBlacklistAdd(reportedUser, reason, reportedByUser)
if (res) {
if (res.name === reportedUser)
interaction.reply({ content: `This user has already been reported`, ephemeral: true })
else {
interaction.reply({ content: `Player ** ${reportedUser}** had been successfully reported for ${reason}`, ephemeral: true })
updateGlobalMessage(interaction)
}
} else
interaction.reply({ content: `ERROR trying to add the player to the blacklist, please contact @Crylia`, ephemeral: true })
const res = await handleBlacklistAdd(reportedUser, reason, reportedByUser)
if (res) {
if (res.name === reportedUser)
interaction.reply({ content: 'This user has already been reported', ephemeral: true })
else {
interaction.reply({ content: `Player ** ${reportedUser}** had been successfully reported for ${reason}`, ephemeral: true })
updateGlobalMessage(interaction)
}
} else
interaction.reply({ content: 'ERROR trying to add the player to the blacklist, please contact @Crylia', ephemeral: true })
break
case 'blacklist-check-player':
const player = interaction.options.getString('player')
break
case 'blacklist-check-player':
const player = interaction.options.getString('player')
const reason2 = await handleBlacklistCheck(player)
reason2 ?
await interaction.reply({ content: `** ${reason2.name}** is blacklisted for: ** ${reason2.reason || 'No reason provided.'}**`, ephemeral: true }) :
await interaction.reply({ content: `** ${player}** is not blacklisted.`, ephemeral: true })
const reason2 = await handleBlacklistCheck(player)
reason2 ?
await interaction.reply({ content: `** ${reason2.name}** is blacklisted for: ** ${reason2.reason || 'No reason provided.'}**`, ephemeral: true }) :
await interaction.reply({ content: `** ${player}** is not blacklisted.`, ephemeral: true })
break
case 'birthday':
const user = interaction.user.username
const birthday = interaction.options.getString('birthday')
break
case 'birthday':
const user = interaction.user.username
const birthday = interaction.options.getString('birthday')
// Matches format xx.xx.xxxx, later dd.mm.yyyy
const match = birthday.match(/^(\d{2})\.(\d{2})\.(\d{4})$/)
if (!match) {
await interaction.reply({ content: 'Invalid date format. Please use dd.mm.yyyy.', ephemeral: true })
return
}
// Matches format xx.xx.xxxx, later dd.mm.yyyy
const match = birthday.match(/^(\d{2})\.(\d{2})\.(\d{4})$/)
if (!match) {
await interaction.reply({ content: 'Invalid date format. Please use dd.mm.yyyy.', ephemeral: true })
return
}
const day = parseInt(match[1], 10)
const month = parseInt(match[2], 10)
const year = parseInt(match[3], 10)
const day = parseInt(match[1], 10)
const month = parseInt(match[2], 10)
const year = parseInt(match[3], 10)
// Validates dd.mm ae legit, year doesnt matter for the birthday
const isValidDate = (day, month, year) => {
if (month < 1 || month > 12) return false
// Validates dd.mm ae legit, year doesnt matter for the birthday
const isValidDate = (day, month, year) => {
if (month < 1 || month > 12) return false
const daysInMonth = [31, ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
return day > 0 && day <= daysInMonth[month - 1]
}
const daysInMonth = [31, ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
return day > 0 && day <= daysInMonth[month - 1]
}
if (!isValidDate(day, month, year)) {
await interaction.reply({ content: 'Invalid date. Please enter a valid birthday as dd.mm.yyyy.', ephemeral: true })
return
}
if (!isValidDate(day, month, year)) {
await interaction.reply({ content: 'Invalid date. Please enter a valid birthday as dd.mm.yyyy.', ephemeral: true })
return
}
await handleBirthdayCheck(user, birthday).length > 0 ?
await handleBirthdayUpdate(user, birthday) :
handleBirthdayAdd(user, birthday) ?
await interaction.reply({ content: `Set ${birthday} as your birthday.Everyone will be notified once the day arrives!`, ephemeral: true }) :
await interaction.reply({ content: `Something went wrong when setting / updating your birthday, please contact @crylia`, ephemeral: true })
break
case 'birthday-check':
const birthdayCheck = await handleBirthdayCheck(interaction.user.username)
birthdayCheck ?
await interaction.reply({ content: `Your birthday is currently set to ${new Date(birthdayCheck[0].date).toLocaleDateString('de-DE')}.`, ephemeral: true }) :
await interaction.reply({ content: "You don't have a birthday set. Use the`birthday` command to set one.", ephemeral: true })
break
case 'birthday-delete':
await handleBirthdayDelete(interaction.user.username) ?
await interaction.reply({ content: "Your birthday has been deleted.", ephemeral: true }) :
await interaction.reply({ content: "You don't have a birthday set.", ephemeral: true })
break
case 'static-create':
await handleBirthdayCheck(user, birthday).length > 0 ?
await handleBirthdayUpdate(user, birthday) :
handleBirthdayAdd(user, birthday) ?
await interaction.reply({ content: `Set ${birthday} as your birthday.Everyone will be notified once the day arrives!`, ephemeral: true }) :
await interaction.reply({ content: 'Something went wrong when setting / updating your birthday, please contact @crylia', ephemeral: true })
break
case 'birthday-check':
const birthdayCheck = await handleBirthdayCheck(interaction.user.username)
birthdayCheck ?
await interaction.reply({ content: `Your birthday is currently set to ${new Date(birthdayCheck[0].date).toLocaleDateString('de-DE')}.`, ephemeral: true }) :
await interaction.reply({ content: 'You don\'t have a birthday set. Use the`birthday` command to set one.', ephemeral: true })
break
case 'birthday-delete':
await handleBirthdayDelete(interaction.user.username) ?
await interaction.reply({ content: 'Your birthday has been deleted.', ephemeral: true }) :
await interaction.reply({ content: 'You don\'t have a birthday set.', ephemeral: true })
break
case 'static-create':
break
case 'static-delete':
break
case 'static-delete':
break
break
case 'static-show':
case 'static-show':
break
default:
break
}
break
default:
break
}
})
client.on('messageReactionAdd', async (reaction, user) => {
messageReactionAdd(user, reaction)
messageReactionAdd(user, reaction)
})
client.on('messageReactionRemove', async (reaction, user) => {
messageReactionRemove(user, reaction)
messageReactionRemove(user, reaction)
})
client.once('ready', async () => {
console.log(`Logged in as ${client.user.tag} `)
startBirthdayCheckCron(client)
startEventCheckCron(client)
updateGlobalMessage(client)
initReactionPerRole(client)
console.log(`Logged in as ${client.user.tag} `)
startBirthdayCheckCron(client)
startEventCheckCron(client)
updateGlobalMessage(client)
initReactionPerRole(client)
})
const connectDiscord = async () => {
try {
console.log('Started refreshing application (/) commands.')
try {
console.log('Started refreshing application (/) commands.')
const commands = [
new SlashCommandBuilder()
.setName('birthday')
.setDescription('Set yourself a birthday')
.addStringOption(option =>
option.setName('birthday')
.setDescription('Set (or overwrite) your birthday as dd.mm.yyyy (e.g. 01.12.1999)')
.setRequired(true)
),
new SlashCommandBuilder()
.setName('birthday-check')
.setDescription('Check your set birthday (only you will see the date)'),
new SlashCommandBuilder()
.setName('birthday-delete')
.setDescription('Delete your birthday, nobody will know when your birthday arrives :('),
new SlashCommandBuilder()
.setName('blacklist')
.setDescription('Add a player to a blacklist with a reason')
.addStringOption(option =>
option.setName('player')
.setDescription('The in-game name of the player')
.setRequired(true)
)
.addStringOption(option =>
option.setName('reason')
.setDescription('Explain what happened, why should this player be blacklisted')
.setRequired(true)
),
new SlashCommandBuilder()
.setName('blacklist-check-player')
.setDescription('Check if a player is blacklisted')
.addStringOption(option =>
option.setName('player')
.setDescription('The in-game name of the player')
.setRequired(true)
)
].map(command => command.toJSON())
const commands = [
new SlashCommandBuilder()
.setName('birthday')
.setDescription('Set yourself a birthday')
.addStringOption(option =>
option.setName('birthday')
.setDescription('Set (or overwrite) your birthday as dd.mm.yyyy (e.g. 01.12.1999)')
.setRequired(true)
),
new SlashCommandBuilder()
.setName('birthday-check')
.setDescription('Check your set birthday (only you will see the date)'),
new SlashCommandBuilder()
.setName('birthday-delete')
.setDescription('Delete your birthday, nobody will know when your birthday arrives :('),
new SlashCommandBuilder()
.setName('blacklist')
.setDescription('Add a player to a blacklist with a reason')
.addStringOption(option =>
option.setName('player')
.setDescription('The in-game name of the player')
.setRequired(true)
)
.addStringOption(option =>
option.setName('reason')
.setDescription('Explain what happened, why should this player be blacklisted')
.setRequired(true)
),
new SlashCommandBuilder()
.setName('blacklist-check-player')
.setDescription('Check if a player is blacklisted')
.addStringOption(option =>
option.setName('player')
.setDescription('The in-game name of the player')
.setRequired(true)
),
].map(command => command.toJSON())
await rest.put(
Routes.applicationCommands(process.env.CLIENT_ID),
{ body: commands },
)
console.log('Successfully reloaded application (/) commands.')
} catch (error) {
console.error(error)
}
try {
client.login(process.env.BOT_TOKEN)
} catch (error) {
console.error('Error logging in to Discord:', error)
}
await rest.put(
Routes.applicationCommands(process.env.CLIENT_ID),
{ body: commands }
)
console.log('Successfully reloaded application (/) commands.')
} catch (error) {
console.error(error)
}
try {
client.login(process.env.BOT_TOKEN)
} catch (error) {
console.error('Error logging in to Discord:', error)
}
}
module.exports = { client, connectDiscord }

View File

@@ -1,43 +1,43 @@
const { CreateBirthday, ReadBirthday, UpdateBirthday, DeleteBirthday } = require('../database/birthdaydb')
const handleBirthdayAdd = async (user, birthday) => {
if (!user || !birthday) return false
if (!user || !birthday) return false
const result = await CreateBirthday(user, birthday)
const result = await CreateBirthday(user, birthday)
return result
return result
}
const handleBirthdayCheck = async (user) => {
if (!user) return false
if (!user) return false
const result = await ReadBirthday(user)
const result = await ReadBirthday(user)
return result
return result
}
const handleBirthdayDelete = async (user) => {
if (!user) return false
if (!user) return false
const result = await DeleteBirthday(user)
const result = await DeleteBirthday(user)
return result
return result
}
const handleBirthdayUpdate = async (user, birthday) => {
if (!user || !birthday) return false
if (!user || !birthday) return false
const result = await UpdateBirthday(user, birthday)
const result = await UpdateBirthday(user, birthday)
return result
return result
}
const handleBirthdayGetAll = async () => await ReadBirthday()
module.exports = {
handleBirthdayAdd,
handleBirthdayCheck,
handleBirthdayDelete,
handleBirthdayUpdate,
handleBirthdayGetAll,
handleBirthdayAdd,
handleBirthdayCheck,
handleBirthdayDelete,
handleBirthdayUpdate,
handleBirthdayGetAll,
}

View File

@@ -2,104 +2,104 @@ const { CreateBlacklist, ReadBlacklist, UpdateBlacklist, DeleteBlacklist } = req
const { EmbedBuilder } = require('discord.js')
const handleBlacklistAdd = async (reportedUser, reason, reportedByUser) => {
if (!reportedUser || !reason || !reportedByUser) return false
if (!reportedUser || !reason || !reportedByUser) return false
const result = await CreateBlacklist(reportedUser, reason, reportedByUser)
const result = await CreateBlacklist(reportedUser, reason, reportedByUser)
return result
return result
}
const handleBlacklistCheck = async (user) => {
if (!user) return false
if (!user) return false
const result = await ReadBlacklist(user)
const result = await ReadBlacklist(user)
return result
return result
}
const handleBlacklistShow = async () => await ReadBlacklist()
const createBlacklistEmbeds = (playerEntries, maxChars = 30) => {
const embeds = []
let embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle('Blacklist (Page 1)')
.setDescription('Players who have been blacklisted and the reasons.')
const embeds = []
let embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle('Blacklist (Page 1)')
.setDescription('Players who have been blacklisted and the reasons.')
let fieldCount = 0
let pageIndex = 1
let fieldCount = 0
let pageIndex = 1
playerEntries.forEach(([playerName, reason]) => {
let splitReason = []
while (reason.length > maxChars) {
let splitIndex = reason.lastIndexOf(' ', maxChars)
if (splitIndex === -1) splitIndex = maxChars
splitReason.push(reason.substring(0, splitIndex))
reason = reason.substring(splitIndex + 1)
}
splitReason.push(reason)
playerEntries.forEach(([playerName, reason]) => {
let splitReason = []
while (reason.length > maxChars) {
let splitIndex = reason.lastIndexOf(' ', maxChars)
if (splitIndex === -1) splitIndex = maxChars
splitReason.push(reason.substring(0, splitIndex))
reason = reason.substring(splitIndex + 1)
}
splitReason.push(reason)
const nameField = playerName || '\u200B'
const valueField = splitReason.join('\n').trim() || '\u200B'
const nameField = playerName || '\u200B'
const valueField = splitReason.join('\n').trim() || '\u200B'
if (valueField !== '\u200B') {
embed.addFields({ name: nameField, value: valueField, inline: true })
fieldCount++
}
if (valueField !== '\u200B') {
embed.addFields({ name: nameField, value: valueField, inline: true })
fieldCount++
}
if (fieldCount >= 25) {
embeds.push(embed)
pageIndex++
embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(`Blacklist (Page ${pageIndex})`)
.setDescription('Players who have been blacklisted and the reasons.')
fieldCount = 0
}
})
if (fieldCount >= 25) {
embeds.push(embed)
pageIndex++
embed = new EmbedBuilder()
.setColor('#0099ff')
.setTitle(`Blacklist (Page ${pageIndex})`)
.setDescription('Players who have been blacklisted and the reasons.')
fieldCount = 0
}
})
if (fieldCount > 0) {
embeds.push(embed)
}
if (fieldCount > 0) {
embeds.push(embed)
}
return embeds
return embeds
}
const updateGlobalMessage = async (client) => {
try {
let targetChannel = null
try {
let targetChannel = null
for (const [_, oauthGuild] of await client.guilds.fetch()) {
targetChannel = (await (await oauthGuild.fetch()).channels.fetch()).find(ch => ch.name === 'blacklist')
break
}
for (const [_, oauthGuild] of await client.guilds.fetch()) {
targetChannel = (await (await oauthGuild.fetch()).channels.fetch()).find(ch => ch.name === 'blacklist')
break
}
if (!targetChannel) {
console.error('Channel with name "blacklist" not found.')
return
}
if (!targetChannel) {
console.error('Channel with name "blacklist" not found.')
return
}
const messages = await targetChannel.messages.fetch({ limit: 100 })
await Promise.all(messages.map(msg => msg.delete()))
const messages = await targetChannel.messages.fetch({ limit: 100 })
await Promise.all(messages.map(msg => msg.delete()))
const blacklistEntries = await handleBlacklistShow()
const blacklistEntries = await handleBlacklistShow()
const playerEntries = blacklistEntries.map(entry => [entry.name, entry.reason])
const playerEntries = blacklistEntries.map(entry => [entry.name, entry.reason])
const embeds = createBlacklistEmbeds(playerEntries)
const embeds = createBlacklistEmbeds(playerEntries)
for (const embed of embeds)
await targetChannel.send({ embeds: [embed] })
for (const embed of embeds)
await targetChannel.send({ embeds: [embed] })
} catch (error) {
console.error('Error updating global message:', error)
}
} catch (error) {
console.error('Error updating global message:', error)
}
}
module.exports = {
handleBlacklistAdd,
handleBlacklistCheck,
handleBlacklistShow,
updateGlobalMessage,
handleBlacklistAdd,
handleBlacklistCheck,
handleBlacklistShow,
updateGlobalMessage,
}

View File

@@ -1,206 +1,206 @@
const { GetIconRole } = require('../database/eventdb')
const cron = require('node-cron');
const cron = require('node-cron')
let reminderMessageID = null
let rolesMap = new Map()
const areMapsEqual = (map1, map2) => {
if (map1.size !== map2.size) return false
if (map1.size !== map2.size) return false
for (const [key, value] of map1)
if (map2.get(key) !== value) return false
for (const [key, value] of map1)
if (map2.get(key) !== value) return false
return true
return true
}
const editReactionMessage = async (client) => {
try {
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const rolesChannel = (await guild.channels.fetch()).find(ch => ch.name === 'roles')
try {
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const rolesChannel = (await guild.channels.fetch()).find(ch => ch.name === 'roles')
if (!rolesChannel) {
console.log("Channel not found")
return
}
const message = await rolesChannel.messages.fetch(reminderMessageID)
if (!rolesChannel) {
console.log('Channel not found')
return
}
const message = await rolesChannel.messages.fetch(reminderMessageID)
const newRolesFromDB = await GetIconRole()
const newRolesFromDB = await GetIconRole()
if (areMapsEqual(rolesMap, newRolesFromDB)) {
console.log(`No changes to the roles, quitting`)
return
}
if (areMapsEqual(rolesMap, newRolesFromDB)) {
console.log('No changes to the roles, quitting')
return
}
rolesMap = newRolesFromDB
rolesMap = newRolesFromDB
const currentLines = message.content.split('\n').slice(1)
const currentLines = message.content.split('\n').slice(1)
const currentRoleMap = new Map()
currentLines.forEach(line => {
if (!line.trim()) return
const [icon, roleName] = line.split(': ')
const iconName = icon.match(/<:(\w+):\d+>/)[1]
currentRoleMap.set(iconName, roleName.replace(/`/g, ''))
})
const currentRoleMap = new Map()
currentLines.forEach(line => {
if (!line.trim()) return
const [icon, roleName] = line.split(': ')
const iconName = icon.match(/<:(\w+):\d+>/)[1]
currentRoleMap.set(iconName, roleName.replace(/`/g, ''))
})
const rolesToAdd = [], rolesToRemove = []
const rolesToAdd = [], rolesToRemove = []
for (const [iconName, roleName] of rolesMap)
if (!currentRoleMap.has(iconName))
rolesToAdd.push({ icon: iconName, name: roleName })
for (const [iconName, roleName] of rolesMap)
if (!currentRoleMap.has(iconName))
rolesToAdd.push({ icon: iconName, name: roleName })
for (const [iconName, roleName] of currentRoleMap)
if (!rolesMap.has(iconName))
rolesToRemove.push({ icon: iconName, name: roleName })
for (const [iconName, roleName] of currentRoleMap)
if (!rolesMap.has(iconName))
rolesToRemove.push({ icon: iconName, name: roleName })
const emojis = await guild.emojis.fetch()
const emojis = await guild.emojis.fetch()
let updatedContent = 'React to get your roles!\n\n'
rolesMap.forEach((roleName, iconName) => {
const emoji = emojis.find(e => e.name === iconName)
if (emoji)
updatedContent += `${emoji}: \`${roleName}\`\n\n`
else
console.log(`Couldn't find emoji ${iconName}`)
})
let updatedContent = 'React to get your roles!\n\n'
rolesMap.forEach((roleName, iconName) => {
const emoji = emojis.find(e => e.name === iconName)
if (emoji)
updatedContent += `${emoji}: \`${roleName}\`\n\n`
else
console.log(`Couldn't find emoji ${iconName}`)
})
await message.edit(updatedContent)
await message.edit(updatedContent)
for (const role of rolesToAdd) {
const icon = emojis.find(e => e.name === role.icon)
if (icon)
await message.react(`${icon}`)
}
for (const role of rolesToAdd) {
const icon = emojis.find(e => e.name === role.icon)
if (icon)
await message.react(`${icon}`)
}
for (const role of rolesToRemove) {
const reaction = message.reactions.cache.find(r => r.emoji.name === role.icon)
if (!reaction) continue
for (const role of rolesToRemove) {
const reaction = message.reactions.cache.find(r => r.emoji.name === role.icon)
if (!reaction) continue
await reaction.remove()
await reaction.remove()
const roleToRemove = message.guild.roles.cache.find(r => r.name === role.name)
if (!roleToRemove) continue
const roleToRemove = message.guild.roles.cache.find(r => r.name === role.name)
if (!roleToRemove) continue
const members = await message.guild.members.fetch();
const membersWithRole = members.filter(member => member.roles.cache.has(roleToRemove.id));
const members = await message.guild.members.fetch()
const membersWithRole = members.filter(member => member.roles.cache.has(roleToRemove.id))
for (const member of membersWithRole.values())
await member.roles.remove(roleToRemove)
}
}
} catch (error) {
console.log(error)
}
for (const member of membersWithRole.values())
await member.roles.remove(roleToRemove)
}
}
} catch (error) {
console.log(error)
}
}
const createReactionMessage = async (client) => {
try {
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const rolesChannel = (await guild.channels.fetch()).find(ch => ch.name === 'roles')
try {
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const rolesChannel = (await guild.channels.fetch()).find(ch => ch.name === 'roles')
if (!rolesChannel) {
console.log("Channel not found")
return
}
if (!rolesChannel) {
console.log('Channel not found')
return
}
const fetchedMessage = await rolesChannel.messages.fetch({ limit: 1 })
if (fetchedMessage.size > 0) {
reminderMessageID = fetchedMessage.first().id
console.log('Reminder MessageID: ', reminderMessageID)
return
}
const fetchedMessage = await rolesChannel.messages.fetch({ limit: 1 })
if (fetchedMessage.size > 0) {
reminderMessageID = fetchedMessage.first().id
console.log('Reminder MessageID: ', reminderMessageID)
return
}
const emojis = await guild.emojis.fetch()
const emojis = await guild.emojis.fetch()
let message = 'React to get your roles!\n\n'
for (const [iconName, roleName] of rolesMap) {
const emoji = emojis.find(e => e.name === iconName)
if (emoji)
message += `<:${emoji.name}:${emoji.id}> : \`${roleName}\`\n\n`
else
console.log(`Emoji for ${iconName} not found`)
}
const sentMessage = await rolesChannel.send(message)
let message = 'React to get your roles!\n\n'
for (const [iconName, roleName] of rolesMap) {
const emoji = emojis.find(e => e.name === iconName)
if (emoji)
message += `<:${emoji.name}:${emoji.id}> : \`${roleName}\`\n\n`
else
console.log(`Emoji for ${iconName} not found`)
}
const sentMessage = await rolesChannel.send(message)
for (const [iconName, _] of rolesMap) {
const emoji = emojis.find(e => e.name === iconName)
if (emoji) await sentMessage.react(emoji.id)
}
for (const [iconName, _] of rolesMap) {
const emoji = emojis.find(e => e.name === iconName)
if (emoji) await sentMessage.react(emoji.id)
}
reminderMessageID = sentMessage.id
}
} catch (error) {
console.log(error)
}
reminderMessageID = sentMessage.id
}
} catch (error) {
console.log(error)
}
}
const messageReactionAdd = async (user, reaction) => {
if (user.id === '1280557738530963506') return
if (user.id === '1280557738530963506') return
const { message, emoji } = reaction
const guild = message.guild
const member = await guild.members.fetch(user.id)
if (!member) return
const { message, emoji } = reaction
const guild = message.guild
const member = await guild.members.fetch(user.id)
if (!member) return
if (message.id === reminderMessageID) {
const roleMap = await GetIconRole()
if (message.id === reminderMessageID) {
const roleMap = await GetIconRole()
const roleName = roleMap.get(emoji.name)
if (roleName) {
try {
const roles = await guild.roles.fetch()
const role = roles.find(r => r.name === roleName)
const roleName = roleMap.get(emoji.name)
if (roleName) {
try {
const roles = await guild.roles.fetch()
const role = roles.find(r => r.name === roleName)
if (role && !member.roles.cache.has(role.id))
await member.roles.add(role)
if (role && !member.roles.cache.has(role.id))
await member.roles.add(role)
} catch (error) {
console.error(`Error fetching role for ${roleName}`, error)
}
}
}
} catch (error) {
console.error(`Error fetching role for ${roleName}`, error)
}
}
}
}
const messageReactionRemove = async (user, reaction) => {
const { message, emoji } = reaction
const guild = message.guild
const { message, emoji } = reaction
const guild = message.guild
const member = await guild.members.fetch(user.id)
if (!member) return
const member = await guild.members.fetch(user.id)
if (!member) return
if (message.id === reminderMessageID) {
const roleMap = await GetIconRole()
if (message.id === reminderMessageID) {
const roleMap = await GetIconRole()
const roleName = roleMap.get(emoji.name)
if (roleName) {
try {
const roles = await guild.roles.fetch()
const role = roles.find(r => r.name === roleName)
const roleName = roleMap.get(emoji.name)
if (roleName) {
try {
const roles = await guild.roles.fetch()
const role = roles.find(r => r.name === roleName)
if (role && member.roles.cache.has(role.id))
await member.roles.remove(role)
if (role && member.roles.cache.has(role.id))
await member.roles.remove(role)
} catch (error) {
console.error(`Error fetching role for ${roleName}`, error)
}
}
}
} catch (error) {
console.error(`Error fetching role for ${roleName}`, error)
}
}
}
}
const initReactionPerRole = async (client) => {
rolesMap = await GetIconRole()
rolesMap = await GetIconRole()
await createReactionMessage(client)
await createReactionMessage(client)
cron.schedule('0 * * * *', async () => {
await editReactionMessage(client)
})
cron.schedule('0 * * * *', async () => {
await editReactionMessage(client)
})
}
module.exports = {
initReactionPerRole,
messageReactionAdd,
messageReactionRemove,
initReactionPerRole,
messageReactionAdd,
messageReactionRemove,
}

View File

@@ -1,31 +1,31 @@
const { CreateStatic, ReadStatic, DeleteStatic } = require('../database/staticdb')
const handleStaticAdd = async (name, creator, members, size) => {
if (!name || !createor || !members || !size) return false
if (!name || !createor || !members || !size) return false
const result = await CreateStatic(name, creator, members, size)
const result = await CreateStatic(name, creator, members, size)
return result
return result
}
const handleStaticGet = async (name) => {
if (!name) return false;
if (!name) return false
const result = await ReadStatic(name)
const result = await ReadStatic(name)
return result
return result
}
const handleStaticDelete = async (name) => {
if (!name) return false
if (!name) return false
const result = await DeleteStatic(name)
const result = await DeleteStatic(name)
return result
return result
}
module.exports = {
handleStaticAdd,
handleStaticGet,
handleStaticDelete,
handleStaticAdd,
handleStaticGet,
handleStaticDelete,
}

View File

@@ -1,16 +1,13 @@
const { Sequelize } = require('sequelize')
const { connectDiscord } = require('./discord/discordClient')
const { connectDatabase, createClient } = require('./database/database');
require('dotenv').config();
(async () => {
try {
const client = createClient({
connectionString: `postgresql://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}/${process.env.DB_NAME}`
})
connectDatabase(client).then(() => {
connectDiscord()
})
} catch (error) {
console.log(error)
}
try {
connectDiscord()
} catch (error) {
console.error('Error initializing application:', error)
}
})()

View File

@@ -1,41 +1,41 @@
const cron = require('node-cron');
const { handleBirthdayGetAll } = require('../features/birthday');
const cron = require('node-cron')
const { handleBirthdayGetAll } = require('../features/birthday')
const startBirthdayCheckCron = async (client) => {
cron.schedule('0 20 * * *', async () => {
try {
console.log('Running birthday check...');
cron.schedule('0 20 * * *', async () => {
try {
console.log('Running birthday check...')
for (const [guildId, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const birthdayChannel = (await guild.channels.fetch()).find(ch => ch.name === 'main')
for (const [guildId, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const birthdayChannel = (await guild.channels.fetch()).find(ch => ch.name === 'main')
if (!birthdayChannel) continue
if (!birthdayChannel) continue
const birthdays = await handleBirthdayGetAll();
console.log("birthdays:", birthdays)
if (birthdays.length < 1) continue
const birthdays = await handleBirthdayGetAll()
console.log('birthdays:', birthdays)
if (birthdays.length < 1) continue
let message = '🎉 **Today\'s Birthdays!** 🎉\n\n';
for (const birthday of birthdays) {
const birthdayDate = new Date(birthday.date);
if (birthdayDate.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) === new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })) {
(await guild.members.fetch()).forEach(user => {
if (user.user.username === birthday.discorduser) {
message += `🎂 **Happy Birthday, <@${user.id}>!** 🎂\nWishing you a fantastic day filled with joy and surprises! 🎁🎈\n\n**Everyone, make sure to wish <@${user.id}> a wonderful birthday!** 🎊🎉\n\n`;
}
})
}
}
console.log(message)
if (message !== '🎉 **Today\'s Birthdays!** 🎉\n\n') {
await birthdayChannel.send(message);
}
}
} catch (error) {
console.log("Error in scheduled birthday check:", error);
}
});
};
let message = '🎉 **Today\'s Birthdays!** 🎉\n\n'
for (const birthday of birthdays) {
const birthdayDate = new Date(birthday.date)
if (birthdayDate.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }) === new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' })) {
(await guild.members.fetch()).forEach(user => {
if (user.user.username === birthday.discorduser) {
message += `🎂 **Happy Birthday, <@${user.id}>!** 🎂\nWishing you a fantastic day filled with joy and surprises! 🎁🎈\n\n**Everyone, make sure to wish <@${user.id}> a wonderful birthday!** 🎊🎉\n\n`
}
})
}
}
console.log(message)
if (message !== '🎉 **Today\'s Birthdays!** 🎉\n\n') {
await birthdayChannel.send(message)
}
}
} catch (error) {
console.log('Error in scheduled birthday check:', error)
}
})
}
module.exports = { startBirthdayCheckCron };
module.exports = { startBirthdayCheckCron }

View File

@@ -1,79 +1,79 @@
const cron = require('node-cron');
const cron = require('node-cron')
const { ReadEvents, GetEventRole } = require('../database/eventdb')
const { EmbedBuilder } = require('discord.js')
let eventCache = []
const FetchEvents = async () => {
const res = await ReadEvents()
const res = await ReadEvents()
eventCache = res
eventCache = res
}
const convertToISO = (time, date) => {
const utcDate = new Date(`${date}T${time}`);
utcDate.setHours(utcDate.getHours());
return utcDate.toISOString().split('.')[0];
};
const utcDate = new Date(`${date}T${time}`)
utcDate.setHours(utcDate.getHours())
return utcDate.toISOString().split('.')[0]
}
const convertToUTC = (time) => {
const [hours, minutes, seconds] = time.split(':').map(Number);
const date = new Date();
date.setUTCHours(hours - 2, minutes, seconds);
return date.toISOString().split('.')[0];
};
const [hours, minutes, seconds] = time.split(':').map(Number)
const date = new Date()
date.setUTCHours(hours - 2, minutes, seconds)
return date.toISOString().split('.')[0]
}
const isReminderTime = (eventStartUTC) => {
const now = new Date();
const [eventHours, eventMinutes] = eventStartUTC.split('T')[1].split(':').map(Number);
const eventStartDateTime = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), eventHours, eventMinutes));
const reminderTime = new Date(eventStartDateTime.getTime() - 15 * 60 * 1000);
console.log(now, reminderTime, eventStartDateTime)
return now >= reminderTime && now < eventStartDateTime;
};
const now = new Date()
const [eventHours, eventMinutes] = eventStartUTC.split('T')[1].split(':').map(Number)
const eventStartDateTime = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), eventHours, eventMinutes))
const reminderTime = new Date(eventStartDateTime.getTime() - 15 * 60 * 1000)
console.log(now, reminderTime, eventStartDateTime)
return now >= reminderTime && now < eventStartDateTime
}
const getDayOfWeek = () => new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate())).toLocaleDateString('en-US', { weekday: 'long' });
const getDayOfWeek = () => new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), new Date().getUTCDate())).toLocaleDateString('en-US', { weekday: 'long' })
const startEventCheckCron = async (client) => {
cron.schedule('45 * * * *', async () => {
await FetchEvents()
cron.schedule('45 * * * *', async () => {
await FetchEvents()
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const channel = (await guild.channels.fetch()).find(ch => ch.name === 'reminder')
for (const [_, oauthGuild] of await client.guilds.fetch()) {
const guild = await oauthGuild.fetch()
const channel = (await guild.channels.fetch()).find(ch => ch.name === 'reminder')
if (!channel) continue
if (!channel) continue
eventCache.forEach(async (event) => {
let { schedule_id, event_name, start_time, end_time, day_of_week } = event
if (!((!day_of_week || day_of_week === getDayOfWeek()) && isReminderTime(convertToUTC(start_time)))) return
eventCache.forEach(async (event) => {
let { schedule_id, event_name, start_time, end_time, day_of_week } = event
if (!((!day_of_week || day_of_week === getDayOfWeek()) && isReminderTime(convertToUTC(start_time)))) return
const rolesEventMap = await GetEventRole()
const role = guild.roles.cache.find(r => r.name === rolesEventMap.get(event_name))
const roleId = role ? role.id : null
const rolesEventMap = await GetEventRole()
const role = guild.roles.cache.find(r => r.name === rolesEventMap.get(event_name))
const roleId = role ? role.id : null
const embed = new EmbedBuilder()
.setTitle(event_name)
.setDescription(`${event_name} starts at **${start_time} CEST** and ends at **${end_time} CEST**. \n ${roleId ? `<@&${roleId}>` : 'No role assigned'} \n`)
.addFields(
{ name: 'Day of Week', value: day_of_week ? day_of_week : 'Daily', inline: true },
{
name: 'Compare Time',
value: `[Click here to compare event time to your local time](https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToISO(start_time, new Date().toISOString().split('T')[0])}&msg=${encodeURIComponent(event_name)})`,
inline: true
}
)
.setFooter({ text: `Schedule ID: ${schedule_id}` })
.setColor('#00FF00')
const embed = new EmbedBuilder()
.setTitle(event_name)
.setDescription(`${event_name} starts at **${start_time} CEST** and ends at **${end_time} CEST**. \n ${roleId ? `<@&${roleId}>` : 'No role assigned'} \n`)
.addFields(
{ name: 'Day of Week', value: day_of_week ? day_of_week : 'Daily', inline: true },
{
name: 'Compare Time',
value: `[Click here to compare event time to your local time](https://www.timeanddate.com/worldclock/fixedtime.html?iso=${convertToISO(start_time, new Date().toISOString().split('T')[0])}&msg=${encodeURIComponent(event_name)})`,
inline: true
}
)
.setFooter({ text: `Schedule ID: ${schedule_id}` })
.setColor('#00FF00')
await channel.send({ embeds: [embed] }).catch(console.error)
})
}
})
await channel.send({ embeds: [embed] }).catch(console.error)
})
}
})
}
module.exports = {
startEventCheckCron,
startEventCheckCron,
}