feat(bot): refresh groups list — manual button + auto event listener
Group sync previously only ran once at pairing time, so groups created in
WhatsApp afterwards never showed up.
Two complementary fixes:
- 🔄 Refresh button in the groups list view triggers
syncGroupsForAccount() on demand and re-renders the menu
- session.ts now subscribes to Baileys 'groups.upsert' and 'groups.update'
events and re-syncs (debounced 1.5s) so new groups appear without
manual action
This commit is contained in:
parent
5259f88776
commit
43882d5a1b
@ -19,6 +19,7 @@ import {
|
||||
showGroupDetail,
|
||||
showSendTestPrompt,
|
||||
executeSendTest,
|
||||
refreshGroupsList,
|
||||
} from "./callbacks.js";
|
||||
import {
|
||||
consumePendingPairLabel,
|
||||
@ -82,6 +83,9 @@ export function createTelegramBot(): Bot {
|
||||
bot.callbackQuery(/^st:(.+)$/, async (ctx) => {
|
||||
await showSendTestPrompt(ctx, ctx.match[1]!);
|
||||
});
|
||||
bot.callbackQuery(/^rs:(.+)$/, async (ctx) => {
|
||||
await refreshGroupsList(ctx, ctx.match[1]!);
|
||||
});
|
||||
|
||||
// Plain-text messages: if the operator is in the "pending pair label" state
|
||||
// (because they tapped 📡 Pair New), treat their next non-command message as
|
||||
|
||||
@ -10,6 +10,7 @@ import { sessionManager } from "../whatsapp/session-manager.js";
|
||||
import { writeAuditLog } from "../audit.js";
|
||||
import { setPendingPairLabel, setPendingSendToGroup } from "./state.js";
|
||||
import { sendTextToGroup } from "../whatsapp/sender.js";
|
||||
import { syncGroupsForAccount } from "../whatsapp/group-sync.js";
|
||||
import {
|
||||
mainMenu,
|
||||
helpMenu,
|
||||
@ -92,6 +93,38 @@ export async function showGroupsList(ctx: Context, accountId: string): Promise<v
|
||||
await showMenu(ctx, view);
|
||||
}
|
||||
|
||||
export async function refreshGroupsList(ctx: Context, accountId: string): Promise<void> {
|
||||
const op = await findOperator(ctx);
|
||||
if (!op) {
|
||||
await ctx.answerCallbackQuery();
|
||||
return;
|
||||
}
|
||||
const account = await db.query.whatsappAccounts.findFirst({
|
||||
where: (a, { eq, and }) => and(eq(a.id, accountId), eq(a.operatorId, op.id)),
|
||||
});
|
||||
if (!account) {
|
||||
await ctx.answerCallbackQuery({ text: "Account not found.", show_alert: true });
|
||||
return;
|
||||
}
|
||||
const session = sessionManager.getSession(accountId);
|
||||
if (!session) {
|
||||
await ctx.answerCallbackQuery({
|
||||
text: "Account not connected. Re-pair first.",
|
||||
show_alert: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
await ctx.answerCallbackQuery({ text: "Refreshing…" });
|
||||
try {
|
||||
const result = await syncGroupsForAccount(accountId, session.socket);
|
||||
logger.info({ accountId, count: result.synced }, "refreshGroupsList: ok");
|
||||
} catch (err) {
|
||||
logger.error({ err, accountId }, "refreshGroupsList: failed");
|
||||
}
|
||||
const view = await groupsListMenu(op.id, accountId);
|
||||
if (view) await showMenu(ctx, view);
|
||||
}
|
||||
|
||||
export async function showUnpairConfirm(ctx: Context, accountId: string): Promise<void> {
|
||||
await ctx.answerCallbackQuery();
|
||||
const op = await findOperator(ctx);
|
||||
|
||||
@ -144,18 +144,22 @@ export async function groupsListMenu(
|
||||
const name = g.name.length > 32 ? `${g.name.slice(0, 31)}…` : g.name;
|
||||
keyboard.text(`👥 ${name}`, `gr:${g.id}`).row();
|
||||
}
|
||||
keyboard.text("⬅ Account", `acc:${accountId}`).text("⬅ Main Menu", "m:main");
|
||||
keyboard
|
||||
.text("🔄 Refresh", `rs:${accountId}`)
|
||||
.row()
|
||||
.text("⬅ Account", `acc:${accountId}`)
|
||||
.text("⬅ Main Menu", "m:main");
|
||||
|
||||
if (groups.length === 0) {
|
||||
return {
|
||||
text: `👥 *Groups in ${account.label}*\n\nNo groups synced yet.`,
|
||||
text: `👥 *Groups in ${account.label}*\n\nNo groups synced yet. Tap *Refresh* to pull the latest list.`,
|
||||
keyboard,
|
||||
};
|
||||
}
|
||||
|
||||
const overflow = groups.length > 30 ? `\n\n_…${groups.length - 30} more not shown_` : "";
|
||||
return {
|
||||
text: `👥 *Groups in ${account.label}*\n\nTap a group to send a test message.${overflow}`,
|
||||
text: `👥 *Groups in ${account.label}*\n\nTap a group to send a test message, or *Refresh* to pick up new groups.${overflow}`,
|
||||
keyboard,
|
||||
};
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
} from "@whiskeysockets/baileys";
|
||||
import { logger } from "../logger.js";
|
||||
import { env } from "../env.js";
|
||||
import { syncGroupsForAccount } from "./group-sync.js";
|
||||
|
||||
export type SessionEvent =
|
||||
| { type: "qr"; payload: string }
|
||||
@ -50,6 +51,22 @@ export async function startSession(params: {
|
||||
|
||||
socket.ev.on("creds.update", () => void saveCreds());
|
||||
|
||||
// Keep `whatsapp_groups` in sync as Baileys discovers new groups or updates.
|
||||
// Debounced so a flurry of upsert events from the initial sync collapses
|
||||
// into a single DB write.
|
||||
let groupsSyncTimer: NodeJS.Timeout | null = null;
|
||||
const scheduleGroupsSync = (): void => {
|
||||
if (groupsSyncTimer) return;
|
||||
groupsSyncTimer = setTimeout(() => {
|
||||
groupsSyncTimer = null;
|
||||
void syncGroupsForAccount(accountId, socket).catch((err) =>
|
||||
logger.warn({ err, accountId }, "auto group sync failed"),
|
||||
);
|
||||
}, 1500);
|
||||
};
|
||||
socket.ev.on("groups.upsert", scheduleGroupsSync);
|
||||
socket.ev.on("groups.update", scheduleGroupsSync);
|
||||
|
||||
socket.ev.on("connection.update", (update: Partial<ConnectionState>) => {
|
||||
if (update.qr) {
|
||||
void onEvent({ type: "qr", payload: update.qr });
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user