Passage roles en DB pour faciliter maintenance

This commit is contained in:
Melaine Gérard 2024-11-08 01:20:55 +01:00
parent 0a79243494
commit 2974baaaba
12 changed files with 190 additions and 77 deletions

View File

@ -1,12 +1,13 @@
TOKEN="BOT_TOKEN" TOKEN="BOT_TOKEN"
GUILD_ID="1234567890" GUILD_ID="1234567890"
DB_DIALECT="mysql"
DB_DIALECT="postgres"
DB_HOST="localhost" DB_HOST="localhost"
DB_NAME="gachamelia" DB_NAME="gachamelia"
DB_USERNAME="gachamelia" DB_USERNAME="postgres"
DB_PASSWORD="gachamelia" DB_PASSWORD="gachamelia"
DB_PORT=3310 DB_PORT=5433
SSR_ROLE=""
SR_ROLE="" WELCOME_CHANNEL=""
R_ROLE=""
WELCOME_CHANNEL="" INIT_DB="true"

View File

@ -1,15 +1,13 @@
services: services:
mysql: postgres:
image: mysql:8 image: postgres:17
environment: environment:
MYSQL_ROOT_PASSWORD: root POSTGRES_PASSWORD: gachamelia
MYSQL_DATABASE: gachamelia POSTGRES_DB: gachamelia
MYSQL_USER: gachamelia
MYSQL_PASSWORD: gachamelia
ports: ports:
- "3310:3306" - "5433:5432"
volumes: volumes:
- mysql_gachamelia_data:/var/lib/mysql - postgres_gachamelia_data:/var/lib/postgresql/data
volumes: volumes:
mysql_gachamelia_data: postgres_gachamelia_data:

View File

