zetabot 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +281 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/Zeta.gemspec +74 -0
- data/bin/console +14 -0
- data/bin/setup +13 -0
- data/bin/zeta +9 -0
- data/bin/zeta-setup +13 -0
- data/lib/Zeta.rb +13 -0
- data/lib/Zeta/access.rb +84 -0
- data/lib/Zeta/admin.rb +10 -0
- data/lib/Zeta/admin/autojoin.rb +25 -0
- data/lib/Zeta/admin/bot.rb +43 -0
- data/lib/Zeta/admin/channels.rb +36 -0
- data/lib/Zeta/admin/eval.rb +43 -0
- data/lib/Zeta/admin/fifo.rb +45 -0
- data/lib/Zeta/admin/ignore.rb +112 -0
- data/lib/Zeta/admin/oper.rb +50 -0
- data/lib/Zeta/admin/plugins.rb +109 -0
- data/lib/Zeta/admin/users.rb +5 -0
- data/lib/Zeta/blacklist.rb +25 -0
- data/lib/Zeta/cache.rb +0 -0
- data/lib/Zeta/cinch.rb +35 -0
- data/lib/Zeta/config.rb +42 -0
- data/lib/Zeta/gems.rb +0 -0
- data/lib/Zeta/locale.rb +4 -0
- data/lib/Zeta/log.rb +2 -0
- data/lib/Zeta/models.rb +5 -0
- data/lib/Zeta/models/channel.rb +3 -0
- data/lib/Zeta/models/plugin.rb +3 -0
- data/lib/Zeta/models/user.rb +3 -0
- data/lib/Zeta/plugins.rb +27 -0
- data/lib/Zeta/plugins/attack.rb +61 -0
- data/lib/Zeta/plugins/botinfo.rb +83 -0
- data/lib/Zeta/plugins/darkscience.rb +215 -0
- data/lib/Zeta/plugins/dbz.rb +31 -0
- data/lib/Zeta/plugins/dcc.rb +25 -0
- data/lib/Zeta/plugins/dnsbl.rb +36 -0
- data/lib/Zeta/plugins/echo.rb +15 -0
- data/lib/Zeta/plugins/eightball.rb +53 -0
- data/lib/Zeta/plugins/fml.rb +35 -0
- data/lib/Zeta/plugins/fnord.rb +329 -0
- data/lib/Zeta/plugins/gem.rb +0 -0
- data/lib/Zeta/plugins/gif.rb +73 -0
- data/lib/Zeta/plugins/help.rb +32 -0
- data/lib/Zeta/plugins/libsecure.rb +34 -0
- data/lib/Zeta/plugins/macros.rb +124 -0
- data/lib/Zeta/plugins/movie.rb +67 -0
- data/lib/Zeta/plugins/pdfinfo.rb +69 -0
- data/lib/Zeta/plugins/rainbow.rb +65 -0
- data/lib/Zeta/plugins/russian_roulette.rb +90 -0
- data/lib/Zeta/plugins/seen.rb +77 -0
- data/lib/Zeta/plugins/silly.rb +183 -0
- data/lib/Zeta/plugins/snooper.rb +146 -0
- data/lib/Zeta/plugins/urban.rb +60 -0
- data/lib/Zeta/plugins/weather.rb +203 -0
- data/lib/Zeta/plugins/whois.rb +25 -0
- data/lib/Zeta/plugins/wiki.rb +75 -0
- data/lib/Zeta/plugins/wolfram.rb +46 -0
- data/lib/Zeta/tasks/db.rb +0 -0
- data/lib/Zeta/version.rb +3 -0
- data/lib/generators/config/config.rb +0 -0
- data/lib/generators/plugin/new_plugin.rb +0 -0
- data/locale/en/8ball.yml +0 -0
- data/locale/en/attack.yml +148 -0
- data/locale/en/dbz.yml +10 -0
- data/locale/en/ircop.yml +5 -0
- data/locale/en/macros.yml +98 -0
- data/locale/en/meme.yml +27 -0
- metadata +636 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
module Plugins
|
2
|
+
class RussianRoulette
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Helpers
|
5
|
+
enable_acl
|
6
|
+
|
7
|
+
set plugin_name: "Russian Roulette",
|
8
|
+
help: "In Soviet Russia, boolet shoots YOU!\nUsage: ?rr <nick>",
|
9
|
+
react_on: :channel
|
10
|
+
|
11
|
+
attr_reader :games
|
12
|
+
|
13
|
+
PHRASES = [
|
14
|
+
"\"BANG\" You're dead! ... Just kidding comrade... for now.",
|
15
|
+
"\"...BLAMMO!\" (hangfires are a bitch, aren't they?)",
|
16
|
+
"Are you scared yet, comrade?",
|
17
|
+
"Are you pissing your pants yet?",
|
18
|
+
"You are lucky, comrade. At least for now.",
|
19
|
+
"The chamber was as empty as your head.",
|
20
|
+
"Damn. And I thought that it had bullet too.",
|
21
|
+
"Lucky you, comrade.",
|
22
|
+
"Must be your lucky day, comrade.",
|
23
|
+
"\"BLAM!\" you can't play russian roulette with a tokarev, comrade.",
|
24
|
+
"... Looks like you get to live another day... or 5 second.",
|
25
|
+
"... Bad primer."
|
26
|
+
]
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
@games = []
|
31
|
+
end
|
32
|
+
|
33
|
+
match /rr(?: (.+))?/, method: :russian
|
34
|
+
|
35
|
+
def russian(m, nick)
|
36
|
+
#return m.reply "I am sorry comrade, but I do not have pistol on me." unless check_user(m.channel, @bot)
|
37
|
+
return m.user.notice "Sorry comrade, but there is already game going on." if @games.include?(m.channel.name)
|
38
|
+
|
39
|
+
# player setup
|
40
|
+
player = User(nick) || m.user
|
41
|
+
player = m.user if player == @bot
|
42
|
+
# be nice, don't force the game on the starter unless the user actually exists in the channel.
|
43
|
+
return m.reply "I am terribly sorry %s, but I don't know %s." % [m.user.nick, player.nick] unless m.channel.users.include?(player)
|
44
|
+
|
45
|
+
# start game
|
46
|
+
@games << m.channel.name
|
47
|
+
|
48
|
+
turns, round_location = Array.new(2) { |i| Random.new.rand(1..6) }
|
49
|
+
m.channel.action "starts a %d-turn game of Russian Roulette with %s." % [turns, player.nick]
|
50
|
+
|
51
|
+
phrases = PHRASES.dup.shuffle
|
52
|
+
|
53
|
+
sleep 5
|
54
|
+
|
55
|
+
turns.times do |chamber|
|
56
|
+
return end_game(m.channel, true) unless m.channel.users.include?(player)
|
57
|
+
if round_location == chamber.succ
|
58
|
+
m.reply "*click*"
|
59
|
+
sleep 5
|
60
|
+
m.channel.kick(player, "*BLAM*")
|
61
|
+
m.reply "*BLAM*"
|
62
|
+
m.channel.action "watches %s's brain splatter across the wall." % player.nick
|
63
|
+
break
|
64
|
+
else
|
65
|
+
phrase = phrases.pop
|
66
|
+
m.reply "*click* %s" % phrase
|
67
|
+
end
|
68
|
+
sleep 5
|
69
|
+
end
|
70
|
+
|
71
|
+
m.reply "Looks like you get to live another day." if turns < round_location
|
72
|
+
sleep 1 if turns < round_location
|
73
|
+
end_game(m.channel)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def end_game(channel, premature=false)
|
79
|
+
@games.delete channel.name
|
80
|
+
channel.msg "Oh vell, it vas fun vhile it lasted." if premature
|
81
|
+
sleep 1
|
82
|
+
channel.action "holsters the pistol."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
# AutoLoad
|
89
|
+
Bot.config.plugins.plugins.push Plugins::RussianRoulette
|
90
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'action_view'
|
2
|
+
module Plugins
|
3
|
+
class Seen
|
4
|
+
class SeenStruct < Struct.new(:who, :where, :what, :time)
|
5
|
+
include ActionView::Helpers::DateHelper
|
6
|
+
def to_s
|
7
|
+
# "[#{time.asctime}] #{who} was seen in #{where} last saying #{what}"
|
8
|
+
time_ago = time_ago_in_words(Time.at(time))
|
9
|
+
"[ \x1F#{where.to_s.upcase}\x0F ] \x0304#{who}\x0F: \"\x0303#{what[0..300]}\x0F\" \x02#{time_ago}\x0F ago"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
include Cinch::Plugin
|
14
|
+
include Cinch::Helpers
|
15
|
+
|
16
|
+
enable_acl(:nobody)
|
17
|
+
|
18
|
+
listen_to :channel
|
19
|
+
match /seen (.+)/
|
20
|
+
match /sync/, method: :sync
|
21
|
+
|
22
|
+
def initialize(*args)
|
23
|
+
super
|
24
|
+
@users = load_seen
|
25
|
+
end
|
26
|
+
|
27
|
+
def finalize
|
28
|
+
save_seen()
|
29
|
+
end
|
30
|
+
|
31
|
+
def listen(m)
|
32
|
+
@users[m.user.nick] = SeenStruct.new(m.user, m.channel, m.message, Time.now)
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute(m, nick)
|
36
|
+
nick.rstrip!
|
37
|
+
if nick == @bot.nick
|
38
|
+
m.reply 'You are a Stupid human!'
|
39
|
+
elsif nick == m.user.nick
|
40
|
+
m.reply "Unfortunately, I see an idiot by the name of #{m.user.nick}"
|
41
|
+
elsif @users.key?(nick)
|
42
|
+
m.reply @users[nick].to_s
|
43
|
+
else
|
44
|
+
m.reply "I haven't seen #{nick}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sync(m)
|
49
|
+
save_seen()
|
50
|
+
end
|
51
|
+
|
52
|
+
def save_seen
|
53
|
+
File.open(File.join(Dir.home, '.zeta', 'cache', 'seen.rb'), 'w+') do |file|
|
54
|
+
Marshal.dump(@users, file)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
def load_seen
|
60
|
+
if File.exists?(File.join(Dir.home, '.zeta', 'cache', 'seen.rb'))
|
61
|
+
File.open(File.join(Dir.home, '.zeta', 'cache', 'seen.rb')) do |file|
|
62
|
+
return Marshal.load(file)
|
63
|
+
end
|
64
|
+
else
|
65
|
+
return Hash.new
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def clear_seen
|
70
|
+
@users = {}
|
71
|
+
File.delete(File.join(Dir.home, '.zeta', 'cache', 'seen.rb'))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# AutoLoad
|
77
|
+
Bot.config.plugins.plugins.push Plugins::Seen
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/time'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
require 'active_support/core_ext/object/blank'
|
6
|
+
require 'chronic_duration'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
|
10
|
+
module Plugins
|
11
|
+
class Silly
|
12
|
+
include Cinch::Plugin
|
13
|
+
include Cinch::Helpers
|
14
|
+
enable_acl
|
15
|
+
|
16
|
+
set(
|
17
|
+
plugin_name: "Silly",
|
18
|
+
help: "You know, silly stuff.",
|
19
|
+
)
|
20
|
+
|
21
|
+
_seconds_in_a_day = 86400
|
22
|
+
|
23
|
+
attr_reader :pokers
|
24
|
+
|
25
|
+
def initialize *args
|
26
|
+
super
|
27
|
+
@pokers = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
match /^pokes (.+)$/, react_on: :action, method: :listen_poke, use_prefix: false
|
31
|
+
|
32
|
+
def listen_poke(m, thebot)
|
33
|
+
|
34
|
+
if User(thebot) == @bot
|
35
|
+
@pokers[m.user] = 0 if !@pokers.include?(m.user)
|
36
|
+
@pokers[m.user] += 1
|
37
|
+
case @pokers[m.user]
|
38
|
+
when 1..3
|
39
|
+
m.reply "Do NOT poke the bot!"
|
40
|
+
when 4
|
41
|
+
m.reply "I said, do NOT poke the bot!"
|
42
|
+
when 5
|
43
|
+
msg = ["WHAT ARE YOU, AN IDIOT? I SAID DO NOT POKE ME!!", "THIS! IS! SPARTA!!"].sample
|
44
|
+
m.channel.kick m.user, ["WHAT ARE YOU, AN IDIOT? I SAID DO NOT POKE ME!!", "THIS! IS! SPARTA!!"].sample
|
45
|
+
@pokers.delete(m.user)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
match /\b(dumb|stupid)\b.+\bbots*\b/i, method: :execute_botinsult, use_prefix: false
|
51
|
+
|
52
|
+
def execute_botinsult(m)
|
53
|
+
|
54
|
+
m.reply ["Stupid human!", "Dumb human!", "Stupid meatbag.", "Silly human, your insults cannot harm me!", "get rekt", "u fkn w0t m8"].sample
|
55
|
+
end
|
56
|
+
|
57
|
+
def tzparser(tz)
|
58
|
+
prefix = (tz[0] !~ /(\+|-)/ ? "+" : "")
|
59
|
+
suffix = (tz =~ /^(?:\+|-)?(\d{1,2})$/ ? ":00" : "")
|
60
|
+
regexp = /^(\+|-)?(\d{1,2})(?::(\d{1,2}))?$/
|
61
|
+
if tz =~ regexp
|
62
|
+
prefix + tz.gsub(regexp) { |match| (!!$1 ? $1 : "") + $2.rjust(2, "0") + (!!$3 ? ":"+$3.rjust(2, "0") : "") } + suffix
|
63
|
+
else
|
64
|
+
raise ArgumentError, "A valid timezone was not supplied."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
match "halloween", method: :halloween
|
69
|
+
match "halloweve", method: :halloween
|
70
|
+
match /halloween (\S+)/, method: :halloween
|
71
|
+
|
72
|
+
def halloween(m, tz = nil)
|
73
|
+
tz ||= "-00:00"
|
74
|
+
tz = tzparser(tz)
|
75
|
+
begin
|
76
|
+
today = Time.now.localtime(tz)
|
77
|
+
hw = Time.new(today.year, 10, 31, 0, 0, 0, tz)
|
78
|
+
hw = hw.next_year if hw.to_date.past?
|
79
|
+
message = if hw.to_date == today.to_date
|
80
|
+
"THIS IS HALLOWEEN!"
|
81
|
+
else
|
82
|
+
"There's #{ChronicDuration.output(hw.to_i - today.to_i, format: :long)} until Hallow's Eve!"
|
83
|
+
end
|
84
|
+
rescue ArgumentError => ae
|
85
|
+
message = ae.message
|
86
|
+
ensure
|
87
|
+
m.reply message, true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
match "xmas", method: :xmas
|
92
|
+
match /xmas (\S+)/, method: :xmas
|
93
|
+
|
94
|
+
def xmas(m, tz = nil)
|
95
|
+
tz ||= "-00:00"
|
96
|
+
tz = tzparser(tz)
|
97
|
+
begin
|
98
|
+
today = Time.now.localtime(tz)
|
99
|
+
xmas = Time.new(today.year, 12, 25, 0, 0, 0, tz)
|
100
|
+
xmas = xmas.next_year if xmas.to_date.past?
|
101
|
+
message = if xmas.to_date == today.to_date
|
102
|
+
"Merry Christmas!"
|
103
|
+
else
|
104
|
+
"There's #{ChronicDuration.output(xmas.to_i - today.to_i, format: :long)} until Christmas!"
|
105
|
+
end
|
106
|
+
rescue ArgumentError => ae
|
107
|
+
message = ae.message
|
108
|
+
ensure
|
109
|
+
m.reply message, true
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
match "newyear", method: :newyear
|
114
|
+
match /newyear (\S+)/, method: :newyear
|
115
|
+
|
116
|
+
def newyear(m, tz = nil)
|
117
|
+
tz ||= "-00:00"
|
118
|
+
tz = tzparser(tz)
|
119
|
+
begin
|
120
|
+
today = Time.now.localtime(tz)
|
121
|
+
nyear = Time.new(today.year.succ, 1, 1, 0, 0, 0, tz)
|
122
|
+
#nyear = nyear.next_year if nyear.to_date.past?
|
123
|
+
message = if nyear.to_date == today.to_date
|
124
|
+
"Happy New Year #{today.year}!"
|
125
|
+
else
|
126
|
+
"There's #{ChronicDuration.output(nyear.to_i - today.to_i, format: :long)} until #{nyear.year}!"
|
127
|
+
end
|
128
|
+
rescue ArgumentError => ae
|
129
|
+
message = ae.message
|
130
|
+
ensure
|
131
|
+
m.reply message, true
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
match "tz", method: :tz
|
136
|
+
match /tz (\S+)/, method: :tz
|
137
|
+
|
138
|
+
def tz(m, tz = nil)
|
139
|
+
tz ||= "-00:00"
|
140
|
+
tz = tzparser(tz)
|
141
|
+
begin
|
142
|
+
today = Time.now.localtime(tz)
|
143
|
+
message = today.to_s
|
144
|
+
rescue ArgumentError => ae
|
145
|
+
message = ae.message
|
146
|
+
ensure
|
147
|
+
m.reply message, true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
match "mayan", method: :mayan
|
152
|
+
|
153
|
+
def mayan(m)
|
154
|
+
msd = (Date.today.jd - Date.new(1, 1, 1).jd) + 1137142
|
155
|
+
lc = {
|
156
|
+
baktun: (msd - (msd % 144000)) / 144000,
|
157
|
+
katun: ((msd - (msd % 7200)) / 7200) % 20,
|
158
|
+
tun: ((msd - (msd % 360)) / 360) % 20,
|
159
|
+
uinal: ((msd - (msd % 20)) / 20) % 18,
|
160
|
+
kin: (msd % 20)
|
161
|
+
}
|
162
|
+
|
163
|
+
m.reply '%<baktun>s.%<katun>s.%<tun>s.%<uinal>s.%<kin>s' % lc
|
164
|
+
end
|
165
|
+
|
166
|
+
match /heavymetalize (.+)/, method: :heavymetalize
|
167
|
+
|
168
|
+
def heavymetalize(m, s)
|
169
|
+
m.reply s.tr('AEIOUaeiouyYWwXx', 'ÄËÏÖÜäëïöüÿŸẄẅẌẍ')
|
170
|
+
end
|
171
|
+
|
172
|
+
match /\bfeature\b.+\brequest\b/i, method: :execute_userproblem, use_prefix: false
|
173
|
+
|
174
|
+
def execute_userproblem(m)
|
175
|
+
m.reply ["user error.", "working as intended", "Status: WONTFIX", "PEBKAC issue", "ID:10T Error"].sample
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
# AutoLoad
|
183
|
+
Bot.config.plugins.plugins.push Plugins::Silly
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# == Author
|
3
|
+
# Marvin Gülker (Quintus)
|
4
|
+
#
|
5
|
+
# == Modification author
|
6
|
+
# Liothen
|
7
|
+
#
|
8
|
+
# == License
|
9
|
+
# A named-pipe plugin for Cinch.
|
10
|
+
# Copyright © 2012 Marvin Gülker
|
11
|
+
#
|
12
|
+
# This program is free software: you can redistribute it and/or modify
|
13
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
14
|
+
# the Free Software Foundation, either version 3 of the License, or
|
15
|
+
# (at your option) any later version.
|
16
|
+
#
|
17
|
+
# This program is distributed in the hope that it will be useful,
|
18
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
19
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
20
|
+
# GNU Lesser General Public License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Lesser General Public License
|
23
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
|
25
|
+
# Plugin for inspecting links pasted into channels.
|
26
|
+
require 'video_info'
|
27
|
+
require 'mechanize'
|
28
|
+
require 'action_view'
|
29
|
+
|
30
|
+
module Plugins
|
31
|
+
class Snooper
|
32
|
+
include Cinch::Plugin
|
33
|
+
include Cinch::Helpers
|
34
|
+
include ActionView::Helpers::DateHelper
|
35
|
+
|
36
|
+
enable_acl(:nobody)
|
37
|
+
|
38
|
+
# Default list of URL regexps to ignore.
|
39
|
+
# DEFAULT_BLACKLIST = [/\.png$/i, /\.jpe?g$/i, /\.bmp$/i, /\.gif$/i, /\.pdf$/i].freeze
|
40
|
+
|
41
|
+
set :help, <<-HELP
|
42
|
+
http[s]://...
|
43
|
+
I’ll fire a GET request at any link I encounter, parse the HTML
|
44
|
+
meta tags, and paste the result back into the channel.
|
45
|
+
HELP
|
46
|
+
|
47
|
+
match %r{\b((https?:\/\/)?(([0-9a-zA-Z_!~*'().&=+$%-]+:)?[0-9a-zA-Z_!~*'().&=+$%-]+\@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+\.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z]\.[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/[0-9a-zA-Z_!~*'().;?:\@&=+$,%#-]+)*\/?))}i,
|
48
|
+
use_prefix: false,
|
49
|
+
react_on: :channel
|
50
|
+
|
51
|
+
def execute(msg, url)
|
52
|
+
url = "http://#{url}" unless url=~/^https?:\/\//
|
53
|
+
url = URI.encode(url)
|
54
|
+
|
55
|
+
# Ignore items on blacklist
|
56
|
+
# blacklist = DEFAULT_BLACKLIST.dup
|
57
|
+
# blacklist.concat(config[:blacklist]) if config[:blacklist]
|
58
|
+
# return if blacklist.any?{|entry| url =~ entry}
|
59
|
+
|
60
|
+
# Log
|
61
|
+
# debug "URL matched: #{url}"
|
62
|
+
|
63
|
+
# Parse URI
|
64
|
+
p = URI(url)
|
65
|
+
|
66
|
+
# API key lookup
|
67
|
+
VideoInfo.provider_api_keys = { youtube: Config.secrets[:google] }
|
68
|
+
|
69
|
+
# Parse out specific websites
|
70
|
+
if p.host == 'youtube.com' || p.host == 'www.youtube.com' || p.host == 'youtu.be'
|
71
|
+
match_youtube(msg, url)
|
72
|
+
elsif p.host == 'i.imgur.com' || p.host == 'imgur.com'
|
73
|
+
match_imgur(msg, url)
|
74
|
+
else
|
75
|
+
match_other(msg,url)
|
76
|
+
end
|
77
|
+
|
78
|
+
rescue => e
|
79
|
+
error "#{e.class.name}: #{e.message}"
|
80
|
+
error "[404] #{msg.user} - #{url}"
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
def match_youtube(msg, url)
|
85
|
+
if Config.secrets[:google]
|
86
|
+
video = VideoInfo.new(url)
|
87
|
+
msg.reply "#{Format(:red, 'YouTube ')}∴ #{video.title} ( #{Format(:green, Time.at(video.duration).strftime("%H:%M:%S"))} )"
|
88
|
+
else
|
89
|
+
match_other(msg, url)
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
def match_github(msg, url)
|
95
|
+
# TODO parse github url
|
96
|
+
end
|
97
|
+
|
98
|
+
def match_imgur(msg, url)
|
99
|
+
id = url.to_s.match(%r{(?:https?://i?\.?imgur.com/)(?:.*\/)?([A-Za-z0-9]+)(?:\.jpg|png|gif|gifv)?}i)
|
100
|
+
return match_other(msg, url) unless id
|
101
|
+
|
102
|
+
# Query Data
|
103
|
+
data = JSON.parse(
|
104
|
+
RestClient.get("https://api.imgur.com/3/image/#{id[1]}", { Authorization: "Client-ID #{Config.secrets[:imgur_id]}" })
|
105
|
+
)
|
106
|
+
return 'Unable to query imgur' unless defined?(data)
|
107
|
+
i = Hashie::Mash.new(data)
|
108
|
+
|
109
|
+
# SET Not Safe For Work
|
110
|
+
if i.data.nsfw
|
111
|
+
nsf = "[#{Format(:red, 'NSFW')}]"
|
112
|
+
else
|
113
|
+
nsf = "[#{Format(:green, 'SAFE')}]"
|
114
|
+
end
|
115
|
+
|
116
|
+
# Trigger reply message
|
117
|
+
msg.reply("#{Format(:purple, 'IMGUR')} #{nsf} ∴ [#{Format(:yellow, i.data.type)}] #{i.data.width}x#{i.data.height} "\
|
118
|
+
"∴ Views: #{ i.data.views.to_s} ∴ #{i.data.title ? i.data.title[0..100] : 'No Title'} "\
|
119
|
+
"∴ Posted #{time_ago_in_words(Time.at(i.data.datetime))} ago")
|
120
|
+
end
|
121
|
+
|
122
|
+
def match_other(msg,url)
|
123
|
+
begin
|
124
|
+
html = Mechanize.start { |m| Nokogiri::HTML(m.get(url).content, nil, 'utf-8') }
|
125
|
+
if node = html.at_xpath("html/head/title")
|
126
|
+
msg.reply("‡ #{node.text.lstrip.gsub(/\r|\n|\n\r/, ' ')[0..300]}")
|
127
|
+
end
|
128
|
+
|
129
|
+
if node = html.at_xpath('html/head/meta[@name="description"]')
|
130
|
+
msg.reply("» #{node[:content].lines.first(3).join.gsub(/\r|\n|\n\r/, ' ')[0..300]}")
|
131
|
+
end
|
132
|
+
|
133
|
+
info "[200] #{msg.user} - #{url}"
|
134
|
+
rescue => e
|
135
|
+
error e
|
136
|
+
error "[404] #{msg.user} - #{url}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
# AutoLoad
|
145
|
+
Bot.config.plugins.plugins.push Plugins::Snooper
|
146
|
+
|