zetabot 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +281 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +41 -0
  7. data/Rakefile +6 -0
  8. data/Zeta.gemspec +74 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +13 -0
  11. data/bin/zeta +9 -0
  12. data/bin/zeta-setup +13 -0
  13. data/lib/Zeta.rb +13 -0
  14. data/lib/Zeta/access.rb +84 -0
  15. data/lib/Zeta/admin.rb +10 -0
  16. data/lib/Zeta/admin/autojoin.rb +25 -0
  17. data/lib/Zeta/admin/bot.rb +43 -0
  18. data/lib/Zeta/admin/channels.rb +36 -0
  19. data/lib/Zeta/admin/eval.rb +43 -0
  20. data/lib/Zeta/admin/fifo.rb +45 -0
  21. data/lib/Zeta/admin/ignore.rb +112 -0
  22. data/lib/Zeta/admin/oper.rb +50 -0
  23. data/lib/Zeta/admin/plugins.rb +109 -0
  24. data/lib/Zeta/admin/users.rb +5 -0
  25. data/lib/Zeta/blacklist.rb +25 -0
  26. data/lib/Zeta/cache.rb +0 -0
  27. data/lib/Zeta/cinch.rb +35 -0
  28. data/lib/Zeta/config.rb +42 -0
  29. data/lib/Zeta/gems.rb +0 -0
  30. data/lib/Zeta/locale.rb +4 -0
  31. data/lib/Zeta/log.rb +2 -0
  32. data/lib/Zeta/models.rb +5 -0
  33. data/lib/Zeta/models/channel.rb +3 -0
  34. data/lib/Zeta/models/plugin.rb +3 -0
  35. data/lib/Zeta/models/user.rb +3 -0
  36. data/lib/Zeta/plugins.rb +27 -0
  37. data/lib/Zeta/plugins/attack.rb +61 -0
  38. data/lib/Zeta/plugins/botinfo.rb +83 -0
  39. data/lib/Zeta/plugins/darkscience.rb +215 -0
  40. data/lib/Zeta/plugins/dbz.rb +31 -0
  41. data/lib/Zeta/plugins/dcc.rb +25 -0
  42. data/lib/Zeta/plugins/dnsbl.rb +36 -0
  43. data/lib/Zeta/plugins/echo.rb +15 -0
  44. data/lib/Zeta/plugins/eightball.rb +53 -0
  45. data/lib/Zeta/plugins/fml.rb +35 -0
  46. data/lib/Zeta/plugins/fnord.rb +329 -0
  47. data/lib/Zeta/plugins/gem.rb +0 -0
  48. data/lib/Zeta/plugins/gif.rb +73 -0
  49. data/lib/Zeta/plugins/help.rb +32 -0
  50. data/lib/Zeta/plugins/libsecure.rb +34 -0
  51. data/lib/Zeta/plugins/macros.rb +124 -0
  52. data/lib/Zeta/plugins/movie.rb +67 -0
  53. data/lib/Zeta/plugins/pdfinfo.rb +69 -0
  54. data/lib/Zeta/plugins/rainbow.rb +65 -0
  55. data/lib/Zeta/plugins/russian_roulette.rb +90 -0
  56. data/lib/Zeta/plugins/seen.rb +77 -0
  57. data/lib/Zeta/plugins/silly.rb +183 -0
  58. data/lib/Zeta/plugins/snooper.rb +146 -0
  59. data/lib/Zeta/plugins/urban.rb +60 -0
  60. data/lib/Zeta/plugins/weather.rb +203 -0
  61. data/lib/Zeta/plugins/whois.rb +25 -0
  62. data/lib/Zeta/plugins/wiki.rb +75 -0
  63. data/lib/Zeta/plugins/wolfram.rb +46 -0
  64. data/lib/Zeta/tasks/db.rb +0 -0
  65. data/lib/Zeta/version.rb +3 -0
  66. data/lib/generators/config/config.rb +0 -0
  67. data/lib/generators/plugin/new_plugin.rb +0 -0
  68. data/locale/en/8ball.yml +0 -0
  69. data/locale/en/attack.yml +148 -0
  70. data/locale/en/dbz.yml +10 -0
  71. data/locale/en/ircop.yml +5 -0
  72. data/locale/en/macros.yml +98 -0
  73. data/locale/en/meme.yml +27 -0
  74. metadata +636 -0
File without changes
@@ -0,0 +1,73 @@
1
+ require 'open-uri'
2
+ require 'nokogiri'
3
+ require 'json'
4
+
5
+ module Plugins
6
+ class Gif
7
+ include Cinch::Plugin
8
+ include Cinch::Helpers
9
+ enable_acl
10
+
11
+ # Author: blahed (https://github.com/blahed/gifbot)
12
+ self.plugin_name = 'GIF'
13
+ self.help = '?randomgif | ?rgif | ?gifme <query>'
14
+
15
+ def initialize(*args)
16
+ super
17
+ @imgurray = []
18
+ @last_update = Time
19
+ end
20
+
21
+ match 'randomgif', method: :imgif
22
+ match 'rgif', method: :imgif
23
+ match 'imgif', method: :imgif
24
+ def imgif(msg)
25
+ msg.reply "IMGUR↦ #{imgur}"
26
+ end
27
+
28
+ match /gifme (.+)/, method: :gifme
29
+ def gifme(msg,query)
30
+ msg.reply "GB↦ #{search(query)}"
31
+ end
32
+
33
+ private
34
+
35
+ def search(query)
36
+ url = URI.encode "http://www.gifbin.com/search/#{query}/"
37
+ doc = Nokogiri::HTML( open(url) )
38
+ e = doc.css('.thumbs li').length
39
+ return "No Results Found" if e == 0
40
+ result = doc.css('.thumbs li')[rand(e)].css('a img').attribute('src').text.gsub(/tn_/, '')
41
+ "http://www.gifbin.com#{result}"
42
+ end
43
+
44
+ def gifbin
45
+ url = URI.encode 'http://www.gifbin.com/random'
46
+ doc = Nokogiri.HTML(open url)
47
+ doc.css('div#gifcontainer a img').attribute('src').text
48
+ end
49
+
50
+ def imgur
51
+ # Cache results for 1 hour
52
+ if @imgurray.empty? || @last_update >= (Time.now + 3600)
53
+ url = URI.encode('http://reddit.com/r/gifs.json')
54
+ doc = JSON.load(open(url))
55
+
56
+ doc['data']['children'].each_with_index do |post, index|
57
+ if doc['data']['children'][index]['data']['url'].to_s =~ /imgur/
58
+ @imgurray << doc['data']['children'][index]['data']['url'].to_s
59
+ end
60
+ end
61
+ @last_update = Time.now
62
+ @imgurray.sample
63
+ else
64
+ @imgurray.sample
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
71
+
72
+ # AutoLoad
73
+ Bot.config.plugins.plugins.push Plugins::Gif
@@ -0,0 +1,32 @@
1
+ module Plugins
2
+ class BotHelp
3
+ include Cinch::Plugin
4
+ include Cinch::Helpers
5
+ enable_acl
6
+
7
+ set(
8
+ plugin_name: "BotHelp",
9
+ help: "Need help?.\nUsage: `?help`\nUsage: `?help [plugin]` `?help plugins`",
10
+ )
11
+ match /help (.+)$/i, method: :execute_help
12
+
13
+ def execute_help(m, name)
14
+ list = {}
15
+ @bot.plugins.each { |p| list[p.class.plugin_name.downcase] = {name: p.class.plugin_name, help: p.class.help} };
16
+ return m.user.notice("Help for \"#{name}\" could not be found.") unless list.has_key?(name.downcase)
17
+ m.user.notice("Help for #{Format(:bold, list[name.downcase][:name])}:\n#{list[name.downcase][:help]}")
18
+ end
19
+
20
+ match 'help', method: :execute_list
21
+ def execute_list(m)
22
+
23
+ list = []
24
+ @bot.plugins.each {|p| list << p.class.plugin_name };
25
+ m.user.notice("All #{list.size} currently loaded plugins for #{@bot.nick}:\n#{list.to_sentence}.\nTo view help for a plugin, use `!help <plugin name>`.")
26
+ end
27
+ end
28
+ end
29
+
30
+
31
+ # AutoLoad
32
+ Bot.config.plugins.plugins.push Plugins::BotHelp
@@ -0,0 +1,34 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'ostruct'
4
+ require 'discourse_api'
5
+ require 'action_view'
6
+
7
+ module Plugins
8
+ class Libsecure
9
+ include Cinch::Plugin
10
+ include Cinch::Helpers
11
+ include ActionView::Helpers::DateHelper
12
+
13
+ enable_acl(:nobody)
14
+
15
+ self.plugin_name = 'DarkScience #libsecure'
16
+ self.help = '?latest'
17
+
18
+ match 'latest', method: :fetch_latest
19
+
20
+ def fetch_latest(m)
21
+ return unless m.channel == '#libsecure' || m.channel == '#bots'
22
+
23
+ client = DiscourseApi::Client.new('https://libsecure.so', Config.secrets[:libsecure], Config.secrets[:libsecure_user] )
24
+ parser = client.latest_topics.sort_by { |hash| hash['last_posted_at'] }
25
+ data = parser.last
26
+
27
+ m.reply "Latest → #{data['title']} -- https://libsecure.so/t/#{data['id']}"
28
+ end
29
+
30
+ end
31
+ end
32
+
33
+ # AutoLoad
34
+ Bot.config.plugins.plugins.push Plugins::Libsecure
@@ -0,0 +1,124 @@
1
+ # coding: utf-8
2
+ require 'yaml'
3
+
4
+ module Plugins
5
+ class Macros
6
+ include Cinch::Plugin
7
+ include Cinch::Helpers
8
+
9
+ enable_acl(:nobody, false)
10
+
11
+ attr_reader :macros
12
+
13
+ set plugin_name: "Macros", help: "Macro's are prefixed by a <dot> example .dnf",
14
+ react_on: :channel
15
+
16
+ def initialize *args
17
+ super
18
+ # @macros = YAML::load_file($root_path + '/locales/macros.yml')
19
+ @macros = load_locale 'macros'
20
+ end
21
+
22
+ match /reload/, method: :execute_reloadmacros, react_on: :private
23
+ def execute_reloadmacros m
24
+ return unless check_user(m, :admin)
25
+ # return unless check_channel(m)
26
+ begin
27
+ # @macros = YAML::load_file($root_path + '/locales/macros.yml')
28
+ @macros = load_locale 'macros'
29
+ m.user.notice "Macros have been reloaded."
30
+ rescue
31
+ m.user.notice "Reloading macros has failed: #{$!}"
32
+ end
33
+ end
34
+
35
+ match /m (\w+)(?: (.+))?/, method: :execute_macro, group: :macro
36
+ def execute_macro m, macro, arguments
37
+ return unless @macros.has_key?(macro)
38
+ parse(arguments.to_s.rstrip, @macros[macro], m.channel, m.user)
39
+
40
+
41
+ # Guide to writing macros:
42
+ # - A macro can be a string, hash, or array
43
+ # - They can be embedded within each other (as lines, etc.)
44
+ # To have options for a macro (either globally or within embedded macros:)
45
+ # => macroname:
46
+ # => type: (string) ['random'] (optional)
47
+ # => sent_as: (string) ['reply','action'] (optional)
48
+ # => sleep: (numeric) a number that represents how many seconds the bot will wait for each line
49
+ # => lines: (array, string, hash) an object that represents the individual lines.
50
+
51
+ # Guide to writing macros v3 templates:
52
+ # transform/(default text)[template]
53
+ # transform/ (optional):
54
+ # cap (all uppercase)
55
+ # lc (all lowercase)
56
+ # (default text) (optional):
57
+ # Can be anything that you want. May want to watch usage of brackets &c.
58
+ # [template] (required):
59
+ # Can be one of these tags:
60
+ # * in (input/argument, will default to the default text if available, otherwise it will choose a random nick.)
61
+ # * channel (the current channel that the command is run in.)
62
+ # * bot (The bot's nick)
63
+ # * self (the originating user's nick)
64
+ end
65
+
66
+ private
67
+
68
+ # @param [String,NilClass] input The arguments for the command.
69
+ # @param [String,Hash,Array] macro The macro object.
70
+ # @param [Channel] channel The target channel.
71
+ # @param [Users] user The user that activated the macro.
72
+ # @param [Hash] params The (optional) parameters for controlling the macro as set in the external resource.
73
+ # @option params [String,NilClass] 'type' The type of output. Can be either nil, or "random"
74
+ # @option params [String] 'sent_as' The method of sending the line. Can be either 'reply' or 'action'
75
+ # @option params [Numeric,NilClass] 'sleep' How long does the bot wait to send the line?
76
+ def parse(input, macro, channel, user, params={})
77
+ params = { 'type' => nil, 'sent_as' => 'reply', 'sleep' => nil }.merge params
78
+
79
+ if macro.respond_to? :has_key?
80
+ lines = macro['lines']
81
+ params = params.merge macro.reject {|k,_| k.eql? 'lines' }
82
+ lines = lines.sample if params['type'].eql?('random') && lines.respond_to?(:each)
83
+ parse(input, lines, channel, user, params)
84
+ elsif macro.respond_to? :each
85
+ macro.each {|line| parse(input, line, channel, user, params) }
86
+ else
87
+ sleep params['sleep'] if params['sleep']
88
+ case params['sent_as']
89
+ when 'action' then channel.action replace_tokens(input, macro.to_s, channel, user)
90
+ else
91
+ channel.send replace_tokens(input, macro.to_s, channel, user)
92
+ end
93
+ end
94
+ end
95
+
96
+ # @see #parse (sans params)
97
+ def replace_tokens(input, macro, channel, user)
98
+ tokens = macro.scan(/((?:(\w+)\/)?(?:\((.+?)\))?(?:\[(\w+)\]))/)
99
+ tokens.each_with_object(macro.dup) {|(token,transform,default,template), memo|
100
+ result = case template
101
+ when 'in' then input || default || channel.users.keys.sample.nick
102
+ when 'bot' then @bot.nick
103
+ when 'channel' then channel.name
104
+ when 'self' then user.nick
105
+ else token
106
+ end
107
+
108
+ result = case transform
109
+ when 'cap' then result.upcase
110
+ when 'lc' then result.downcase
111
+ else result
112
+ end
113
+
114
+ memo.sub!(token, result)
115
+ }
116
+ end
117
+
118
+
119
+ end
120
+ end
121
+
122
+
123
+ # AutoLoad
124
+ Bot.config.plugins.plugins.push Plugins::Macros
@@ -0,0 +1,67 @@
1
+ module Plugins
2
+ class Movie
3
+ include Cinch::Plugin
4
+ include Cinch::Helpers
5
+
6
+ enable_acl
7
+
8
+ set(
9
+ plugin_name: 'Movie',
10
+ help: 'Movie Plots \nUsage: `?movie <name of movie>`;',
11
+ react_on: :channel
12
+ )
13
+
14
+ match /movie (.*)/, method: :find_movie
15
+ def find_movie(m, movie)
16
+ data = query_movie(movie)
17
+ if data && data.response == 'True'
18
+ m.reply "Movie ⊥ #{data.title} (#{data.year}) <#{data.rated}> #{data.plot.to_s.strip[0..800]} [www.imdb.com/title/#{data.imdbid}/]"
19
+ elsif data && data.response == 'False'
20
+ m.reply data.error
21
+ else
22
+ m.reply 'Unable to find movie!'
23
+ end
24
+ end
25
+
26
+ private
27
+ def query_movie(m)
28
+ year = m[/:\d+/].gsub(/:/, '') if m[/:\d+/]
29
+ movie = URI.encode(m.gsub(/:\d+/, ''))
30
+ data = JSON.parse(
31
+ # RestClient.get("http://www.omdbapi.com/?t=#{movie}&y=#{year}")
32
+ open("http://www.omdbapi.com/?t=#{movie}&y=#{year}").read
33
+ )
34
+ OpenStruct.new(
35
+ title: data['Title'],
36
+ year: data['Year'],
37
+ rated: data['Rated'],
38
+ released: data['Released'],
39
+ runtime: data['Runtime'],
40
+ genre: data['Genre'],
41
+ director: data['Director'],
42
+ writer: data['Writer'],
43
+ actors: data['Actors'],
44
+ plot: data['Plot'],
45
+ language: data['Language'],
46
+ country: data['Country'],
47
+ awards: data['Awards'],
48
+ poster: data['Poster'],
49
+ metascore: data['Metascore'],
50
+ imdbrating: data['imdbRating'],
51
+ imdbvotes: data['imdbVotes'],
52
+ imdbid: data['imdbID'],
53
+ type: data['Type'],
54
+ response: data['Response'],
55
+ error: data['Error']
56
+ )
57
+ rescue
58
+ nil
59
+ end
60
+
61
+
62
+ end
63
+ end
64
+
65
+
66
+ # AutoLoad
67
+ Bot.config.plugins.plugins.push Plugins::Movie
@@ -0,0 +1,69 @@
1
+ require 'faraday'
2
+ require 'open-uri'
3
+ require 'action_view'
4
+ require 'pdf-reader'
5
+ require 'humanize-bytes'
6
+
7
+ module Plugins
8
+ class PDFinfo
9
+ include Cinch::Plugin
10
+ include Cinch::Helpers
11
+ include ActionView::Helpers::DateHelper
12
+
13
+ enable_acl(:nobody, false)
14
+
15
+ self.plugin_name = 'PDF Information'
16
+ self.help = 'This plugin will check a url for a pdf link and fetch metadata from it'
17
+
18
+
19
+ # Default list of URL regexps to ignore.
20
+ DEFAULT_ALLOWED = [/\.pdf$/i].freeze
21
+ FILE_SIZE_LIMIT = 4000000
22
+
23
+
24
+ match %r{(https?://.*?)(?:\s|$|,|\.\s|\.$)}, :use_prefix => false
25
+
26
+ def execute(msg, url)
27
+
28
+ allowedlist = DEFAULT_ALLOWED.dup
29
+ allowedlist.concat(config[:blacklist]) if config[:blacklist]
30
+
31
+ return unless allowedlist.any? { |entry| url =~ entry }
32
+ debug "URL matched: #{url}"
33
+
34
+ # Grab header and check filesize
35
+ # one line to make request
36
+ head = Faraday.head url
37
+
38
+ # example with headers
39
+ file_size = head.headers['Content-Length']
40
+ humanize_size = Humanize::Byte.new(file_size.to_i).to_k.to_s.to_i.round(2)
41
+ if file_size.to_i > FILE_SIZE_LIMIT
42
+ return msg.reply("PDF → Unable to parse. file too big #{humanize_size}kb")
43
+ end
44
+
45
+
46
+ # Get file and parse metadata
47
+ open(url, "rb") do |io|
48
+ reader = PDF::Reader.new(io)
49
+ creator = reader.info[:Creator] || 'Anon'
50
+ producer = reader.info[:Producer] || 'Anon'
51
+ creation = reader.info[:CreationDate] || 'now'
52
+ modification = reader.info[:ModDate] || 'now'
53
+ title = reader.info[:Title] || nil
54
+ display = title ? title : "Title: None <> Creator: #{creator} <> Producer: #{producer} <> Creation: #{creation}"
55
+ msg.reply "PDF (#{humanize_size}kb) → #{display}"
56
+ end
57
+
58
+
59
+ rescue => e
60
+ error "#{e.class.name}: #{e.message}"
61
+ end
62
+
63
+
64
+ end
65
+
66
+ end
67
+
68
+ # AutoLoad
69
+ Bot.config.plugins.plugins.push Plugins::PDFinfo
@@ -0,0 +1,65 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class String # moved from lib\obj_ext\string.rb
4
+ def irc_colorize
5
+ self.gsub(/!\[(.*?)\]/) { $1.tr('boruic', 2.chr + 15.chr + 18.chr + 31.chr + 29.chr + 3.chr) }
6
+ #Note to self, tr and gsub is your friend!
7
+ #Thanks to j416 on #ruby@freenode!
8
+ end
9
+ end
10
+
11
+
12
+ module Plugins
13
+ class Rainbow
14
+ include Cinch::Plugin
15
+ include Cinch::Helpers
16
+ enable_acl
17
+
18
+ set plugin_name: "Rainbow", help: "Rainbowificates your text.\nUsage: `?rainbow [text]`.\nUsage: `?eyerape [text]`.", suffix: /$/
19
+
20
+ def rainbowification(s)
21
+ s.gsub(/\x03([0-9]{2}(,[0-9]{2})?)?/, "") # Because total function abuse.
22
+ colour = %w{04 07 08 09 10 06 13}
23
+ i = Random.new.rand(0..colour.size-1);
24
+ new_string = ""
25
+ s.each_char { |c|
26
+ new_string << "\x03#{colour[i]}#{c}";
27
+ i = i < colour.size-1 ? i.next : 0;
28
+ }
29
+ new_string
30
+ end
31
+
32
+ def eyerapeification(s)
33
+ sd = s.dup
34
+ sd.gsub(/\x03([0-9]{2}(,[0-9]{2})?)?/, "") # Because total function abuse.
35
+ colour = %w{04 07 08 09 10 06 13}
36
+ offset = Random.new.rand(0..colour.size-1)
37
+ sd = "\x02" + sd.upcase.split(" ").map { |c|
38
+ offset = (offset < colour.size-1 ? offset.next : 0)
39
+ "\x03#{colour[offset]},#{colour[offset-4]}#{c.each_char.each_with_index.map { |char, index| index % 2 == 0 ? char : char.downcase }.join}"
40
+ }.join(" ")
41
+ #sd
42
+ end
43
+
44
+ match /rainbow (.+)/, method: :execute_rainbow
45
+
46
+ def execute_rainbow(m, string)
47
+ m.reply(rainbowification(string), false)
48
+ end
49
+
50
+
51
+
52
+ match /eyerape (.+)/, method: :execute_eyerape
53
+
54
+ def execute_eyerape(m, string)
55
+ m.reply(eyerapeification(string), false)
56
+ end
57
+
58
+
59
+ end
60
+ end
61
+
62
+ # AutoLoad
63
+ Bot.config.plugins.plugins.push Plugins::Rainbow
64
+
65
+