nadoka 0.8.3 → 0.8.4
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.
- data/.gitignore +1 -0
- data/ndk/server.rb +2 -0
- data/ndk/version.rb +1 -1
- data/plugins/githubissuesbot.nb +141 -0
- data/plugins/googlebot.nb +10 -1
- data/plugins/tenkibot.nb +48 -51
- data/plugins/titlebot.nb +42 -10
- data/plugins/twitterbot.nb +36 -25
- data/rice/irc.rb +2 -2
- metadata +3 -2
data/.gitignore
CHANGED
data/ndk/server.rb
CHANGED
|
@@ -353,11 +353,13 @@ module Nadoka
|
|
|
353
353
|
context.cert = OpenSSL::X509::Certificate.new(File.read(@config.client_server_ssl_cert_file))
|
|
354
354
|
context.key = OpenSSL::PKey::RSA.new(File.read(@config.client_server_ssl_key_file))
|
|
355
355
|
@cserver = OpenSSL::SSL::SSLServer.new(@cserver, context)
|
|
356
|
+
@cserver.start_immediately = false
|
|
356
357
|
end
|
|
357
358
|
|
|
358
359
|
while true
|
|
359
360
|
# wait for client connections
|
|
360
361
|
Thread.start(@cserver.accept){|cc|
|
|
362
|
+
cc.accept if OpenSSL::SSL::SSLSocket === cc rescue NameError
|
|
361
363
|
client = nil
|
|
362
364
|
begin
|
|
363
365
|
if !@config.acl_object || @config.acl_object.allow_socket?(cc)
|
data/ndk/version.rb
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# -*-ruby; coding: utf-8 -*- vim:set ft=ruby:
|
|
2
|
+
# Copyright (C) 2013 Kazuhiro NISHIYAMA
|
|
3
|
+
#
|
|
4
|
+
# This program is free software with ABSOLUTELY NO WARRANTY.
|
|
5
|
+
# You can re-distribute and/or modify this program under
|
|
6
|
+
# the same terms of the Ruby's license.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
=begin
|
|
10
|
+
|
|
11
|
+
== Configuration:
|
|
12
|
+
|
|
13
|
+
BotConfig << {
|
|
14
|
+
:name => :GithubIssuesBot,
|
|
15
|
+
:bot_name => 'gh',
|
|
16
|
+
:ch => '#nadoka_check',
|
|
17
|
+
:tm => 30, # min
|
|
18
|
+
#:nkf => "--oc=CP50221 --ic=UTF-8 --fb-xml",
|
|
19
|
+
:owner => "nadoka",
|
|
20
|
+
:repo => "nadoka",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
=end
|
|
24
|
+
require 'open-uri'
|
|
25
|
+
require 'time'
|
|
26
|
+
begin
|
|
27
|
+
require 'json'
|
|
28
|
+
rescue LoadError
|
|
29
|
+
require 'rubygems'
|
|
30
|
+
require 'json'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module GithubIssues
|
|
34
|
+
module_function
|
|
35
|
+
|
|
36
|
+
def issues(owner, repo, since=nil, state='open')
|
|
37
|
+
since = since.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
38
|
+
uri = URI("https://api.github.com/repos/#{owner}/#{repo}/issues?since=#{since}&state=#{state}")
|
|
39
|
+
issues = JSON.parse(uri.read)
|
|
40
|
+
issues.each do |issue|
|
|
41
|
+
comments_uri = URI("#{issue['comments_url']}?since=#{since}")
|
|
42
|
+
comments = JSON.parse(comments_uri.read)
|
|
43
|
+
if comments.empty?
|
|
44
|
+
yield [:issue, issue, issue_to_s(issue)]
|
|
45
|
+
else
|
|
46
|
+
comments.each do |comment|
|
|
47
|
+
yield [:comment, comment, comment_to_s(comment, issue)]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def user_to_s(user)
|
|
54
|
+
return unless user
|
|
55
|
+
"@#{user['login']} "
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def time_to_s(time)
|
|
59
|
+
return unless time
|
|
60
|
+
time = Time.parse(time)
|
|
61
|
+
time.localtime.strftime("%H:%M ")
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def issue_to_s(issue)
|
|
65
|
+
return unless issue
|
|
66
|
+
"#{issue['html_url']} [#{issue['state']}] #{time_to_s(issue['updated_at'])}#{user_to_s(issue['user'])}#{issue['title']}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def comment_to_s(comment, issue=nil)
|
|
70
|
+
return unless comment
|
|
71
|
+
if issue
|
|
72
|
+
info = "[#{issue['state']}] "
|
|
73
|
+
else
|
|
74
|
+
end
|
|
75
|
+
"#{comment['html_url']} #{info}#{time_to_s(comment['updated_at'])}#{user_to_s(comment['user'])}#{comment['body']}"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
if __FILE__ == $0
|
|
80
|
+
owner = "rubima"
|
|
81
|
+
repo = "rubima"
|
|
82
|
+
since = Time.now - 60*60*3
|
|
83
|
+
GithubIssues.issues(owner, repo, since) do |_, _, s|
|
|
84
|
+
puts s.gsub(/\s+/, ' ')
|
|
85
|
+
end
|
|
86
|
+
GithubIssues.issues(owner, repo, since, 'close') do |_, _, s|
|
|
87
|
+
puts s.gsub(/\s+/, ' ')
|
|
88
|
+
end
|
|
89
|
+
exit
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
require 'nkf'
|
|
93
|
+
|
|
94
|
+
class GithubIssuesBot < Nadoka::NDK_Bot
|
|
95
|
+
def bot_initialize
|
|
96
|
+
@ch = @bot_config.fetch(:ch, '#nadoka_check')
|
|
97
|
+
@tm = @bot_config.fetch(:tm, 30) # min
|
|
98
|
+
@prevtm = Time.now
|
|
99
|
+
@nkf_options = @bot_config.fetch(:nkf, "--oc=CP50221 --ic=UTF-8 --fb-xml")
|
|
100
|
+
@owner = @bot_config.fetch(:owner, "nadoka")
|
|
101
|
+
@repo = @bot_config.fetch(:repo, "nadoka")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def bot_state
|
|
105
|
+
nt = Time.at(@prevtm.to_i + @tm * 60)
|
|
106
|
+
"<#{self.class}: next check at #{nt.asctime}@#{@ch}>"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def send_notice(ch, msg)
|
|
110
|
+
msg = msg.gsub(/\s+/, ' ')
|
|
111
|
+
if @nkf_options
|
|
112
|
+
msg = NKF.nkf(@nkf_options, msg)
|
|
113
|
+
end
|
|
114
|
+
super(ch, msg)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def on_timer tm
|
|
118
|
+
check
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def check
|
|
122
|
+
tm = Time.now
|
|
123
|
+
if tm.to_i - @tm * 60 > @prevtm.to_i
|
|
124
|
+
make_notice tm
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def make_notice tm
|
|
129
|
+
since = @prevtm
|
|
130
|
+
@prevtm = tm
|
|
131
|
+
GithubIssues.issues(@owner, @repo, since) do |_, _, s|
|
|
132
|
+
send_notice @ch, s
|
|
133
|
+
end
|
|
134
|
+
GithubIssues.issues(@owner, @repo, since, 'close') do |_, _, s|
|
|
135
|
+
send_notice @ch, s
|
|
136
|
+
end
|
|
137
|
+
rescue Exception => e
|
|
138
|
+
send_notice(@ch, "rss bot error: #{e}")
|
|
139
|
+
@manager.ndk_error e
|
|
140
|
+
end
|
|
141
|
+
end
|
data/plugins/googlebot.nb
CHANGED
|
@@ -182,7 +182,16 @@ class GoogleBot < Nadoka::NDK_Bot
|
|
|
182
182
|
result.gsub!(/<sup>(.+?)<\/sup>/u) { "^(#{$1})" }
|
|
183
183
|
result.gsub!(/<.+?>/u, '')
|
|
184
184
|
result.gsub!(/&\#215;/u, "\303\227")
|
|
185
|
-
result
|
|
185
|
+
return result
|
|
186
|
+
elsif /<[^<>]+ id="cwos"[^<>]*>([^<>]+)</u =~ html
|
|
187
|
+
result = $1
|
|
188
|
+
if /<[^<>]+ id="cwles"[^<>]*>([^<>]+)</u =~ html
|
|
189
|
+
result = "#{$1}#{result}"
|
|
190
|
+
end
|
|
191
|
+
#@logger.slog("google_calc>#{result.dump}")
|
|
192
|
+
result.gsub!(/ /u, " ")
|
|
193
|
+
result.gsub!(/\s+/, " ")
|
|
194
|
+
return result
|
|
186
195
|
else
|
|
187
196
|
"response error"
|
|
188
197
|
end
|
data/plugins/tenkibot.nb
CHANGED
|
@@ -13,18 +13,15 @@
|
|
|
13
13
|
|
|
14
14
|
Answer weather information using "Livedoor Weather Web Service / LWWS".
|
|
15
15
|
|
|
16
|
-
LWWS: http://weather.livedoor.com/weather_hacks/webservice
|
|
16
|
+
LWWS: http://weather.livedoor.com/weather_hacks/webservice
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
== Usage
|
|
20
20
|
|
|
21
21
|
tenki> [CITY]
|
|
22
|
-
tenki:[today|tomorrow|dayaftertomorrow]> [CITY]
|
|
23
22
|
|
|
24
23
|
[CITY] should be city name in Kanji listed on following table.
|
|
25
|
-
http://weather.livedoor.com/forecast/rss/
|
|
26
|
-
|
|
27
|
-
If timing is not specified, show today's information.
|
|
24
|
+
http://weather.livedoor.com/forecast/rss/primary_area.xml
|
|
28
25
|
|
|
29
26
|
|
|
30
27
|
== Configuration
|
|
@@ -32,7 +29,7 @@ LWWS: http://weather.livedoor.com/weather_hacks/webservice.html
|
|
|
32
29
|
BotConfig = [
|
|
33
30
|
{
|
|
34
31
|
:name => :TenkiBot,
|
|
35
|
-
:ch => /nadoka/, # default:
|
|
32
|
+
:ch => /nadoka/, # default: //
|
|
36
33
|
}
|
|
37
34
|
]
|
|
38
35
|
|
|
@@ -42,62 +39,65 @@ BotConfig = [
|
|
|
42
39
|
require 'open-uri'
|
|
43
40
|
require 'pp'
|
|
44
41
|
require 'kconv'
|
|
45
|
-
require 'rexml/document'
|
|
46
42
|
require 'date'
|
|
43
|
+
begin
|
|
44
|
+
require 'json'
|
|
45
|
+
rescue LoadError
|
|
46
|
+
require 'rubygems'
|
|
47
|
+
require 'json'
|
|
48
|
+
end
|
|
47
49
|
|
|
48
50
|
module Tenki
|
|
49
51
|
CityIDs = {}
|
|
50
52
|
|
|
51
53
|
def init_tenki
|
|
52
|
-
open('http://weather.livedoor.com/forecast/rss/
|
|
53
|
-
f.
|
|
54
|
+
open('http://weather.livedoor.com/forecast/rss/primary_area.xml') do |f|
|
|
55
|
+
f.each_line do |line|
|
|
54
56
|
if /city title="(.+?)" id="(\d+)"/ =~ line
|
|
55
|
-
CityIDs[$1.toutf8] = $2
|
|
57
|
+
CityIDs[$1.toutf8] = $2
|
|
56
58
|
end
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
end
|
|
60
|
+
end
|
|
59
61
|
end
|
|
60
62
|
|
|
61
|
-
def tenki
|
|
62
|
-
|
|
63
|
-
"http://weather.livedoor.com/forecast/
|
|
64
|
-
"city=#{CityIDs.fetch(city)}&day=#{timing}"){|f|
|
|
65
|
-
REXML::Document.new f.read
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
title = doc.elements['/lwws/title/'].text.toutf8
|
|
69
|
-
telop = doc.elements['/lwws/telop/'].text.toutf8
|
|
70
|
-
link = doc.elements['/lwws/link/'].text.toutf8
|
|
71
|
-
desc = doc.elements['/lwws/description/'].text.toutf8
|
|
72
|
-
max = doc.elements['/lwws/temperature/max/celsius/'].text
|
|
73
|
-
min = doc.elements['/lwws/temperature/min/celsius/'].text
|
|
74
|
-
date = Date.parse(doc.elements['/lwws/forecastdate/'].text)
|
|
75
|
-
datestr = date.strftime('%m/%d')
|
|
76
|
-
|
|
77
|
-
desc.sub!(/\.\.\..*/m, '...')
|
|
78
|
-
|
|
79
|
-
celsius = []
|
|
80
|
-
celsius << "max: #{max}" if max
|
|
81
|
-
celsius << "min: #{min}" if min
|
|
82
|
-
unless celsius.empty?
|
|
83
|
-
celsius = "(#{celsius.join(', ')}) "
|
|
63
|
+
def tenki(city)
|
|
64
|
+
unless city_id = CityIDs[city]
|
|
65
|
+
return "Unknown city. Check city title on http://weather.livedoor.com/forecast/rss/primary_area.xml"
|
|
84
66
|
end
|
|
85
|
-
|
|
67
|
+
json = open("http://weather.livedoor.com/forecast/webservice/json/v1?city=#{city_id}") do |f|
|
|
68
|
+
JSON.parse f.read
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
tenki = "#{json['title']}: "
|
|
72
|
+
tenki << json['forecasts'].map do |forecast|
|
|
73
|
+
max = forecast['temperature']['max']
|
|
74
|
+
min = forecast['temperature']['min']
|
|
75
|
+
celsius = []
|
|
76
|
+
celsius << "min:#{min['celsius']}" if min
|
|
77
|
+
celsius << "max:#{max['celsius']}" if max
|
|
78
|
+
unless celsius.empty?
|
|
79
|
+
temperature = "(#{celsius.join(',')})"
|
|
80
|
+
end
|
|
81
|
+
"#{forecast['dateLabel']}:#{forecast['telop']}#{temperature}"
|
|
82
|
+
end.join(', ')
|
|
83
|
+
desc = json['description']
|
|
84
|
+
text, = desc['text'].split(/\n\n/, 2)
|
|
85
|
+
text.gsub!(/\n/, '')
|
|
86
|
+
tenki << " - #{text}(#{desc['publicTime']})"
|
|
87
|
+
tenki << " - #{json['link']}"
|
|
88
|
+
|
|
89
|
+
tenki
|
|
86
90
|
end
|
|
87
91
|
end
|
|
88
92
|
|
|
89
93
|
if __FILE__ == $0
|
|
90
94
|
include Tenki
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if city.nil?
|
|
94
|
-
puts "#$0 city [today|tomorrow|dayaftertomorrow]"
|
|
95
|
+
if ARGV.empty?
|
|
96
|
+
puts "#$0 city"
|
|
95
97
|
else
|
|
96
98
|
init_tenki
|
|
97
|
-
|
|
98
|
-
puts tenki(city
|
|
99
|
-
rescue IndexError
|
|
100
|
-
puts "Unknown city. Check city title on http://weather.livedoor.com/forecast/rss/forecastmap.xml"
|
|
99
|
+
ARGV.each do |city|
|
|
100
|
+
puts tenki(city)
|
|
101
101
|
end
|
|
102
102
|
end
|
|
103
103
|
exit
|
|
@@ -116,17 +116,14 @@ class TenkiBot < Nadoka::NDK_Bot
|
|
|
116
116
|
return unless @available_channel === ch
|
|
117
117
|
return if same_bot?(ch)
|
|
118
118
|
msg = NKF.nkf('-w', msg)
|
|
119
|
-
if /\Atenki
|
|
120
|
-
city = $
|
|
121
|
-
timing = ($2 || 'today').strip
|
|
119
|
+
if /\Atenki>/ =~ msg
|
|
120
|
+
city = $'.strip.toutf8
|
|
122
121
|
begin
|
|
123
|
-
result = tenki(city
|
|
124
|
-
rescue IndexError
|
|
125
|
-
result = "Unknown city. Check city title on http://weather.livedoor.com/forecast/rss/forecastmap.xml"
|
|
122
|
+
result = tenki(city)
|
|
126
123
|
rescue => e
|
|
127
124
|
result = "#{e}"
|
|
128
125
|
end
|
|
129
|
-
send_notice ch, NKF.nkf(@nkf, "tenki bot: #{result}")
|
|
126
|
+
send_notice ch, NKF.nkf(@nkf, "tenki bot: #{result}".gsub(/\s+/, ' '))
|
|
130
127
|
end
|
|
131
128
|
end
|
|
132
129
|
end
|
data/plugins/titlebot.nb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# -*-ruby-*-
|
|
1
|
+
# -*-ruby; coding: utf-8 -*-
|
|
2
2
|
# vim:set ft=ruby:
|
|
3
3
|
#
|
|
4
4
|
# Copyright (c) 2009, 2011, 2012 Kazuhiro NISHIYAMA
|
|
@@ -33,6 +33,12 @@ require 'open-uri'
|
|
|
33
33
|
require 'timeout'
|
|
34
34
|
require 'tmpdir'
|
|
35
35
|
|
|
36
|
+
begin
|
|
37
|
+
require 'cgi/util'
|
|
38
|
+
rescue LoadError
|
|
39
|
+
require 'cgi'
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
begin
|
|
37
43
|
require 'rubygems'
|
|
38
44
|
require 'nokogiri'
|
|
@@ -92,10 +98,10 @@ module URL2Title
|
|
|
92
98
|
when /euc-jp/i # euc-jp, x-euc-jp
|
|
93
99
|
charset = "eucjp-ms"
|
|
94
100
|
end
|
|
95
|
-
if /\
|
|
101
|
+
if /\A(?:utf-8|eucjp-ms)\z/i =~ charset
|
|
96
102
|
# avoid #<ArgumentError: invalid byte sequence in UTF-8>
|
|
97
103
|
# or Iconv::IllegalSequence
|
|
98
|
-
body = NKF.nkf("-
|
|
104
|
+
body = NKF.nkf("-wm0x --ic=#{charset}", body)
|
|
99
105
|
elsif charset
|
|
100
106
|
charset.sub!(/\Ax-?/i, '')
|
|
101
107
|
begin
|
|
@@ -127,20 +133,33 @@ module URL2Title
|
|
|
127
133
|
title = tweet unless tweet.empty?
|
|
128
134
|
end
|
|
129
135
|
end
|
|
130
|
-
|
|
136
|
+
else
|
|
131
137
|
if %r"<title\b(?>[^<>]*)>(.*?)</title(?>[^<>]*)>"miu =~ body
|
|
132
138
|
title = $1
|
|
133
139
|
end
|
|
134
|
-
if
|
|
140
|
+
if defined?(::Nokogiri)
|
|
141
|
+
doc ||= Nokogiri::HTML(body, uri.to_s, 'utf-8')
|
|
142
|
+
og_title = doc.xpath("//meta[@property='og:title'][1]/@content")
|
|
143
|
+
unless og_title.empty?
|
|
144
|
+
# title is escaped string when get by regexp
|
|
145
|
+
title = CGI.escapeHTML(og_title.text)
|
|
146
|
+
end
|
|
147
|
+
elsif /<meta property="og:title" content="(.+?)">/ =~ body
|
|
135
148
|
title = $1
|
|
136
149
|
end
|
|
137
|
-
|
|
138
|
-
|
|
150
|
+
if defined?(::Nokogiri)
|
|
151
|
+
doc ||= Nokogiri::HTML(body, uri.to_s, 'utf-8')
|
|
152
|
+
og_title = doc.xpath("//meta[@property='og:title']/@content")
|
|
153
|
+
unless og_title.empty?
|
|
154
|
+
# title is escaped string when get by regexp
|
|
155
|
+
title = CGI.escapeHTML(og_title.text)
|
|
156
|
+
end
|
|
157
|
+
elsif /<meta property="og:title" content="(.+?)">/ =~ body
|
|
139
158
|
title = $1
|
|
140
159
|
end
|
|
141
160
|
if uri.fragment && defined?(::Nokogiri)
|
|
142
161
|
begin
|
|
143
|
-
doc
|
|
162
|
+
doc ||= Nokogiri::HTML(body, uri.to_s, 'utf-8')
|
|
144
163
|
xpath = "//*[@id='#{uri.fragment}' or @name='#{uri.fragment}']"
|
|
145
164
|
fragment_element = doc.xpath(xpath)
|
|
146
165
|
# tDiary style
|
|
@@ -153,6 +172,19 @@ module URL2Title
|
|
|
153
172
|
end
|
|
154
173
|
end
|
|
155
174
|
end
|
|
175
|
+
if defined?(::Nokogiri)
|
|
176
|
+
doc ||= Nokogiri::HTML(body, uri.to_s, 'utf-8')
|
|
177
|
+
canonical_uri = doc.xpath("//link[@rel='canonical'][1]/@href")
|
|
178
|
+
unless canonical_uri.empty?
|
|
179
|
+
info[:uri] = URI(canonical_uri.text)
|
|
180
|
+
end
|
|
181
|
+
elsif /<link rel="canonical" href="(.+?)"/i =~ body
|
|
182
|
+
info[:uri] = URI(CGI.unescapeHTML($1))
|
|
183
|
+
end
|
|
184
|
+
if title
|
|
185
|
+
title = CGI.unescapeHTML(title)
|
|
186
|
+
title.gsub!(/\xE3\x80\x9C/u, "\xEF\xBD\x9E") # WAVE DASH -> FULLWIDTH TILDE
|
|
187
|
+
end
|
|
156
188
|
info[:title] = title || body
|
|
157
189
|
return info
|
|
158
190
|
when /\Aimage\//
|
|
@@ -211,7 +243,7 @@ if __FILE__ == $0
|
|
|
211
243
|
ARGV.each do |url|
|
|
212
244
|
info = u2t(url)
|
|
213
245
|
p info
|
|
214
|
-
puts
|
|
246
|
+
puts info[:uri]
|
|
215
247
|
puts info[:title]
|
|
216
248
|
end
|
|
217
249
|
end
|
|
@@ -232,7 +264,7 @@ class TitleBot < Nadoka::NDK_Bot
|
|
|
232
264
|
end
|
|
233
265
|
|
|
234
266
|
@same_bot = @bot_config.fetch(:same_bot, /(?!)/)
|
|
235
|
-
@nkf_options = @bot_config.fetch(:nkf, "--oc=CP50221 --ic=UTF-8 --
|
|
267
|
+
@nkf_options = @bot_config.fetch(:nkf, "--oc=CP50221 --ic=UTF-8 --fb-xml")
|
|
236
268
|
@timeout = @bot_config.fetch(:timeout, 10)
|
|
237
269
|
@fragment_size_range = @bot_config.fetch(:fragment_size_range, 5..100)
|
|
238
270
|
@headers = @bot_config.fetch(:headers, {})
|
data/plugins/twitterbot.nb
CHANGED
|
@@ -95,39 +95,50 @@ class TwitterBot < Nadoka::NDK_Bot
|
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
@streamer = Thread.new do
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
when status[:delete]
|
|
101
|
-
when status[:scrub_geo]
|
|
102
|
-
when status[:limit]
|
|
103
|
-
when status[:status_withheld]
|
|
104
|
-
when status[:user_withheld]
|
|
105
|
-
when status[:friends]
|
|
106
|
-
when status[:event]
|
|
107
|
-
when status[:for_user]
|
|
108
|
-
when status[:control]
|
|
109
|
-
when status[:warning]
|
|
110
|
-
screen_name = status[:code]
|
|
111
|
-
time = Time.parse(status[:created_at])
|
|
112
|
-
send_notice @ch, "#{time.strftime('%H:%M')} #{screen_name}: #{status.text}"
|
|
113
|
-
else
|
|
98
|
+
loop do
|
|
99
|
+
UserStream.client.user do |status|
|
|
114
100
|
begin
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
101
|
+
case # https://dev.twitter.com/docs/streaming-apis/messages
|
|
102
|
+
#when status[:delete]
|
|
103
|
+
#when status[:scrub_geo]
|
|
104
|
+
when status[:limit]
|
|
105
|
+
when status[:status_withheld]
|
|
106
|
+
when status[:user_withheld]
|
|
107
|
+
when status[:friends]
|
|
108
|
+
when status[:event]
|
|
109
|
+
when status[:for_user]
|
|
110
|
+
when status[:control]
|
|
111
|
+
when status[:warning]
|
|
112
|
+
screen_name = status[:code]
|
|
113
|
+
time = Time.parse(status[:created_at])
|
|
114
|
+
send_notice @ch, "#{time.strftime('%H:%M')} #{screen_name}: #{status.text}"
|
|
115
|
+
when status[:user]
|
|
116
|
+
screen_name = status[:user][:screen_name]
|
|
117
|
+
if status[:retweeted_status]
|
|
118
|
+
status = status[:retweeted_status]
|
|
119
|
+
screen_name << ":"
|
|
120
|
+
screen_name << status[:user][:screen_name]
|
|
121
|
+
end
|
|
122
|
+
time = Time.parse(status[:created_at])
|
|
123
|
+
text = status.text
|
|
124
|
+
text.tr!("\r\n", ' ')
|
|
125
|
+
text.gsub!(/</, '<')
|
|
126
|
+
text.gsub!(/>/, '>')
|
|
127
|
+
text.gsub!(/"/, '"')
|
|
128
|
+
text = NKF.nkf('--numchar-input --ic=UTF-8 --oc=' + @nkf_encoding, text) if @nkf_encoding
|
|
129
|
+
text.gsub!(/&/, '&')
|
|
130
|
+
send_notice @ch, "#{time.strftime('%H:%M')} #{screen_name}: #{text}"
|
|
131
|
+
else
|
|
132
|
+
send_notice @ch, status.inspect
|
|
120
133
|
end
|
|
121
|
-
time = Time.parse(status[:created_at])
|
|
122
|
-
text = status.text.tr("\r\n", ' ')
|
|
123
|
-
text = NKF.nkf('--ic=UTF-8 --oc=' + @nkf_encoding, text) if @nkf_encoding
|
|
124
|
-
send_notice @ch, "#{time.strftime('%H:%M')} #{screen_name}: #{text}"
|
|
125
134
|
rescue => e
|
|
135
|
+
@logger.slog e.inspect
|
|
126
136
|
slog e.backtrace
|
|
127
137
|
slog e.inspect
|
|
128
138
|
slog status.inspect
|
|
129
139
|
end
|
|
130
140
|
end
|
|
141
|
+
@logger.slog "user stream finished...and restart"
|
|
131
142
|
end
|
|
132
143
|
end
|
|
133
144
|
end
|
data/rice/irc.rb
CHANGED
|
@@ -300,7 +300,7 @@ module RICE
|
|
|
300
300
|
|
|
301
301
|
rescue Closed
|
|
302
302
|
begin
|
|
303
|
-
@main_th.run if
|
|
303
|
+
@main_th.run if alive?
|
|
304
304
|
rescue Closed
|
|
305
305
|
end
|
|
306
306
|
retry
|
|
@@ -317,7 +317,7 @@ module RICE
|
|
|
317
317
|
def close(restart = false)
|
|
318
318
|
begin
|
|
319
319
|
unless restart
|
|
320
|
-
@main_th.exit if
|
|
320
|
+
@main_th.exit if alive?
|
|
321
321
|
@read_th.exit if @read_th.alive?
|
|
322
322
|
end
|
|
323
323
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nadoka
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -10,7 +10,7 @@ authors:
|
|
|
10
10
|
autorequire:
|
|
11
11
|
bindir: bin
|
|
12
12
|
cert_chain: []
|
|
13
|
-
date: 2013-
|
|
13
|
+
date: 2013-04-29 00:00:00.000000000 Z
|
|
14
14
|
dependencies: []
|
|
15
15
|
description: Nadoka is a tool for monitoring and logging IRC conversations and responding
|
|
16
16
|
to specially formatted requests. You define and customize these responses in Ruby.
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- plugins/drbcl.rb
|
|
53
53
|
- plugins/drbot.nb
|
|
54
54
|
- plugins/evalbot.nb
|
|
55
|
+
- plugins/githubissuesbot.nb
|
|
55
56
|
- plugins/gonzuibot.nb
|
|
56
57
|
- plugins/googlebot.nb
|
|
57
58
|
- plugins/identifynickserv.nb
|