mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 14:27:27 +00:00
feat(irc): add ssh irc@ built-in client for the members-only network
Adds an in-process IRC client (internal/irc) and an `irc@` SSH route that drops a member straight into the BBS's own Ergo network with no client to install and no SASL to configure. - internal/irc/client.go: minimal IRC client (SASL PLAIN, IRCv3 CAP, PING, PRIVMSG/JOIN/PART/NICK, event stream). Dials Ergo on the loopback 127.0.0.1:6667; presents the member's account name (the SSH key already proved membership; Ergo's auth-script ignores the passphrase by design). - internal/irc/tui.go: Bubble Tea TUI over the SSH PTY (mirrors internal/chat) with /join /part /msg /me /names /nick /help and a current-channel input. - cmd/agentbbs: handleIRC resolves the member by key (members-only, free) and runs the client; routed via auth.IsIRCName. AGENTBBS_IRC_ADDR overrides the target on dev hosts. - auth: reserve `irc` as a route name. Unlike copying tor-irc@ (a third-party client in a pod), this runs our own Go code in-process, so there is no /exec shell-escape surface, and the host process can reach Ergo's loopback listener directly. Validated live against a members-only Ergo: non-members are rejected, a member authenticates via SASL, and channel messages are received. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
8adafaf515
commit
302259f65c
6 changed files with 631 additions and 11 deletions
|
|
@ -56,6 +56,11 @@ var TorIRCNames = map[string]bool{"tor-irc": true}
|
|||
// member's pod (premium). Checked after the more specific tor-* routes.
|
||||
var TorNames = map[string]bool{"tor": true}
|
||||
|
||||
// IRCNames route a member straight into the BBS's own (members-only) IRC
|
||||
// network via an in-process client. Distinct from tor-irc@, which is a client
|
||||
// for connecting OUT to remote IRC servers over Tor.
|
||||
var IRCNames = map[string]bool{"irc": true}
|
||||
|
||||
// GameNames are usernames that route to AgentGames: the line-delimited-JSON
|
||||
// agent-vs-agent match protocol (PRD §5.2). `play@` stays a guest hub alias.
|
||||
var GameNames = map[string]bool{"game": true, "games": true}
|
||||
|
|
@ -84,6 +89,9 @@ func IsTorIRCName(u string) bool { return TorIRCNames[strings.ToLower(u)] }
|
|||
// IsTorName reports whether the SSH username requests the generic tor passthrough.
|
||||
func IsTorName(u string) bool { return TorNames[strings.ToLower(u)] }
|
||||
|
||||
// IsIRCName reports whether the SSH username requests the in-BBS IRC client.
|
||||
func IsIRCName(u string) bool { return IRCNames[strings.ToLower(u)] }
|
||||
|
||||
// systemReserved are names that don't drive an SSH route but would still
|
||||
// collide with a per-user subdomain (<name>.<host>), the agent route, or common
|
||||
// infra hostnames — so members may not claim them as account names.
|
||||
|
|
@ -100,7 +108,7 @@ var systemReserved = map[string]bool{
|
|||
func IsReservedName(name string) bool {
|
||||
n := strings.ToLower(name)
|
||||
if GuestNames[n] || PodNames[n] || JoinNames[n] || DomainNames[n] || AdminNames[n] ||
|
||||
TorURLNames[n] || TorIRCNames[n] || TorNames[n] || systemReserved[n] {
|
||||
TorURLNames[n] || TorIRCNames[n] || TorNames[n] || IRCNames[n] || systemReserved[n] {
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(n, "video-") // video-<code> call routes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue