Compare commits
No commits in common. "62247b81bc775ea915eb6d713729529c1de0f190" and "18d9bf7b9e15588486e91a9fb5dfaa18ec71c445" have entirely different histories.
62247b81bc
...
18d9bf7b9e
@ -136,7 +136,7 @@ async function processGenerationJob(
|
|||||||
await bot.api.editMessageText(
|
await bot.api.editMessageText(
|
||||||
state.replyMessage.chat.id,
|
state.replyMessage.chat.id,
|
||||||
state.replyMessage.message_id,
|
state.replyMessage.message_id,
|
||||||
`Generating your prompt now... 0% using ${sdInstance.name || sdInstance.id}`,
|
`Generating your prompt now... 0% using ${sdInstance.name}`,
|
||||||
{ maxAttempts: 1 },
|
{ maxAttempts: 1 },
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -221,9 +221,9 @@ async function processGenerationJob(
|
|||||||
await bot.api.editMessageText(
|
await bot.api.editMessageText(
|
||||||
state.replyMessage.chat.id,
|
state.replyMessage.chat.id,
|
||||||
state.replyMessage.message_id,
|
state.replyMessage.message_id,
|
||||||
`Generating your prompt now... ${(progressResponse.data.progress * 100).toFixed(0)}% using ${
|
`Generating your prompt now... ${
|
||||||
sdInstance.name || sdInstance.id
|
(progressResponse.data.progress * 100).toFixed(0)
|
||||||
}`,
|
}% using ${sdInstance.name}`,
|
||||||
{ maxAttempts: 1 },
|
{ maxAttempts: 1 },
|
||||||
).catch(() => undefined);
|
).catch(() => undefined);
|
||||||
|
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
import { CommandContext } from "grammy";
|
|
||||||
import { bold, fmt, FormattedString } from "grammy_parse_mode";
|
|
||||||
import { distinctBy } from "std/collections";
|
|
||||||
import { getConfig } from "../app/config.ts";
|
|
||||||
import { generationStore } from "../app/generationStore.ts";
|
|
||||||
import { ErisContext, logger } from "./mod.ts";
|
|
||||||
import { formatUserChat } from "../utils/formatUserChat.ts";
|
|
||||||
|
|
||||||
export async function broadcastCommand(ctx: CommandContext<ErisContext>) {
|
|
||||||
if (!ctx.from?.username) {
|
|
||||||
return ctx.reply("I don't know who you are.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const config = await getConfig();
|
|
||||||
|
|
||||||
if (!config.adminUsernames.includes(ctx.from.username)) {
|
|
||||||
return ctx.reply("Only a bot admin can use this command.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const text = ctx.match.trim();
|
|
||||||
|
|
||||||
if (!text) {
|
|
||||||
return ctx.reply("Please specify a message to broadcast.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// find users who interacted with bot in the last 24 hours
|
|
||||||
const gens = await generationStore.getAll(
|
|
||||||
{ after: new Date(Date.now() - 24 * 60 * 60 * 1000) },
|
|
||||||
{ reverse: true },
|
|
||||||
).then((gens) => distinctBy(gens, (gen) => gen.value.from.id));
|
|
||||||
|
|
||||||
let sentCount = 0;
|
|
||||||
const errors: FormattedString[] = [];
|
|
||||||
const getMessage = () =>
|
|
||||||
fmt([
|
|
||||||
fmt`Broadcasted to ${sentCount}/${gens.length} users.\n\n`,
|
|
||||||
errors.length > 0 ? fmt([bold("Errors:"), "\n", ...errors]) : "",
|
|
||||||
]);
|
|
||||||
|
|
||||||
const replyMessage = await ctx.replyFmt(getMessage(), {
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
// send message to each user
|
|
||||||
for (const gen of gens) {
|
|
||||||
try {
|
|
||||||
await ctx.api.sendMessage(gen.value.from.id, text);
|
|
||||||
logger().info(`Broadcasted to ${formatUserChat({ from: gen.value.from })}`);
|
|
||||||
sentCount++;
|
|
||||||
} catch (err) {
|
|
||||||
logger().error(`Broadcasting to ${formatUserChat({ from: gen.value.from })} failed: ${err}`);
|
|
||||||
errors.push(fmt`${bold(formatUserChat({ from: gen.value.from }))} - ${err.message}\n`);
|
|
||||||
}
|
|
||||||
const fmtMessage = getMessage();
|
|
||||||
if (sentCount % 20 === 0) {
|
|
||||||
await ctx.api.editMessageText(
|
|
||||||
replyMessage.chat.id,
|
|
||||||
replyMessage.message_id,
|
|
||||||
fmtMessage.text,
|
|
||||||
{ entities: fmtMessage.entities },
|
|
||||||
).catch(() => undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const fmtMessage = getMessage();
|
|
||||||
await ctx.api.editMessageText(
|
|
||||||
replyMessage.chat.id,
|
|
||||||
replyMessage.message_id,
|
|
||||||
fmtMessage.text,
|
|
||||||
{ entities: fmtMessage.entities },
|
|
||||||
).catch(() => undefined);
|
|
||||||
}
|
|
@ -7,7 +7,5 @@ export async function cancelCommand(ctx: ErisContext) {
|
|||||||
.filter((job) => job.lockUntil < new Date())
|
.filter((job) => job.lockUntil < new Date())
|
||||||
.filter((j) => j.state.from.id === ctx.from?.id);
|
.filter((j) => j.state.from.id === ctx.from?.id);
|
||||||
for (const job of userJobs) await generationQueue.deleteJob(job.id);
|
for (const job of userJobs) await generationQueue.deleteJob(job.id);
|
||||||
await ctx.reply(`Cancelled ${userJobs.length} jobs`, {
|
await ctx.reply(`Cancelled ${userJobs.length} jobs`);
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -28,34 +28,30 @@ async function img2img(
|
|||||||
state: QuestionState = {},
|
state: QuestionState = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!ctx.message?.from?.id) {
|
if (!ctx.message?.from?.id) {
|
||||||
await ctx.reply("I don't know who you are", {
|
await ctx.reply("I don't know who you are");
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
|
|
||||||
if (config.pausedReason != null) {
|
if (config.pausedReason != null) {
|
||||||
await ctx.reply(`I'm paused: ${config.pausedReason || "No reason given"}`, {
|
await ctx.reply(`I'm paused: ${config.pausedReason || "No reason given"}`);
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobs = await generationQueue.getAllJobs();
|
const jobs = await generationQueue.getAllJobs();
|
||||||
if (jobs.length >= config.maxJobs) {
|
if (jobs.length >= config.maxJobs) {
|
||||||
await ctx.reply(`The queue is full. Try again later. (Max queue size: ${config.maxJobs})`, {
|
await ctx.reply(
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
`The queue is full. Try again later. (Max queue size: ${config.maxJobs})`,
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userJobs = jobs.filter((job) => job.state.from.id === ctx.message?.from?.id);
|
const userJobs = jobs.filter((job) => job.state.from.id === ctx.message?.from?.id);
|
||||||
if (userJobs.length >= config.maxUserJobs) {
|
if (userJobs.length >= config.maxUserJobs) {
|
||||||
await ctx.reply(`You already have ${config.maxUserJobs} jobs in queue. Try again later.`, {
|
await ctx.reply(
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
`You already have ${config.maxUserJobs} jobs in queue. Try again later.`,
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,11 +91,7 @@ async function img2img(
|
|||||||
await ctx.reply(
|
await ctx.reply(
|
||||||
"Please show me a picture to repaint." +
|
"Please show me a picture to repaint." +
|
||||||
img2imgQuestion.messageSuffixMarkdown(JSON.stringify(state satisfies QuestionState)),
|
img2imgQuestion.messageSuffixMarkdown(JSON.stringify(state satisfies QuestionState)),
|
||||||
{
|
{ reply_markup: { force_reply: true, selective: true }, parse_mode: "Markdown" },
|
||||||
reply_markup: { force_reply: true, selective: true },
|
|
||||||
parse_mode: "Markdown",
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,18 +100,12 @@ async function img2img(
|
|||||||
await ctx.reply(
|
await ctx.reply(
|
||||||
"Please describe the picture you want to repaint." +
|
"Please describe the picture you want to repaint." +
|
||||||
img2imgQuestion.messageSuffixMarkdown(JSON.stringify(state satisfies QuestionState)),
|
img2imgQuestion.messageSuffixMarkdown(JSON.stringify(state satisfies QuestionState)),
|
||||||
{
|
{ reply_markup: { force_reply: true, selective: true }, parse_mode: "Markdown" },
|
||||||
reply_markup: { force_reply: true, selective: true },
|
|
||||||
parse_mode: "Markdown",
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const replyMessage = await ctx.reply("Accepted. You are now in queue.", {
|
const replyMessage = await ctx.reply("Accepted. You are now in queue.");
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
await generationQueue.pushJob({
|
await generationQueue.pushJob({
|
||||||
task: { type: "img2img", fileId: state.fileId, params: state.params },
|
task: { type: "img2img", fileId: state.fileId, params: state.params },
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Api, Bot, Context, RawApi, session, SessionFlavor } from "grammy";
|
import { Api, Bot, Context, RawApi, session, SessionFlavor } from "grammy";
|
||||||
|
import { autoQuote } from "grammy_autoquote";
|
||||||
import { FileFlavor, hydrateFiles } from "grammy_files";
|
import { FileFlavor, hydrateFiles } from "grammy_files";
|
||||||
import { hydrateReply, ParseModeFlavor } from "grammy_parse_mode";
|
import { hydrateReply, ParseModeFlavor } from "grammy_parse_mode";
|
||||||
import { getLogger } from "std/log";
|
import { getLogger } from "std/log";
|
||||||
import { getConfig, setConfig } from "../app/config.ts";
|
import { getConfig, setConfig } from "../app/config.ts";
|
||||||
import { formatUserChat } from "../utils/formatUserChat.ts";
|
import { formatUserChat } from "../utils/formatUserChat.ts";
|
||||||
import { broadcastCommand } from "./broadcastCommand.ts";
|
|
||||||
import { cancelCommand } from "./cancelCommand.ts";
|
import { cancelCommand } from "./cancelCommand.ts";
|
||||||
import { img2imgCommand, img2imgQuestion } from "./img2imgCommand.ts";
|
import { img2imgCommand, img2imgQuestion } from "./img2imgCommand.ts";
|
||||||
import { pnginfoCommand, pnginfoQuestion } from "./pnginfoCommand.ts";
|
import { pnginfoCommand, pnginfoQuestion } from "./pnginfoCommand.ts";
|
||||||
@ -45,6 +45,7 @@ export const bot = new Bot<ErisContext, ErisApi>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
bot.use(autoQuote);
|
||||||
bot.use(hydrateReply);
|
bot.use(hydrateReply);
|
||||||
bot.use(session<SessionData, ErisContext>({
|
bot.use(session<SessionData, ErisContext>({
|
||||||
type: "multi",
|
type: "multi",
|
||||||
@ -128,8 +129,6 @@ bot.command("queue", queueCommand);
|
|||||||
|
|
||||||
bot.command("cancel", cancelCommand);
|
bot.command("cancel", cancelCommand);
|
||||||
|
|
||||||
bot.command("broadcast", broadcastCommand);
|
|
||||||
|
|
||||||
bot.command("pause", async (ctx) => {
|
bot.command("pause", async (ctx) => {
|
||||||
if (!ctx.from?.username) return;
|
if (!ctx.from?.username) return;
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
|
@ -23,11 +23,7 @@ async function pnginfo(ctx: ErisContext, includeRepliedTo: boolean): Promise<voi
|
|||||||
await ctx.reply(
|
await ctx.reply(
|
||||||
"Please send me a PNG file." +
|
"Please send me a PNG file." +
|
||||||
pnginfoQuestion.messageSuffixMarkdown(),
|
pnginfoQuestion.messageSuffixMarkdown(),
|
||||||
{
|
{ reply_markup: { force_reply: true, selective: true }, parse_mode: "Markdown" },
|
||||||
reply_markup: { force_reply: true, selective: true },
|
|
||||||
parse_mode: "Markdown",
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -47,7 +43,7 @@ async function pnginfo(ctx: ErisContext, includeRepliedTo: boolean): Promise<voi
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
await ctx.reply(paramsText.text, {
|
await ctx.reply(paramsText.text, {
|
||||||
entities: paramsText.entities,
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
reply_to_message_id: ctx.message?.message_id,
|
||||||
|
entities: paramsText.entities,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,7 @@ import { ErisContext } from "./mod.ts";
|
|||||||
|
|
||||||
export async function queueCommand(ctx: CommandContext<ErisContext>) {
|
export async function queueCommand(ctx: CommandContext<ErisContext>) {
|
||||||
let formattedMessage = await getMessageText();
|
let formattedMessage = await getMessageText();
|
||||||
const queueMessage = await ctx.replyFmt(formattedMessage, {
|
const queueMessage = await ctx.replyFmt(formattedMessage, { disable_notification: true });
|
||||||
disable_notification: true,
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
handleFutureUpdates().catch(() => undefined);
|
handleFutureUpdates().catch(() => undefined);
|
||||||
|
|
||||||
async function getMessageText() {
|
async function getMessageText() {
|
||||||
|
@ -20,32 +20,30 @@ export async function txt2imgCommand(ctx: CommandContext<ErisContext>) {
|
|||||||
|
|
||||||
async function txt2img(ctx: ErisContext, match: string, includeRepliedTo: boolean): Promise<void> {
|
async function txt2img(ctx: ErisContext, match: string, includeRepliedTo: boolean): Promise<void> {
|
||||||
if (!ctx.message?.from?.id) {
|
if (!ctx.message?.from?.id) {
|
||||||
await ctx.reply("I don't know who you are", { reply_to_message_id: ctx.message?.message_id });
|
await ctx.reply("I don't know who you are");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = await getConfig();
|
const config = await getConfig();
|
||||||
|
|
||||||
if (config.pausedReason != null) {
|
if (config.pausedReason != null) {
|
||||||
await ctx.reply(`I'm paused: ${config.pausedReason || "No reason given"}`, {
|
await ctx.reply(`I'm paused: ${config.pausedReason || "No reason given"}`);
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const jobs = await generationQueue.getAllJobs();
|
const jobs = await generationQueue.getAllJobs();
|
||||||
if (jobs.length >= config.maxJobs) {
|
if (jobs.length >= config.maxJobs) {
|
||||||
await ctx.reply(`The queue is full. Try again later. (Max queue size: ${config.maxJobs})`, {
|
await ctx.reply(
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
`The queue is full. Try again later. (Max queue size: ${config.maxJobs})`,
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const userJobs = jobs.filter((job) => job.state.from.id === ctx.message?.from?.id);
|
const userJobs = jobs.filter((job) => job.state.from.id === ctx.message?.from?.id);
|
||||||
if (userJobs.length >= config.maxUserJobs) {
|
if (userJobs.length >= config.maxUserJobs) {
|
||||||
await ctx.reply(`You already have ${config.maxUserJobs} jobs in queue. Try again later.`, {
|
await ctx.reply(
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
`You already have ${config.maxUserJobs} jobs in queue. Try again later.`,
|
||||||
});
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,18 +69,12 @@ async function txt2img(ctx: ErisContext, match: string, includeRepliedTo: boolea
|
|||||||
await ctx.reply(
|
await ctx.reply(
|
||||||
"Please tell me what you want to see." +
|
"Please tell me what you want to see." +
|
||||||
txt2imgQuestion.messageSuffixMarkdown(),
|
txt2imgQuestion.messageSuffixMarkdown(),
|
||||||
{
|
{ reply_markup: { force_reply: true, selective: true }, parse_mode: "Markdown" },
|
||||||
reply_markup: { force_reply: true, selective: true },
|
|
||||||
parse_mode: "Markdown",
|
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const replyMessage = await ctx.reply("Accepted. You are now in queue.", {
|
const replyMessage = await ctx.reply("Accepted. You are now in queue.");
|
||||||
reply_to_message_id: ctx.message?.message_id,
|
|
||||||
});
|
|
||||||
|
|
||||||
await generationQueue.pushJob({
|
await generationQueue.pushJob({
|
||||||
task: { type: "txt2img", params },
|
task: { type: "txt2img", params },
|
||||||
|
Loading…
Reference in New Issue
Block a user