1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
require "http/client"
require "json"
require "pretty_print"
require "xml"
require "inotify"
require "time"
require "twitcr"
settings = Hash(String, String).new
settings["home"] = Path.home.to_s
["access_token", "channel", "channel_id", "client_id", "client_id_twitch"].each do |key|
begin
settings[key] = File.read( settings["home"] + "/.config/twitch/" + key ).chomp
rescue IO::Error
STDERR.puts "Warning: Missing " + settings["home"] + "/.config/twitch/" + key
end
end
client = Twitcr::Client.new( settings )
def ircmsg( home : String, channel : String, msg : String)
if msg !~ /(\r|\n)/
sock = Socket.unix
# sock.connect Socket::UNIXAddress.new( home + "/.irssi/twitch-socket".to_s, type: Socket::Type::DGRAM )
sock.connect Socket::UNIXAddress.new( home + "/.irssi/twitch-socket".to_s )
sock.puts( "#" + channel + " | " + msg )
sock.close
end
end
voices = Hash(String, String).new
File.each_line( settings["home"] + "/voicelist" ) do |line|
voices[ line.downcase ] = line
end
#FIXME: cache twitch results
def urbandef( term : String )
#http://api.urbandictionary.com/v0/define?term=waifu
client = HTTP::Client.new( "api.urbandictionary.com" )
response = client.exec( "GET", "/v0/define?term=" + term )
puts response.status_code
json = JSON.parse( response.body )
return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /\n/, "" )
end
def commanderroot_changelog( uid )
client = HTTP::Client.new( "twitch-tools.rootonline.de", port = 443, tls = true )
response = client.exec( "GET", "/username_changelogs_search.php?q=" + uid )
client.close
puts response.status_code
document = XML.parse_html( response.body )
rows = document.xpath_nodes( "/html/body/div/table/tbody/tr" )
text = Array(String).new
rows.each do |row|
text.push( row.first_element_child.not_nil!.next_element.not_nil!.inner_text.chomp(" ").match(/[0-9a-z_]+/).not_nil![0] + " " + row.first_element_child.not_nil!.next_element.not_nil!.next_element.not_nil!.next_element.not_nil!.inner_text.chomp(" ").match(/\d{4}-\d{2}-\d{2}/).not_nil![0] )
end
text.reverse!
return text
end
logwatcher = logwatch( settings, client, voices, settings["home"] + "/irclogs/twitch/#" + settings["channel"] + "/" + Time.local.to_s("%Y-%m-%d") + ".log".to_s )
dirwatcher = Inotify.watch( settings["home"] + "/irclogs/twitch/#" + settings["channel"] + "/" ) do | event |
if event.type.to_s == "CREATE" && event.name =~ /\.log$/
# FIXME: logwatcher is wrong scope, probably should move the function boundary further into it so we still hold the watcher handle
logwatcher.close
puts [ event.type, event.path, event.name ].join(" ")
logwatcher = logwatch( settings, client, voices, event.path.not_nil! + event.name.not_nil! )
end
end
def logwatch( settings, client, voices, logfile )
log = File.open( logfile )
log.seek(log.size)
logwatcher = Inotify.watch( logfile ) do | event |
if event.type.to_s == "MODIFY"
log.read_string( log.size - log.pos ).each_line do | string |
# FIXME: support old names? might get confusing with e.g. reverse5612
next unless match = string.match(/^[0-9][0-9]:[0-9][0-9] <.([a-z0-9_]+)> !([A-Za-z]+) (([a-zA-Z0-9' _\:,&.-]|!)+)/) || string.match(/^[0-9][0-9]:[0-9][0-9] <.([a-z0-9_]+)> !([A-Za-z]+)/)
if match[1] == settings["channel"]
# if match[2].downcase == "status"
# begin
# if match[3]?
# json = JSON.parse( client.put_channel!( settings["channel_id"].to_u64, status: match[3] ) )
# ircmsg( settings["home"], settings["channel"], "Status is now \"#{ json["status"] }\"")
# else
# json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
# ircmsg( settings["home"], settings["channel"], "Status is currently \"#{ json["status"] }\"")
# end
# rescue ex
# ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
# end
# end
# if match[2].downcase == "game"
# begin
# if match[3]?
# json = JSON.parse( client.put_channel!( settings["channel_id"].to_u64, game: match[3] ) )
# ircmsg( settings["home"], settings["channel"], "Game is now \"#{ json["game"] }\"")
# else
# json = JSON.parse( client.get_channel( settings["channel_id"].to_u64 ) )
# ircmsg( settings["home"], settings["channel"], "Game is currently \"#{ json["game"] }\"")
# end
# rescue ex
# ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
# end
# end
end
if match[2].downcase == "name"
begin
if match[3]? == nil
puts match[1]
arg = match[1]
elsif match[3]? =~ /^([a-zA-Z0-9_]+)$/
puts match[3]
arg = match[3]
else
ircmsg( settings["home"], settings["channel"], "Argument must be a valid Twitch username or user id." )
next
end
if arg =~ /^[0-9]+$/
user_id = arg.to_u64
name = client.user( user_id ).login
else
name = arg
user_id = client.user( name ).id
end
# FIXME: more specific exception handling
pp user_id
pp name
user_ctime = JSON.parse( client.get_channel( user_id ) )["created_at"].to_s.match( /\d{4}-\d{2}-\d{2}/ ).not_nil![0]
history = commanderroot_changelog( user_id.to_s )
history.unshift( user_ctime )
history.unshift( user_id.to_s )
history.push( name )
puts history.join(" ")
ircmsg( settings["home"], settings["channel"], history.join( " " ) )
rescue ex
ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
end
end
if match[2].downcase == "urban"
begin
if match[3]?
arg = match[3]
if arg =~ /^[a-zA-Z0-9 -]+$/
definition = urbandef( arg )
ircmsg( settings["home"], settings["channel"], definition )
else
ircmsg( settings["home"], settings["channel"], "Urban Dictionary search term should consist of letters, numbers, spaces, and/or hyphens." )
end
else
ircmsg( settings["home"], settings["channel"], "Requires an Urban Dictionary search term" )
end
rescue ex
ircmsg( settings["home"], settings["channel"], "An error occurred! " + ex.message.to_s )
end
end
end
end
end
return logwatcher
end
loop do
sleep 300
end
#watcher.close
#log.close
|