Compare commits

...

29 Commits

Author SHA1 Message Date
Robert Gerus 2f0518a7f0 Modify the xpath 2015-08-11 23:26:32 +02:00
Robert Gerus e1ad4ad3d5 Add images from bonjourmadame.fr 2015-08-11 23:16:43 +02:00
Robert Gerus d68fc1a8df List nettops connected to the network 2015-07-28 19:16:44 +02:00
Robert Gerus cdcd0985e6 Add invite plugin. 2015-05-27 11:11:50 +02:00
Robert Gerus dad51df229 Default access_level → 5 2015-04-28 11:02:31 +02:00
Robert Gerus b98bae59de uhm… we do need scope here. 2015-04-28 10:16:32 +02:00
Robert Gerus 890cfbc18e Consistency pt2 2015-04-19 19:01:09 +02:00
Robert Gerus d4a1dbf7d5 Consistency 2015-04-19 18:37:30 +02:00
Robert Gerus 70d0cf8e7e fixorz 2015-04-19 18:26:37 +02:00
Robert Gerus ba8bbb6c97 Renamed channel to target a while ago. 2015-04-16 12:33:03 +02:00
Robert Gerus 09b03ddb5c Keys in scope are strings, not symbols… 2015-04-16 12:24:13 +02:00
Robert Gerus 06b011f715 Fix responding to privmsgs in eval 2015-04-16 12:17:22 +02:00
Robert Gerus 711b7adfbc Fix the fix fixing the fix 2015-04-16 11:57:25 +02:00
Robert Gerus 6c868ce15d Fix the fix 2015-04-16 11:45:15 +02:00
Robert Gerus b74aa04cff Fix scope creation - return freenode account as person, if possible 2015-04-16 11:38:26 +02:00
Robert Gerus 953f73edd2 Fix commands plugin. 2015-04-16 11:32:32 +02:00
Robert Gerus fd8108e0e5 whoopsie 2015-04-16 10:58:22 +02:00
Robert Gerus f2b7c280ed Not everywhere String is a safe default ;) 2015-04-16 10:55:39 +02:00
Robert Gerus 9ff54e0a06 Fix register_trigger calls. 2015-04-16 10:40:52 +02:00
Robert Gerus fa8ee9d02e whoopsie 2015-04-16 10:37:37 +02:00
Robert Gerus 137e0eb0a8 whoopsie 2015-04-16 10:36:07 +02:00
Robert Gerus 11a9042c56 whoopsie 2015-04-16 10:35:04 +02:00
Robert Gerus 52c1a888cf whoopsie 2015-04-16 10:34:09 +02:00
Robert Gerus ef6c54e0c1 plug some holes 2015-04-16 10:14:55 +02:00
Robert Gerus 1bc794e9f9 plug some holes 2015-04-16 10:07:44 +02:00
Robert Gerus 50ce39da5c Override the lookup method for now, because we often call it with empty default and empty scope anyway. 2015-04-16 10:04:18 +02:00
Robert Gerus d5d6f7f12a Bombs away 2015-04-15 21:15:02 +02:00
Robert Gerus 196d57ffd7 It *should* start to work, but it is not yet tested 2015-04-15 19:55:25 +02:00
Robert Gerus 7e32bc2419 It's hierryfying and it has no chance to work… yet ;) 2015-04-15 14:06:24 +02:00
17 changed files with 116 additions and 61 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
config.rb
config/
*.swp
*.swo
*~

View File

