IRC: join after NickServ login, keyed auto-join, SASL fallback

- With NickServ, auto-join waits for the logged-in reply (900) or 2 s
  at most, so registered-only IRC channels let us in
- A failed SASL login falls back to NickServ (its own password, or the
  SASL account and password)
- IDENTIFY names the account explicitly, and once logged in on a
  fallback nick, REGAIN takes ours back from a stale session
- Auto-join entries take keys ("#private key, #public"); keys from
  /join are reused when rejoining; keyed channels go first in JOIN
- Serial irc dump: whole Buffers, and which login is configured
  (never the secrets)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-03 19:48:16 +02:00
co-authored by Claude Opus 5.5
parent 83eb791924
commit 1f0c1b2e14
9 changed files with 263 additions and 41 deletions
+10 -3
View File
@@ -7,6 +7,11 @@
namespace roro {
struct IrcChannel {
std::string channel; // "#roro"
std::string key; // empty when the IRC channel has none
};
// The one IRC server the IRC Service connects to, persisted in internal flash.
class IrcConfig {
public:
@@ -20,7 +25,7 @@ class IrcConfig {
std::string nick;
std::string saslUser, saslPassword; // SASL PLAIN when both are set
std::string nickservPassword; // otherwise IDENTIFY with NickServ, if set
std::vector<std::string> autojoin;
std::vector<IrcChannel> autojoin;
// A copy is a draft the UI can edit freely; copySettingsFrom() applies one.
IrcConfig(const IrcConfig&) = default;
@@ -41,8 +46,10 @@ class IrcConfig {
std::string save(); // empty on success, otherwise why it was refused
std::string validate() const;
static std::vector<std::string> parseChannels(const std::string& text);
static std::string formatChannels(const std::vector<std::string>& channels);
// "#private key, #public": a word starting with # or & is an IRC channel, the word after it
// (if it doesn't) its key. Spaces or commas separate entries, so "#a #b" also reads.
static std::vector<IrcChannel> parseChannels(const std::string& text);
static std::string formatChannels(const std::vector<IrcChannel>& channels);
private:
KeyValueStore& store_;