module ClockStore
ClockStore — per-channel clock enable state and atomic minute claims. Public: load_state, save_state, normalize_state, enable_state, disable_state, deactivate_other_channels!, claim_minute! Depends: ClockSegment, RabbotDb Tests: test/plugins/clock_test.rb
Constants
- DEFAULT_LINES
- PLUGIN
- STATE_KEY
Public Instance Methods
Source
# File lib/clock/store.rb, line 88 def claim_minute!(network:, channel:, minute:, store: RabbotDb) minute = minute.to_s.strip claimed = false state = normalize_state({}) store.with_connection do |db| db.transaction do row = db.get_first_row(<<~SQL, [PLUGIN, STATE_KEY, "channel", RabbotDb.current_bot_id, RabbotDb.normalize_network(network), RabbotDb.normalize_channel(channel), ""]) SELECT value FROM plugin_data WHERE plugin = ? AND key = ? AND scope = ? AND bot_id = ? AND group_id = 0 AND network = ? AND channel = ? AND nick = ? SQL raw = row ? JSON.parse(row["value"]) : {} state = normalize_state(raw) next unless state["enabled"] && state["last_minute"] != minute state = state.merge("last_minute" => minute) write_state_row(db, network: network, channel: channel, state: state) claimed = true end end { claimed: claimed, state: state } rescue JSON::ParserError { claimed: false, state: normalize_state({}) } end
Source
# File lib/clock/store.rb, line 71 def deactivate_other_channels!(network:, channel:, channels:, store: RabbotDb) active = RabbotDb.normalize_channel(channel) Array(channels).each do |name| next if RabbotDb.normalize_channel(name).casecmp?(active) state = load_state(network: network, channel: name, store: store) next unless state["enabled"] save_state( network: network, channel: name, state: disable_state(lines: state["lines"], require_voice: state["require_voice"]), store: store ) end end
Source
# File lib/clock/store.rb, line 62 def disable_state(lines: DEFAULT_LINES, require_voice: true) { "enabled" => false, "lines" => lines, "last_minute" => "", "require_voice" => !!require_voice } end
Source
# File lib/clock/store.rb, line 53 def enable_state(lines: DEFAULT_LINES, require_voice: true) { "enabled" => true, "lines" => ClockSegment.clamp_lines(lines), "last_minute" => "", "require_voice" => !!require_voice } end
Source
# File lib/clock/store.rb, line 20 def load_state(network:, channel:, store: RabbotDb) raw = store.get_plugin_json( plugin: PLUGIN, key: STATE_KEY, network: network, channel: channel, default: {} ) normalize_state(raw) end
Source
# File lib/clock/store.rb, line 41 def normalize_state(raw) data = raw.is_a?(Hash) ? raw : {} lines = data["lines"].to_i lines = DEFAULT_LINES unless (1..ClockSegment::MAX_LINES).cover?(lines) { "enabled" => !!data["enabled"], "lines" => lines, "last_minute" => data["last_minute"].to_s.strip, "require_voice" => data.key?("require_voice") ? !!data["require_voice"] : true } end
Source
# File lib/clock/store.rb, line 116 def plugin_row_params(network:, channel:) [ PLUGIN, STATE_KEY, "channel", RabbotDb.normalize_network(network), RabbotDb.normalize_channel(channel), "" ] end
Source
# File lib/clock/store.rb, line 31 def save_state(network:, channel:, state:, store: RabbotDb) store.set_plugin_json( plugin: PLUGIN, key: STATE_KEY, network: network, channel: channel, value: normalize_state(state) ) end
Source
# File lib/clock/store.rb, line 128 def write_state_row(db, network:, channel:, state:) plugin, key, scope, net, chan, nick = plugin_row_params(network: network, channel: channel) value = JSON.generate(normalize_state(state)) now = RabbotDb.iso_time db.execute(<<~SQL, [scope, RabbotDb.current_bot_id, net, chan, nick, plugin, key, value, now]) INSERT INTO plugin_data (scope, bot_id, group_id, network, channel, nick, plugin, key, value, updated_at) VALUES (?, ?, 0, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(scope, bot_id, group_id, network, channel, nick, plugin, key) DO UPDATE SET value = excluded.value, updated_at = excluded.updated_at SQL end