mirror of
https://github.com/domfelipe/mika-agent-assist.git
synced 2026-08-07 09:16:46 +00:00
Desativou fallback do webhook
X-Lovable-Edit-ID: edt-e1324392-3177-4d5d-8fca-a9af40465190 Co-authored-by: domfelipe <53182096+domfelipe@users.noreply.github.com>
This commit is contained in:
commit
435d68f4a0
2 changed files with 16 additions and 96 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
// configure-telegram-webhook
|
// configure-telegram-webhook
|
||||||
// Gera secret aleatório, configura webhook no Telegram e marca telegram_webhook_configured=true.
|
// Mantém compatibilidade com o wizard: garante que o webhook do Telegram fique desligado,
|
||||||
|
// pois o Hermes responde via polling/runtime.
|
||||||
|
|
||||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
||||||
import { corsHeaders } from "../_shared/cors.ts";
|
import { corsHeaders } from "../_shared/cors.ts";
|
||||||
|
|
@ -12,14 +13,6 @@ function jsonResponse(body: unknown, status = 200): Response {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomHex(bytes: number): string {
|
|
||||||
const buf = new Uint8Array(bytes);
|
|
||||||
crypto.getRandomValues(buf);
|
|
||||||
return Array.from(buf)
|
|
||||||
.map((b) => b.toString(16).padStart(2, "0"))
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
async function getDecryptedSecret(
|
async function getDecryptedSecret(
|
||||||
admin: any,
|
admin: any,
|
||||||
|
|
@ -81,21 +74,14 @@ Deno.serve(async (req) => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const webhookSecret = randomHex(32);
|
const deleteRes = await telegramApi(token, "deleteWebhook", {
|
||||||
const webhookUrl =
|
drop_pending_updates: false,
|
||||||
`${supabaseUrl}/functions/v1/telegram-webhook?token=${agent.uuid_tenant}`;
|
|
||||||
|
|
||||||
const setRes = await telegramApi(token, "setWebhook", {
|
|
||||||
url: webhookUrl,
|
|
||||||
allowed_updates: ["message"],
|
|
||||||
drop_pending_updates: true,
|
|
||||||
secret_token: webhookSecret,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!setRes.ok) {
|
if (!deleteRes.ok) {
|
||||||
console.error("setWebhook failed", setRes);
|
console.error("deleteWebhook failed", deleteRes);
|
||||||
return jsonResponse(
|
return jsonResponse(
|
||||||
{ error: "Falha ao configurar webhook no Telegram." },
|
{ error: "Falha ao liberar o Telegram para o runtime do agente." },
|
||||||
500,
|
500,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -103,8 +89,8 @@ Deno.serve(async (req) => {
|
||||||
const { error: updErr } = await admin
|
const { error: updErr } = await admin
|
||||||
.from("agent_instances")
|
.from("agent_instances")
|
||||||
.update({
|
.update({
|
||||||
telegram_webhook_secret: webhookSecret,
|
telegram_webhook_secret: null,
|
||||||
telegram_webhook_configured: true,
|
telegram_webhook_configured: false,
|
||||||
updated_at: new Date().toISOString(),
|
updated_at: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
.eq("id", agent.id);
|
.eq("id", agent.id);
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,14 @@
|
||||||
// telegram-webhook (PÚBLICA — verify_jwt = false)
|
// telegram-webhook (PÚBLICA — verify_jwt = false)
|
||||||
// Recebe updates do Telegram, valida 3 camadas (uuid_tenant, secret, rate limit),
|
// Recebe updates legados do Telegram, valida 3 camadas (uuid_tenant, secret, rate limit)
|
||||||
// registra mensagem em telegram_messages_log e responde com placeholder via sendMessage.
|
// e registra mensagem em telegram_messages_log. O Hermes responde via polling/runtime;
|
||||||
//
|
// esta função nunca deve enviar fallback para o usuário final.
|
||||||
// TODO Fase 5: substituir resposta placeholder por proxy para container Hermes via SSH/API.
|
|
||||||
|
|
||||||
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
|
||||||
import { telegramApi, telegramAck } from "../_shared/telegram.ts";
|
import { telegramAck } from "../_shared/telegram.ts";
|
||||||
|
|
||||||
const RATE_LIMIT_MAX = 30;
|
const RATE_LIMIT_MAX = 30;
|
||||||
const RATE_LIMIT_WINDOW_MS = 60_000;
|
const RATE_LIMIT_WINDOW_MS = 60_000;
|
||||||
|
|
||||||
function firstName(fullName: string | null | undefined): string {
|
|
||||||
if (!fullName) return "Mika";
|
|
||||||
const parts = fullName.trim().split(/\s+/);
|
|
||||||
return parts[0] || "Mika";
|
|
||||||
}
|
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
async function getDecryptedSecret(
|
|
||||||
admin: any,
|
|
||||||
secretId: string,
|
|
||||||
): Promise<string | null> {
|
|
||||||
const { data, error } = await admin
|
|
||||||
.rpc("vault_decrypt_secret", { secret_id: secretId })
|
|
||||||
.single();
|
|
||||||
if (!error && data) {
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
return (data as any).decrypted_secret ?? (data as unknown as string);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Deno.serve(async (req) => {
|
Deno.serve(async (req) => {
|
||||||
// Sempre responde 200 para o Telegram não retentar — ack cedo em qualquer falha.
|
// Sempre responde 200 para o Telegram não retentar — ack cedo em qualquer falha.
|
||||||
try {
|
try {
|
||||||
|
|
@ -48,7 +26,7 @@ Deno.serve(async (req) => {
|
||||||
const { data: agent, error: agentErr } = await admin
|
const { data: agent, error: agentErr } = await admin
|
||||||
.from("agent_instances")
|
.from("agent_instances")
|
||||||
.select(
|
.select(
|
||||||
"id, user_id, status, telegram_webhook_secret, telegram_bot_token_vault_id, telegram_connected_at, profiles:profiles!agent_instances_user_id_fkey(full_name)",
|
"id, user_id, status, telegram_webhook_secret, telegram_connected_at",
|
||||||
)
|
)
|
||||||
.eq("uuid_tenant", uuidTenant)
|
.eq("uuid_tenant", uuidTenant)
|
||||||
.maybeSingle();
|
.maybeSingle();
|
||||||
|
|
@ -157,54 +135,10 @@ Deno.serve(async (req) => {
|
||||||
raw_payload: payload,
|
raw_payload: payload,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 7) Resposta placeholder via sendMessage
|
console.log("telegram-webhook: update logged; runtime/polling owns the reply", {
|
||||||
// TODO Fase 5: substituir resposta placeholder por proxy para container Hermes via SSH/API.
|
agent_id: agent.id,
|
||||||
if (!agent.telegram_bot_token_vault_id) return telegramAck();
|
|
||||||
const token = await getDecryptedSecret(admin, agent.telegram_bot_token_vault_id as string);
|
|
||||||
if (!token) return telegramAck();
|
|
||||||
|
|
||||||
// deno-lint-ignore no-explicit-any
|
|
||||||
const fullName = (agent as any).profiles?.full_name as string | null | undefined;
|
|
||||||
const replyText =
|
|
||||||
`Olá! Sou o Mika de ${firstName(fullName)}. Estou quase pronto para conversar com você de verdade — meu cérebro está sendo configurado pela DOMCO. Em breve vou responder de forma inteligente! Por enquanto, este é apenas um teste de conexão. ✨`;
|
|
||||||
|
|
||||||
let send = await telegramApi(token, "sendMessage", {
|
|
||||||
chat_id: chatId,
|
chat_id: chatId,
|
||||||
text: replyText,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!send.ok && send.status === 401) {
|
|
||||||
await admin
|
|
||||||
.from("agent_instances")
|
|
||||||
.update({ telegram_token_invalid: true, updated_at: new Date().toISOString() })
|
|
||||||
.eq("id", agent.id);
|
|
||||||
return telegramAck();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!send.ok && send.status === 429) {
|
|
||||||
const retryAfter = send.parameters?.retry_after ?? 1;
|
|
||||||
await new Promise((r) => setTimeout(r, Math.min(retryAfter, 5) * 1000));
|
|
||||||
send = await telegramApi(token, "sendMessage", {
|
|
||||||
chat_id: chatId,
|
|
||||||
text: replyText,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (send.ok) {
|
|
||||||
await admin.from("telegram_messages_log").insert({
|
|
||||||
agent_instance_id: agent.id,
|
|
||||||
user_id: agent.user_id,
|
|
||||||
telegram_chat_id: chatId,
|
|
||||||
direction: "outgoing",
|
|
||||||
message_text: replyText,
|
|
||||||
message_type: "text",
|
|
||||||
is_first_message: false,
|
|
||||||
raw_payload: send.result ?? null,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error("sendMessage failed", send);
|
|
||||||
}
|
|
||||||
|
|
||||||
return telegramAck();
|
return telegramAck();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("telegram-webhook fatal", err);
|
console.error("telegram-webhook fatal", err);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue