mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-02 05:31:02 +00:00
- Add GroupGate class for group access control with three policies: disabled (default), allowlist, and open - Implement mention gating: bot only responds when @mentioned or replied to in groups (configurable per-group) - Extend Envelope type with isGroup, isMentioned, isReplyToBot fields - Update TelegramAdapter to detect group context and mentions - Add comprehensive documentation for group chat setup and troubleshooting This enables using Qwen Code bots in Telegram groups with fine-grained access control and mention-based activation to prevent noise. Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import type { GroupPolicy, GroupConfig, Envelope } from './types.js';
|
|
|
|
export interface GroupCheckResult {
|
|
allowed: boolean;
|
|
reason?: 'disabled' | 'not_allowlisted' | 'mention_required';
|
|
}
|
|
|
|
export class GroupGate {
|
|
private policy: GroupPolicy;
|
|
private groups: Record<string, GroupConfig>;
|
|
|
|
constructor(
|
|
policy: GroupPolicy = 'disabled',
|
|
groups: Record<string, GroupConfig> = {},
|
|
) {
|
|
this.policy = policy;
|
|
this.groups = groups;
|
|
}
|
|
|
|
/**
|
|
* Full group check: policy + allowlist + mention gating.
|
|
* Evaluation order:
|
|
* 1. groupPolicy (disabled → drop)
|
|
* 2. group allowlist (allowlist mode, no match → drop)
|
|
* 3. mention gating (requireMention + not mentioned → drop silently)
|
|
*
|
|
* Mention gating runs before sender gate so that unmentioned messages
|
|
* in groups don't trigger pairing flows.
|
|
*/
|
|
check(envelope: Envelope): GroupCheckResult {
|
|
if (!envelope.isGroup) {
|
|
return { allowed: true };
|
|
}
|
|
|
|
if (this.policy === 'disabled') {
|
|
return { allowed: false, reason: 'disabled' };
|
|
}
|
|
|
|
if (this.policy === 'allowlist') {
|
|
// In allowlist mode, "*" is only a default config — not a wildcard allow.
|
|
// The group must be explicitly listed by ID.
|
|
if (!this.groups[envelope.chatId]) {
|
|
return { allowed: false, reason: 'not_allowlisted' };
|
|
}
|
|
}
|
|
|
|
// Per-group config, falling back to "*" defaults, then built-in defaults
|
|
const groupConfig = this.groups[envelope.chatId] || this.groups['*'] || {};
|
|
const requireMention = groupConfig.requireMention ?? true;
|
|
|
|
if (requireMention && !envelope.isMentioned && !envelope.isReplyToBot) {
|
|
return { allowed: false, reason: 'mention_required' };
|
|
}
|
|
|
|
return { allowed: true };
|
|
}
|
|
}
|