Module: Brainiac::Plugins::Discord::Gateway

Defined in:
lib/brainiac/plugins/discord/gateway.rb

Overview

Discord WebSocket gateway connections.

Each agent with a DISCORD_BOT_TOKEN gets its own persistent WebSocket connection. The gateway dispatches MESSAGE_CREATE, MESSAGE_UPDATE, and MESSAGE_REACTION_ADD events to handler functions.

Constant Summary collapse

GATEWAY_URL =
"wss://gateway.discord.gg/?v=10&encoding=json"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.botsObject (readonly)

Returns the value of attribute bots.



22
23
24
# File 'lib/brainiac/plugins/discord/gateway.rb', line 22

def bots
  @bots
end

.bots_mutexObject (readonly)

Returns the value of attribute bots_mutex.



22
23
24
# File 'lib/brainiac/plugins/discord/gateway.rb', line 22

def bots_mutex
  @bots_mutex
end

Class Method Details

.bot_countObject



24
25
26
# File 'lib/brainiac/plugins/discord/gateway.rb', line 24

def bot_count
  @bots_mutex.synchronize { @bots.size }
end

.bot_token(agent_key) ⇒ Object

Get a bot's token.



36
37
38
# File 'lib/brainiac/plugins/discord/gateway.rb', line 36

def bot_token(agent_key)
  @bots_mutex.synchronize { @bots.dig(agent_key, :token) }
end

.bot_user_id(agent_key) ⇒ Object

Get a bot's user_id.



41
42
43
# File 'lib/brainiac/plugins/discord/gateway.rb', line 41

def bot_user_id(agent_key)
  @bots_mutex.synchronize { @bots.dig(agent_key, :user_id) }
end

.bots_statusObject

Summary of all bot statuses for the API endpoint.



83
84
85
86
87
88
89
# File 'lib/brainiac/plugins/discord/gateway.rb', line 83

def bots_status
  @bots_mutex.synchronize do
    @bots.transform_values do |info|
      { status: info[:status], user_id: info[:user_id] }
    end
  end
end

.detect_sender_agent(author, current_agent_key) ⇒ Object

Detect if a message author is a known bot (local or remote). Returns the agent_key of the sender, or nil if unknown.



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/brainiac/plugins/discord/gateway.rb', line 93

def detect_sender_agent(author, current_agent_key)
  sender_id = author["id"]
  sender_agent_key = nil

  @bots_mutex.synchronize do
    @bots.each do |key, info|
      if info[:user_id] == sender_id && key != current_agent_key
        sender_agent_key = key
        break
      end
    end
  end

  unless sender_agent_key
    Config.user_mappings.each do |name, discord_id|
      if discord_id == sender_id
        sender_agent_key = name.downcase
        break
      end
    end
  end

  if !sender_agent_key && defined?(LOG)
    LOG.info "[Discord:#{current_agent_key}] Ignoring unknown bot: id=#{sender_id}, username=#{author["username"]}"
  end

  sender_agent_key
end

.discord_bot_tokensObject

Collect all agent Discord bot tokens from the registry. Returns { "galen" => "token...", "glados" => "token..." }



47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/brainiac/plugins/discord/gateway.rb', line 47

def discord_bot_tokens
  tokens = {}
  AGENT_REGISTRY.each do |key, entry|
    next unless entry.is_a?(Hash)

    token = (entry["env"] || {})["DISCORD_BOT_TOKEN"]
    next unless token

    tokens[key] = token
  end
  tokens
end

.each_botObject

Iterate over bots under mutex.



29
30
31
32
33
# File 'lib/brainiac/plugins/discord/gateway.rb', line 29

def each_bot(&)
  @bots_mutex.synchronize do
    @bots.each(&)
  end
end

.start_all!Object

Start all per-agent Discord bots.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/brainiac/plugins/discord/gateway.rb', line 61

def start_all!
  tokens = discord_bot_tokens
  if tokens.empty?
    LOG.info "[Discord] No agents have DISCORD_BOT_TOKEN configured — Discord disabled" if defined?(LOG)
    return
  end

  LOG.info "[Discord] Starting #{tokens.size} bot(s): #{tokens.keys.join(", ")}" if defined?(LOG)

  @bots_mutex.synchronize do
    tokens.each do |agent_key, token|
      @bots[agent_key] = { token: token, status: "starting", user_id: nil }
    end
  end

  tokens.each do |agent_key, token|
    start_gateway_for(agent_key, token)
    sleep 1 # Stagger connections to avoid rate limits
  end
end