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"
GUILD_ID="1234567890"
DB_DIALECT="mysql"
DB_DIALECT="postgres"
DB_HOST="localhost"
DB_NAME="gachamelia"
DB_USERNAME="gachamelia"
DB_USERNAME="postgres"
DB_PASSWORD="gachamelia"
DB_PORT=3310
SSR_ROLE=""
SR_ROLE=""
R_ROLE=""
DB_PORT=5433
WELCOME_CHANNEL=""
INIT_DB="true"

View File

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

View File

@ -9,6 +9,7 @@ import {Database} from "./Database";
import {IDatabaseConfig} from "../interfaces/IDatabaseConfig";
import {Dialect} from "sequelize";
import {User} from "../models/User";
import {Rank} from "../models/Rank";
export class CustomClient extends Client implements ICustomClient {
config: IConfig;
@ -47,7 +48,20 @@ export class CustomClient extends Client implements ICustomClient {
}
async init(): Promise<void> {
await this.database.connect();
Rank.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({
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 { Rank } from '../enums/Rank';
import {
Model,
DataTypes,
Sequelize,
ForeignKey,
NonAttribute,
InferAttributes, InferCreationAttributes, CreationOptional, Association
} from 'sequelize';
import {Rank} from "./Rank";
export class User extends Model {
declare id: number;
export class User extends Model<
InferAttributes<User>,
InferCreationAttributes<User>> {
declare id: CreationOptional<number>;
declare discordId: string;
declare rank: Rank;
declare createdAt: Date;
declare updatedAt: Date;
declare rankId: ForeignKey<number>;
declare rank: NonAttribute<Rank>;
declare createdAt: CreationOptional<Date>;
declare updatedAt: CreationOptional<Date>;
public static initModel(sequelize: Sequelize): void {
User.init({
@ -20,9 +30,13 @@ export class User extends Model {
allowNull: false,
unique: true
},
rank: {
type: DataTypes.STRING,
allowNull: false
rankId: {
type: DataTypes.INTEGER,
allowNull: false,
references: {
model: Rank,
key: 'id'
}
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE
@ -31,4 +45,10 @@ export class User extends Model {
tableName: 'users'
});
}
declare static associations: {
rank: Association<User, Rank>;
};
}

View File

@ -1,33 +1,24 @@
import {CustomClient} from "../classes/CustomClient";
import {User} from "../models/User";
import {getRandomRank} from "./RandomUtils";
import {Rank} from "../enums/Rank";
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 {
let rRoleId = client.config.rRole;
let srRoleId = client.config.srRole;
let ssrRoleId = client.config.ssrRole;
if (user.rank === Rank.R) {
const rRole = await member.guild.roles.fetch(rRoleId);
if (rRole) {
await member.roles.add(rRole);
let userRank = await Rank.findOne({
where: {
id: user.rankId
}
} else if (user.rank === Rank.SR) {
const srRole = await member.guild.roles.fetch(srRoleId);
});
if (srRole) {
await member.roles.add(srRole);
if (!userRank) {
return;
}
} else if (user.rank === Rank.SSR) {
const ssrRole = await member.guild.roles.fetch(ssrRoleId);
if (ssrRole) {
await member.roles.add(ssrRole);
}
const discordRank = await member.guild.roles.fetch(userRank.discordId);
if (discordRank) {
await member.roles.add(userRank.discordId);
}
} catch (e: Error | any) {
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({
where: {
discordId: member.id
},
include: {
model: Rank,
as: 'rank'
}
})
if (!user) {
user = await User.create({
discordId: member.id,
rank: getRandomRank()
rankId: (await getRandomRank()).id
}, {
include: [{
model: Rank,
as: 'rank'
}]
});
await addRole(member, user, client);
await addRole(member, user);
count++;
}

View File

@ -1,16 +1,20 @@
import {Rank} from "../enums/Rank";
import {RankChance} from "../enums/RankChance";
import {Rank} from "../models/Rank";
export function getRandomRank(): Rank {
export async function getRandomRank(): Promise<Rank> {
const rand = Math.random() * 100;
let cumulativeChance = 0;
const ranks = await Rank.findAll();
for (const rank of Object.values(Rank)) {
cumulativeChance += RankChance[rank as keyof typeof RankChance];
if (ranks.length === 0) {
throw new Error('No ranks found');
}
for (const rank of ranks) {
cumulativeChance += rank.percentage;
if (rand <= cumulativeChance) {
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 {EmbedBuilder, GuildMember, PermissionsBitField, SlashCommandUserOption} from "discord.js";
import {User} from "../base/models/User";
import {Rank} from "../base/enums/Rank";
import {Rank} from "../base/models/Rank";
import {getRandomRank} from "../base/utils/RandomUtils";
export class PingCommand extends Command {
@ -26,19 +26,23 @@ export class PingCommand extends Command {
async execute(interaction: any): Promise<void> {
let discordUser = (interaction.options.getMember('user') || interaction.member) as GuildMember;
console.log(discordUser.id);
let user = await User.findOne(
{
where: {
discordId: discordUser.id
}
},
include: [{
model: Rank,
as: 'rank'
}],
}
);
if (!user) {
user = await User.create({
discordId: discordUser.id,
rank: getRandomRank()
rankId: (await getRandomRank()).id
});
}
@ -46,7 +50,7 @@ export class PingCommand extends Command {
let embed = new EmbedBuilder()
.setTitle(`Rang de ${discordUser.displayName}`)
.setThumbnail(discordUser.displayAvatarURL())
.setDescription(`Cet utilisateur est de rang : ${Rank[user.rank]}`)
.setDescription(`Cet utilisateur est de rang : ${user.rank.name}`)
.setTimestamp(new Date())
.setColor('#0078DE')
;

View File

@ -3,6 +3,7 @@ import {CustomClient} from "../../base/classes/CustomClient";
import {Collection, Events, REST, Routes} from "discord.js";
import {Command} from "../../base/classes/Command";
import {createAllUsers} from "../../base/utils/GachaUtils";
import {Rank} from "../../base/models/Rank";
export class Ready extends Event {
constructor(client: CustomClient) {
super(client, {
@ -29,8 +30,12 @@ export class Ready extends Event {
console.log(`${setCommands.length} Commandes mises à jours avec succès !`);
if (process.env.INIT_DB === 'true') {
await this.initDb();
} else {
await createAllUsers(this.client);
}
}
private getJson(commands: Collection<string, Command>): object[] {
const data: object[] = [];
@ -47,4 +52,38 @@ export class Ready extends Event {
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 {User} from "../../base/models/User";
import {getRandomRank} from "../../base/utils/RandomUtils";
import {Rank} from "../../base/enums/Rank";
import {addRole} from "../../base/utils/GachaUtils";
import {Rank} from "../../base/models/Rank";
export class GuildMemberJoin extends Event {
constructor(client: CustomClient) {
@ -26,11 +26,16 @@ export class GuildMemberJoin extends Event {
if (!user) {
user = await User.create({
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);
@ -39,7 +44,7 @@ export class GuildMemberJoin extends Event {
let embed = new EmbedBuilder()
.setTitle(`Bienvenue sur le serveur ${member.displayName} !`)
.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())
.setColor('#0078DE')
;