Skip to content

Commit b00a79e

Browse files
committed
[Update]
1 parent 75529ef commit b00a79e

File tree

7 files changed

+105
-42
lines changed

7 files changed

+105
-42
lines changed

command/ctf.command.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CacheType, Client, GuildMember, Interaction } from "discord.js"
22
import { checkFlag, deleteChallenge, getAllChallenge, saveFlag, scoreBoard, updateURLChall } from "../controller/flag.controller";
3-
import { createTeam, getInfoHacker, leaveTeam, updateLevelAllUser } from "../controller/player.controller";
3+
import { createTeam, getInfoHacker, leaveTeam, listParticipatedContest, updateLevelAllUser } from "../controller/player.controller";
44
import { addChallengeContest, createContest, joinContest, listContests, scoreBoardContest } from "../controller/contest.controller";
55
import { joinTeam } from "../controller/player.controller";
66
import { createEmbed } from "../feature/component";
@@ -36,6 +36,9 @@ const CTFCommand = {
3636
options.getBoolean("public"),
3737
options.getString("url"),
3838
options.getString("category"),
39+
options.getString("status"),
40+
options.getBoolean("public"),
41+
options.getString("passwordcontest"),
3942
interaction
4043
);
4144
if (options.getString("idContest")) {
@@ -50,7 +53,7 @@ const CTFCommand = {
5053
await getInfoHacker(hacker ?? user, interaction);
5154
break;
5255
case "listchall":
53-
await getAllChallenge(options.getString("password") == adminPassword, options.getString("category"), options.getString("idcontest"), interaction);
56+
await getAllChallenge(options.getString("password") == adminPassword, options.getString("category"), options.getString("idcontest"), options.getString("passwordcontest"), interaction);
5457
break;
5558
case "rmchall":
5659
await deleteChallenge(options.getString("password") == adminPassword,
@@ -77,7 +80,7 @@ const CTFCommand = {
7780
await listContests(interaction);
7881
break;
7982
case "joincontest":
80-
await joinContest(options.getString("id"), user, interaction);
83+
await joinContest(options.getString("id"), user, options.getString("password"), interaction);
8184
break;
8285
case "scoreboardcontest":
8386
await scoreBoardContest(options.getString("id"), interaction);
@@ -96,6 +99,9 @@ const CTFCommand = {
9699
case "leaveteam":
97100
await leaveTeam(user, interaction);
98101
break;
102+
case "contest":
103+
await listParticipatedContest(user, interaction);
104+
break;
99105
case "help":
100106
const embed = createEmbed("Help", "```" +
101107
"***Feature:***\n" +

command/slash.deploy.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const serverCommands: Array<RESTPostAPIChatInputApplicationCommandsJSONBody> = [
2323
{ name: 'Web Exploitation', value: 'Web Exploitation' } as APIApplicationCommandOptionChoice<string>,
2424
).setDescription("Type category"))
2525
.addStringOption(option => option.setName("idcontest").setDescription("Type contest ID (No if not)"))
26+
.addStringOption(option => option.setName("passwordcontest").setDescription("Type contest password (No if not)"))
2627
.addStringOption(option => option.setName("password").setDescription("Type password to verify")),
2728
new SlashCommandBuilder().setName("challenge").setDescription("Add new flag!")
2829
.addStringOption(option => option.setName('id').setDescription("Add new flag!").setRequired(true))
@@ -58,7 +59,13 @@ const serverCommands: Array<RESTPostAPIChatInputApplicationCommandsJSONBody> = [
5859
.addStringOption(option => option.setName("description").setDescription("Contest description").setRequired(true))
5960
.addStringOption(option => option.setName("start").setDescription("Contest start time").setRequired(true))
6061
.addStringOption(option => option.setName("endt").setDescription("Contest end time").setRequired(true))
61-
.addBooleanOption(option => option.setName("status").setDescription("Contest status").setRequired(true)),
62+
.addStringOption(option => option.setName("status").addChoices(
63+
{ name: "Coming", value: 'Coming' } as APIApplicationCommandOptionChoice<string>,
64+
{ name: 'Running', value: 'Running' } as APIApplicationCommandOptionChoice<string>,
65+
{ name: 'Ended', value: 'Ended' } as APIApplicationCommandOptionChoice<string>,
66+
).setDescription("Contest status").setRequired(true))
67+
.addBooleanOption(option => option.setName("public").setDescription("Contest public").setRequired(true))
68+
.addStringOption(option => option.setName("passwordcontest").setDescription("Contest password (Pass it if contest is public)").setRequired(true)),
6269
new SlashCommandBuilder().setName("listcontest").setDescription("View all contest (Normal or admin)")
6370
.addStringOption(option => option.setName("password").setDescription("Type password to verify")),
6471
new SlashCommandBuilder().setName("rmcontest").setDescription("Admin delete contest")
@@ -75,7 +82,8 @@ const serverCommands: Array<RESTPostAPIChatInputApplicationCommandsJSONBody> = [
7582
new SlashCommandBuilder().setName("infocontest").setDescription("View contest information!")
7683
.addStringOption(option => option.setName("id").setDescription("Contest ID").setRequired(true)),
7784
new SlashCommandBuilder().setName("joincontest").setDescription("Join contest!")
78-
.addStringOption(option => option.setName("id").setDescription("Contest ID").setRequired(true)),
85+
.addStringOption(option => option.setName("id").setDescription("Contest ID").setRequired(true))
86+
.addStringOption(option => option.setName("password").setDescription("Contest password (Pass it if contest is public)").setRequired(true)),
7987
new SlashCommandBuilder().setName("leavecontest").setDescription("Leave contest!")
8088
.addStringOption(option => option.setName("id").setDescription("Contest ID").setRequired(true)),
8189
new SlashCommandBuilder().setName("help").setDescription("View help!"),
@@ -96,7 +104,8 @@ const UserCommands: Array<RESTPostAPIChatInputApplicationCommandsJSONBody> = [
96104
new SlashCommandBuilder().setName("createteam").setDescription("Create team!")
97105
.addStringOption(option => option.setName("name").setDescription("Team name").setRequired(true))
98106
.addStringOption(option => option.setName("description").setDescription("Team description").setRequired(true)),
99-
new SlashCommandBuilder().setName("leaveteam").setDescription("Leave team!")
107+
new SlashCommandBuilder().setName("leaveteam").setDescription("Leave team!"),
108+
new SlashCommandBuilder().setName("contest").setDescription("View participating competitions!"),
100109

101110
].map(command => command.toJSON());
102111

controller/contest.controller.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export const getInfoContest = async (idContest: String | null, interaction: Chat
7878
}
7979
}
8080

81-
export const joinContest = async (idContest: String | null, user: User, interaction: ChatInputCommandInteraction<CacheType>) => {
81+
export const joinContest = async (idContest: String | null, user: User, password: String | null, interaction: ChatInputCommandInteraction<CacheType>) => {
8282
try {
8383
const contest = await ContestModel.findOne({ idContest });
8484
if (contest) {
@@ -89,6 +89,9 @@ export const joinContest = async (idContest: String | null, user: User, interact
8989
if (teamContest) {
9090
await interaction.reply("Bạn đã tham gia contest này rồi!");
9191
} else {
92+
if ((contest.public == false) && (password !== contest.password)) {
93+
return await interaction.reply("Mật khẩu của contest không đúng!");
94+
}
9295
const newTeam = {
9396
team: {
9497
idTeam: idTeam,
@@ -106,6 +109,7 @@ export const joinContest = async (idContest: String | null, user: User, interact
106109
}
107110
});
108111
await interaction.reply("Tham gia contest thành công!");
112+
109113
}
110114
} else {
111115
await interaction.reply("Hãy gia nhập một team để đăng ký contest!");

controller/flag.controller.ts

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { CacheType, ChatInputCommandInteraction, Interaction, User } from "discord.js";
2-
import { Flags } from "../interface/model.interface";
2+
import { Contest, Flags } from "../interface/model.interface";
33
import FlagModel from "../model/flag.model";
44
import scoreModel from "../model/score.model";
55
import playerModel from "../model/player.model";
@@ -17,10 +17,13 @@ export const saveFlag = async (
1717
mode: Boolean | null,
1818
url: String | null,
1919
category: String | null,
20+
status: String | null,
21+
publicMode: Boolean | null,
22+
password: String | null,
2023
interaction: ChatInputCommandInteraction<CacheType>) =>
2124
{
2225
try {
23-
const newFlag = new FlagModel({ idChall, nameAuthor, nameChall, point, level, description, flag, mode, url, category });
26+
const newFlag = new FlagModel({ idChall, nameAuthor, nameChall, point, level, description, flag, mode, url, category, status, public: publicMode, password, createdBy: interaction.user.id });
2427
await newFlag.save();
2528
await interaction.reply("Thêm thành công!");
2629
} catch (error) {
@@ -55,41 +58,48 @@ export const checkFlag = async (flag: String | null, players: User, interaction:
5558
}
5659

5760

58-
export const getAllChallenge = async (admin: Boolean, category: String | null, idContest: String | null, interaction: ChatInputCommandInteraction<CacheType>) => {
61+
export const getAllChallenge = async (admin: Boolean, category: String | null, idContest: String | null, password: String | null, interaction: ChatInputCommandInteraction<CacheType>) => {
62+
let contest: Contest | null = null;
63+
if (idContest != null) {
64+
contest = await contestModel.findOne({ idContest: idContest });
65+
if (contest == null) {
66+
return await interaction.reply("Không tìm thấy contest này!");
67+
}
5968

60-
const contest = await contestModel.findOne({ idContest: idContest });
69+
// Testing
70+
const checkUser = contest.teams.find(team => team.team.members.find(member => member.idUser == interaction.user.id));
71+
if (!checkUser) {
72+
return await interaction.reply("Bạn không tham gia contest này!");
73+
}
74+
}
6175

62-
if (contest == null) {
63-
await interaction.reply("Không tìm thấy contest này!");
64-
} else {
65-
let challenges: Array<Flags> = [];
66-
challenges = await FlagModel.find({
67-
mode: !admin,
68-
category: category ?? { $regex: /.*/ },
69-
idContest: idContest
70-
}, "idChall nameAuthor nameChall point level description mode url category");
76+
let challenges: Array<Flags> = [];
77+
challenges = await FlagModel.find({
78+
mode: !admin,
79+
category: category ?? { $regex: /.*/ },
80+
idContest: idContest
81+
}, "idChall nameAuthor nameChall point level description mode url category");
7182

72-
if (challenges.length == 0) {
73-
await interaction.reply(`Các challenge của contest ***${contest.nameContest}*** chưa được cập nhập hoặc public!`);
74-
}
75-
else {
76-
let infoChallenges = "";
77-
challenges.map((challenge: Flags, index: number) => {
78-
infoChallenges += `${index + 1}. ***Tên thử thách:*** ` + challenge.nameChall +
79-
"***\n\tID:*** " + challenge.idChall +
80-
"***\n\tTác giả:*** " + challenge.nameAuthor +
81-
"***\n\tLoại:*** " + challenge.category +
82-
"***\n\tMô tả:*** " + challenge.description +
83-
"***\n\tĐiểm:*** " + challenge.point +
84-
"***\n\tĐộ khó:*** " + challenge.level +
85-
"***\n\tLink thử thách:*** " + challenge.url + "\n";
86-
if (admin) {
87-
infoChallenges += "***\n\tTrạng thái:*** " + (challenge.mode ? "Public" : "Private") + "***\tID Challenge:*** " + challenge.idChall + "\n" + "***\n\tID Contest:*** " + challenge.idContest ?? "Không" + "\n";
88-
}
89-
});
90-
const embed = createEmbed("Danh sách thử thách" + (category ? ` thuộc loại ${category}` : ""), infoChallenges);
91-
await interaction.reply({ embeds: [embed] });
92-
}
83+
if (challenges.length == 0 && contest != null) {
84+
await interaction.reply(`Các challenge của contest ***${contest.nameContest}*** chưa được cập nhập hoặc public!`);
85+
}
86+
else {
87+
let infoChallenges = "";
88+
challenges.map((challenge: Flags, index: number) => {
89+
infoChallenges += `${index + 1}. ***Tên thử thách:*** ` + challenge.nameChall +
90+
"***\n\tID:*** " + challenge.idChall +
91+
"***\n\tTác giả:*** " + challenge.nameAuthor +
92+
"***\n\tLoại:*** " + challenge.category +
93+
"***\n\tMô tả:*** " + challenge.description +
94+
"***\n\tĐiểm:*** " + challenge.point +
95+
"***\n\tĐộ khó:*** " + challenge.level +
96+
"***\n\tLink thử thách:*** " + challenge.url + "\n";
97+
if (admin) {
98+
infoChallenges += "***\n\tTrạng thái:*** " + (challenge.mode ? "Public" : "Private") + "***\tID Challenge:*** " + challenge.idChall + "\n" + "***\n\tID Contest:*** " + challenge.idContest ?? "Không" + "\n";
99+
}
100+
});
101+
const embed = createEmbed("Danh sách thử thách" + (category ? ` thuộc loại ${category}` : ""), infoChallenges);
102+
await interaction.reply({ embeds: [embed] });
93103
}
94104
}
95105

controller/player.controller.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,24 @@ export const leaveTeam = async (hacker: User, interaction: ChatInputCommandInter
148148
}
149149
}
150150

151+
export const listParticipatedContest = async (hacker: User, interaction: ChatInputCommandInteraction<CacheType>) => {
152+
const user = await playerModel.findOne({ idUser: hacker.id });
153+
if (user) {
154+
const listContest = await teamModel.find({ "members.idUser": user.idUser }, "name idTeam contests");
155+
if (listContest.length > 0) {
156+
const listContestName = listContest.map((contest: any) => {
157+
return contest.name + " - " + contest.idTeam;
158+
});
159+
const embed = createEmbed("Danh sách contest đã tham gia", listContestName.join("\n\t\t"));
160+
await interaction.reply({ embeds: [embed] });
161+
} else {
162+
await interaction.reply("Bạn chưa tham gia contest nào!");
163+
}
164+
} else {
165+
await interaction.reply("Người dùng này chưa có trong hệ thống! Submit ít nhất một Flag để được thêm vào hệ thống");
166+
}
167+
}
168+
151169
// export const getAllChallengeSolved = async (hacker: User, interaction: ChatInputCommandInteraction<CacheType>){
152170

153171
// }

interface/model.interface.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export interface Contest extends Document {
6666
endTime?: String,
6767
teams: TeamContest[],
6868
submit: SubmitContest[],
69+
createdBy: mongoose.Schema.Types.ObjectId,
70+
password: String,
71+
public: Boolean,
6972
}
7073

7174
export interface FlagContest extends mongoose.Document {

model/contest.model.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,20 @@ const ContestSchema = new mongoose.Schema<Contest>({
3434
submit: {
3535
type: Array<SubmitContest>(),
3636
default: [],
37-
}
37+
},
38+
createdBy: {
39+
type: mongoose.Schema.Types.ObjectId,
40+
ref: "User",
41+
required: true
42+
},
43+
password: {
44+
type: String,
45+
default: null
46+
},
47+
public: {
48+
type: Boolean,
49+
default: false
50+
},
3851
}, { timestamps: true });
3952

4053
export default mongoose.model<Contest>("Contest", ContestSchema);

0 commit comments

Comments
 (0)