2026-03-14 02:50:17 -07:00
import {
appendMatchMetadata ,
asString ,
isRecord ,
resolveEnabledConfiguredAccountId ,
2026-03-16 21:13:56 -07:00
} from "openclaw/plugin-sdk/channel-runtime" ;
2026-03-14 02:50:17 -07:00
import type {
ChannelAccountSnapshot ,
ChannelStatusIssue ,
2026-03-16 21:13:56 -07:00
} from "openclaw/plugin-sdk/channel-runtime" ;
2026-03-14 02:50:17 -07:00
type TelegramAccountStatus = {
accountId? : unknown ;
enabled? : unknown ;
configured? : unknown ;
allowUnmentionedGroups? : unknown ;
audit? : unknown ;
} ;
type TelegramGroupMembershipAuditSummary = {
unresolvedGroups? : number ;
hasWildcardUnmentionedGroups? : boolean ;
groups? : Array < {
chatId : string ;
ok? : boolean ;
status? : string | null ;
error? : string | null ;
matchKey? : string ;
matchSource? : string ;
} > ;
} ;
function readTelegramAccountStatus ( value : ChannelAccountSnapshot ) : TelegramAccountStatus | null {
if ( ! isRecord ( value ) ) {
return null ;
}
return {
accountId : value.accountId ,
enabled : value.enabled ,
configured : value.configured ,
allowUnmentionedGroups : value.allowUnmentionedGroups ,
audit : value.audit ,
} ;
}
function readTelegramGroupMembershipAuditSummary (
value : unknown ,
) : TelegramGroupMembershipAuditSummary {
if ( ! isRecord ( value ) ) {
return { } ;
}
const unresolvedGroups =
typeof value . unresolvedGroups === "number" && Number . isFinite ( value . unresolvedGroups )
? value . unresolvedGroups
: undefined ;
const hasWildcardUnmentionedGroups =
typeof value . hasWildcardUnmentionedGroups === "boolean"
? value . hasWildcardUnmentionedGroups
: undefined ;
const groupsRaw = value . groups ;
const groups = Array . isArray ( groupsRaw )
? ( groupsRaw
. map ( ( entry ) = > {
if ( ! isRecord ( entry ) ) {
return null ;
}
const chatId = asString ( entry . chatId ) ;
if ( ! chatId ) {
return null ;
}
const ok = typeof entry . ok === "boolean" ? entry.ok : undefined ;
const status = asString ( entry . status ) ? ? null ;
const error = asString ( entry . error ) ? ? null ;
const matchKey = asString ( entry . matchKey ) ? ? undefined ;
const matchSource = asString ( entry . matchSource ) ? ? undefined ;
return { chatId , ok , status , error , matchKey , matchSource } ;
} )
. filter ( Boolean ) as TelegramGroupMembershipAuditSummary [ "groups" ] )
: undefined ;
return { unresolvedGroups , hasWildcardUnmentionedGroups , groups } ;
}
export function collectTelegramStatusIssues (
accounts : ChannelAccountSnapshot [ ] ,
) : ChannelStatusIssue [ ] {
const issues : ChannelStatusIssue [ ] = [ ] ;
for ( const entry of accounts ) {
const account = readTelegramAccountStatus ( entry ) ;
if ( ! account ) {
continue ;
}
const accountId = resolveEnabledConfiguredAccountId ( account ) ;
if ( ! accountId ) {
continue ;
}
if ( account . allowUnmentionedGroups === true ) {
issues . push ( {
channel : "telegram" ,
accountId ,
kind : "config" ,
message :
"Config allows unmentioned group messages (requireMention=false). Telegram Bot API privacy mode will block most group messages unless disabled." ,
fix : "In BotFather run /setprivacy → Disable for this bot (then restart the gateway)." ,
} ) ;
}
const audit = readTelegramGroupMembershipAuditSummary ( account . audit ) ;
if ( audit . hasWildcardUnmentionedGroups === true ) {
issues . push ( {
channel : "telegram" ,
accountId ,
kind : "config" ,
message :
'Telegram groups config uses "*" with requireMention=false; membership probing is not possible without explicit group IDs.' ,
fix : "Add explicit numeric group ids under channels.telegram.groups (or per-account groups) to enable probing." ,
} ) ;
}
if ( audit . unresolvedGroups && audit . unresolvedGroups > 0 ) {
issues . push ( {
channel : "telegram" ,
accountId ,
kind : "config" ,
message : ` Some configured Telegram groups are not numeric IDs (unresolvedGroups= ${ audit . unresolvedGroups } ). Membership probe can only check numeric group IDs. ` ,
fix : "Use numeric chat IDs (e.g. -100...) as keys in channels.telegram.groups for requireMention=false groups." ,
} ) ;
}
for ( const group of audit . groups ? ? [ ] ) {
if ( group . ok === true ) {
continue ;
}
const status = group . status ? ` status= ${ group . status } ` : "" ;
const err = group . error ? ` : ${ group . error } ` : "" ;
const baseMessage = ` Group ${ group . chatId } not reachable by bot. ${ status } ${ err } ` ;
issues . push ( {
channel : "telegram" ,
accountId ,
kind : "runtime" ,
message : appendMatchMetadata ( baseMessage , {
matchKey : group.matchKey ,
matchSource : group.matchSource ,
} ) ,
fix : "Invite the bot to the group, then DM the bot once (/start) and restart the gateway." ,
} ) ;
}
}
return issues ;
}