Signal fixes

This commit is contained in:
Darren Clarke 2025-11-13 11:18:08 +01:00
parent 0e8c9be247
commit 457a86ebcd
7 changed files with 91 additions and 70 deletions

View file

@ -1,2 +1,2 @@
*/1 * * * * signal:fetch-signal-messages ?max=1&id=fetchSignalMessagesCron {"scheduleTasks": "true"}
*/2 * * * * signal:check-group-membership ?max=1&id=checkGroupMembershipCron {}
*/1 * * * * fetch-signal-messages ?max=1&id=fetchSignalMessagesCron {"scheduleTasks": "true"}
*/2 * * * * check-group-membership ?max=1&id=checkGroupMembershipCron {}

View file

@ -5,6 +5,10 @@
* This task queries the Signal CLI API to check if users have joined
* their assigned groups. When a user joins (moves from pendingInvites to members),
* it updates the ticket's group_joined flag in Zammad.
*
* Note: This task sends webhooks for all group members every time it runs.
* The Zammad webhook handler is idempotent and will ignore duplicate notifications
* if group_joined is already true.
*/
import { db, getWorkerUtils } from "@link-stack/bridge-common";

View file

@ -1,4 +1,5 @@
import { createLogger } from "@link-stack/logger";
import { db } from "@link-stack/bridge-common";
import { Zammad, getUser } from "../../lib/zammad.js";
import {
loadFieldMapping,
@ -233,23 +234,47 @@ const createTicketFromFormTask = async (
// Check if this is a Signal ticket
let signalArticleType = null;
let signalChannel = null;
let signalChannelId = null;
let signalBotToken = null;
if (signalAccount) {
try {
logger.info({ signalAccount }, "Looking up Signal channel and article type");
// Look up Signal channels (admin-only endpoint)
// Look up Signal channels from Zammad (admin-only endpoint)
// Note: bot_token is NOT included in this response for security reasons
const channels = await zammad.get("cdr_signal_channels");
if (channels.length > 0) {
signalChannel = channels[0]; // Use first active Signal channel
const zammadChannel = channels[0]; // Use first active Signal channel
signalChannelId = zammadChannel.id;
logger.info(
{
channelId: signalChannel.id,
phoneNumber: signalChannel.phone_number,
channelId: zammadChannel.id,
phoneNumber: zammadChannel.phone_number,
},
"Found active Signal channel",
"Found active Signal channel from Zammad",
);
// Look up the bot_token from our own cdr database using the phone number
const signalBot = await db
.selectFrom("SignalBot")
.selectAll()
.where("phoneNumber", "=", zammadChannel.phone_number)
.executeTakeFirst();
if (signalBot) {
signalBotToken = signalBot.token;
logger.info(
{ botId: signalBot.id, phoneNumber: signalBot.phoneNumber },
"Found Signal bot token from cdr database",
);
} else {
logger.warn(
{ phoneNumber: zammadChannel.phone_number },
"Signal bot not found in cdr database",
);
}
} else {
logger.warn("No active Signal channels found");
}
@ -306,18 +331,18 @@ const createTicketFromFormTask = async (
// Add Signal preferences if we have Signal channel and article type
// Note: signalAccount from Formstack is the phone number the user typed in
// Groups are added later via update_group webhook from bridge-worker
if (signalChannel && signalArticleType && signalAccount) {
if (signalChannelId && signalBotToken && signalArticleType && signalAccount) {
ticketData.preferences = {
channel_id: signalChannel.id,
channel_id: signalChannelId,
cdr_signal: {
bot_token: signalChannel.bot_token,
bot_token: signalBotToken,
chat_id: signalAccount, // Use Signal phone number as chat_id
},
};
logger.info(
{
channelId: signalChannel.id,
channelId: signalChannelId,
chatId: signalAccount,
},
"Adding Signal preferences to ticket",
@ -339,7 +364,7 @@ const createTicketFromFormTask = async (
const ticket = await zammad.ticket.create(ticketData);
// Set create_article_type_id for Signal tickets to enable proper replies
if (signalArticleType && signalChannel) {
if (signalArticleType && signalChannelId) {
try {
await zammad.ticket.update(ticket.id, {
create_article_type_id: signalArticleType.id,
@ -367,7 +392,7 @@ const createTicketFromFormTask = async (
ticketId: ticket.id,
ticketNumber: ticket.id,
title,
isSignalTicket: !!signalChannel,
isSignalTicket: !!signalChannelId,
},
"Successfully created ticket from Formstack submission",
);