module DirectchatPlan
Public Instance Methods
Source
# File lib/directchat/plan.rb, line 116 def build_plan(requester:, guest_nicks:, channel:, channel_users:, bot_nicks:) bots = channel_bots(channel_users, bot_nicks) return { error: "No Rabbot personas are in #{channel}." } if bots.empty? max_guests = bots.length - 1 if guest_nicks.length > max_guests return { error: "Too many guests — #{channel} has #{bots.length} bot(s), so invite at most #{max_guests} other nick(s)." } end requester_nick = Normalize.nick(requester) unless user_in_channel?(channel_users, requester_nick) return { error: "You must be in #{channel} to start a direct chat." } end guest_nicks.each do |guest| if bot_nicks.any? { |bot| bot.casecmp?(guest) } return { error: "#{guest} is a bot — invite humans only." } end unless user_in_channel?(channel_users, guest) return { error: "#{guest} is not in #{channel}." } end end participants = [requester_nick] + guest_nicks assignments = bots.each_with_index.filter_map do |bot, index| participant = participants[index] next unless participant { bot: bot, participant: participant } end { channel: channel, requester: requester_nick, assignments: assignments, bot_count: bots.length } end
Source
# File lib/directchat/plan.rb, line 99 def channel_bots(channel_users, bot_nicks) users = normalize_channel_users(channel_users) bot_keys = bot_nicks.map { |nick| Normalize.user_key(nick) } users .map { |user| user.respond_to?(:nick) ? user.nick.to_s : user.to_s } .select { |nick| bot_keys.include?(Normalize.user_key(nick)) } .sort_by { |nick| Normalize.user_key(nick) } end
Source
# File lib/directchat/plan.rb, line 60 def channel_lookup(channels) channels.map { |channel| [Normalize.channel(channel), channel.to_s] }.to_h end
Source
# File lib/directchat/plan.rb, line 90 def normalize_channel_users(channel_users) case channel_users when Hash channel_users.keys else Array(channel_users) end end
Source
# File lib/directchat/plan.rb, line 22 def parse_command(text, requester: nil) stripped = text.to_s.strip return { error: usage_message } if stripped.empty? action_key = stripped.split(/\s+/, 2).first.to_s.downcase case action_key when "stop" return { action: :stop } when "status" return { action: :status } when "prd" return { action: :prd } when "inventory" return { action: :inventory } end channel = nil rest = stripped if (match = rest.match(/\A(#\S+)\s+(.*)\z/m)) channel = match[1].strip rest = match[2].strip end guest_nicks = rest.split(/\s+/).map { |nick| Normalize.nick(nick) }.reject(&:empty?) return { error: usage_message } if guest_nicks.empty? keys = guest_nicks.map { |nick| Normalize.user_key(nick) } if keys.length != keys.uniq.length return { error: "Duplicate nick in guest list." } end if requester && guest_nicks.any? { |nick| Normalize.user_key(nick) == Normalize.user_key(requester) } return { error: "You cannot invite yourself." } end { channel: channel, guest_nicks: guest_nicks } end
Source
# File lib/directchat/plan.rb, line 158 def prepare_start(args:, requester:, user_channels:, bot_channels:, channel_users:, bot_nicks:, network:, store: RabbotDb) parsed = parse_command(args, requester: requester) return parsed if parsed[:error] target = if parsed[:channel] resolve_explicit_channel( channel: parsed[:channel], user_channels: user_channels, bot_channels: bot_channels ) else resolve_target_channel(user_channels: user_channels, bot_channels: bot_channels) end return target if target[:error] channel = target[:channel] if DirectchatSession.active_for_channel(network: network, channel: channel, store: store) return { error: "A direct chat is already active in #{channel}. Use !directchat stop first." } end plan = build_plan( requester: requester, guest_nicks: parsed[:guest_nicks], channel: channel, channel_users: channel_users, bot_nicks: bot_nicks ) return plan if plan[:error] session = DirectchatSession.create( network: network, channel: channel, requester: plan[:requester], assignments: plan[:assignments], bot_count: plan[:bot_count], store: store ) { session: session } end
Source
# File lib/directchat/plan.rb, line 74 def resolve_explicit_channel(channel:, user_channels:, bot_channels:) target_key = Normalize.channel(channel) user_by_key = channel_lookup(user_channels) bot_keys = bot_channels.map { |name| Normalize.channel(name) } unless user_by_key.key?(target_key) return { error: "You must share that channel with the bot to start a direct chat." } end unless bot_keys.include?(target_key) return { error: "The bot is not in that channel." } end { channel: user_by_key[target_key] } end
Source
# File lib/directchat/plan.rb, line 64 def resolve_target_channel(user_channels:, bot_channels:) user_by_key = channel_lookup(user_channels) bot_keys = bot_channels.map { |channel| Normalize.channel(channel) } shared_keys = user_by_key.keys & bot_keys shared_keys.sort! return { error: "You must share a channel with the bot to start a direct chat." } if shared_keys.empty? { channel: user_by_key[shared_keys.first] } end
Source
# File lib/directchat/plan.rb, line 18 def usage_message "Usage: /msg <bot> !directchat [#channel] <nick> [...] | stop | status | prd | inventory" end
Source
# File lib/directchat/plan.rb, line 108 def user_in_channel?(channel_users, nick) key = Normalize.user_key(nick) normalize_channel_users(channel_users).any? do |user| candidate = user.respond_to?(:nick) ? user.nick : user Normalize.user_key(candidate) == key end end