2024-07-16 23:29:20 +02:00
|
|
|
import { parseUserAddress, userAddressValidator } from "@/api";
|
2024-05-08 02:10:14 +02:00
|
|
|
import { Args, type Command, Flags, type Interfaces } from "@oclif/core";
|
2025-01-28 17:43:43 +01:00
|
|
|
import { Emoji, Instance, User } from "@versia/kit/db";
|
2024-11-01 21:05:54 +01:00
|
|
|
import { Emojis, Instances, Users } from "@versia/kit/tables";
|
2024-05-08 02:10:14 +02:00
|
|
|
import chalk from "chalk";
|
2025-01-28 17:43:43 +01:00
|
|
|
import { and, eq, inArray, like } from "drizzle-orm";
|
2024-10-04 15:22:48 +02:00
|
|
|
import { BaseCommand } from "./base.ts";
|
2024-05-07 09:41:02 +02:00
|
|
|
|
|
|
|
|
export type FlagsType<T extends typeof Command> = Interfaces.InferredFlags<
|
|
|
|
|
(typeof BaseCommand)["baseFlags"] & T["flags"]
|
|
|
|
|
>;
|
|
|
|
|
export type ArgsType<T extends typeof Command> = Interfaces.InferredArgs<
|
|
|
|
|
T["args"]
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
export abstract class UserFinderCommand<
|
|
|
|
|
T extends typeof BaseCommand,
|
|
|
|
|
> extends BaseCommand<typeof UserFinderCommand> {
|
2024-11-01 21:20:12 +01:00
|
|
|
public static baseFlags = {
|
2024-05-07 09:41:02 +02:00
|
|
|
pattern: Flags.boolean({
|
|
|
|
|
char: "p",
|
|
|
|
|
description:
|
|
|
|
|
"Process as a wildcard pattern (don't forget to escape)",
|
|
|
|
|
}),
|
|
|
|
|
type: Flags.string({
|
|
|
|
|
char: "t",
|
|
|
|
|
description: "Type of identifier",
|
2024-07-16 23:29:20 +02:00
|
|
|
options: [
|
|
|
|
|
"id",
|
|
|
|
|
"username",
|
|
|
|
|
"note",
|
|
|
|
|
"display-name",
|
|
|
|
|
"email",
|
|
|
|
|
"address",
|
|
|
|
|
],
|
|
|
|
|
default: "address",
|
2024-05-07 09:41:02 +02:00
|
|
|
}),
|
|
|
|
|
limit: Flags.integer({
|
|
|
|
|
char: "n",
|
|
|
|
|
description: "Limit the number of users",
|
|
|
|
|
default: 100,
|
|
|
|
|
}),
|
|
|
|
|
print: Flags.boolean({
|
|
|
|
|
allowNo: true,
|
|
|
|
|
default: true,
|
|
|
|
|
char: "P",
|
|
|
|
|
description: "Print user(s) found before processing",
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public static baseArgs = {
|
2024-05-07 09:41:02 +02:00
|
|
|
identifier: Args.string({
|
|
|
|
|
description:
|
2024-07-16 23:29:20 +02:00
|
|
|
"Identifier of the user (by default this must be an address, i.e. name@host.com)",
|
2024-05-07 09:41:02 +02:00
|
|
|
required: true,
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
protected flags!: FlagsType<T>;
|
|
|
|
|
protected args!: ArgsType<T>;
|
|
|
|
|
|
|
|
|
|
public async init(): Promise<void> {
|
|
|
|
|
await super.init();
|
|
|
|
|
const { args, flags } = await this.parse({
|
|
|
|
|
flags: this.ctor.flags,
|
|
|
|
|
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
|
|
|
|
|
args: this.ctor.args,
|
|
|
|
|
strict: this.ctor.strict,
|
|
|
|
|
});
|
|
|
|
|
this.flags = flags as FlagsType<T>;
|
|
|
|
|
this.args = args as ArgsType<T>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async findUsers(): Promise<User[]> {
|
2024-05-08 02:10:14 +02:00
|
|
|
// Check if there are asterisks in the identifier but no pattern flag, warn the user if so
|
|
|
|
|
if (this.args.identifier.includes("*") && !this.flags.pattern) {
|
|
|
|
|
this.log(
|
|
|
|
|
chalk.bold(
|
|
|
|
|
`${chalk.yellow(
|
|
|
|
|
"⚠",
|
|
|
|
|
)} Your identifier has asterisks but the --pattern flag is not set. This will match a literal string. If you want to use wildcards, set the --pattern flag.`,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 09:41:02 +02:00
|
|
|
const operator = this.flags.pattern ? like : eq;
|
|
|
|
|
// Replace wildcards with an SQL LIKE pattern
|
2024-07-16 23:29:20 +02:00
|
|
|
const identifier: string = this.flags.pattern
|
2024-05-07 09:41:02 +02:00
|
|
|
? this.args.identifier.replace(/\*/g, "%")
|
|
|
|
|
: this.args.identifier;
|
|
|
|
|
|
2024-07-16 23:29:20 +02:00
|
|
|
if (this.flags.type === "address") {
|
|
|
|
|
// Check if the address is valid
|
|
|
|
|
if (!userAddressValidator.exec(identifier)) {
|
|
|
|
|
this.log(
|
|
|
|
|
"Invalid address. Please check the address format and try again. For example: name@host.com",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
this.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check instance exists, if not, create it
|
|
|
|
|
await Instance.resolve(
|
|
|
|
|
`https://${parseUserAddress(identifier).domain}`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-07 09:41:02 +02:00
|
|
|
return await User.manyFromSql(
|
|
|
|
|
and(
|
|
|
|
|
this.flags.type === "id"
|
|
|
|
|
? operator(Users.id, identifier)
|
|
|
|
|
: undefined,
|
|
|
|
|
this.flags.type === "username"
|
|
|
|
|
? operator(Users.username, identifier)
|
|
|
|
|
: undefined,
|
|
|
|
|
this.flags.type === "note"
|
|
|
|
|
? operator(Users.note, identifier)
|
|
|
|
|
: undefined,
|
|
|
|
|
this.flags.type === "display-name"
|
|
|
|
|
? operator(Users.displayName, identifier)
|
|
|
|
|
: undefined,
|
|
|
|
|
this.flags.type === "email"
|
|
|
|
|
? operator(Users.email, identifier)
|
|
|
|
|
: undefined,
|
2024-07-16 23:29:20 +02:00
|
|
|
this.flags.type === "address"
|
|
|
|
|
? and(
|
|
|
|
|
operator(
|
|
|
|
|
Users.username,
|
|
|
|
|
parseUserAddress(identifier).username,
|
|
|
|
|
),
|
|
|
|
|
operator(
|
|
|
|
|
Users.instanceId,
|
|
|
|
|
(
|
|
|
|
|
await Instance.fromSql(
|
|
|
|
|
eq(
|
|
|
|
|
Instances.baseUrl,
|
|
|
|
|
new URL(
|
|
|
|
|
`https://${
|
|
|
|
|
parseUserAddress(identifier)
|
|
|
|
|
.domain
|
|
|
|
|
}`,
|
|
|
|
|
).host,
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
)?.id ?? "",
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
: undefined,
|
2024-05-07 09:41:02 +02:00
|
|
|
),
|
|
|
|
|
undefined,
|
|
|
|
|
this.flags.limit,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-05-09 04:07:33 +02:00
|
|
|
|
|
|
|
|
export abstract class EmojiFinderCommand<
|
|
|
|
|
T extends typeof BaseCommand,
|
|
|
|
|
> extends BaseCommand<typeof EmojiFinderCommand> {
|
2024-11-01 21:20:12 +01:00
|
|
|
public static baseFlags = {
|
2024-05-09 04:07:33 +02:00
|
|
|
pattern: Flags.boolean({
|
|
|
|
|
char: "p",
|
|
|
|
|
description:
|
|
|
|
|
"Process as a wildcard pattern (don't forget to escape)",
|
|
|
|
|
}),
|
|
|
|
|
type: Flags.string({
|
|
|
|
|
char: "t",
|
|
|
|
|
description: "Type of identifier",
|
|
|
|
|
options: ["shortcode", "instance"],
|
|
|
|
|
default: "shortcode",
|
|
|
|
|
}),
|
|
|
|
|
limit: Flags.integer({
|
|
|
|
|
char: "n",
|
|
|
|
|
description: "Limit the number of emojis",
|
|
|
|
|
default: 100,
|
|
|
|
|
}),
|
|
|
|
|
print: Flags.boolean({
|
|
|
|
|
allowNo: true,
|
|
|
|
|
default: true,
|
|
|
|
|
char: "P",
|
|
|
|
|
description: "Print emoji(s) found before processing",
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
2024-11-01 21:20:12 +01:00
|
|
|
public static baseArgs = {
|
2024-05-09 04:07:33 +02:00
|
|
|
identifier: Args.string({
|
|
|
|
|
description: "Identifier of the emoji (defaults to shortcode)",
|
|
|
|
|
required: true,
|
|
|
|
|
}),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
protected flags!: FlagsType<T>;
|
|
|
|
|
protected args!: ArgsType<T>;
|
|
|
|
|
|
|
|
|
|
public async init(): Promise<void> {
|
|
|
|
|
await super.init();
|
|
|
|
|
const { args, flags } = await this.parse({
|
|
|
|
|
flags: this.ctor.flags,
|
|
|
|
|
baseFlags: (super.ctor as typeof BaseCommand).baseFlags,
|
|
|
|
|
args: this.ctor.args,
|
|
|
|
|
strict: this.ctor.strict,
|
|
|
|
|
});
|
|
|
|
|
this.flags = flags as FlagsType<T>;
|
|
|
|
|
this.args = args as ArgsType<T>;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-28 17:43:43 +01:00
|
|
|
public async findEmojis(): Promise<Emoji[]> {
|
2024-05-09 04:07:33 +02:00
|
|
|
// Check if there are asterisks in the identifier but no pattern flag, warn the user if so
|
|
|
|
|
if (this.args.identifier.includes("*") && !this.flags.pattern) {
|
|
|
|
|
this.log(
|
|
|
|
|
chalk.bold(
|
|
|
|
|
`${chalk.yellow(
|
|
|
|
|
"⚠",
|
|
|
|
|
)} Your identifier has asterisks but the --pattern flag is not set. This will match a literal string. If you want to use wildcards, set the --pattern flag.`,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const operator = this.flags.pattern ? like : eq;
|
|
|
|
|
// Replace wildcards with an SQL LIKE pattern
|
|
|
|
|
const identifier = this.flags.pattern
|
|
|
|
|
? this.args.identifier.replace(/\*/g, "%")
|
|
|
|
|
: this.args.identifier;
|
|
|
|
|
|
2025-01-28 17:43:43 +01:00
|
|
|
const instanceIds =
|
|
|
|
|
this.flags.type === "instance"
|
|
|
|
|
? (
|
|
|
|
|
await Instance.manyFromSql(
|
|
|
|
|
operator(Instances.baseUrl, identifier),
|
|
|
|
|
)
|
|
|
|
|
).map((instance) => instance.id)
|
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
|
|
return await Emoji.manyFromSql(
|
|
|
|
|
and(
|
|
|
|
|
this.flags.type === "shortcode"
|
|
|
|
|
? operator(Emojis.shortcode, identifier)
|
|
|
|
|
: undefined,
|
|
|
|
|
instanceIds && instanceIds.length > 0
|
|
|
|
|
? inArray(Emojis.instanceId, instanceIds)
|
|
|
|
|
: undefined,
|
|
|
|
|
),
|
|
|
|
|
undefined,
|
|
|
|
|
this.flags.limit,
|
|
|
|
|
);
|
2024-05-09 04:07:33 +02:00
|
|
|
}
|
|
|
|
|
}
|