class Clock
Constants
- COUPLED_PLUGIN_FILES
- DEFAULT_LINES
- PLUGIN
- REQUIRE_VOICE_ENV
- STATE_KEY
- TICK_INTERVAL_SEC
Public Class Methods
Source
# File plugins/clock.rb, line 52 def self.bot_can_speak?(channel, bot) return false unless channel moderated = channel.respond_to?(:modes) && channel.modes["m"] return true unless moderated (channel.respond_to?(:opped?) && channel.opped?(bot)) || (channel.respond_to?(:voiced?) && channel.voiced?(bot)) end
Source
# File plugins/clock.rb, line 155 def self.build_tick_message(now:, utc_offset:, lines:, meaning_lookup: ClockFlipMeaning, rng: Random.new, lookup_now: nil) ClockTick.build_tick_message( now: now, utc_offset: utc_offset, lines: lines, meaning_lookup: meaning_lookup, rng: rng, lookup_now: lookup_now ) end
Source
# File plugins/clock.rb, line 151 def self.channel_timezone(network:, channel:, store: RabbotDb, now: Time.now) ClockTick.channel_timezone(network: network, channel: channel, store: store, now: now) end
Source
# File plugins/clock.rb, line 182 def self.claim_minute!(network:, channel:, minute:, store: RabbotDb) ClockStore.claim_minute!(network: network, channel: channel, minute: minute, store: store) end
Source
# File plugins/clock.rb, line 39 def self.command_pattern /clock(?:\s+(.+))?$/i end
Source
# File plugins/clock.rb, line 104 def self.deactivate_other_channels!(network:, channel:, channels:, store: RabbotDb) ClockStore.deactivate_other_channels!( network: network, channel: channel, channels: channels, store: store ) end
Source
# File plugins/clock.rb, line 100 def self.disable_state(lines: DEFAULT_LINES, require_voice: true) ClockStore.disable_state(lines: lines, require_voice: require_voice) end
Source
# File plugins/clock.rb, line 143 def self.due_for_tick?(state, now:, utc_offset:) ClockTick.due_for_tick?(state, now: now, utc_offset: utc_offset) end
Source
# File plugins/clock.rb, line 96 def self.enable_state(lines: DEFAULT_LINES, require_voice: true) ClockStore.enable_state(lines: lines, require_voice: require_voice) end
Source
# File plugins/clock.rb, line 170 def self.format_status(enabled:, lines:, require_voice: true) ClockReport.format_status(enabled: enabled, lines: lines, require_voice: require_voice) end
Source
# File plugins/clock.rb, line 174 def self.format_voice_status(require_voice:) ClockReport.format_voice_status(require_voice: require_voice) end
Source
# File plugins/clock.rb, line 84 def self.load_state(network:, channel:, store: RabbotDb) ClockStore.load_state(network: network, channel: channel, store: store) end
Source
# File plugins/clock.rb, line 147 def self.mark_tick(state, now:, utc_offset:) ClockTick.mark_tick(state, now: now, utc_offset: utc_offset) end
Source
# File plugins/clock.rb, line 139 def self.minute_key(now, utc_offset:) ClockTick.minute_key(now, utc_offset: utc_offset) end
Source
# File plugins/clock.rb, line 46 def initialize(bot) super PluginTimers.start(self) self.class.refresh_coupled_plugins! end
Calls superclass method
Source
# File plugins/clock.rb, line 92 def self.normalize_state(raw) ClockStore.normalize_state(raw) end
Source
# File plugins/clock.rb, line 113 def self.parse_command(args) text = args.to_s.strip return { action: :status } if text.empty? return { action: :off } if text.casecmp?("off") if (match = text.match(/\Avoice\s+(on|off)\z/i)) return { action: :voice, require_voice: match[1].casecmp?("on") } end if (match = text.match(/\Aon(?:\s+(\d+))?\z/i)) lines = match[1] ? match[1].to_i : DEFAULT_LINES unless (1..ClockSegment::MAX_LINES).cover?(lines) return { error: "Lines must be between 1 and #{ClockSegment::MAX_LINES}." } end return { action: :on, lines: lines } end { error: usage_message } end
Source
# File plugins/clock.rb, line 135 def self.parse_time_command(args) ClockFlipCommand.parse_command(args) end
Source
# File plugins/clock.rb, line 186 def self.poll_channel(network:, channel_name:, state:, bot:, now: Time.now, store: RabbotDb, reply_to: nil, tick_may_send: nil) ClockPoll.poll_channel( network: network, channel_name: channel_name, state: state, bot: bot, now: now, store: store, reply_to: reply_to, tick_may_send: tick_may_send ) end
Source
# File plugins/clock.rb, line 200 def self.poll_channels(bot, store: RabbotDb, now: Time.now, tick_may_send: nil) ClockPoll.poll_channels(bot, store: store, now: now, tick_may_send: tick_may_send) end
Source
# File plugins/clock.rb, line 33 def self.refresh_coupled_plugins! COUPLED_PLUGIN_FILES.each do |path| load path if File.file?(path) end end
Source
# File plugins/clock.rb, line 67 def self.require_voice_for_channel?(state) return false unless require_voice_globally? data = state.is_a?(Hash) ? state : {} data.fetch("require_voice", true) != false end
Source
# File plugins/clock.rb, line 62 def self.require_voice_globally? value = ENV.fetch(REQUIRE_VOICE_ENV, "true").to_s.strip.downcase !%w[0 false off no].include?(value) end
Source
# File plugins/clock.rb, line 88 def self.save_state(network:, channel:, state:, store: RabbotDb) ClockStore.save_state(network: network, channel: channel, state: state, store: store) end
Source
# File plugins/clock.rb, line 178 def self.tick_channel(state:, now:, utc_offset:) ClockTick.tick_channel(state: state, now: now, utc_offset: utc_offset) end
Source
# File plugins/clock.rb, line 74 def self.tick_may_send?(channel:, bot:, state:) return true unless require_voice_for_channel?(state) bot_can_speak?(channel, bot) end
Source
# File plugins/clock.rb, line 166 def self.timezone_short_label(local_time) ClockTick.timezone_short_label(local_time) end
Source
# File plugins/clock.rb, line 80 def self.usage_message "Usage: !clock on|off [lines 1–20] — !clock voice on|off" end
Public Instance Methods
Source
# File plugins/clock.rb, line 204 def bot_can_speak?(channel, bot_ref = bot) self.class.bot_can_speak?(channel, bot_ref) end
Source
# File plugins/clock.rb, line 212 def deliver_channel_tick(network:, channel_name:, state:, reply_to: nil) result = self.class.poll_channel( network: network, channel_name: channel_name, state: state, bot: bot, reply_to: reply_to, tick_may_send: method(:tick_may_send?) ) return unless result[:text] themed_flood_safe_reply(result[:target], result[:text]) end
Source
# File plugins/clock.rb, line 236 def execute(m, args = nil) return unless m.channel parsed = self.class.parse_command(args) if parsed[:error] themed_flood_safe_reply(m, parsed[:error]) return end network = bot.config.server channel = m.channel.name state = self.class.load_state(network: network, channel: channel) case parsed[:action] when :status themed_flood_safe_reply( m, self.class.format_status( enabled: state["enabled"], lines: state["lines"], require_voice: state["require_voice"] ) ) when :on self.class.deactivate_other_channels!( network: network, channel: channel, channels: bot.config.channels ) updated = self.class.enable_state( lines: parsed[:lines], require_voice: state["require_voice"] ) self.class.save_state(network: network, channel: channel, state: updated) themed_flood_safe_reply( m, self.class.format_status( enabled: true, lines: parsed[:lines], require_voice: updated["require_voice"] ) ) deliver_channel_tick(network: network, channel_name: channel, state: updated, reply_to: m) when :off updated = self.class.disable_state( lines: state["lines"], require_voice: state["require_voice"] ) self.class.save_state(network: network, channel: channel, state: updated) themed_flood_safe_reply( m, self.class.format_status( enabled: false, lines: state["lines"], require_voice: updated["require_voice"] ) ) when :voice updated = state.merge("require_voice" => parsed[:require_voice]) self.class.save_state(network: network, channel: channel, state: updated) themed_flood_safe_reply(m, self.class.format_voice_status(require_voice: parsed[:require_voice])) end end
Source
# File plugins/clock.rb, line 226 def poll_clock return unless bot tick_may_send = ->(channel, state) { tick_may_send?(channel, state) } self.class.poll_channels(bot, tick_may_send: tick_may_send).each do |entry| channel = bot.channels.find { |item| item.name.casecmp?(entry[:channel].to_s) } themed_flood_safe_reply(channel, entry[:text]) if channel end end
Source
# File plugins/clock.rb, line 208 def tick_may_send?(channel, state) self.class.tick_may_send?(channel: channel, bot: bot, state: state) end