diff --git a/README.md b/README.md index 7f049b5..ddea5c9 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,23 @@ [![Build Status](https://travis-ci.org/apachelogger/kde-bugzilla-rbot-plugin.svg?branch=master)](https://travis-ci.org/apachelogger/kde-bugzilla-rbot-plugin) # Installation - Clone anywhere - Install dependencies - When using Bundler: `bundle install --without=development` - Manually: `gem install finer_struct && gem install faraday` - Add clone path to `~/.rbot/conf.yaml` ``` plugins.path: - /home/me/src/git/rbot-bugzilla ``` - Restart bot + +# Blacklists + +The plugin supports configuring a list of channels to be blacklisted. This +inhibits either all message handling or specific message handling. + +- `bugzilla.blacklist` disables all message handling +- `bugzilla.url_blacklist` disables handling of URLs (keywords remain + active - e.g. `https://bugs.kde.org/123` is not handled but `bug 123` still is) diff --git a/bugzilla.rb b/bugzilla.rb index d7b61d9..ed8e2b2 100644 --- a/bugzilla.rb +++ b/bugzilla.rb @@ -1,72 +1,79 @@ # encoding: utf-8 # frozen_string_literal: true # # Copyright (C) 2016 Harald Sitter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 3 of # the License or any later version accepted by the membership of # KDE e.V. (or its successor approved by the membership of KDE # e.V.), which shall act as a proxy defined in Section 14 of # version 3 of the license. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . require(File.expand_path('lib/bug', File.dirname(__FILE__))) -require(File.expand_path('lib/kde_rbot_config', File.dirname(__FILE__))) # Bugzilla Plugin class BugzillaPlugin < Plugin + Config.register Config::ArrayValue.new('bugzilla.blacklist', + :default => %w[#kde-bugs-activity], + :desc => 'Disables all message handling in the listed channels.') + + Config.register Config::ArrayValue.new('bugzilla.url_blacklist', + :default => [], + :desc => 'Disables message handling on URLs only in the listed channels. Trigger words still get handled.') + def unreplied(m, _ = {}) return if skip?(m) # Bot by default only handles messages directed at it directly by either # its name or a shortcut prefix. For the bug plugin we additionally want # to handle casual conversation to give context. match = m.message.scan(/\bbug\s+(\d+)\b/i) if match.empty? && !skip_url_handling?(m) # Attempt to match URL. match = m.message.scan(%r{\bhttps://bugs\.kde\.(?:[^\s]+)=(\d+)\b}i) end match.flatten.each do |number| bug(m, {:number => number}) end end def bug(m, options = {}) number = options.fetch(:number) bug = Bugzilla::Bug.get(number) m.reply "KDE bug #{bug.id} in #{bug.product} (#{bug.component}) \"#{bug.summary}\" [#{bug.severity},#{bug.resolution}] #{bug.web_url}" rescue => e m.notify "Bug not found (ノಠ益ಠ)ノ彡┻━┻ #{e}" end private def skip?(m) - KDERBotConfig.handler_blacklist.any? do |exclude| + bot.config['bugzilla.blacklist'].any? do |exclude| m.channel && m.channel.name == exclude end end def skip_url_handling?(m) - KDERBotConfig.url_handler_blacklist.any? do |exclude| + bot.config['bugzilla.url_blacklist'].any? do |exclude| m.channel && m.channel.name == exclude end end end plugin = BugzillaPlugin.new plugin.map 'bug :number', requirements: { number: /^[^ ]+$/ }, action: 'bug', thread: 'yes' # , auth_path: 'view' diff --git a/lib/kde_rbot_config.rb b/lib/kde_rbot_config.rb deleted file mode 100644 index deaf332..0000000 --- a/lib/kde_rbot_config.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true -# -# Copyright (C) 2019 Harald Sitter -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) version 3, or any -# later version accepted by the membership of KDE e.V. (or its -# successor approved by the membership of KDE e.V.), which shall -# act as a proxy defined in Section 6 of version 3 of the license. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see . - -require 'yaml' - -# KDE specific config to override behavior of custom plugins. -# NB: this thing is copied across all plugins since I am unclear if/what best -# sharing mechansim we want to use. Specifically since the server still uses -# ruby1.9 I am not too excited about making this a proper gem. -module KDERBotConfig - class << self - def handler_blacklist - data['handler_blacklist'] || %w[#kde-bugs-activity] - end - - def url_handler_blacklist - data['url_handler_blacklist'] || [] - end - - def reset! - @data = nil - end - - private - - def xdg_config_dirs - [ENV.fetch('XDG_CONFIG_HOME', "#{Dir.home}/.config")] + - ENV.fetch('XDG_CONFIG_DIRS', '/etc/xdg').split(':') - end - - def possible_configs - xdg_config_dirs.collect { |dir| File.join(dir, 'org.kde.rbot.yaml') } - end - - def load_data - file = possible_configs.find { |config| File.exist?(config) } - return YAML.load_file(file) if file - - {} - end - - def data - @data ||= load_data - end - end -end diff --git a/test/fixtures/kde_rbot_config/org.kde.rbot.yaml b/test/fixtures/kde_rbot_config/org.kde.rbot.yaml deleted file mode 100644 index eab493a..0000000 --- a/test/fixtures/kde_rbot_config/org.kde.rbot.yaml +++ /dev/null @@ -1,2 +0,0 @@ -url_handler_blacklist: - - '#message-double-channel' diff --git a/test/kde_rbot_config_test.rb b/test/kde_rbot_config_test.rb deleted file mode 100644 index 05245ac..0000000 --- a/test/kde_rbot_config_test.rb +++ /dev/null @@ -1,49 +0,0 @@ -# frozen_string_literal: true -# -# Copyright (C) 2019 Harald Sitter -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) version 3, or any -# later version accepted by the membership of KDE e.V. (or its -# successor approved by the membership of KDE e.V.), which shall -# act as a proxy defined in Section 6 of version 3 of the license. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library. If not, see . - -require(File.expand_path('test_helper', File.dirname(__FILE__))) - -require 'lib/kde_rbot_config' - -class KDERBotConfigTest < Test::Unit::TestCase - def setup - ENV['XDG_CONFIG_DIRS'] = "/b:/c" - ENV['XDG_CONFIG_HOME'] = "/a" - KDERBotConfig.reset! - end - - def teardown - ENV.delete('XDG_DATA_DIRS') - ENV.delete('XDG_CONFIG_HOME') - KDERBotConfig.reset! - end - - def test_possible_configs - confs = KDERBotConfig.send(:possible_configs) - assert_equal(%w[/a/org.kde.rbot.yaml /b/org.kde.rbot.yaml /c/org.kde.rbot.yaml].sort, - confs.sort) - end - - def test_url_handler_blacklist - ENV['XDG_CONFIG_HOME'] = - File.expand_path('fixtures/kde_rbot_config', File.dirname(__FILE__)) - assert_equal(%w[#message-double-channel], KDERBotConfig.url_handler_blacklist) - end -end diff --git a/test/plugin_test.rb b/test/plugin_test.rb index c56615a..ac9d7a2 100644 --- a/test/plugin_test.rb +++ b/test/plugin_test.rb @@ -1,104 +1,137 @@ # encoding: utf-8 require(File.expand_path('test_helper', File.dirname(__FILE__))) # Dud base class. We mocha this for functionality later. class Plugin + class Config + class ArrayValue + @@kdebugsactivity_defaulted = false + + def self.kdebugsactivity_defaulted + # At least one ArrayValue must have had a default value with the bugs + # activity channel. This is technically a very specific value but + # asserting any had it should be good enough. + @@kdebugsactivity_defaulted + end + + def initialize(_, params = {}) + return unless params[:default] == %w[#kde-bugs-activity] + + @@kdebugsactivity_defaulted = true + end + end + + def self.register(_) + end + end + def map(*args) end + + def bot + end end require 'bugzilla' class PluginTest < Test::Unit::TestCase # NB: mocha is stupid with the quotes and can't tell single from double! def setup ENV.delete('XDG_DATA_DIRS') ENV.delete('XDG_CONFIG_HOME') - KDERBotConfig.reset! + + assert(Plugin::Config::ArrayValue.kdebugsactivity_defaulted, + 'blacklist ArrayValue should have had the bugs activity channel blacklisted') + + config = mock('config') + # Do not give an api_token as we need the environment to take over. + config.stubs(:[]).with('phabricator.api_token').returns(nil) + # This default value is also set in the rb and asserted via our duds + config.stubs(:[]).with('bugzilla.blacklist').returns(%w[#kde-bugs-activity]) + config.stubs(:[]).with('bugzilla.url_blacklist').returns([]) + bot = mock('bot') + bot.stubs(:config).returns(config) + Plugin.any_instance.stubs(:bot).returns(bot) + + @config = config end def teardown - KDERBotConfig.reset! end def message_double channel = mock('message-channel') channel.stubs(:name).returns('#message-double-channel') mock('message').tap { |m| m.stubs(:channel).returns(channel) } end def test_get_unreplied - # make sure this triggers even when url handling is disabled - ENV['XDG_CONFIG_HOME'] = - File.expand_path('fixtures/kde_rbot_config', File.dirname(__FILE__)) - message = message_double message.stubs(:message).returns('yolo brooom bug 123') plugin = BugzillaPlugin.new plugin.expects(:bug).with(message, number: '123') plugin.unreplied(message) end def test_get_unreplied_url_blacklist - ENV['XDG_CONFIG_HOME'] = - File.expand_path('fixtures/kde_rbot_config', File.dirname(__FILE__)) + @config.stubs(:[]).with('bugzilla.url_blacklist').returns(%w[#message-double-channel]) message = message_double message.stubs(:message).returns('yolo brooom bug https://bugs.kde.org/show_bug.cgi?id=123') plugin = BugzillaPlugin.new plugin.expects(:bug).never plugin.unreplied(message) end def test_bug message = message_double message.expects(:reply).with('KDE bug 359887 in neon (general) "Neon packages change DISTRIB_ID in /etc/lsb-release" [normal,FIXED] https://bugs.kde.org/show_bug.cgi?id=359887') VCR.use_cassette(__method__) do plugin = BugzillaPlugin.new plugin.bug(message, { :number => 359887 }) end end def test_bug_fail message = message_double message.expects(:notify).with('Bug not found (ノಠ益ಠ)ノ彡┻━┻ JSONError {:message=>"Bug #1 does not exist.", :code=>101}') VCR.use_cassette(__method__) do plugin = BugzillaPlugin.new plugin.bug(message, { :number => 1 }) end end def test_get_unreplied_multi_match message = message_double message.stubs(:message).returns('yolo brooom bug 123 and bug 321') plugin = BugzillaPlugin.new plugin.expects(:bug).with(message, number: '123') plugin.expects(:bug).with(message, number: '321') plugin.unreplied(message) end def test_get_unreplied_multi_match_url message = message_double message.stubs(:message).returns('yolo brooom https://bugs.kde.org/show_bug.cgi?id=366701 and https://bugs.kde.org/show_bug.cgi?id=366702') plugin = BugzillaPlugin.new plugin.expects(:bug).with(message, number: '366701') plugin.expects(:bug).with(message, number: '366702') plugin.unreplied(message) end def test_skip message = message_double message.channel.stubs(:name).returns('#kde-bugs-activity') plugin = BugzillaPlugin.new plugin.unreplied(message) end end