Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report command part3 #2446

Merged
merged 4 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions Core/src/commands/player/ReportCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import {Possibility} from "../../data/events/Possibility";
import {applyPossibilityOutcome} from "../../data/events/PossibilityOutcome";
import {ErrorPacket} from "../../../../Lib/src/packets/commands/ErrorPacket";
import {Effect} from "../../../../Lib/src/enums/Effect";
import {MapLocationDataController} from "../../data/MapLocation";

export default class ReportCommand {
@packetHandler(CommandReportPacketReq)
Expand Down Expand Up @@ -205,7 +206,7 @@ async function doPossibility(

const newMapLink = await applyPossibilityOutcome(event.id, possibility[0], randomOutcome, player, time, context, response);

if (!await player.killIfNeeded(response, NumberChangeReason.BIG_EVENT) && newMapLink) {
if (!await player.killIfNeeded(response, NumberChangeReason.BIG_EVENT) && !newMapLink) {
await chooseDestination(context, player, newMapLink, response);
}

Expand Down Expand Up @@ -322,9 +323,11 @@ async function doRandomBigEvent(
*/
async function automaticChooseDestination(forcedLink: MapLink, player: Player, destinationMaps: number[], response: DraftBotPacket[]): Promise<void> {
const newLink = forcedLink && forcedLink.id !== -1 ? forcedLink : MapLinkDataController.instance.getLinkByLocations(player.getDestinationId(), destinationMaps[0]);
const endMap = MapLocationDataController.instance.getById(newLink.endMap);
await Maps.startTravel(player, newLink, Date.now());
response.push(makePacket(CommandReportChooseDestinationRes, {
mapId: newLink.endMap,
mapTypeId: endMap.type,
tripDuration: newLink.tripDuration
}));
}
Expand Down Expand Up @@ -359,9 +362,14 @@ async function chooseDestination(

const mapReactions: ReactionCollectorChooseDestinationReaction[] = destinationMaps.map((mapId) => {
const mapLink = MapLinkDataController.instance.getLinkByLocations(player.getDestinationId(), mapId);
const mapTypeId = MapLocationDataController.instance.getById(mapId).type;
const isPveMap = MapCache.allPveMapLinks.includes(mapLink.id);

return {mapId, tripDuration: isPveMap || RandomUtils.draftbotRandom.bool() ? mapLink.tripDuration : null};
return {
mapId,
mapTypeId,
tripDuration: isPveMap || RandomUtils.draftbotRandom.bool() ? mapLink.tripDuration : null
};
});

const collector = new ReactionCollectorChooseDestination(mapReactions);
Expand All @@ -372,9 +380,11 @@ async function chooseDestination(
(firstReaction.reaction.data as ReactionCollectorChooseDestinationReaction).mapId :
(RandomUtils.draftbotRandom.pick(collector.creationPacket.reactions).data as ReactionCollectorChooseDestinationReaction).mapId;
const newLink = MapLinkDataController.instance.getLinkByLocations(player.getDestinationId(), mapId);
const endMap = MapLocationDataController.instance.getById(mapId);
await Maps.startTravel(player, newLink, Date.now());
response.push(makePacket(CommandReportChooseDestinationRes, {
mapId: newLink.endMap,
mapTypeId: endMap.type,
tripDuration: newLink.tripDuration
}));
BlockingUtils.unblockPlayer(player.id, BlockingConstants.REASONS.CHOOSE_DESTINATION);
Expand Down
6 changes: 3 additions & 3 deletions Core/src/core/database/logs/LogsDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,15 +438,15 @@ export class LogsDatabase extends Database {
* Log the appearance of a big event
* @param keycloakId
* @param eventId
* @param possibilityEmote
* @param possibilityName
* @param outcome
*/
public async logBigEvent(keycloakId: string, eventId: number, possibilityEmote: string, outcome: string): Promise<void> {
public async logBigEvent(keycloakId: string, eventId: number, possibilityName: string, outcome: string): Promise<void> {
const player = await LogsDatabase.findOrCreatePlayer(keycloakId);
const [possibility] = await LogsPossibilities.findOrCreate({
where: {
bigEventId: eventId,
emote: possibilityEmote === "end" ? null : possibilityEmote,
possibilityName: possibilityName === "end" ? null : possibilityName,
issueIndex: parseInt(outcome)
}
});
Expand Down
12 changes: 8 additions & 4 deletions Core/src/core/database/logs/migrations/006-v5.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {QueryInterface} from "sequelize";
import {Effect} from "../../../../../../Lib/src/enums/Effect";
import {DataTypes, QueryInterface} from "sequelize";
import {Effect} from "../../../../../../Lib/src/enums/Effect"; // eslint-disable-next-line new-cap

// Populated by v5 migration of game
// Map discordId => new ID
Expand All @@ -12,14 +12,18 @@ export async function up({context}: { context: QueryInterface }): Promise<void>
await context.sequelize.query(`UPDATE players SET discordId = "${id[1]}" WHERE discordId = "${id[0]}"`);
}

await context.renameColumn("players", "discordId", "keycloakId");
await context.renameColumn("players", "gameId", "keycloakId");

// Change alterations name in logs
for (const effect of Effect.getAll()) {
await context.sequelize.query(`UPDATE alterations SET alteration = "${effect.id}" WHERE alteration = "${effect.v4Id}"`);
}

// Extend logs possibilities emote length + rename
await context.changeColumn("possibilities", "emote", DataTypes.STRING(256)); // eslint-disable-line new-cap
await context.renameColumn("possibilities", "emote", "possibilityName");
}

export async function down({context}: { context: QueryInterface }): Promise<void> {
await context.renameColumn("players", "keycloakId", "discordId");
await context.renameColumn("players", "keycloakId", "gameId");
}
6 changes: 3 additions & 3 deletions Core/src/core/database/logs/models/LogsPossibilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export class LogsPossibilities extends Model {

declare readonly bigEventId: number;

declare readonly emote: string;
declare readonly possibilityName: string;

declare readonly issueIndex: number;
}
Expand All @@ -21,8 +21,8 @@ export function initModel(sequelize: Sequelize): void {
type: DataTypes.SMALLINT.UNSIGNED,
allowNull: false
},
emote: {
type: DataTypes.STRING(5), // eslint-disable-line new-cap
possibilityName: {
type: DataTypes.STRING(256), // eslint-disable-line new-cap
allowNull: true // Null for end
},
issueIndex: {
Expand Down
139 changes: 90 additions & 49 deletions Discord/src/commands/player/ReportCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
} from "../../../../Lib/src/packets/commands/CommandReportPacket";
import {KeycloakUser} from "../../../../Lib/src/keycloak/KeycloakUser";
import {
ReactionCollectorCreationPacket,

Check warning on line 11 in Discord/src/commands/player/ReportCommand.ts

View workflow job for this annotation

GitHub Actions / eslint-discord-module

Unexpected trailing comma
ReactionCollectorReactPacket
} from "../../../../Lib/src/packets/interaction/ReactionCollectorPacket";
import {
ReactionCollectorBigEventData,
Expand All @@ -26,10 +25,13 @@
import {DiscordCache} from "../../bot/DiscordCache";
import {DraftBotIcons} from "../../../../Lib/src/DraftBotIcons";
import {sendInteractionNotForYou} from "../../utils/ErrorUtils";
import {DiscordWebSocket} from "../../bot/Websocket";
import {Constants} from "../../../../Lib/src/constants/Constants";
import {Effect} from "../../../../Lib/src/enums/Effect";
import {minutesDisplay} from "../../../../Lib/src/utils/TimeUtils";
import {DraftBotEmbed} from "../../messages/DraftBotEmbed";
import {ReactionCollectorChooseDestinationReaction} from "../../../../Lib/src/packets/interaction/ReactionCollectorChooseDestination";
import {Language} from "../../../../Lib/src/Language";
import {DiscordCollectorUtils} from "../../utils/DiscordCollectorUtils";

async function getPacket(interaction: DraftbotInteraction, user: KeycloakUser): Promise<CommandReportPacketReq> {
await interaction.deferReply();
Expand Down Expand Up @@ -71,35 +73,7 @@
const respondToEvent = (possibilityName: string, buttonInteraction: ButtonInteraction | null): void => {
if (!responded) {
responded = true;

const responsePacket = makePacket(
ReactionCollectorReactPacket,
{
id: packet.id,
keycloakId: user.id,
reactionIndex: reactions.findIndex((reaction) => reaction.name === possibilityName)
}
);

if (buttonInteraction) {
DiscordCache.cacheButtonInteraction(buttonInteraction);
}
DiscordWebSocket.socket!.send(JSON.stringify({
packet: {
name: responsePacket.constructor.name,
data: responsePacket
},
context: {
keycloakId: user.id,
discord: {
user: interaction.user.id,
channel: interaction.channel.id,
interaction: interaction.id,
buttonInteraction: buttonInteraction?.id,
language: interaction.userLanguage
}
}
}));
DiscordCollectorUtils.sendReaction(packet, context, user, buttonInteraction, reactions.findIndex((reaction) => reaction.name === possibilityName));
}
};

Expand All @@ -123,20 +97,17 @@
buttonCollector.on("end", async (collected) => {
const firstReaction = collected.first() as ButtonInteraction;

if (!firstReaction) {
respondToEvent("end", null);
}
else {
if (firstReaction) {
await firstReaction.deferReply();
respondToEvent(firstReaction.customId, firstReaction);
}
});

endCollector.on("collect", () => {
respondToEvent("end", null);

buttonCollector.stop();
endCollector.stop();

respondToEvent("end", null);
});
}

Expand All @@ -146,41 +117,41 @@

let result = "";
if (packet.score) {
result += i18n.t("commands:report.points", { lng: interaction.channel.language, score: packet.score });
result += i18n.t("commands:report.points", { lng: interaction.userLanguage, score: packet.score });
}
if (packet.money < 0) {
result += i18n.t("commands:report.moneyLoose", { lng: interaction.channel.language, money: -packet.money });
result += i18n.t("commands:report.moneyLoose", { lng: interaction.userLanguage, money: -packet.money });
}
else if (packet.money > 0) {
result += i18n.t("commands:report.money", { lng: interaction.channel.language, money: packet.money });
result += i18n.t("commands:report.money", { lng: interaction.userLanguage, money: packet.money });
}
if (packet.health < 0) {
result += i18n.t("commands:report.healthLoose", { lng: interaction.channel.language, health: -packet.health });
result += i18n.t("commands:report.healthLoose", { lng: interaction.userLanguage, health: -packet.health });
}
else if (packet.health > 0) {
result += i18n.t("commands:report.health", { lng: interaction.channel.language, health: packet.health });
result += i18n.t("commands:report.health", { lng: interaction.userLanguage, health: packet.health });
}
if (packet.energy) {
result += i18n.t("commands:report.energy", { lng: interaction.channel.language, energy: packet.energy });
result += i18n.t("commands:report.energy", { lng: interaction.userLanguage, energy: packet.energy });
}
if (packet.gems) {
result += i18n.t("commands:report.gems", { lng: interaction.channel.language, gems: packet.gems });
result += i18n.t("commands:report.gems", { lng: interaction.userLanguage, gems: packet.gems });
}
if (packet.experience) {
result += i18n.t("commands:report.experience", { lng: interaction.channel.language, experience: packet.experience });
result += i18n.t("commands:report.experience", { lng: interaction.userLanguage, experience: packet.experience });
}
if (packet.effect && packet.effect.name === Effect.OCCUPIED.id) {
result += i18n.t("commands:report.timeLost", { lng: interaction.channel.language, timeLost: minutesDisplay(packet.effect.time) });
result += i18n.t("commands:report.timeLost", { lng: interaction.userLanguage, timeLost: minutesDisplay(packet.effect.time) });
}

const content = i18n.t("commands:report.doPossibility", {
lng: interaction.channel.language,
lng: interaction.userLanguage,
interpolation: { escapeValue: false },
pseudo: user.attributes.gameUsername,
result,
event: i18n.t(`events:${packet.eventId}.possibilities.${packet.possibilityId}.outcomes.${packet.outcomeId}`),
event: i18n.t(`events:${packet.eventId}.possibilities.${packet.possibilityId}.outcomes.${packet.outcomeId}`, { lng: interaction.userLanguage }),
emoji: packet.possibilityId === "end" ? (DraftBotIcons.events[packet.eventId].end as { [outcomeId: string]: string })[packet.outcomeId] : DraftBotIcons.events[packet.possibilityId],
alte: packet.effect ? DraftBotIcons.effects[packet.effect.name] : ""
alte: packet.effect && packet.effect.name !== Effect.OCCUPIED.id ? DraftBotIcons.effects[packet.effect.name] : ""
});

const buttonInteraction = context.discord?.buttonInteraction ? DiscordCache.getButtonInteraction(context.discord?.buttonInteraction) : null;
Expand All @@ -193,6 +164,76 @@
}
}

const destinationChoiceEmotes = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣"];

/**
* Creates the description for a chooseDestination embed
* @param reactions
* @param language
*/
function createDescriptionChooseDestination(reactions: ReactionCollectorChooseDestinationReaction[], language: Language): string {
let desc = `${i18n.t("commands:report.chooseDestinationIndications", { lng: language })}\n`;
for (let i = 0; i < reactions.length; ++i) {
const reaction = reactions[i];
const duration = reaction.tripDuration ? minutesDisplay(reaction.tripDuration) : "?h";
desc += `${destinationChoiceEmotes[i]} - ${DraftBotIcons.map_types[reaction.mapTypeId]} ${i18n.t(`models:map_locations.${reaction.mapId}.name`, { lng: language })} (${duration})\n`;
}
return desc;
BastLast marked this conversation as resolved.
Show resolved Hide resolved
}

export async function chooseDestinationCollector(packet: ReactionCollectorCreationPacket, context: PacketContext): Promise<void> {
const user = (await KeycloakUtils.getUserByKeycloakId(keycloakConfig, context.keycloakId!))!;
const interaction = DiscordCache.getInteraction(context.discord!.interaction)!;

const embed = new DraftBotEmbed();
embed.formatAuthor(i18n.t("commands:report.destinationTitle", {
lng: interaction.userLanguage,
pseudo: user.attributes.gameUsername
}), interaction.user);
embed.setDescription(
createDescriptionChooseDestination(
packet.reactions.map(reaction => reaction.data) as ReactionCollectorChooseDestinationReaction[],
interaction.userLanguage
)
);

const row = new ActionRowBuilder<ButtonBuilder>();

for (let i = 0; i < packet.reactions.length; ++i) {
const button = new ButtonBuilder()
.setEmoji(parseEmoji(destinationChoiceEmotes[i])!)
.setCustomId(i.toString())
.setStyle(ButtonStyle.Secondary);
row.addComponents(button);
}

const msg = await interaction?.channel.send({
embeds: [embed],
components: [row]
}) as Message;

const buttonCollector = msg.createMessageComponentCollector({
time: packet.endTime - Date.now()
});

buttonCollector.on("collect", async (buttonInteraction: ButtonInteraction) => {
if (buttonInteraction.user.id !== context.discord?.user) {
await sendInteractionNotForYou(buttonInteraction.user, buttonInteraction, interaction.userLanguage);
return;
}

buttonCollector.stop();
});
buttonCollector.on("end", async (collected) => {
const firstReaction = collected.first() as ButtonInteraction;

if (firstReaction) {
await firstReaction.deferReply();
DiscordCollectorUtils.sendReaction(packet, context, user, firstReaction, parseInt(firstReaction.customId));
}
});
}

export const commandInfo: ICommand = {
slashCommandBuilder: SlashCommandBuilderGenerator.generateBaseCommand("report"),
getPacket,
Expand Down
10 changes: 1 addition & 9 deletions Discord/src/packetHandlers/handlers/ErrorHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,7 @@ export default class ErrorHandler {
.setTitle(i18n.t("error:unexpectedError", {lng: interaction?.channel?.language}))
.setDescription(packet.message);

if (interaction?.deferred && !interaction.replyEdited) {
interaction?.editReply({embeds: [embed]});
}
else if (!interaction?.deferred && !interaction?.replied) {
interaction?.reply({embeds: [embed]});
}
else {
interaction?.channel.send({embeds: [embed]});
}
await interaction?.channel.send({embeds: [embed]});
}

@packetHandler(BlockedPacket)
Expand Down
Loading
Loading