diff options
Diffstat (limited to 'crystal')
-rw-r--r-- | crystal/name-command.cr | 233 |
1 files changed, 139 insertions, 94 deletions
diff --git a/crystal/name-command.cr b/crystal/name-command.cr index fa1a0f9..26b423c 100644 --- a/crystal/name-command.cr +++ b/crystal/name-command.cr @@ -4,135 +4,180 @@ require "pretty_print" require "xml" require "inotify" require "time" +require "twitcr" -home = Path["~/"].expand.to_s +settings = Hash(String, String).new -access_token = File.read( home + ".config/twitch/access_token" ).chomp -client_id = File.read( home + ".config/twitch/client_id" ).chomp -channel = File.read( home + ".config/twitch/channel" ).chomp -channel_id = File.read( home + ".config/twitch/channel_id" ).chomp +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( home + "voicelist" ) do |line| +File.each_line( settings["home"] + "/voicelist" ) do |line| voices[ line.downcase ] = line end #FIXME: cache twitch results -def twitch_name_to_uid( client_id, name ) - twitchclient = HTTP::Client.new( "api.twitch.tv", port = 443, tls = true ) - response = twitchclient.exec( "GET", "/helix/users?login=" + name, headers: HTTP::Headers{ "Client-ID" => client_id } ) +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 ) - uid = json["data"][0]["id"].to_s.match(/[0-9]+/).not_nil![0] - twitchclient.close - return uid + return json["list"][0]["definition"].to_s.gsub( /[\[\]]/, "" ).gsub( /\n/, "" ) end -def twitch_uid_to_name( client_id, uid ) - client = HTTP::Client.new( "api.twitch.tv", port = 443, tls = true ) - response = client.exec( "GET", "/helix/users?id=" + uid, headers: HTTP::Headers{ "Client-ID" => client_id } ) - puts response.status_code - json = JSON.parse( response.body ) - name = json["data"][0]["login"].to_s.match(/[a-z0-9_]+/).not_nil![0] - client.close - return name -end -def twitch_v5_channel( client_id, uid ) - client = HTTP::Client.new( "api.twitch.tv", port = 443, tls = true ) - response = client.exec( "GET", "/kraken/channels?id=" + uid, headers: HTTP::Headers{ "Client-ID" => client_id, "Accept" => "application/vnd.twitchtv.v5+json" } ) - puts response.status_code - json = JSON.parse( response.body ) - - client.close - ctime = json["channels"][0]["created_at"].to_s.match( /\d{4}-\d{2}-\d{2}/ ).not_nil![0] - return ctime -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 -log = File.open(home + "irclogs/twitch/#" + channel + "/" + Time.local.to_s("%Y-%m-%d") + ".log".to_s) -log.seek(log.size) -watcher = Inotify.watch(home + "irclogs/twitch/#" + channel + "/" + Time.local.to_s("%Y-%m-%d") + ".log".to_s) 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 - match = string.match(/^[0-9][0-9]:[0-9][0-9] <.([a-z0-9_]+)> !([a-z]+) ([a-zA-Z0-9_-]+)/) || next - if match[2] == "name" - begin - puts match[3] - arg = match[3] - if arg =~ /^[0-9]+$/ - user_id = arg - name = twitch_uid_to_name( client_id, user_id ).to_s - else - name = arg - user_id = twitch_name_to_uid( client_id, name ).to_s + 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 - # FIXME: more specific exception handling - - pp user_id - pp name - - user_ctime = twitch_v5_channel( client_id, user_id ) - - history = commanderroot_changelog( user_id ) - - history.unshift( user_ctime ) - history.unshift( user_id ) - history.push( name ) - - puts history.join(" ") - - sock = Socket.unix - sock.connect Socket::UNIXAddress.new( home + ".irssi/twitch-socket".to_s ) - sock.puts( "#bungmonkey | " + history.join( " " ) ) - sock.close - rescue - sock = Socket.unix - sock.connect Socket::UNIXAddress.new( home + ".irssi/twitch-socket".to_s ) - sock.puts( "#bungmonkey | An error occurred" ) - sock.close end - end - if match[2] == "voice" - chatuser = match[1] - voice = match[3].downcase - if voices.has_key?( voice ) - csvoice = voices[voice] - dir = home + ".cache/twitchtools/users/" + chatuser - File.directory?( dir ) || Dir.mkdir( dir ) - File.write( dir + "/voice", csvoice ) - pp dir - pp File.read( dir + "/voice" ) - # TODO: make separate script to print streamelements URLs to client machine - end end end end + return logwatcher +end +loop do + sleep 300 end -sleep 300.seconds -watcher.close -log.close +#watcher.close +#log.close |