@ -5,11 +5,7 @@ class Repost
attr_accessor :commands
def register_command(keyword, &code)
begin
access_level = Config[:commands][keyword.to_sym][:access_level].nil? ? 5 : Config[keyword.to_sym][:access_level]
rescue NoMethodError
access_level = 5
end
access_level = Config.lookup("commands::#{keyword}::access_level", 0)
self.commands = [] if self.commands.nil?
self.commands << {
@ -39,14 +35,14 @@ end
Client.load_commands
Client.register_trigger("PRIVMSG") { |msg|
Client.register_trigger("PRIVMSG", "commands") { |msg|
# who sent the message
src_nick = msg[:prefix].split('!').first
# what was it
message = msg[:params][1]
# Was the message sent directly to us...
if msg[:params][0] == Config[:client][:nick] then
if msg[:params][0] == Config.lookup("client::nick", "repost", msg[:scope]) then
target = src_nick
reply_prefix = ""
# or to a channel (probably)
@ -58,7 +54,7 @@ Client.register_trigger("PRIVMSG") { |msg|
# Did the message contain our nick with ":" "completion character"?
# If so, use the second word as a command and everything else as arguments
# array
if message.split.first == Config[:client][:nick] + ":" then
if message.split.first == Config.lookup("client::nick", "repost", msg[:scope]) + ":" then
command = message.split[1]
arguments = message.split[2..-1]
else
@ -80,8 +76,9 @@ Client.register_trigger("PRIVMSG") { |msg|
# command call
Client.commands.each do |cmd|
# couldn't inline the if into second argument of Client.privmsg() call
if command.downcase == cmd[:keyword] then
next if cmd[:access_level] > Client.access_level(msg[:prefix], target)
if command.downcase == cmd[:keyword] and
cmd[:access_level] <= Config.lookup("access_level", 0, msg[:scope]) and
not Config.lookup("commands::disabled", [], msg[:scope]).include? cmd[:keyword] then
retval = cmd[:code].call(arguments)
# if the command returned a String, we want to show it
Client.privmsg(target, reply_prefix + retval) if retval.instance_of? String

View File

@ -6,7 +6,7 @@ Client.register_command("at") { |args|
now = []
recently = []
r_msg = ""
h = JSON.parse(Net::HTTP.get(URI(Config[:commands][:at][:url])))
h = JSON.parse(Net::HTTP.get(URI(Config.lookup("commands::at::url"))))
h["users"].each { |u|
if (Time.now.to_i - u["timestamp"]) > 600 then
recently << u["login"]
@ -15,10 +15,11 @@ Client.register_command("at") { |args|
end
}
r_msg += "now: #{now.join(' ')}#{Config[:commands][:at][:separator]} " if not now.empty?
r_msg += "recently: #{recently.join(' ')}#{Config[:commands][:at][:separator]} " if not recently.empty?
r_msg += Config[:commands][:at][:empty] if now.empty? and recently.empty?
r_msg += "unknown: #{h["unknown"]}#{Config[:commands][:at][:separator]} " if h["unknown"] > 0
r_msg += "now: #{now.join(' ')}#{Config.lookup("commands::at::separator")} " if not now.empty?
r_msg += "recently: #{recently.join(' ')}#{Config.lookup("commands::at::separator")} " if not recently.empty?
r_msg += Config.lookup("commands::at::empty") if now.empty? and recently.empty?
r_msg += Config.lookup("commands::at::nettops") if h["kektops"] > 0
r_msg += "unknown: #{h["unknown"]}#{Config.lookup("commands::at::separator")} " if h["unknown"] > 0
r_msg
}

View File

@ -0,0 +1,7 @@
require 'net/http'
require 'nokogiri'
Client.register_command("bonjour") { |args|
link = Config.lookup("commands::bonjour::url") + String(rand(1..2370))
Config.lookup("commands::bonjour::message") + Nokogiri::HTML(Net::HTTP.get(URI(link))).xpath('//div[@class="photo post"]//img/@src').inner_text
}

View File

@ -4,7 +4,7 @@ require 'nokogiri'
Client.register_command("cycki") { |args|
link = ""
begin
link = Nokogiri::HTML(Net::HTTP.get(URI(Config[:commands][:cycki][:url]))).xpath('//img/@src').inner_text.gsub("_preview", "")
link = Nokogiri::HTML(Net::HTTP.get(URI(Config.lookup("commands::cycki::url")))).xpath('//img/@src').inner_text.gsub("_preview", "")
end while link !~ /http/
Config[:commands][:cycki][:message] + link
Config.lookup("commands::cycki::message") + link
}

View File

@ -3,8 +3,9 @@ require 'nokogiri'
Client.register_command("bug") { |args|
if args[0] =~ /^[0-9]+$/ then
doc = Nokogiri::HTML(Net::HTTP.get(URI(Config[:commands][:bug][:url] + args[0])))
[Config[:commands][:bug][:url] + args[0], doc.title().delete!('\n'),
doc = Nokogiri::HTML(Net::HTTP.get(URI(Config.lookup("commands::bug::url") + args[0])))
[
Config.lookup("commands::bug::url") + args[0], doc.title().delete!('\n'),
doc.xpath('//span[@id="static_bug_status"]').inner_text.split,
doc.xpath('//td[@id="field_container_product"]').inner_text,
].join('; ')

View File

@ -2,20 +2,20 @@ Client.register_command("jan") { |args|
if not args[0].nil? then
if args[0].force_encoding("UTF-8") =~ /ł$/ then
predicate = args[0]
object = File.readlines(Config[:commands][:jan][:object]).sample.strip
object = File.readlines(Config.lookup("commands::jan::objects")).sample.strip
else
predicate = File.readlines(Config[:commands][:jan][:predicates]).sample.strip
predicate = File.readlines(Config.lookup("commands::jan::predicates")).sample.strip
object = args[0]
end
else
object = File.readlines(Config[:commands][:jan][:object]).sample.strip
predicate = File.readlines(Config[:commands][:jan][:predicates]).sample.strip
object = File.readlines(Config.lookup("commands::jan::objects")).sample.strip
predicate = File.readlines(Config.lookup("commands::jan::predicates")).sample.strip
end
[
Config[:commands][:jan][:subject],
Config.lookup("commands::jan::subject"),
predicate,
Config[:commands][:jan][:attribute],
Config.lookup("commands::jan::attribute"),
object
].join " "
}

View File

@ -2,7 +2,7 @@ require 'net/http'
require 'uri'
Client.register_command("kotki") { |args|
url = URI.parse(Config[:commands][:kotki][:url])
url = URI.parse(Config.lookup("commands::kotki::url"))
req = Net::HTTP::Get.new(url.path)
response = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }

View File

@ -1,8 +1,8 @@
Client.register_command("papież") { |args|
Config[:commands][:papiez][:noun] + " " +
File.readlines(Config[:commands][:papiez][:adjectives]).sample
Config.lookup("commands::papiez::noun") + " " +
File.readlines(Config.lookup("commands::papiez::adjectives")).sample
}
Client.register_command("papiez") { |args|
Config[:commands][:papiez][:noun] + " " +
File.readlines(Config[:commands][:papiez][:adjectives]).sample
Config.lookup("commands::papiez::noun") + " " +
File.readlines(Config.lookup("commands::papiez::adjectives")).sample
}

View File

@ -2,6 +2,6 @@ require 'net/http'
require 'nokogiri'
Client.register_command("sjp") { |args|
doc = Nokogiri::HTML(Net::HTTP.get(URI(Config[:commands][:sjp][:url] + args[0])))
doc = Nokogiri::HTML(Net::HTTP.get(URI(Config.lookup("commands::sjp::url") + args[0])))
doc.xpath('//ul[@id="listahasel"]/li/div/div').inner_text
}

View File

@ -1,11 +1,15 @@
include EventMachine::IRC::Commands
Client.register_trigger("PRIVMSG") { |msg|
Client.register_trigger("PRIVMSG", "eval") { |msg|
message = msg[:params][1]
destination = msg[:params][0]
destination = if msg[:params][0] == Config.lookup("client::nick", "repost", msg[:scope]) then
msg[:prefix].split("!").first
else
msg[:params][0]
end
if message[0..5] == ":eval " then
if Config[:eval][:owners].include?(msg[:prefix]) then
if Config.lookup("eval::owners", [], msg[:scope]).include?(msg[:scope]["person"]) then
code = message[6..-1]
begin
retval = proc {
@ -19,7 +23,7 @@ Client.register_trigger("PRIVMSG") { |msg|
puts e.backtrace
end
else
Client.privmsg(destination, Config[:eval][:denied])
Client.privmsg(destination, Config.lookup("commands::eval::denied", "go away!", msg[:scope]))
end
end
}

5
plugins/invite.rb Normal file
View File

@ -0,0 +1,5 @@
include EventMachine::IRC::Commands
Client.register_trigger("INVITE", "invite") { |msg|
Client.send_data "JOIN #{msg[:params][1]}"
}

View File

@ -1,7 +1,7 @@
include EventMachine::IRC::Commands
Client.register_trigger("PRIVMSG") { |msg|
Client.register_trigger("PRIVMSG", "mikrofalowka") { |msg|
nick = msg[:prefix].split('!').first
destination = msg[:params][0]
Client.privmsg(destination, "#{nick}: napraw mikrofalowke") if nick.match /[Bb].[Rr][Tt]/
Client.privmsg(destination, "#{nick}: napraw mikrofalowke") if nick.match(/[Bb].[Rr][Tt]/)
}

View File

@ -1,5 +1,7 @@
require 'pp'
include EventMachine::IRC::Commands
Client.register_trigger("PRIVMSG") { |msg|
p msg
Client.register_trigger("PRIVMSG", "pretty_print") { |msg|
puts Time.now.to_s + msg.pretty_inspect
}

View File

@ -2,17 +2,18 @@ require 'open-uri'
require 'digest/md5'
require 'data_mapper'
require 'nokogiri'
require 'dm-postgres-adapter'
include EventMachine::IRC::Commands
DataMapper.setup(:default, Config[:scrape][:db])
DataMapper.setup(:default, Config.lookup("plugins::scrape::db", "", nil))
module Scrape
def self.download(uri)
ext = "." + uri.sub(/.*[.]([^.]*)/, '\1') if uri.match(/[^.]+[.][^.]+/)
content = open(uri).read
md5 = Digest::MD5.hexdigest(content)
File.open(Config[:scrape][:basepath] + md5 + ext, 'w') do |file|
File.open(Config.lookup("plugins::scrape::basepath", "", nil) + md5 + ext, 'w') do |file|
file.write(content)
end
@ -32,7 +33,7 @@ end
DataMapper.auto_upgrade!
Client.register_trigger("PRIVMSG") do |msg|
Client.register_trigger("PRIVMSG", "scrape") do |msg|
titles = []
return 0 if msg[:params][1].nil?
msg[:params][1].split.each do |word|
@ -60,5 +61,5 @@ Client.register_trigger("PRIVMSG") do |msg|
end
end
Client.privmsg(msg[:params][0], Config[:scrape][:title_prefix] + titles.join(' ')) if not titles.count == 0
Client.privmsg(msg[:params][0], Config.lookup("plugins::scrape::title_prefix", "", msg[:scope]) + titles.join(' ')) if not titles.count == 0
end

View File

@ -1,10 +1,23 @@
class Repost < EventMachine::IRC::Client
attr_accessor :triggers
attr_accessor :triggers, :network
def dispatch_raw_message(message = {})
return if Config[:ignore].include?(message[:prefix])
message[:scope] = {
"network" => @network,
"target" => message[:params][0],
}
message[:scope]["person"] = if message[:prefix] then
message[:prefix].split("/").last
else
message[:prefix]
end
return if Config.lookup("ignore", [], message[:scope]).include? message[:prefix]
self.triggers.each do |trigger|
Config.lookup("plugins::disabled", [], message[:scope]).include? trigger[:name]
# Having per-command lists of blocks of code to call would be
# faster, but it's not a problem for now. Might refactor this loop
# and register_trigger() method if it comes to that.
@ -19,22 +32,18 @@ class Repost < EventMachine::IRC::Client
end
end
def register_trigger(command, &code)
def register_trigger(command, name, &code)
# Append a Hash containing the command it should be called at and the
# and the code.
self.triggers << {:command => command, :code => code}
self.triggers << {:command => command, :code => code, :name => name}
end
def load_plugins
def load_plugins(scope = { "network" => @network })
self.triggers = []
Config[:plugins].each do |plugin|
Config.lookup("plugins::list", [], scope).each do |plugin|
puts "Loading plugin #{plugin}"
load File.dirname($0) + '/plugins/' + plugin + '.rb'
end if not Config[:plugins].nil?
end
def load_config(file = "config.rb")
load File.dirname($0) + "/" + file
end
end
end

41
run.rb
View File

@ -5,24 +5,49 @@ require 'rubygems'
require 'eventmachine'
require 'em-irc'
require 'logger'
# Our config file is just a single Hash, nothing too fancy.
require_relative 'config'
require 'hiera'
require 'deep_merge'
require_relative 'repost'
hiera_configuration = {
backends: "yaml",
merge_behavior: "deeper",
yaml: {
datadir: File.join(File.dirname(__FILE__), "config"),
},
hierarchy: [
'%{network}/%{target}/%{person}',
'%{network}/%{person}',
'%{network}/%{target}',
'%{network}',
'common',
],
}
class ConfigSource < Hiera
def lookup key, default="", scope=nil, *stuff
super
end
end
Config = ConfigSource.new(config: hiera_configuration)
# Will have to change it to a normal EM loop if/when i'll want to make a usable
# local console for the bot.
Client = Repost.new do
host Config[:server][:host]
port Config[:server][:port]
scope = { "network" => "freenode" }
host Config.lookup("server::host", "", scope)
port Config.lookup("server::port", "", scope)
on :connect do
puts "connected! changing nick to #{Config[:client][:nick]}"
nick Config[:client][:nick]
puts "connected! changing nick to #{Config.lookup("client::nick")}"
nick Config.lookup("client::nick")
end
on :nick do
Config[:client][:channels].each do |channel|
Config.lookup("channels", [], scope).each do |channel|
puts "joining #{channel}"
join channel
end
@ -42,4 +67,6 @@ end
# to do anything.
Client.load_plugins
Client.network = "freenode"
Client.run!