feat: add beta googlechat channel

This commit is contained in:
iHildy
2026-01-23 16:45:37 -06:00
committed by Peter Steinberger
parent 60661441b1
commit b76cd6695d
58 changed files with 3216 additions and 51 deletions

View File

@@ -41,6 +41,11 @@ export type ChannelAccountSnapshot = {
tokenSource?: string | null;
botTokenSource?: string | null;
appTokenSource?: string | null;
credentialSource?: string | null;
audienceType?: string | null;
audience?: string | null;
webhookPath?: string | null;
webhookUrl?: string | null;
baseUrl?: string | null;
allowUnmentionedGroups?: boolean | null;
cliPath?: string | null;
@@ -133,6 +138,28 @@ export type DiscordStatus = {
lastProbeAt?: number | null;
};
export type GoogleChatProbe = {
ok: boolean;
status?: number | null;
error?: string | null;
elapsedMs?: number | null;
};
export type GoogleChatStatus = {
configured: boolean;
credentialSource?: string | null;
audienceType?: string | null;
audience?: string | null;
webhookPath?: string | null;
webhookUrl?: string | null;
running: boolean;
lastStartAt?: number | null;
lastStopAt?: number | null;
lastError?: string | null;
probe?: GoogleChatProbe | null;
lastProbeAt?: number | null;
};
export type SlackBot = {
id?: string | null;
name?: string | null;

View File

@@ -0,0 +1,74 @@
import { html, nothing } from "lit";
import { formatAgo } from "../format";
import type { GoogleChatStatus } from "../types";
import { renderChannelConfigSection } from "./channels.config";
import type { ChannelsProps } from "./channels.types";
export function renderGoogleChatCard(params: {
props: ChannelsProps;
googleChat?: GoogleChatStatus | null;
accountCountLabel: unknown;
}) {
const { props, googleChat, accountCountLabel } = params;
return html`
<div class="card">
<div class="card-title">Google Chat</div>
<div class="card-sub">Chat API webhook status and channel configuration.</div>
${accountCountLabel}
<div class="status-list" style="margin-top: 16px;">
<div>
<span class="label">Configured</span>
<span>${googleChat ? (googleChat.configured ? "Yes" : "No") : "n/a"}</span>
</div>
<div>
<span class="label">Running</span>
<span>${googleChat ? (googleChat.running ? "Yes" : "No") : "n/a"}</span>
</div>
<div>
<span class="label">Credential</span>
<span>${googleChat?.credentialSource ?? "n/a"}</span>
</div>
<div>
<span class="label">Audience</span>
<span>
${googleChat?.audienceType
? `${googleChat.audienceType}${googleChat.audience ? ` · ${googleChat.audience}` : ""}`
: "n/a"}
</span>
</div>
<div>
<span class="label">Last start</span>
<span>${googleChat?.lastStartAt ? formatAgo(googleChat.lastStartAt) : "n/a"}</span>
</div>
<div>
<span class="label">Last probe</span>
<span>${googleChat?.lastProbeAt ? formatAgo(googleChat.lastProbeAt) : "n/a"}</span>
</div>
</div>
${googleChat?.lastError
? html`<div class="callout danger" style="margin-top: 12px;">
${googleChat.lastError}
</div>`
: nothing}
${googleChat?.probe
? html`<div class="callout" style="margin-top: 12px;">
Probe ${googleChat.probe.ok ? "ok" : "failed"} ·
${googleChat.probe.status ?? ""} ${googleChat.probe.error ?? ""}
</div>`
: nothing}
${renderChannelConfigSection({ channelId: "googlechat", props })}
<div class="row" style="margin-top: 12px;">
<button class="btn" @click=${() => props.onRefresh(true)}>
Probe
</button>
</div>
</div>
`;
}

View File

@@ -6,6 +6,7 @@ import type {
ChannelUiMetaEntry,
ChannelsStatusSnapshot,
DiscordStatus,
GoogleChatStatus,
IMessageStatus,
NostrProfile,
NostrStatus,
@@ -22,6 +23,7 @@ import type {
import { channelEnabled, renderChannelAccountCount } from "./channels.shared";
import { renderChannelConfigSection } from "./channels.config";
import { renderDiscordCard } from "./channels.discord";
import { renderGoogleChatCard } from "./channels.googlechat";
import { renderIMessageCard } from "./channels.imessage";
import { renderNostrCard } from "./channels.nostr";
import { renderSignalCard } from "./channels.signal";
@@ -38,6 +40,7 @@ export function renderChannels(props: ChannelsProps) {
| TelegramStatus
| undefined;
const discord = (channels?.discord ?? null) as DiscordStatus | null;
const googlechat = (channels?.googlechat ?? null) as GoogleChatStatus | null;
const slack = (channels?.slack ?? null) as SlackStatus | null;
const signal = (channels?.signal ?? null) as SignalStatus | null;
const imessage = (channels?.imessage ?? null) as IMessageStatus | null;
@@ -61,6 +64,7 @@ export function renderChannels(props: ChannelsProps) {
whatsapp,
telegram,
discord,
googlechat,
slack,
signal,
imessage,
@@ -97,7 +101,16 @@ function resolveChannelOrder(snapshot: ChannelsStatusSnapshot | null): ChannelKe
if (snapshot?.channelOrder?.length) {
return snapshot.channelOrder;
}
return ["whatsapp", "telegram", "discord", "slack", "signal", "imessage", "nostr"];
return [
"whatsapp",
"telegram",
"discord",
"googlechat",
"slack",
"signal",
"imessage",
"nostr",
];
}
function renderChannel(
@@ -129,6 +142,12 @@ function renderChannel(
discord: data.discord,
accountCountLabel,
});
case "googlechat":
return renderGoogleChatCard({
props,
googlechat: data.googlechat,
accountCountLabel,
});
case "slack":
return renderSlackCard({
props,

View File

@@ -1,15 +1,16 @@
import type {
ChannelAccountSnapshot,
ChannelsStatusSnapshot,
ConfigUiHints,
DiscordStatus,
IMessageStatus,
NostrProfile,
NostrStatus,
SignalStatus,
SlackStatus,
TelegramStatus,
WhatsAppStatus,
ChannelAccountSnapshot,
ChannelsStatusSnapshot,
ConfigUiHints,
DiscordStatus,
GoogleChatStatus,
IMessageStatus,
NostrProfile,
NostrStatus,
SignalStatus,
SlackStatus,
TelegramStatus,
WhatsAppStatus,
} from "../types";
import type { NostrProfileFormState } from "./channels.nostr-profile-form";
@@ -52,6 +53,7 @@ export type ChannelsChannelData = {
whatsapp?: WhatsAppStatus;
telegram?: TelegramStatus;
discord?: DiscordStatus | null;
googlechat?: GoogleChatStatus | null;
slack?: SlackStatus | null;
signal?: SignalStatus | null;
imessage?: IMessageStatus | null;