class Directchat
Public Class Methods
Source
# File plugins/directchat.rb, line 43 def self.channel_users_from(channel) return [] unless channel raw = if channel.respond_to?(:user_list) channel.user_list else channel.users end DirectchatPlan.normalize_channel_users(raw) end
Source
# File plugins/directchat.rb, line 26 def self.command_pattern /directchat(?:\s+(.+))?$/i end
Source
# File plugins/directchat.rb, line 58 def self.dispatch(args, requester:, user_channels:, bot_channels:, channel_users:, bot_nicks:, network:, bot_nick:, store: RabbotDb, project_root: nil) parsed = DirectchatPlan.parse_command(args, requester: requester) return { error: parsed[:error] } if parsed[:error] case parsed[:action] when :stop dispatch_stop( requester: requester, user_channels: user_channels, bot_channels: bot_channels, network: network, bot_nick: bot_nick, store: store ) when :status dispatch_status( requester: requester, user_channels: user_channels, bot_channels: bot_channels, network: network, store: store ) when :prd dispatch_prd(project_root: project_root || self.project_root) when :inventory dispatch_inventory(project_root: project_root || self.project_root) else dispatch_start( args: args, requester: requester, user_channels: user_channels, bot_channels: bot_channels, channel_users: channel_users, bot_nicks: bot_nicks, network: network, bot_nick: bot_nick, store: store ) end end
Source
# File plugins/directchat.rb, line 163 def self.dispatch_inventory(project_root:) written = DirectchatMircInventory.write(project_root: project_root) { reply: DirectchatMircInventory.format_reply( path: written[:path], file_count: written[:file_count], popup_count: written[:popup_count] ), inventory_path: written[:path] } end
Source
# File plugins/directchat.rb, line 155 def self.dispatch_prd(project_root:) written = DirectchatPrd.write(project_root: project_root) { reply: DirectchatPrd.format_reply(catalog: written[:catalog], path: written[:path]), prd_path: written[:path] } end
Source
# File plugins/directchat.rb, line 99 def self.dispatch_start(args:, requester:, user_channels:, bot_channels:, channel_users:, bot_nicks:, network:, bot_nick:, store: RabbotDb) result = DirectchatPlan.prepare_start( args: args, requester: requester, user_channels: user_channels, bot_channels: bot_channels, channel_users: channel_users, bot_nicks: bot_nicks, network: network, store: store ) return { error: result[:error] } if result[:error] session = result[:session] { reply: DirectchatSession.format_start_reply(session: session), session_id: session[:id], session: session, invites: invite_payloads(session: session), mesh_targets: DirectchatMesh.mesh_targets(session: session, exclude_bot: bot_nick), mesh_sync: mesh_sync_frame(session: session) } end
Source
# File plugins/directchat.rb, line 142 def self.dispatch_status(requester:, user_channels:, bot_channels:, network:, store: RabbotDb) session = find_session_for_requester( requester: requester, user_channels: user_channels, bot_channels: bot_channels, network: network, store: store ) return { reply: DirectchatSession.format_no_session_reply } unless session { reply: DirectchatSession.format_status_reply(session: session) } end
Source
# File plugins/directchat.rb, line 123 def self.dispatch_stop(requester:, user_channels:, bot_channels:, network:, bot_nick:, store: RabbotDb) session = find_session_for_requester( requester: requester, user_channels: user_channels, bot_channels: bot_channels, network: network, store: store ) return { error: "No active direct chat to stop." } unless session mesh_targets = DirectchatMesh.mesh_targets(session: session, exclude_bot: bot_nick) DirectchatSession.close(network: network, session_id: session[:id], store: store) { reply: DirectchatSession.format_stop_reply(channel: session[:channel]), mesh_targets: mesh_targets, mesh_stop: session[:id] } end
Source
# File plugins/directchat.rb, line 175 def self.find_session_for_requester(requester:, user_channels:, bot_channels:, network:, store: RabbotDb) shared = shared_channels(user_channels: user_channels, bot_channels: bot_channels) shared.each do |channel| session = DirectchatSession.active_for_channel(network: network, channel: channel, store: store) next unless session return session if Normalize.user_key(session[:requester]) == Normalize.user_key(requester) end nil end
Source
# File plugins/directchat.rb, line 217 def self.handle_private_message(text:, sender:, network:, bot_nick:, user_channels:, store: RabbotDb) stripped = text.to_s.strip return { ignored: true } if stripped.match?(/\A[!\/]directchat\b/i) session = DirectchatSession.active_for_participant(network: network, participant: sender, store: store) return { ignored: true } unless session channel_key = Normalize.channel(session[:channel]) unless user_channels.any? { |channel| Normalize.channel(channel) == channel_key } return { ignored: true } end assignment = DirectchatSession.assignment_for_bot(session: session, bot_nick: bot_nick) return { ignored: true } unless assignment return { ignored: true } unless Normalize.user_key(assignment[:participant]) == Normalize.user_key(sender) relay = DirectchatMesh.split_relay( session: session, from_participant: sender, text: stripped, origin_bot: bot_nick ) return { ignored: true } if relay[:ignored] relay end
Source
# File plugins/directchat.rb, line 191 def self.invite_payloads(session:) peers_by_participant = session[:assignments].to_h do |entry| [Normalize.user_key(entry[:participant]), participant_peers(session: session, participant: entry[:participant])] end session[:assignments].map do |entry| { bot: entry[:bot], participant: entry[:participant], message: DirectchatSession.format_invite( channel: session[:channel], participant: entry[:participant], bot_nick: entry[:bot], peers: peers_by_participant[Normalize.user_key(entry[:participant])] ) } end end
Source
# File plugins/directchat.rb, line 244 def self.mesh_push_lines(mesh_targets:, lines:) Array(mesh_targets).each do |target| DirectchatMeshIo.send_lines( host: target[:host], port: target[:port], lines: lines ) end end
Source
# File plugins/directchat.rb, line 39 def self.mesh_sync_frame(session:) DirectchatWire.encode_session(session: session) end
Source
# File plugins/directchat.rb, line 254 def self.offer_dcc_chat(user:, bot:, on_line:, on_close: nil) own_ip = bot.config.dcc.own_ip || bot.irc.socket.addr[2] server = TCPServer.new("0.0.0.0", 0) port = server.addr[1] handshake = DirectchatDcc.build_chat_handshake(own_ip: own_ip, port: port) user.send(handshake) Thread.new do socket = server.accept server.close loop do line = socket.gets break if line.nil? cleaned = DirectchatDcc.sanitize_line(line) next unless cleaned on_line.call(cleaned) end rescue StandardError nil ensure socket&.close on_close&.call end { port: port, server: server } end
Source
# File plugins/directchat.rb, line 210 def self.participant_peers(session:, participant:) key = Normalize.user_key(participant) session[:assignments] .reject { |entry| Normalize.user_key(entry[:participant]) == key } .map { |entry| entry[:participant] } end
Source
# File plugins/directchat.rb, line 35 def self.persona_bot_nicks ChannelTrust.persona_bot_nicks end
Source
# File plugins/directchat.rb, line 54 def self.project_root File.expand_path("..", __dir__) end
Public Instance Methods
Source
# File plugins/directchat.rb, line 283 def execute(m, args = nil) channel = shared_channel_for_user(m.user) channel_users = channel ? self.class.channel_users_from(channel) : [] result = self.class.dispatch( args, requester: m.user.nick, user_channels: m.user.channels.map(&:name), bot_channels: bot.channels.map(&:name), channel_users: channel_users, bot_nicks: self.class.persona_bot_nicks, network: bot.config.server, bot_nick: bot.nick ) if result[:error] themed_flood_safe_reply(m, result[:error]) return end themed_flood_safe_reply(m, result[:reply]) if result[:reply] push_mesh_stop(result) if result[:mesh_stop] push_mesh_sync(result) deliver_invites(result) end
Source
# File plugins/directchat.rb, line 309 def on_connect(_m) start_mesh_listener deliver_pending_invites end
Source
# File plugins/directchat.rb, line 318 def on_private_message(m) return if m.channel return if m.user.nick == bot.nick result = self.class.handle_private_message( text: m.message.to_s, sender: m.user.nick, network: bot.config.server, bot_nick: bot.nick, user_channels: m.user.channels.map(&:name) ) return if result[:ignored] deliver_relay(result) end
Source
# File plugins/directchat.rb, line 314 def poll_invites deliver_pending_invites end