summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-08-06 06:17:33 -0700
committerJoe Rayhawk <jrayhawk+git@omgwallhack.org>2022-08-06 06:17:33 -0700
commitd5020890fd7cfe55307b94c04f59d0c396f32677 (patch)
tree386fc77e56ca6b58bed00d19aa3b380a22f65af3
parent6e29c3d5c02eeb4892dc0088b0198c6b2e539f28 (diff)
downloadtwitchtools-d5020890fd7cfe55307b94c04f59d0c396f32677.tar.gz
twitchtools-d5020890fd7cfe55307b94c04f59d0c396f32677.zip
bungmobott: add "uptime", profile users on entrance, assorted fixes
-rwxr-xr-xcrystal/bungmobott.cr122
1 files changed, 101 insertions, 21 deletions
diff --git a/crystal/bungmobott.cr b/crystal/bungmobott.cr
index 396b5db..bbaac50 100755
--- a/crystal/bungmobott.cr
+++ b/crystal/bungmobott.cr
@@ -100,9 +100,40 @@ end
obsipc = Channel( String ).new
ircipc = Channel( Tuple( String, String ) ).new
t2sipc = Channel( Tuple( String, String ) ).new
+twitchipc = Channel( Tuple( String, Union( String, UInt64 ) ) ).new
+
+# Twitch API request handling thread
+spawn do
+ loop do
+ begin
+ while twitchtuple = twitchipc.receive
+ cmd, arg = [ *twitchtuple ]
+ case cmd
+ when "get_user"
+ userinfo = JSON.parse( client.get_user( arg.to_u64 ) )["data"][0]
+ pp userinfo
+ unless userinfo["broadcaster_type"].as_s.blank?
+ puts "\033[38;5;12m#{userinfo["login"]} is #{userinfo["broadcaster_type"]}\033[0m"
+ end
+ userage = ( Time.utc.to_unix - Time::Format::RFC_3339.parse( userinfo["created_at"].as_s ).to_unix )
+ if ( userage - 172800 ) < 0
+ puts "\033[38;5;1m#{userinfo["login"]}'s account is #{((172800 - userage)/60/60).to_i64} hours old.\033[0m"
+ end
+ when "get_followers"
+ followers = JSON.parse( client.get_user_follows( to: arg.to_u64 ) )["total"].as_i64
+ if followers > 500
+ puts "\033[38;5;2m#{followers} followers\033[0m"
+ end
+ end
+ end
+ end
+ end
+end
+
snifflast = Int64.new(0)
+
def urbandef( term : String )
#http://api.urbandictionary.com/v0/define?term=waifu
client = HTTP::Client.new( "api.urbandictionary.com" )
@@ -141,7 +172,11 @@ def userlog( ircipc : Channel, settings : Hash(String, String), message : FastIR
end
basedir = settings["statedir"]
userdir = basedir + "/uids/" + uid
- lastseen = File.info( userdir ).modification_time.to_unix
+ if File.directory?( userdir )
+ lastseen = File.info( userdir ).modification_time.to_unix
+ else
+ lastseen = 0
+ end
Dir.mkdir_p( basedir + "/names" )
Dir.mkdir_p( userdir + "/names" )
File.touch( userdir )
@@ -215,6 +250,12 @@ def t2s( t2sipc : Channel, settings : Hash(String, String), userdir : String, ch
{ /\%([^ ])/, " percent sign \\1"},
{ /!([^ ])/, " tchik \\1"},
{ /([^ ])\$/, "\\1 dollar sign "},
+ { /\(/, " open paren "},
+ { /\)/, " close paren "},
+ { /\{/, " open curly bracket "},
+ { /\}/, " close curly bracket "},
+ { /\[/, " open square bracket "},
+ { /\]/, " close square bracket "},
{ /0/, " zero " },
{ /1/, " one " },
{ /2/, " two " },
@@ -373,6 +414,9 @@ end
lastvoice = Array(String).new
+#streamstatus = Hash(String, Union( Bool, Float64, Int64, UInt64, String ) ).new
+streamstatus = Hash(String, JSON::Any).new
+
# Put tts stuff into the same thread so each playback blocks the next
spawn do
loop do
@@ -477,7 +521,6 @@ spawn do
request["item"] = source
if ( match = msg.match( /^\x10source ([a-z0-9-_]+) (true|false)/ ) )
request["visible"] = ( match[2] == "true" )
- obs_pubsub.send( request.to_json )
elsif ( match = msg.match( /^\x10source ([a-z0-9-_]+)/ ) )
pp scenes[scene][source]["render"]
request["visible"] = ( scenes[scene][source]["render"]? != true )
@@ -492,8 +535,20 @@ spawn do
request["item"] = source
end
end
- obs_pubsub.send( request.to_json )
end
+ obs_pubsub.send( request.to_json )
+ #if scene == currentscene
+ request = Hash( String, String | Bool ).new
+ request["request-type"] = "SetPreviewScene"
+ request["message-id"] = "SetPreviewScene"
+ request["scene-name"] = currentscene
+ obs_pubsub.send( request.to_json )
+ request = Hash( String, String ).new
+ request["request-type"] = "TransitionToProgram"
+ request["message-id"] = "TransitionToProgram"
+ obs_pubsub.send( request.to_json )
+
+ #end
elsif ( match = msg.match( /^\x10source/ ) )
request = Hash( String, String ){
"request-type" => "GetCurrentScene",
@@ -515,6 +570,7 @@ spawn do
end
case json["update-type"]?
when "StreamStatus" # these are a bit noisy,
+ streamstatus = json
next # so skip them
when "SwitchScenes"
ircipc.send( { "#" + settings["channel"], "| obs: switched scene to " + ( json["scene-name"]?.as_s? || "unknown" ) } )
@@ -524,17 +580,18 @@ spawn do
pp json
source = json["sourceName"].as_s
sources = reversesource( scenes, currentscene )
- scene = sources[source]
- if scenes[scene][source]["render"] == true
- request = Hash( String, String | Bool ){
- "request-type" => "SetSceneItemProperties",
- "message-id" => "SetSceneItemProperties",
- "scene-name" => scene,
- "item" => source,
- "visible" => false
- }
- ircipc.send( { "##{settings["channel"]}", "| obs: Media ended; disabling #{source}" } )
- obsipc.send( request.to_json )
+ if scene = sources[source]?
+ if ( scenes[scene][source]["render"] == true ) && ( source =~ /^media-/ )
+ request = Hash( String, String | Bool ){
+ "request-type" => "SetSceneItemProperties",
+ "message-id" => "SetSceneItemProperties",
+ "scene-name" => scene,
+ "item" => source,
+ "visible" => false
+ }
+ ircipc.send( { "##{settings["channel"]}", "| obs: Media ended; disabling #{source}" } )
+ obsipc.send( request.to_json )
+ end
end
# If we want to start deleting temporary media sources?
# if ( ( source =~ /^media-/ ) && ( scene !~ /^meta/ ) )
@@ -651,8 +708,20 @@ loop do
spawn do
next unless ( userlogreturn = userlog( ircipc, settings, message ) )
chatuser, uid, userdir, lastseen = userlogreturn
- # play random fanfare if available.
+ if ( t2sreturn = t2s( t2sipc, settings, userdir, chatuser, message.params[1] ) )
+ lastvoice.insert( 0, t2sreturn )
+ lastvoice = lastvoice[0..4]
+ end
+ # Have we seen this user lately?
if ( ( Time.utc.to_unix - lastseen ) >= 14400 )
+ twitchipc.send( { "get_user", uid.to_u64 } )
+ twitchipc.send( { "get_followers", uid.to_u64 } )
+ prevnames = Array( String ).new
+ if ( prevnames = Dir.children( settings["statedir"] + "/uids/" + uid + "/names" ) ) && ( prevnames.size > 1 )
+ prevnames.delete( chatuser )
+ puts "\033[38;5;14m#{chatuser} previous names: #{prevnames.join(", ")}\033[0m"
+ end
+ # play random fanfare if available.
{% if flag?(:windows) %}
# This file hierarchy gets manually set up for now.
# Maybe someday let mods do something like:
@@ -664,10 +733,6 @@ loop do
t2smsg( settings, "fanfare #{uid} #{chatuser}" )
{% end %}
end
- if ( t2sreturn = t2s( t2sipc, settings, userdir, chatuser, message.params[1] ) )
- lastvoice.insert( 0, t2sreturn )
- lastvoice = lastvoice[0..4]
- end
next unless ( ( match = message.params[1].match(/^ *!([A-Za-z]+) (([a-zA-Z0-9= _\:,.&'\/?;\\\(\)\[\]+\-]|!)+)/) || message.params[1].match(/^ *!([A-Za-z]+)/) ) )
cmd = match[1]
own = ( message.tags["room-id"] == message.tags["user-id"] )
@@ -744,13 +809,21 @@ loop do
when 3
else
end
- elsif ( ( cmd =~ /^scene$/ ) && ( mod || own ) )
+ elsif ( cmd =~ /^uptime$/ )
+ ircipc.send( { "##{settings["channel"]}", "| #{streamstatus["stream-timecode"].as_s[0..7]} Usage: #{streamstatus["cpu-usage"].as_f.to_i64}% #{streamstatus["memory-usage"].as_f.to_i64}MiB #{streamstatus["kbits-per-sec"].as_i64}kbps Frame losses: #{streamstatus["render-missed-frames"].as_i64} #{streamstatus["num-dropped-frames"].as_i64} #{streamstatus["output-skipped-frames"].as_i64}" } )
+ # !newimage [name] [url] (random|top|bottom|left|right|center)
+ # download url, verify mimetype with libmagic, duplicate existing medialoop source, change "file" SourceSetting
+ elsif ( ( cmd =~ /^sourcesettings$/ ) && ( mod || own || vip ) )
+ if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
+ obsipc.send( "{ \"request-type\": \"GetSourceSettings\", \"message-id\": \"GetSourceSettings\", \"sourceName\": \"#{match[2]}\" }" )
+ end
+ elsif ( ( cmd =~ /^scene$/ ) && ( mod || own || vip ) )
if ( match[2]? && match[2] =~ /^[a-zA-Z0-9-_]+$/ )
obsipc.send( "{ \"request-type\": \"SetCurrentScene\", \"message-id\": \"SetCurrentScene\", \"scene-name\": \"" + match[2] + "\" }" )
else
obsipc.send( "{ \"request-type\": \"GetSceneList\", \"message-id\": \"GetSceneList\" }" )
end
- elsif ( ( cmd =~ /^source$/ ) && ( mod || own ) )
+ elsif ( ( cmd =~ /^source$/ ) && ( mod || own || vip ) )
request = Hash( String, String | Bool ).new
if ( match[2]? ) && ( sourceargs = match[2].match( /^([a-zA-Z0-9-_]+) +(true|false)$/ ) )
obsipc.send( "\x10source #{match[2]}" )
@@ -789,6 +862,13 @@ loop do
end
elsif ( cmd =~ /^(metaminute|youdied)$/ )
obsipc.send( "\x10source media-#{cmd}" )
+ # FIXME: This is only half-implemented
+ elsif ( ( cmd =~ /^(user)$/ ) && ( mod || own ) )
+ if match[2]? && match[2] =~ /[0-9]+/
+ twitchipc.send( { "get_user", match[2].to_u64 } )
+ else
+ twitchipc.send( { "get_user", settings["channel_id"].to_u64 } )
+ end
elsif ( ( cmd =~ /^(status|title)$/ ) && ( mod || own ) )
begin
if match[2]?