|
|
|
@@ -131,7 +131,6 @@
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
body: JSON.stringify({ language_code: lang }),
|
|
|
|
|
});
|
|
|
|
|
// Update local state immutably
|
|
|
|
|
chats[botId] = (chats[botId] || []).map(c =>
|
|
|
|
|
c.id === chat.id ? { ...c, language_code: lang } : c
|
|
|
|
|
);
|
|
|
|
@@ -139,6 +138,19 @@
|
|
|
|
|
} catch (err: any) { snackError(err.message); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function toggleChatCommands(botId: number, chat: TelegramChat) {
|
|
|
|
|
const newVal = !chat.commands_enabled;
|
|
|
|
|
try {
|
|
|
|
|
await api(`/telegram-bots/${botId}/chats/${chat.id}`, {
|
|
|
|
|
method: 'PUT',
|
|
|
|
|
body: JSON.stringify({ commands_enabled: newVal }),
|
|
|
|
|
});
|
|
|
|
|
chats[botId] = (chats[botId] || []).map(c =>
|
|
|
|
|
c.id === chat.id ? { ...c, commands_enabled: newVal } : c
|
|
|
|
|
);
|
|
|
|
|
} catch (err: any) { snackError(err.message); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function loadListenerStatus(botId: number) {
|
|
|
|
|
botListenerLoading = { ...botListenerLoading, [botId]: true };
|
|
|
|
|
try {
|
|
|
|
@@ -156,6 +168,19 @@
|
|
|
|
|
botListenerLoading = { ...botListenerLoading, [botId]: false };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function toggleListenerEnabled(botId: number, trk: CommandTrackerSummary) {
|
|
|
|
|
const endpoint = trk.enabled ? 'disable' : 'enable';
|
|
|
|
|
try {
|
|
|
|
|
await api(`/command-trackers/${trk.id}/${endpoint}`, { method: 'POST' });
|
|
|
|
|
botListenerStatus = {
|
|
|
|
|
...botListenerStatus,
|
|
|
|
|
[botId]: (botListenerStatus[botId] || []).map(t =>
|
|
|
|
|
t.id === trk.id ? { ...t, enabled: !t.enabled } : t
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
} catch (err: any) { snackError(err.message); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function syncCommands(botId: number) {
|
|
|
|
|
modeChanging = { ...modeChanging, [botId]: true };
|
|
|
|
|
try {
|
|
|
|
@@ -337,13 +362,14 @@
|
|
|
|
|
{:else if (chats[bot.id] || []).length === 0}
|
|
|
|
|
<p class="text-xs text-[var(--color-muted-foreground)]">{t('telegramBot.noChats')}</p>
|
|
|
|
|
{:else}
|
|
|
|
|
{@const gridStyle = "display:grid; grid-template-columns:1fr 80px 100px 130px 60px; align-items:center; gap:0.5rem;"}
|
|
|
|
|
{@const gridStyle = "display:grid; grid-template-columns:1fr 80px 100px 50px 130px 60px; align-items:center; gap:0.5rem;"}
|
|
|
|
|
<!-- Header -->
|
|
|
|
|
<div style="{gridStyle} padding:0.25rem 0.5rem; border-bottom:1px solid var(--color-border);"
|
|
|
|
|
class="text-[0.65rem] font-semibold uppercase tracking-wide text-[var(--color-muted-foreground)]">
|
|
|
|
|
<span>{t('telegramBot.chatName')}</span>
|
|
|
|
|
<span style="text-align:center">{t('telegramBot.chatType')}</span>
|
|
|
|
|
<span style="text-align:center">{t('telegramBot.chatLang')}</span>
|
|
|
|
|
<span style="text-align:center">{t('telegramBot.cmds')}</span>
|
|
|
|
|
<span style="text-align:center">{t('telegramBot.chatId')}</span>
|
|
|
|
|
<span></span>
|
|
|
|
|
</div>
|
|
|
|
@@ -364,6 +390,14 @@
|
|
|
|
|
onselect={(val) => updateChatLanguage(bot.id, chat, String(val ?? ''))}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div style="justify-self:center" onclick={(e: MouseEvent) => e.stopPropagation()}>
|
|
|
|
|
<button
|
|
|
|
|
style="width:28px; height:16px; border-radius:8px; position:relative; transition:background-color 0.2s; background-color:{chat.commands_enabled ? 'var(--color-primary)' : 'var(--color-border)'};"
|
|
|
|
|
title={t('telegramBot.commandsToggle')}
|
|
|
|
|
onclick={() => toggleChatCommands(bot.id, chat)}>
|
|
|
|
|
<span style="position:absolute; top:2px; width:12px; height:12px; border-radius:50%; transition:left 0.2s; left:{chat.commands_enabled ? '14px' : '2px'}; background:{chat.commands_enabled ? 'white' : 'var(--color-muted-foreground)'};" ></span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<span style="text-align:center" class="text-xs text-[var(--color-muted-foreground)] font-mono">{chat.chat_id}</span>
|
|
|
|
|
<div style="justify-self:end" class="flex items-center gap-1">
|
|
|
|
|
<IconButton icon="mdiSend" title="Test message" size={14}
|
|
|
|
@@ -395,16 +429,14 @@
|
|
|
|
|
<div class="flex items-center justify-between text-sm px-2 py-1 rounded hover:bg-[var(--color-muted)]">
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
<MdiIcon name={trk.icon || 'mdiConsoleLine'} size={14} />
|
|
|
|
|
<span class="font-medium">{trk.name}</span>
|
|
|
|
|
<span class="text-xs px-1.5 py-0.5 rounded font-mono {trk.enabled
|
|
|
|
|
? 'bg-emerald-500/10 text-emerald-500'
|
|
|
|
|
: 'bg-red-500/10 text-red-500'}">
|
|
|
|
|
{trk.enabled ? t('commandTracker.enabled') : t('commandTracker.disabled')}
|
|
|
|
|
</span>
|
|
|
|
|
<a href="/command-trackers" class="font-medium text-[var(--color-primary)] hover:underline">{trk.name}</a>
|
|
|
|
|
</div>
|
|
|
|
|
<a href="/command-trackers" class="text-xs text-[var(--color-primary)] hover:underline">
|
|
|
|
|
{t('common.edit')}
|
|
|
|
|
</a>
|
|
|
|
|
<button
|
|
|
|
|
style="width:28px; height:16px; border-radius:8px; position:relative; transition:background-color 0.2s; background-color:{trk.enabled ? 'var(--color-primary)' : 'var(--color-border)'};"
|
|
|
|
|
title={trk.enabled ? t('notificationTracker.pause') : t('notificationTracker.resume')}
|
|
|
|
|
onclick={() => toggleListenerEnabled(bot.id, trk)}>
|
|
|
|
|
<span style="position:absolute; top:2px; width:12px; height:12px; border-radius:50%; transition:left 0.2s; left:{trk.enabled ? '14px' : '2px'}; background:{trk.enabled ? 'white' : 'var(--color-muted-foreground)'};" ></span>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
{/each}
|
|
|
|
|
</div>
|
|
|
|
|