Skip to content

Commit

Permalink
Option to filter including/excluding remixes (#1747)
Browse files Browse the repository at this point in the history
* Option to filter including/excluding remixes

* Add remix description to GAMEPLAY.md

* Remove exclusively playing remixes

* Deprecate text command
  • Loading branch information
taahamahdi authored Oct 21, 2023
1 parent a48bd8d commit 981f84d
Show file tree
Hide file tree
Showing 17 changed files with 410 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/GAMEPLAY.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ Use `/help action:[command_name]` for more details about the following commands:
- `/language`: Choose whether to include Japanese/English/Chinese songs, or only Korean songs
- `/subunits`: Choose whether to automatically include a group's subunits when using `/groups`
- `/ost`: Include, exclude, or exclusively play OST music videos
- `/remix`: Include or exclude remixed songs
- `/multiguess`: Choose whether to allow multiple players to guess correctly in a round
- `/shuffle`: Choose whether songs should play in random order, or based on popularity
- `/seek`: Choose whether each song starts from the beginning, middle, or a random point
Expand Down
14 changes: 14 additions & 0 deletions i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "release"
}
},
"remix": {
"help": {
"description": "Choose whether to include remixed songs.",
"example": {
"exclude": "Exclude remixes",
"include": "Include remixes",
"reset": "Reset to the default option of {{defaultRemix}}"
},
"name": "remix"
},
"interaction": {
"remix": "Whether to include or exclude remixed songs"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
14 changes: 14 additions & 0 deletions i18n/es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "lanzamiento"
}
},
"remix": {
"help": {
"description": "Elige si incluir canciones remezcladas.",
"example": {
"exclude": "Excluir remezclas",
"include": "Incluir remezclas",
"reset": "Restablecer a la opción predeterminada de {{defaultRemix}}"
},
"name": "remezcla"
},
"interaction": {
"remix": "Si incluir o excluir canciones remezcladas"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
14 changes: 14 additions & 0 deletions i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "sortie"
}
},
"remix": {
"help": {
"description": "Choisissez si vous souhaitez inclure des chansons remixées.",
"example": {
"exclude": "Exclure les remixes",
"include": "Inclure les remixes",
"reset": "Réinitialiser à l'option par défaut de {{defaultRemix}}"
},
"name": "remix"
},
"interaction": {
"remix": "Que ce soit pour inclure ou exclure des chansons remixées"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
14 changes: 14 additions & 0 deletions i18n/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "リリース"
}
},
"remix": {
"help": {
"description": "リミックスされた曲を含めるかどうかを選択してください。",
"example": {
"exclude": "リミックスを除外",
"include": "リミックスを含める",
"reset": "デフォルトのオプション{{defaultRemix}}にリセット"
},
"name": "リミックス"
},
"interaction": {
"remix": "リミックスされた曲を含めるか、または除外するか"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
14 changes: 14 additions & 0 deletions i18n/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "릴리즈"
}
},
"remix": {
"help": {
"description": "리믹스 된 노래를 포함할지 선택하세요.",
"example": {
"exclude": "리믹스 제외",
"include": "리믹스 포함",
"reset": "기본 옵션 {{defaultRemix}}로 재설정"
},
"name": "리믹스"
},
"interaction": {
"remix": "리믹스 된 노래를 포함하거나 제외할지 여부"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
14 changes: 14 additions & 0 deletions i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,20 @@
"name": "发布"
}
},
"remix": {
"help": {
"description": "选择是否包括混音歌曲。",
"example": {
"exclude": "排除混音",
"include": "包括混音",
"reset": "重置为默认选项{{defaultRemix}}"
},
"name": "混音"
},
"interaction": {
"remix": "是否包括或排除混音歌曲"
}
},
"remove": {
"failure": {
"noGroupsSelected": {
Expand Down
236 changes: 236 additions & 0 deletions src/commands/game_options/remix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import { DEFAULT_REMIX_PREFERENCE, OptionAction } from "../../constants";
import { IPCLogger } from "../../logger";
import {
getDebugLogHeader,
getInteractionValue,
sendDeprecatedTextCommandMessage,
sendOptionsMessage,
} from "../../helpers/discord_utils";
import CommandPrechecks from "../../command_prechecks";
import Eris from "eris";
import GameOption from "../../enums/game_option_name";
import GuildPreference from "../../structures/guild_preference";
import LocaleType from "../../enums/locale_type";
import MessageContext from "../../structures/message_context";
import RemixPreference from "../../enums/option_types/remix_preference";
import Session from "../../structures/session";
import i18n from "../../helpers/localization_manager";
import type { DefaultSlashCommand } from "../interfaces/base_command";
import type BaseCommand from "../interfaces/base_command";
import type CommandArgs from "../../interfaces/command_args";
import type HelpDocumentation from "../../interfaces/help";

const logger = new IPCLogger("remix");

export default class RemixCommand implements BaseCommand {
preRunChecks = [
{ checkFn: CommandPrechecks.competitionPrecheck },
{ checkFn: CommandPrechecks.notSpotifyPrecheck },
];

aliases = ["remixes"];

validations = {
minArgCount: 0,
maxArgCount: 1,
arguments: [
{
name: "remixPreference",
type: "enum" as const,
enums: Object.values(RemixPreference),
},
],
};

help = (guildID: string): HelpDocumentation => ({
name: "remix",
description: i18n.translate(guildID, "command.remix.help.description"),
usage: "/remix set\nremix:[include | exclude]\n\n/remix reset",
examples: [
{
example: "`/remix set remix:include`",
explanation: i18n.translate(
guildID,
"command.remix.help.example.include"
),
},
{
example: "`/remix set remix:exclude`",
explanation: i18n.translate(
guildID,
"command.remix.help.example.exclude"
),
},
{
example: "`/remix reset`",
explanation: i18n.translate(
guildID,
"command.remix.help.example.reset",
{ defaultRemix: `\`${DEFAULT_REMIX_PREFERENCE}\`` }
),
},
],
priority: 130,
});

slashCommands = (): Array<
DefaultSlashCommand | Eris.ChatInputApplicationCommandStructure
> => [
{
type: Eris.Constants.ApplicationCommandTypes.CHAT_INPUT,
options: [
{
name: OptionAction.SET,
description: i18n.translate(
LocaleType.EN,
"command.remix.help.description"
),
description_localizations: Object.values(LocaleType)
.filter((x) => x !== LocaleType.EN)
.reduce(
(acc, locale) => ({
...acc,
[locale]: i18n.translate(
locale,
"command.remix.help.description"
),
}),
{}
),

type: Eris.Constants.ApplicationCommandOptionTypes
.SUB_COMMAND,
options: [
{
name: "remix",
description: i18n.translate(
LocaleType.EN,
"command.remix.interaction.remix"
),
description_localizations: Object.values(LocaleType)
.filter((x) => x !== LocaleType.EN)
.reduce(
(acc, locale) => ({
...acc,
[locale]: i18n.translate(
locale,
"command.remix.interaction.remix"
),
}),
{}
),

type: Eris.Constants.ApplicationCommandOptionTypes
.STRING,
required: true,
choices: Object.values(RemixPreference).map(
(remixPreference) => ({
name: remixPreference,
value: remixPreference,
})
),
},
],
},
{
name: OptionAction.RESET,
description: i18n.translate(
LocaleType.EN,
"misc.interaction.resetOption",
{ optionName: "remix" }
),
description_localizations: Object.values(LocaleType)
.filter((x) => x !== LocaleType.EN)
.reduce(
(acc, locale) => ({
...acc,
[locale]: i18n.translate(
locale,
"misc.interaction.resetOption",
{ optionName: "remix" }
),
}),
{}
),

type: Eris.Constants.ApplicationCommandOptionTypes
.SUB_COMMAND,
options: [],
},
],
},
];

call = async ({ message }: CommandArgs): Promise<void> => {
logger.warn("Text-based command not supported for remix");
await sendDeprecatedTextCommandMessage(
MessageContext.fromMessage(message)
);
};

static async updateOption(
messageContext: MessageContext,
remixPreference: RemixPreference | null,
interaction?: Eris.CommandInteraction
): Promise<void> {
const guildPreference = await GuildPreference.getGuildPreference(
messageContext.guildID
);

const reset = remixPreference == null;
if (reset) {
await guildPreference.reset(GameOption.REMIX_PREFERENCE);
logger.info(
`${getDebugLogHeader(messageContext)} | Remix preference reset.`
);
} else {
await guildPreference.setRemixPreference(remixPreference);
logger.info(
`${getDebugLogHeader(
messageContext
)} | Remix preference set to ${remixPreference}`
);
}

await sendOptionsMessage(
Session.getSession(messageContext.guildID),
messageContext,
guildPreference,
[{ option: GameOption.REMIX_PREFERENCE, reset }],
false,
undefined,
undefined,
interaction
);
}

/**
* @param interaction - The interaction
* @param messageContext - The message context
*/
async processChatInputInteraction(
interaction: Eris.CommandInteraction,
messageContext: MessageContext
): Promise<void> {
const { interactionName, interactionOptions } =
getInteractionValue(interaction);

let remixValue: RemixPreference | null;

const action = interactionName as OptionAction;
if (action === OptionAction.RESET) {
remixValue = null;
} else if (action === OptionAction.SET) {
remixValue = interactionOptions["remix"] as RemixPreference;
} else {
logger.error(`Unexpected interaction name: ${interactionName}`);
remixValue = null;
}

await RemixCommand.updateOption(
messageContext,
remixValue,
interaction
);
}
}
3 changes: 3 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import LocaleType from "./enums/locale_type";
import MultiGuessType from "./enums/option_types/multiguess_type";
import OstPreference from "./enums/option_types/ost_preference";
import ReleaseType from "./enums/option_types/release_type";
import RemixPreference from "./enums/option_types/remix_preference";
import SeekType from "./enums/option_types/seek_type";
import ShuffleType from "./enums/option_types/shuffle_type";
import SpecialType from "./enums/option_types/special_type";
Expand Down Expand Up @@ -54,6 +55,7 @@ export const DEFAULT_GENDER: Array<GenderModeOptions> = [
"male",
"coed",
];
export const DEFAULT_REMIX_PREFERENCE = RemixPreference.EXCLUDE;
export const DEFAULT_LIMIT = 500;
export const SONG_START_DELAY = 3000;

Expand Down Expand Up @@ -185,6 +187,7 @@ export const enum GameOptionInternal {
OST_PREFERENCE = "ostPreference",
FORCE_PLAY_SONG = "forcePlaySongID",
SPOTIFY_PLAYLIST_ID = "spotifyPlaylistID",
REMIX_PREFERENCE = "remixPreference",
}

export const GameOptionInternalToGameOption: { [option: string]: string } = {
Expand Down
Loading

0 comments on commit 981f84d

Please sign in to comment.