@ -9,6 +9,7 @@ import {Database} from "./Database";
import {IDatabaseConfig} from "../interfaces/IDatabaseConfig"; import {IDatabaseConfig} from "../interfaces/IDatabaseConfig";
import {Dialect} from "sequelize"; import {Dialect} from "sequelize";
import {User} from "../models/User"; import {User} from "../models/User";
import {Rank} from "../models/Rank";
export class CustomClient extends Client implements ICustomClient { export class CustomClient extends Client implements ICustomClient {
config: IConfig; config: IConfig;
@ -47,7 +48,20 @@ export class CustomClient extends Client implements ICustomClient {
} }
async init(): Promise<void> { async init(): Promise<void> {
await this.database.connect(); await this.database.connect();
Rank.initModel(this.database.getSequelize());
User.initModel(this.database.getSequelize()); User.initModel(this.database.getSequelize());
Rank.hasMany(User, {
foreignKey: 'rankId',
as: 'users'
});
User.belongsTo(Rank, {
foreignKey: 'rankId',
as: 'rank'
});
await this.database.sync({ await this.database.sync({
alter: true alter: true
}); });

View File

@ -1,6 +0,0 @@
export enum Rank {
SSR = 'SSR',
SR = 'SR',
R = 'R',
}

View File

@ -1,6 +0,0 @@
export enum RankChance {
SSR = 3,
SR = 17,
R = 80,
}

40
src/base/models/Rank.ts Normal file
View File

@ -0,0 +1,40 @@
import { Model, DataTypes, Sequelize } from 'sequelize';
import {User} from "./User";
export class Rank extends Model {
declare id: number;
declare name: string;
declare discordId: string;
declare percentage: number;
declare createdAt: Date;
declare updatedAt: Date;
declare users: User[];
public static initModel(sequelize: Sequelize): void {
Rank.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
discordId: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
percentage: {
type: DataTypes.INTEGER,
allowNull: false
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE,
}, {
sequelize,
tableName: 'ranks'
});
}
}

View File

@ -1,12 +1,22 @@
import { Model, DataTypes, Sequelize } from 'sequelize'; import {
import { Rank } from '../enums/Rank'; Model,
DataTypes,
Sequelize,
ForeignKey,
NonAttribute,
InferAttributes, InferCreationAttributes, CreationOptional, Association
} from 'sequelize';
import {Rank} from "./Rank";
export class User extends Model { export class User extends Model<
declare id: number; InferAttributes<User>,
InferCreationAttributes<User>> {
declare id: CreationOptional<number>;
declare discordId: string; declare discordId: string;
declare rank: Rank; declare rankId: ForeignKey<number>;
declare createdAt: Date; declare rank: NonAttribute<Rank>;
declare updatedAt: Date; declare createdAt: CreationOptional<Date>;
declare updatedAt: CreationOptional<Date>;
public static initModel(sequelize: Sequelize): void { public static initModel(sequelize: Sequelize): void {
User.init({ User.init({
@ -20,9 +30,13 @@ export class User extends Model {
allowNull: false, allowNull: false,
unique: true unique: true
}, },
rank: { rankId: {
type: DataTypes.STRING, type: DataTypes.INTEGER,
allowNull: false allowNull: false,
references: {
model: Rank,
key: 'id'
}
}, },
createdAt: DataTypes.DATE, createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE updatedAt: DataTypes.DATE
@ -31,4 +45,10 @@ export class User extends Model {
tableName: 'users' tableName: 'users'
}); });
} }
declare static associations: {
rank: Association<User, Rank>;
};
} }

View File

@ -1,33 +1,24 @@
import {CustomClient} from "../classes/CustomClient"; import {CustomClient} from "../classes/CustomClient";
import {User} from "../models/User"; import {User} from "../models/User";
import {getRandomRank} from "./RandomUtils"; import {getRandomRank} from "./RandomUtils";
import {Rank} from "../enums/Rank";
import {GuildMember} from "discord.js"; import {GuildMember} from "discord.js";
import {Rank} from "../models/Rank";
export async function addRole(member: GuildMember, user: User, client: CustomClient): Promise<void> { export async function addRole(member: GuildMember, user: User): Promise<void> {
try { try {
let rRoleId = client.config.rRole; let userRank = await Rank.findOne({
let srRoleId = client.config.srRole; where: {
let ssrRoleId = client.config.ssrRole; id: user.rankId
if (user.rank === Rank.R) {
const rRole = await member.guild.roles.fetch(rRoleId);
if (rRole) {
await member.roles.add(rRole);
} }
} else if (user.rank === Rank.SR) { });
const srRole = await member.guild.roles.fetch(srRoleId);
if (srRole) { if (!userRank) {
await member.roles.add(srRole); return;
} }
} else if (user.rank === Rank.SSR) {
const ssrRole = await member.guild.roles.fetch(ssrRoleId);
if (ssrRole) { const discordRank = await member.guild.roles.fetch(userRank.discordId);
await member.roles.add(ssrRole); if (discordRank) {
} await member.roles.add(userRank.discordId);
} }
} catch (e: Error | any) { } catch (e: Error | any) {
console.log(`Impossible d'ajouter les rôles à ${member.displayName}`); console.log(`Impossible d'ajouter les rôles à ${member.displayName}`);
@ -43,16 +34,25 @@ export async function createAllUsers(client: CustomClient): Promise<void> {
let user = await User.findOne({ let user = await User.findOne({
where: { where: {
discordId: member.id discordId: member.id
},
include: {
model: Rank,
as: 'rank'
} }
}) })
if (!user) { if (!user) {
user = await User.create({ user = await User.create({
discordId: member.id, discordId: member.id,
rank: getRandomRank() rankId: (await getRandomRank()).id
}, {
include: [{
model: Rank,
as: 'rank'
}]
}); });
await addRole(member, user, client); await addRole(member, user);
count++; count++;
} }

View File

@ -1,16 +1,20 @@
import {Rank} from "../enums/Rank"; import {Rank} from "../models/Rank";
import {RankChance} from "../enums/RankChance";
export function getRandomRank(): Rank { export async function getRandomRank(): Promise<Rank> {
const rand = Math.random() * 100; const rand = Math.random() * 100;
let cumulativeChance = 0; let cumulativeChance = 0;
const ranks = await Rank.findAll();
for (const rank of Object.values(Rank)) { if (ranks.length === 0) {
cumulativeChance += RankChance[rank as keyof typeof RankChance]; throw new Error('No ranks found');
}
for (const rank of ranks) {
cumulativeChance += rank.percentage;
if (rand <= cumulativeChance) { if (rand <= cumulativeChance) {
return rank as Rank; return rank as Rank;
} }
} }
return Rank.R; return ranks[0] as Rank;
} }

View File

@ -3,7 +3,7 @@ import {CustomClient} from "../base/classes/CustomClient";
import {Category} from "../base/enums/Category"; import {Category} from "../base/enums/Category";
import {EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandUserOption} from "discord.js"; import {EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandUserOption} from "discord.js";
import {User} from "../base/models/User"; import {User} from "../base/models/User";
import {Rank} from "../base/enums/Rank"; import {Rank} from "../base/models/Rank";
import {getRandomRank} from "../base/utils/RandomUtils"; import {getRandomRank} from "../base/utils/RandomUtils";
export class PingCommand extends Command { export class PingCommand extends Command {
@ -26,19 +26,23 @@ export class PingCommand extends Command {
async execute(interaction: any): Promise<void> { async execute(interaction: any): Promise<void> {
let discordUser = (interaction.options.getMember('user') || interaction.member) as GuildMember; let discordUser = (interaction.options.getMember('user') || interaction.member) as GuildMember;
console.log(discordUser.id);
let user = await User.findOne( let user = await User.findOne(
{ {
where: { where: {
discordId: discordUser.id discordId: discordUser.id
} },
include: [{
model: Rank,
as: 'rank'
}],
} }
); );
if (!user) { if (!user) {
user = await User.create({ user = await User.create({
discordId: discordUser.id, discordId: discordUser.id,
rank: getRandomRank() rankId: (await getRandomRank()).id
}); });
} }
@ -46,7 +50,7 @@ export class PingCommand extends Command {
let embed = new EmbedBuilder() let embed = new EmbedBuilder()
.setTitle(`Rang de ${discordUser.displayName}`) .setTitle(`Rang de ${discordUser.displayName}`)
.setThumbnail(discordUser.displayAvatarURL()) .setThumbnail(discordUser.displayAvatarURL())
.setDescription(`Cet utilisateur est de rang : ${Rank[user.rank]}`) .setDescription(`Cet utilisateur est de rang : ${user.rank.name}`)
.setTimestamp(new Date()) .setTimestamp(new Date())
.setColor('#0078DE') .setColor('#0078DE')
; ;

View File

@ -3,6 +3,7 @@ import {CustomClient} from "../../base/classes/CustomClient";
import {Collection, Events, REST, Routes} from "discord.js"; import {Collection, Events, REST, Routes} from "discord.js";
import {Command} from "../../base/classes/Command"; import {Command} from "../../base/classes/Command";
import {createAllUsers} from "../../base/utils/GachaUtils"; import {createAllUsers} from "../../base/utils/GachaUtils";
import {Rank} from "../../base/models/Rank";
export class Ready extends Event { export class Ready extends Event {
constructor(client: CustomClient) { constructor(client: CustomClient) {
super(client, { super(client, {
@ -29,7 +30,11 @@ export class Ready extends Event {
console.log(`${setCommands.length} Commandes mises à jours avec succès !`); console.log(`${setCommands.length} Commandes mises à jours avec succès !`);
await createAllUsers(this.client); if (process.env.INIT_DB === 'true') {
await this.initDb();
} else {
await createAllUsers(this.client);
}
} }
private getJson(commands: Collection<string, Command>): object[] { private getJson(commands: Collection<string, Command>): object[] {
@ -47,4 +52,38 @@ export class Ready extends Event {
return data; return data;
} }
private async initDb() {
// On commence par vérifier si les rangs existent déjà
const ranks = await Rank.findAll();
if (ranks.length > 0) {
return;
}
await Rank.create({
name: '1★',
discordId: '1234567890',
percentage: 1,
});
await Rank.create({
name: '2★',
discordId: '2345678901',
percentage: 48,
});
await Rank.create({
name: '3★',
discordId: '3456789012',
percentage: 41,
});
await Rank.create({
name: '4★',
discordId: '4567890123',
percentage: 2,
});
await Rank.create({
name: '5★',
discordId: '5678901234',
percentage: 3,
});
}
} }

View File

@ -3,8 +3,8 @@ import {CustomClient} from "../../base/classes/CustomClient";
import {Event} from "../../base/classes/Event"; import {Event} from "../../base/classes/Event";
import {User} from "../../base/models/User"; import {User} from "../../base/models/User";
import {getRandomRank} from "../../base/utils/RandomUtils"; import {getRandomRank} from "../../base/utils/RandomUtils";
import {Rank} from "../../base/enums/Rank";
import {addRole} from "../../base/utils/GachaUtils"; import {addRole} from "../../base/utils/GachaUtils";
import {Rank} from "../../base/models/Rank";
export class GuildMemberJoin extends Event { export class GuildMemberJoin extends Event {
constructor(client: CustomClient) { constructor(client: CustomClient) {
@ -26,11 +26,16 @@ export class GuildMemberJoin extends Event {
if (!user) { if (!user) {
user = await User.create({ user = await User.create({
discordId: member.id, discordId: member.id,
rank: getRandomRank() rankId: (await getRandomRank()).id
}, {
include: [{
model: Rank,
as: 'rank'
}]
}); });
} }
await addRole(member, user, this.client); await addRole(member, user);
const channel = await member.guild.channels.fetch(this.client.config.welcomeChannel); const channel = await member.guild.channels.fetch(this.client.config.welcomeChannel);
@ -39,7 +44,7 @@ export class GuildMemberJoin extends Event {
let embed = new EmbedBuilder() let embed = new EmbedBuilder()
.setTitle(`Bienvenue sur le serveur ${member.displayName} !`) .setTitle(`Bienvenue sur le serveur ${member.displayName} !`)
.setThumbnail(member.displayAvatarURL()) .setThumbnail(member.displayAvatarURL())
.setDescription(`Bien joué ! Tu as obtenu le rang : ${Rank[user.rank]}`) .setDescription(`Bien joué ! Tu as obtenu le rang : ${user.rank.name}`)
.setTimestamp(new Date()) .setTimestamp(new Date())
.setColor('#0078DE') .setColor('#0078DE')
; ;