- Home»
- Cod sursa: steamcast.tcl
steamcast.tcl
steamcast.tcl
Steamcast BotScript v1.0 that connects to shoutcast stream station and post song information on irc channel. Designed to operate with Eggdrop 1.6.15
| Postat de | Copyright | Categorie | Review user | Vizualizari | Data |
|---|---|---|---|---|---|
| btc | ^DooM^ | media | Cod netestat | 559 | 2023-12-25 12:02:53 |
# Steamcast BotScript v1.0 #
# By ^DooM^ modded by coldfyre - #dialtone efnet #
# ------------------------------------------------------------------------ #
# Designed to operate with Eggdrop 1.6.15 #
# ------------------------------------------------------------------------ #
set shoutcast(vershort) "1.0"
set shoutcast(verlong) "010000"
# ------------------------------------------------------------------------
# Configuration settings!
# ------------------------------------------------------------------------
# Access flag specifiers
set shoutcast(perm_operator) "D"
set shoutcast(perm_anyone) "-"
# Command Character (Prepends the command itself, i.e. '!'addserver
set shoutcast(command_char) "!"
# Help trigger
set shoutcast(help_trigger) "$shoutcast(command_char)help"
# The details for the interface servers
set shoutcast(interface_page) "/status.xml"
set shoutcast(kickdj_page) "/admin.cgi?mode=kicksrc"
set shoutcast(admin_page) "/admin.cgi"
set shoutcast(listen_page) "/listen.m3u?src=0"
set shoutcast(interface_user_agent) "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)"
# Channel to display in
set shoutcast(broadcast_channel) "#yuorchan"
# Not designed to be filled out by you... Yes that means you!
set sc_servercount 0
# Server Lists (Host, Name, Port, Password etc)
set sc_servers($sc_servercount,Host) "serverip"
set sc_servers($sc_servercount,Name) "FQHN"
set sc_servers($sc_servercount,Port) "8000"
set sc_servers($sc_servercount,Pass) "pass"
incr sc_servercount
# Add as many as you want.
#set sc_servers($sc_servercount,Host) "192.168.0.100"
#set sc_servers($sc_servercount,Name) "shoutcast2.shoutcast.com"
#set sc_servers($sc_servercount,Port) "8000"
#set sc_servers($sc_servercount,Pass) "password"
#incr sc_servercount
# Which is the primary server (retrieves playing stats etc from)
set shoutcast(primary_server) 0
# Number of milliseconds to wait for page request timeout
set shoutcast(page_timeout) 4000
# ------------------------------------------------------------------------
# Eggdrop Bindings (Pubs and Msgs are bound separately to ensure full
# support on most eggdrops, and to workaround several painful bugs).
# ------------------------------------------------------------------------
bind pub $shoutcast(perm_anyone) [string trim $shoutcast(command_char)]stream sc_stream
bind pub $shoutcast(perm_anyone) [string trim $shoutcast(command_char)]playing sc_playing
bind pub $shoutcast(perm_anyone) [string trim $shoutcast(command_char)]users sc_userstats
bind pub $shoutcast(perm_anyone) [string trim $shoutcast(command_char)]help sc_help
bind pub $shoutcast(perm_anyone) [string trim $shoutcast(command_char)]site sc_site
bind pub $shoutcast(perm_operator) [string trim $shoutcast(command_char)]sckickdj sc_kickdj
bind pub $shoutcast(perm_operator) [string trim $shoutcast(command_char)]scwho sc_who
#bind time - "* * * * *" sc_update
# --------------------------------
# Global Variables - DO NOT TOUCH!
# --------------------------------
set sc_sock 0
set sc_packet_count 0
set sc_page_dump_complete 0
set sc_buffer ""
set sc_laststatus 0
set sc_lasttitle ""
set sc_lastsong ""
set sc_lastbitrate 0
# Setup global array data
for {set i 0} {$i < $sc_servercount} {incr i} {
set sc_responses($i,lastlistenercount) 0
}
proc sc_site { nick channel } {
set strCommand "site"
set strHelp "\037 YOUR SITE HERE!!!\037"
sc_output $nick $channel $strHelp
return
}
proc sc_help { nick uhost handle channel args } {
set strCommand "help"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set strHelp [sc_get_usage [lindex $args 0] [sc_isop $nick]]
sc_output $nick $channel $strHelp
return
}
proc sc_update { minute hour day month year } {
global shoutcast botnick sc_responses sc_servers sc_servercount
global sc_lastsong sc_lastbitrate sc_laststatus sc_lasttitle
set strCommand "update"
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand "" "" $shoutcast(broadcast_channel) $outArgs] == 0 } {
putlog "Unable to execute update command."
return
}
set iServer $shoutcast(primary_server)
set strTopic ""
set updateTopic 0
if { $sc_responses($iServer,streamstatus) == 1 } {
if { $sc_responses($iServer,songtitle) != $sc_lastsong } {
set sc_lastsong $sc_responses($iServer,songtitle)
set strStream "Now Playing:\00313\002\037 $sc_responses($iServer,songtitle)"
sc_output "" $shoutcast(broadcast_channel) $strStream
}
if { $sc_laststatus != 1 || $sc_lasttitle != $sc_responses($iServer,servertitle) || $sc_lastbitrate != $sc_responses($iServer,bitrate) } {
set strTopic "$sc_responses($iServer,servertitle) Online @ $sc_responses($iServer,bitrate)kbps - "
# append strTopic "http://$sc_servers($iServer,Name):$sc_servers($iServer,Port)$shoutcast(listen_page)"
set updateTopic 0
}
set sc_laststatus 1
set sc_lastbitrate $sc_responses($iServer,bitrate)
set sc_lasttitle $sc_responses($iServer,servertitle)
} else {
if { $sc_laststatus != 0 } {
set strTopic "Shoutcast: Offline"
set updateTopic 0
}
set sc_laststatus 1
set sc_lastbitrate 0
}
if { $updateTopic == 1 } {
# putserv "PRIVMSG $shoutcast(broadcast_channel) :$strTopic"
}
for { set i 0 } { $i < $sc_servercount } { incr i } {
if { $sc_responses($i,streamstatus) == 1 } {
if { $sc_responses($i,currentlisteners) != $sc_responses($i,lastlistenercount) } {
set sc_responses($i,lastlistenercount) $sc_responses($i,currentlisteners)
set strStream "$sc_servers($i,Name) - $sc_responses($i,currentlisteners) of $sc_responses($i,maxlisteners) connected (peaking at $sc_responses($i,peaklisteners))"
if { $sc_responses($i,currentlisteners) > 0 } {
append strStream ", utilising "
set iBandwidth [expr [expr $sc_responses($i,currentlisteners) * $sc_responses($i,bitrate)] / 8]
append strStream "$iBandwidth k/sec, for an average of [duration $sc_responses($i,averagetime)]."
}
sc_output "" $shoutcast(broadcast_channel) $strStream
}
}
}
return
}
proc sc_stream { nick uhost handle channel args } {
global shoutcast botnick sc_servers sc_responses sc_servercount
set strCommand "stream"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand $nick $uhost $channel $outArgs] == 0 } {
sc_output $nick $channel "Unable to execute command."
return
}
for { set i 0 } { $i < $sc_servercount } { incr i } {
set strStream "[expr $i + 1]) http://$sc_servers($i,Name):$sc_servers($i,Port)$shoutcast(listen_page) - "
if { $sc_responses($i,streamstatus) == 0 } {
append strStream "Offline"
sc_output $nick $channel $strStream
continue
} else {
append strStream "Online @ $sc_responses($i,bitrate)kbps - "
}
set iSlotsFree [expr $sc_responses($i,maxlisteners) - $sc_responses($i,currentlisteners)]
if { $iSlotsFree == 0 } {
append strStream "Server full."
sc_output $nick $channel $strStream
continue
} else {
set strAppend ""
if { $iSlotsFree > 1 } { set strAppend "s" }
append strStream "$iSlotsFree slot$strAppend remaining."
}
sc_output $nick $channel $strStream
}
return
}
proc sc_playing { nick uhost handle channel args } {
global shoutcast botnick sc_servers sc_responses sc_servercount
set strCommand "playing"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand $nick $uhost $channel $outArgs] == 0 } {
sc_output $nick $channel "Unable to execute command."
return
}
set iServer $shoutcast(primary_server)
set strStream "Primary server is currently offline."
if { $sc_responses($iServer,streamstatus) == 1 } {
set strStream "\00313,1\037\002Currently Playing: $sc_responses($iServer,songtitle)"
}
sc_output $nick $channel $strStream
}
proc sc_userstats { nick uhost handle channel args } {
global shoutcast botnick sc_servers sc_responses sc_servercount
set strCommand "users"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand $nick $uhost $channel $outArgs] == 0 } {
sc_output $nick $channel "Unable to execute command."
return
}
set iServersFound 0
for { set i 0 } { $i < $sc_servercount } { incr i } {
if { $sc_responses($i,streamstatus) == 0 } { continue }
set strStream "$sc_servers($i,Name) - $sc_responses($i,currentlisteners) of $sc_responses($i,maxlisteners) connected (peaking at $sc_responses($i,peaklisteners)), utilising "
set iBandwidth [expr [expr $sc_responses($i,currentlisteners) * $sc_responses($i,bitrate)] / 8]
append strStream "$iBandwidth k/sec, for an average of [duration $sc_responses($i,averagetime)]."
sc_output $nick $channel $strStream
incr iServersFound
}
if { $iServersFound == 0 } { sc_output $nick $channel "No active servers to list." }
return
}
proc sc_kickdj { nick uhost handle channel args } {
global shoutcast botnick sc_servers
set strCommand "sckickdj"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand $nick $uhost $channel $outArgs] == 0 } {
sc_output $nick $channel "Unable to execute command."
return
}
sc_output $nick $channel "DJ kicked from primary server."
}
proc sc_who { nick uhost handle channel args } {
global shoutcast botnick sc_servers sc_responses sc_servercount
set strCommand "scwho"
set args [string map -nocase {"\\" "\\\\"} $args]
set args [lindex $args 0]
set outArgs ""
if { [sc_execute_command [clock seconds] $strCommand $nick $uhost $channel $outArgs] == 0 } {
sc_output $nick $channel "Unable to execute command."
return
}
set iServersFound 0
for { set i 0 } { $i < $sc_servercount } { incr i } {
if { $sc_responses($i,streamstatus) == 0 } { continue }
set strStream "http://$sc_servers($i,Name):$sc_servers($i,Port)$shoutcast(admin_page)\n"
append strStream "[string repeat "-" [expr [string length $strStream] - 1]][string repeat " " $i]\n"
if { $sc_responses($i,listenerhosts) == "" } {
append strStream "No listeners currently connected."
} else {
set counter 1
foreach listener $sc_responses($i,listenerhosts) {
append strStream "$counter) [sc_nickfromhost $listener][string repeat " " $i][string repeat " " $counter]\n"
incr counter
}
}
append strStream "[string repeat " " [expr $i + 1]]\n"
sc_output $nick $channel $strStream
incr iServersFound
}
if { $iServersFound == 0 } { sc_output $nick $channel "No active servers to list." }
return
}
# ************************************************************************
# Script utility functions.
# ************************************************************************
proc sc_get_usage { command ischannelop } {
global shoutcast botnick
set command [string tolower $command]
set strMessage ""
if { $ischannelop && $command == "scwho" } {
append strMessage "Usage for $shoutcast(command_char)scwho follows.\n"
append strMessage "------------------------------------------------------------------\n"
append strMessage "Retrieves the list of people (nicks / hosts) currently listening\n"
append strMessage "------------------------------------------------------------------ "
} elseif { $command == "sckickdj" } {
append strMessage "Usage for $shoutcast(command_char)sckickdj follows.\n"
append strMessage "------------------------------------------------------------------\n"
append strMessage "Kicks the source from the server!\n"
append strMessage "------------------------------------------------------------------ "
} elseif { $command == "stream" } {
append strMessage "Usage for $shoutcast(command_char)stream follows.\n"
append strMessage "------------------------------------------------------------------\n"
append strMessage "Lists current streams.\n"
append strMessage "------------------------------------------------------------------ "
} elseif { $command == "playing" } {
append strMessage "Usage for $shoutcast(command_char)playing follows.\n"
append strMessage "------------------------------------------------------------------\n"
append strMessage "Shows current song.\n"
append strMessage "------------------------------------------------------------------ "
} elseif { $command == "users" } {
append strMessage "Usage for $shoutcast(command_char)users follows.\n"
append strMessage "------------------------------------------------------------------\n"
append strMessage "Shows user stats for all streams.\n"
append strMessage "------------------------------------------------------------------ "
} elseif { $ischannelop } {
#crap ....
} else {
#crap ....
}
return [string trim $strMessage "\n"]
}
proc sc_execute_command { timestamp command nick uhost channel args } {
global shoutcast sc_servers
set args [lindex $args 0]
switch -- $command {
"stream" {
sc_get_stats 0
}
"users" {
sc_get_stats 0
}
"scwho" {
sc_get_stats 0
}
"update" {
sc_get_stats 0
}
"playing" {
sc_get_stats 1
}
"sckickdj" {
set strHost $sc_servers($shoutcast(primary_server),Host);
set strPort $sc_servers($shoutcast(primary_server),Port);
set strPass $sc_servers($shoutcast(primary_server),Pass);
set strPageData [sc_get_page $strHost $strPort "$shoutcast(kickdj_page)&pass=$strPass"]
if { $strPageData == "" } { return 0 }
}
default {
return 1
}
}
return 1
}
proc sc_get_stats { primary_only } {
global shoutcast sc_servers sc_responses sc_servercount
for { set i 0 } { $i < $sc_servercount } { incr i } {
if { $primary_only == 1 && $i != $shoutcast(primary_server) } { continue }
set strHost $sc_servers($i,Host);
set strPort $sc_servers($i,Port);
set strPass $sc_servers($i,Pass);
set strPageData [sc_get_page $strHost $strPort "$shoutcast(interface_page)"]
if { $strPageData == "" } {
set sc_responses($i,streamstatus) 0
set sc_responses($i,currentlisteners) 0
set sc_responses($i,maxlisteners) 0
set sc_responses($i,peaklisteners) 0
set sc_responses($i,averagetime) 0
set sc_responses($i,servergenre) ""
set sc_responses($i,serverurl) "http://$sc_servers($i,Name):$sc_servers($i,Port)$shoutcast(listen_page)"
set sc_responses($i,servertitle) ""
set sc_responses($i,songtitle) ""
set sc_responses($i,bitrate) ""
set sc_responses($i,version) ""
set sc_responses($i,listenerhosts) ""
set sc_responses($i,lastlistenercount) 0
# Bail
continue
}
sc_parse_xml $strPageData $i sc_responses
}
}
proc sc_parse_xml { pagedata serverNumber outArray } {
upvar $outArray serverData
regexp "<status>(.*?)</status>" $pagedata data value
set serverData($serverNumber,streamstatus) $value
regexp "<total_nodes>(.*?)</total_nodes>" $pagedata data value
set serverData($serverNumber,currentlisteners) $value
regexp "<total_max_nodes>(.*?)</total_max_nodes>" $pagedata data value
set serverData($serverNumber,maxlisteners) $value
regexp "<total_peak_nodes>(.*?)</total_peak_nodes>" $pagedata data value
set serverData($serverNumber,peaklisteners) $value
regexp "<genre>(.*?)</genre>" $pagedata data value
set serverData($serverNumber,servergenre) $value
regexp "<url>(.*?)</url>" $pagedata data value
set serverData($serverNumber,serverurl) $value
regexp "<name>(.*?)</name>" $pagedata data value
set serverData($serverNumber,servertitle) $value
regexp "<meta_song>(.*?)</meta_song>" $pagedata data value
# Repair the song title (i.e. remove all XML elements)
# Specify remap template
set charRemap {
"<" "<"
">" ">"
"&" "&"
""" "\\"
"'" "'"
"ÿ" ""
}
set value [string map -nocase $charRemap $value]
set serverData($serverNumber,songtitle) $value
regexp "<bitrate>(.*?)</bitrate>" $pagedata data value
set serverData($serverNumber,bitrate) $value
regexp "<version>(.*?)</version>" $pagedata data value
set serverData($serverNumber,version) $value
set serverData($serverNumber,averagetime) 0
set serverData($serverNumber,listenerhosts) ""
set lstListener ""
set connectCount 0
if { [regexp "<total_nodes>(.*?)</total_nodes>" $pagedata data value] } {
set listenerdata $value
regsub -all "</total_node>" $listenerdata "</total_node>\n" listenerdata
set listenerdata [split $listenerdata \n]
foreach strListener $listenerdata {
if { [regexp "<name>(.*?)</name>" $strListener data value] } { lappend lstListener $value }
if { [regexp "<connect_time>(.*?)</connect_time>" $strListener data value] } {
incr serverData($serverNumber,averagetime) $value
incr connectCount
}
}
if { $connectCount > 0 } { set serverData($serverNumber,averagetime) [expr $serverData($serverNumber,averagetime) / $connectCount] }
}
set serverData($serverNumber,listenerhosts) $lstListener
}
proc sc_output { nick channel msg } {
global shoutcast
set strPrepend "PRIVMSG #shoutcast(broadcast_channel) :"
set line_array [split $msg "\n"]
foreach line $line_array { putserv "$strPrepend$line" }
}
# ------------------------------------------------------------------------
# Desc : Retrieve any data from any arbitrary page on any server / port.
# Note : Yes I know TCL 8 has an http API, but I don't want to rely
# on it being available. It's also not quite as flexible as we need.
# ------------------------------------------------------------------------
proc sc_get_page { host port page } {
global shoutcast sc_packet_count sc_page_dump_complete sc_sock sc_buffer errorInfo
set sc_page_dump_complete 0
set sc_packet_count 0
set sc_buffer ""
set urldump_Task [ after $shoutcast(page_timeout) { set sc_page_dump_complete 1; putlog "*** Page data retrieval timed out!" } ]
if [catch {socket -async $host $port} sc_sock] {
putlog "Shoutcast Error : $errorInfo"
after cancel $urldump_Task
return ""
}
fconfigure $sc_sock -blocking 0
fileevent $sc_sock readable "sc_read_page $sc_sock"
puts $sc_sock "GET $page HTTP/1.0\nHost: $host\nContent-type: text/plain\nUser-Agent: $shoutcast(interface_user_agent)\n\n"
if [catch {flush $sc_sock} x] {
putlog "Shoutcast Error : $errorInfo"
close $sc_sock
after cancel $urldump_Task
return ""
}
vwait sc_page_dump_complete
after cancel $urldump_Task
catch {close $sc_sock}
set sc_packet_count 0
set line_array [split $sc_buffer "\n"]
set header_closed 0
set sc_buffer ""
set i 0
foreach line $line_array {
if { $header_closed == 0 } {
switch $i {
0 {
set tokens [split $line " "]
set server_code [lindex $tokens 1]
#putlog "Server responded with $server_code [lrange $tokens 2 end]"
if { $server_code != 200 && $server_code != 302 } { return "" }
}
}
if { $line == "" } { set header_closed 1 }
} else {
append sc_buffer "$line\n"
}
incr i
}
regsub -all "\r" $sc_buffer "" sc_buffer
return [string trim $sc_buffer "\n"]
}
proc sc_read_page socket {
global sc_packet_count sc_page_dump_complete sc_buffer
if [eof $socket] {
close $socket;
set sc_packet_count 0
after idle set sc_page_dump_complete 1
return;
}
gets $socket data
append sc_buffer "$data\n"
incr sc_packet_count
}
proc urlencode { text } {
regsub -all {\%} $text "%25" text
set i [string length $text]
while {([regexp -nocase {[^a-z0-9%]} $text toh])&&!($i < 0 )} {
scan "$toh" %c dec
regsub -all "\\${toh}" $text "%[format %X $dec]" text
incr i -1
}
if {$i < 0} {putlog "Infinite loop something is very wrong: $text"}
return $text
}
proc sc_nickfromhost { host } {
global shoutcast
set FoundUsers 0
set NickList ""
set DuplicateList ""
foreach chan [channels] {
if { ![botonchan $chan] } { continue }
foreach user [chanlist $chan] {
if { [string match "* $user *" $DuplicateList] == 1} { continue }
set uhost "[getchanhost $user $chan]"
if { [string match -nocase "*@$host" $uhost] } {
append DuplicateList " $user "
if { $FoundUsers == 0 } {
append NickList $user
} else {
append NickList ", $user"
}
incr FoundUsers
}
}
}
if { $FoundUsers == 0 } { return "*!*@$host" }
set CharPos [string last , $NickList]
if { $CharPos == -1} { return $NickList }
set NickList "[string range $NickList 0 [expr $CharPos - 1]] or [string range $NickList [expr $CharPos + 2] 99999999]"
return $NickList
}
proc sc_isop { nick } {
global shoutcast
foreach chan [channels] {
if { ![botonchan $chan] } { continue }
if { [onchan $nick $chan] } {
if { [isop $nick $chan] } { return 1 }
}
}
return 0
}
putlog "** Shoutcast Stats Initialising $shoutcast(vershort) By ^DooM^ modded by coldfyre"
IRC Snippets