Skip to content

Commit

Permalink
Introduce passive mode (#107)
Browse files Browse the repository at this point in the history
In passive mode, Wheatley will not advertise or react to commands, and
only load components that are marked as passive. This is to allow
additional secondary instances of the bot to coexist with a running
primary instance on the same server without interference, e.g., for
testing new features.
  • Loading branch information
michael-kenzel authored Jul 15, 2024
1 parent ee562cb commit 6c10710
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,15 @@ Secrets and other bot info must be configured in the `auth.json` file. An exampl
"host": "127.0.0.1", // optional
"port": 27017 // optional
},
"freestanding": false
"freestanding": false, // optional
"passive": false // optional
}
```

Mongo credentials can be omitted locally if you don't need to work on components that use mongo. `freestanding: true`
can be specified to turn on only components which don't rely on channels etc. specific to Together C & C++ to exist.
Freestanding mode also disables connecting to MongoDB.
`passive: true` can be specified to run the bot in passive mode, where it will not advertise or react to commands, and only load components that are marked as passive (useful for testing new features in a second instance without interfering with a running primary instance).

## Bot Component Abstraction

Expand All @@ -71,6 +73,9 @@ export class BotComponent {
static get is_freestanding() {
return false;
}
static get is_passive() {
return false;
}
// Add a command
add_command<T extends unknown[]>(
command:
Expand Down
4 changes: 4 additions & 0 deletions src/bot-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class BotComponent {
return false;
}

static get is_passive() {
return false;
}

constructor(protected readonly wheatley: Wheatley) {
wheatley.event_hub.on("wheatley_ready", this.wrap(this.on_wheatley_ready.bind(this)));
}
Expand Down
18 changes: 16 additions & 2 deletions src/wheatley.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export type wheatley_auth = {
guild?: string;
token: string;
freestanding?: boolean;
passive?: boolean;
mongo?: wheatley_database_credentials;
sentry?: string;
virustotal?: string;
Expand Down Expand Up @@ -316,6 +317,8 @@ export class Wheatley {
readonly guildId: string;
// True if freestanding mode is enabled. Defaults to false.
readonly freestanding: boolean;
// True if passive mode is enabled. Defaults to false.
readonly passive: boolean;

// Some emojis
readonly pepereally = "<:pepereally:643881257624666112>";
Expand Down Expand Up @@ -426,6 +429,7 @@ export class Wheatley {
) {
this.id = auth.id;
this.freestanding = auth.freestanding ?? false;
this.passive = auth.passive ?? false;
this.guildId = auth.guild ?? TCCPP_ID;

this.parameters = drop_token(auth);
Expand Down Expand Up @@ -602,8 +606,12 @@ export class Wheatley {
await wrap(() => this.fetch_root_mod_list(this.client));
}

async add_component<T extends BotComponent>(component: { new (w: Wheatley): T; get is_freestanding(): boolean }) {
if (!this.freestanding || component.is_freestanding) {
async add_component<T extends BotComponent>(component: {
new (w: Wheatley): T;
get is_freestanding(): boolean;
get is_passive(): boolean;
}) {
if ((!this.passive || component.is_passive) && (!this.freestanding || component.is_freestanding)) {
M.log(`Initializing ${component.name}`);
assert(!this.components.has(component.name), "Duplicate component name");
const instance = new component(this);
Expand Down Expand Up @@ -964,6 +972,9 @@ export class Wheatley {
| MessageContextMenuInteractionBuilder<true>
| ModalInteractionBuilder<true>,
) {
if (this.passive) {
return;
}
if (command instanceof TextBasedCommandBuilder) {
for (const descriptor of command.to_command_descriptors(this)) {
assert(!(descriptor.name in this.text_commands));
Expand All @@ -986,6 +997,9 @@ export class Wheatley {

// returns false if the message was not a wheatley command
async handle_text_command(message: Discord.Message, prev_command_obj?: TextBasedCommand) {
if (this.passive) {
return false;
}
const match = message.content.match(Wheatley.command_regex);
if (match) {
const command_name = match[1];
Expand Down

0 comments on commit 6c10710

Please sign in to comment.