#######################################################################################################
## iceRadio 1.2 (23/04/2020) 		                 Copyright 2008 - 2020 @ WwW.TCLScripts.NET  ##
##                        _   _   _   _   _   _   _   _   _   _   _   _   _   _                      ##
##                       / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \ / \                     ##
##                      ( T | C | L | S | C | R | I | P | T | S | . | N | E | T )                    ##
##                       \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/                     ##
##                                                                                                   ##
##                                      ® BLaCkShaDoW Production ®                                   ##
##                                                                                                   ##
##                                              PRESENTS                                             ##
##									                           ® ##
########################################  ICE MINI RADIO TCL   ########################################
##									                             ##
##  DESCRIPTION: 						 	                             ##
##  Mini simple & easy to use script for iceCast servers ONLY.                                       ##
##        (works only if stream/radio is running/online)                                             ##
##									                             ##
##  !!! Supports ONLY iceCast servers !!!                                                            ##
##									                             ##
##  Tested on Eggdrop v1.8.3 (Debian Linux 3.16.0-4-amd64) Tcl version: 8.6.6                        ##
##									                             ##
#######################################################################################################
##									                             ##
##  INSTALLATION: 							                             ##
##     ++ http package is REQUIRED for this script to work.                                          ##
##     ++ Edit the iceRadio.tcl script and place it into your /scripts directory,                    ##
##     ++ add "source scripts/iceRadio.tcl" to your eggdrop config and rehash the bot.               ##
##									                             ##
#######################################################################################################
##									                             ##
##  CHANGELOG:                                                                                       ##
##  - 1.0 version                                                                                    ##
##    + auto announcing for currently playing songs.                                                 ##
##    + auto announcing the listeners count.                                                         ##
##    + flood protection settings against those who abuse the use of commands.                       ##
##    + added utf-8 support.                                                                         ##
##    + added maketiny to shorten radio listen links with tinyurl. 				     ##
##  - 1.1 version									             ##
##    + solved some compatibility issues with icecast2 version	       				     ##
##  - 1.2 version
##    + added support for multiple mount							     ##
##    + added !listeners command that also supports multiple mount                                   ##
##    + auto announcing the listeners count (foreach mount)					     ##
##    + solved some minor bugs                                                                       ##
##											             ##
#######################################################################################################
##									                             ##
##  OFFICIAL LINKS:                                                                                  ##
##   Bugs report : http://www.tclscripts.net                                                         ##
##   GitHub page : https://github.com/tclscripts/ 			                             ##
##   Online help : irc://irc.undernet.org/tcl-help                                                   ##
##                 #TCL-HELP / UnderNet        	                                                     ##
##                 You can ask in english or romanian                                                ##
##									                                                                 ##
##     paypal.me/DanielVoipan = Please consider a donation. Thanks!                                  ##
##									                                                                 ##
#######################################################################################################
##									                                                                 ##
##  THE MAGIC MAKERS (TCLscripts.net's team):                                                        ##
##                                                                                                   ##
##  o BLaCkShaDoW (Daniel) - coding 'magic' maker & the botsfather.                                  ##
##    BLaCkShaDoW@tclscripts.net [ www.tclscripts.net ]                                              ##
##									                                                                 ##
##  o Settore (Stefan) - generous hosting storage & bandwidth for tclscripts.net project website.    ##                                                                           ##
##    settore@tclscripts.net [ www.thedeveloper.site ]                                               ##
##									                                                                 ##
##  o Florian (most craziest imagination guy) - an earful of wonderful ideas for new scripts and all ##
##    the required/ necessary materials needed for our eggdrops to run & tcl scripts to be released. ##
##    florian@tclscripts.net [ www.tntradio.ro ]                                                     ##
##									                                                                 ##
##  o Time2Go (Ionut) - [ #Tcl-Help Admin ] retired..                                                ##
##									                                                                 ##
##  o zeke - our secret demon "behind the hood".                                                     ##
##    zeke@tclscripts.net [ www.tclscripts.net ]                                                     ##
##									                                                                 ##
#######################################################################################################
##									                                                                 ##
##                           You want a customised TCL Script for your eggdrop?                      ##
##                                Easy-peasy, just tell us what you need!                            ##
##               We can create almost anything in TCL based on your ideas and donations.             ##
##                  Email blackshadow@tclscripts.net or info@tclscripts.net with your                ##
##                   request informations and we'll contact you as soon as possible.                 ##
##									                                                                 ##
#######################################################################################################
##									                                                                 ##
##  COMMANDS:                                                                                        ##
##								                                                                     ##
##  To activate:                                                                                     ##
##  .chanset +iceradio | from BlackTools: .set #chan +iceradio                                       ##
##									                                                                 ##
##  !links - shows the radio listen links.                                                           ##
##									                                                                 ##
##  !radio - shows the song, listeners, radio website url.                                           ##
##									                                                                 ##
##  !radio -version - shows the actual tcl script version.                                           ##
##									                                                                 ##
##  !!! ATTENTION !!!                                                                                ##
##									                                                                 ##
##  + ONLY iceCast servers are supported.                                                            ##
##  + Works only if stream/radio is running/online.                                                  ##
##									                                                                 ##
#######################################################################################################
##									                                                                 ##
##  PERSONAL AND NON-COMMERCIAL USE LIMITATION.                                                      ##
##									                                                                 ##
##  This program is provided on an "as is" and "as available" basis, with ABSOLUTELY NO WARRANTY.    ##
##  Use it at your own risk.                                                                         ##
##									                                                                 ##
##  Use this code for personal and NON-COMMERCIAL purposes ONLY.                                     ##
##									                                                                 ##
##  Unless otherwise specified, YOU SHALL NOT copy, reproduce, sublicense, distribute, disclose,     ##
##  create derivatives, in any way ANY PART OF THIS CONTENT, nor sell or offer it for sale.          ##
##									                                                                 ##
##  You will NOT take and/or use any screenshots of this source code for any purpose without the     ##
##  express written consent or knowledge of author(s)/co-author(s).                                  ##
##									                                                                 ##
##  You may NOT alter or remove any trademark, copyright or other notice from this source code.      ##
##									                                                                 ##
##                        Copyright 2008 - 2019 @ WwW.TCLScripts.NET                                 ##
##									                                                                 ##
#######################################################################################################

#######################################################################################################
##                                            CONFIGURATIONS                                         ##
#######################################################################################################

###
#Set here the radio name
set iceradio(radio_name) "My Radio"

###
#Set here the ip:port
set iceradio(ip_port) "penuel.itmate.net:8010"

###
#Set here the radio /mount
set iceradio(mount) {
"mountname"
}
###
#Set here the radio website url (will appear next to the now playing song)
set iceradio(website_url) "www.penuel.itmate.net"

###
#Here are the links for !links cmd ( url link )
set iceradio(links_links) {
{ Browser http://myradio.com/player }
{ Winamp https://www.myradio.com/listen.pls }
{ TuneIn http://tunein.com/radio/TNT-Radio-s221539 }
}

###
#Here is the now playing message
set iceradio(now_playing) "Currently Playing: %song%"

###
#Here is the listeners message (if they change)
set iceradio(listeners) "\002$iceradio(radio_name)\002 current listeners:\002 %listeners%\002 (\/%mount%)."

###
#Here is the !links message
set iceradio(links_message) "Listen \002$iceradio(radio_name)\002 on %name% → \037%link%\037"

###
#Here is the !listeners message
set iceradio(listeners_message) "\002$iceradio(radio_name)\002 current listeners: %listeners%"

###
#Here is the !radio message
set iceradio(radio_message) "Now on \002$iceradio(radio_name)\002 : %song% with %listeners% listeners on $iceradio(website_url)"

###
# FLOOD PROTECTION
# - set the number of minute(s) to ignore flooders (0 to disable)
###
set iceradio(ignore_prot) "1"

###
#Here is the flood message
set iceradio(flood_text) "Flood protection enabled. You need to wait\002 %get_seconds% seconds\002 before using commands again."

###
# FLOOD PROTECTION
# - set the number of !links before trigger flood protection.
# By default, 3:10, which allows for upto 3 queries in 10 seconds. 
# 3 or more quries in 10 seconds would cuase the forth and later 
# queries to be ignored for the amount of time specifide above.
###
set iceradio(flood_prot) "3:10"

###
#script banner
set iceradio(banner_radio) "\[R\]"

###
# Cmdchar trigger
# - set here the trigger you want to use.
set iceradio(char) "."

#######################################################################################################
###                       DO NOT MODIFY HERE UNLESS YOU KNOW WHAT YOU'RE DOING                      ###
#######################################################################################################

package require http

###
# Bindings
# - using commands
bind time - "* * * * *" iceradio:timer
bind pub - $iceradio(char)links iceradio:links
bind pub - $iceradio(char)radio iceradio:cmds
bind pub - $iceradio(char)listeners iceradio:listeners

###
# Channel flags
setudef flag iceradio

proc iceradio:radio_cmd {nick host hand chan arg} {
	global iceradio
	set listeners ""
	set current_song ""
	set listeners [iceradio:getinfo "listeners"]
if {$listeners == "-1"} { 
	puthelp "PRIVMSG $chan :\002$iceradio(banner_radio)\002 No info at the moment."
	return
}
foreach entry $listeners {
	set num [lindex $entry 0]
	set mount [lindex $entry 1]
	lappend output "\002$num\002\(\/$mount\)"
		}
	set current_song [iceradio:getinfo "song"]
	set replace(%listeners%) [join $output ", "]
	set replace(%song%) $current_song
	puthelp "PRIVMSG $chan :\002$iceradio(banner_radio)\002 [string map [array get replace] $iceradio(radio_message)]"
}


###
proc iceradio:listeners {nick host hand chan arg} {
	global iceradio
	set output ""
if {[channel get $chan iceradio]} {
if {$iceradio(ignore_prot) != "0"} {
	set flood_protect [iceradio:flood:prot $chan $host]
if {$flood_protect == "1"} {
	set get_seconds [iceradio:get:flood_time $host $chan]
	set replace(%get_seconds%) $get_seconds
	puthelp "NOTICE $nick :$iceradio(banner_radio) \002$nick\002: [string map [array get replace] $iceradio(flood_text)]"
	return
			}
	
		}
	set listeners [iceradio:getinfo "listeners"]
if {$listeners == "-1"} { 
	puthelp "PRIVMSG $chan :\002$iceradio(banner_radio)\002 No info at the moment."
	return
}
foreach entry $listeners {
	set num [lindex $entry 0]
	set mount [lindex $entry 1]
	lappend output "\002$num\002 listeners \(\/$mount\)"
		}
	set replace(%listeners%) [join $output ", "]
	puthelp "PRIVMSG $chan :\002$iceradio(banner_radio)\002 [string map [array get replace] $iceradio(listeners_message)]"
	}
}

###
proc iceradio:links {nick host hand chan arg} {
	global iceradio
if {[channel get $chan iceradio]} {
if {$iceradio(ignore_prot) != "0"} {
	set flood_protect [iceradio:flood:prot $chan $host]
if {$flood_protect == "1"} {
	set get_seconds [iceradio:get:flood_time $host $chan]
	set replace(%get_seconds%) $get_seconds
	puthelp "NOTICE $nick :$iceradio(banner_radio) \002$nick\002: [string map [array get replace] $iceradio(flood_text)]"
	return
	}
}
foreach ap $iceradio(links_links) {
	set name [lindex $ap 0]
	set link [maketiny [lindex $ap 1]]
	set replace(%name%) $name
	set replace(%link%) $link
	puthelp "PRIVMSG $chan :\002$iceradio(banner_radio)\002 [string map [array get replace] $iceradio(links_message)]"
		}
	}
}


###
proc iceradio:timer {min hour day mon year} {
	global iceradio
	set channels ""
	set new_song 0
	set listeners_list ""
	set new_listeners 0
	array set listen [list]
foreach chan [channels] {
if {[channel get $chan iceradio]} {
	lappend channels $chan
		}
	}
if {$channels != ""} {
	set current_song [iceradio:getinfo "song"]
if {$current_song == ""} { return }
	set listeners [iceradio:getinfo "listeners"]
if {![info exists iceradio(current_song)]} {
	set new_song 1
	set iceradio(current_song) $current_song
} elseif {$iceradio(current_song) != $current_song} {
	set new_song 1
	set iceradio(current_song) $current_song
}
if {![info exists iceradio(current_listeners)]} {
	set new_listeners 1
	set iceradio(current_listeners) $listeners
} else {
	set llength_mount [llength $iceradio(current_listeners)]
for {set i 0} { $i < $llength_mount} { incr i} {
	set saved_mount [lindex $iceradio(current_listeners) $i]
	set current_mount [lindex $listeners $i]
if {$saved_mount != $current_mount} {
	lappend listeners_list $current_mount
	}
}
if {$listeners_list != ""} {
	set new_listeners 1
	set iceradio(current_listeners) $listeners	
			}
		}
	iceradio:timer:act $channels 0 $current_song $listeners_list $new_song $new_listeners
	}
}

###
proc iceradio:reset {} {
	global iceradio
if {[info exists iceradio(current_song)]} {
	unset iceradio(current_song)
	}
if {[info exists iceradio(current_listeners)]} {
	unset iceradio(current_listeners)
	}
}

###
proc iceradio:timer:act {channels num current_song listeners new_song new_listeners} {
	global iceradio
	set chan [lindex $channels $num]
	set replace(%song%) $current_song
if {$current_song == "-1"} { 
	iceradio:reset
	return 
}
if {$new_song == "1"} {
	putserv "PRIVMSG $chan :\002$iceradio(banner_radio)\002 [string map [array get replace] $iceradio(now_playing)] ( -\002 $iceradio(website_url)\002 - )"
}
if {$new_listeners == "1"} {
if {$listeners == ""} {
	set listeners $iceradio(current_listeners)
}
foreach entry $listeners {
	set num [lindex $entry 0]
	set mount [lindex $entry 1]
	set replace(%mount%) $mount
	set replace(%listeners%) $num
	putserv "PRIVMSG $chan :\002$iceradio(banner_radio)\002 [string map [array get replace] $iceradio(listeners)]"
	}
}
	set counter [expr $num + 1]
if {[lindex $channels $counter] != ""} {
	utimer 2 [list iceradio:timer:act $channels $counter $current_song $listeners $new_song]
	}
}

###
proc iceradio:getinfo {type} {
	global iceradio
	set info ""
	set data [iceradio:getdata]
if {$data == "-1"} { return -1 }
if {[string equal -nocase $type "song"]} {
	return [iceradio:get_song $data]
} elseif {[string equal -nocase $type "listeners"]} {
	return [iceradio:get_listeners $data]
	}
}

###
proc iceradio:get_song {data} {
	global iceradio
	set song ""
	set song_2 ""
	set s_data [split $data "\n"]
	regexp {Current Song:</td><td class="streamdata">(.*)} $data song
	regexp {Currently playing:</td><td class="streamstats">(.*)} $data song_2
if {$song != ""} {
	regsub -all {</td></tr></table></div(.*)} $song "" song
	set song [encoding convertfrom utf-8 [iceradio:filter $song]]
} elseif {$song == "" && $song_2 != ""} {
	regsub -all {</td></tr></tbody>(.*)} $song_2 "" song
	set song [encoding convertfrom utf-8 [iceradio:filter $song]]
} else {
	set counter 0
foreach line $s_data {
if {[string match -nocase "*Current Song:*" $line]} {
	set song [lindex $s_data [expr $counter + 1]]
	break
			}
	set counter [expr $counter + 1]
		}
	}
	return [encoding convertfrom utf-8 [iceradio:filter $song]]
}

###
proc iceradio:get_listeners {data} {
	global iceradio
	set listeners ""
	set current ""
	set list_listeners ""
foreach m $iceradio(mount) {
	set text "Mount Point /$m\(.*\)"
	regexp -nocase $text $data listeners
	regsub -all {</td></tr><tr><td>Peak Listeners:</td>(.*)} $listeners "" line
	regexp {Current Listeners:(.*)} $line current
	if {$current == ""} {
	regexp {Listeners \(current\):</td><td class="streamstats">(.*?)</tr>} $line -> current
	}
	lappend list_listeners [list [iceradio:filter $current]	$m]
	}
	return $list_listeners
}

###
proc iceradio:getdata {} {
	global iceradio
	set link "http://$iceradio(ip_port)"
	set ipq [http::config -useragent "lynx"]
	set error [catch {set ipq [http::geturl $link -timeout 5000]} eror]
	set status [http::status $ipq]
if {$status != "ok"} { return }
	set getipq [http::data $ipq]
	::http::cleanup $ipq
	return $getipq
}

###
proc iceradio:filter {data} {
	global iceradio
	set text [string map { "Current Song:" ""
							"Peak Listeners:" ""
							"</td><td class=\"streamdata\">" ""
							"</td><td class=\"streamdata\">" ""
							"<td class=\"streamdata\">" ""
							"Currently playing:<td class=\"streamstats\">" ""
							"Listeners (current):</td><td class=\"streamstats\">" ""
							"</td>" ""
							"&amp;" "&"
							"&apos;" "'"
							"&gt;" ">"
							"&lt;" "<"
							"<a>" ""
							"</a>" ""
							 "Current Listeners:</td><td class=\"streamdata\">" ""
							} $data]
	return $text
}

###
proc iceradio:flood:prot {chan host} {
	global iceradio
	set number [scan $iceradio(flood_prot) %\[^:\]]
	set timer [scan $iceradio(flood_prot) %*\[^:\]:%s]
if {[info exists iceradio(flood:$host:$chan:act)]} {
	return 1
}
foreach tmr [utimers] {
if {[string match "*iceradio:remove:flood $host $chan*" [join [lindex $tmr 1]]]} {
	killutimer [lindex $tmr 2]
	}
}
if {![info exists iceradio(flood:$host:$chan)]} { 
	set iceradio(flood:$host:$chan) 0 
}
	incr iceradio(flood:$host:$chan)
	utimer $timer [list iceradio:remove:flood $host $chan]	
if {$iceradio(flood:$host:$chan) > $number} {
	set iceradio(flood:$host:$chan:act) 1
	utimer [expr $iceradio(ignore_prot) * 60] [list iceradio:expire:flood $host $chan]
	return 1
	} else {
	return 0
	}
}

###
proc iceradio:remove:flood {host chan} {
	global iceradio
if {[info exists iceradio(flood:$host:$chan)]} {
	unset iceradio(flood:$host:$chan)
	}
}

###
proc iceradio:expire:flood {host chan} {
	global iceradio
if {[info exists iceradio(flood:$host:$chan:act)]} {
	unset iceradio(flood:$host:$chan:act)
	}
}

###
proc iceradio:get:flood_time {host chan} {
	global iceradio
		foreach tmr [utimers] {
if {[string match "*iceradio:expire:flood $host $chan*" [join [lindex $tmr 1]]]} {
	return [lindex $tmr 0]
		}
	}
}

###
proc iceradio:cmds {nick host hand chan arg} {
	global iceradio
	if {![channel get $chan iceradio]} {
		return
	}
if {$iceradio(ignore_prot) != "0"} {
	set flood_protect [iceradio:flood:prot $chan $host]
	if {$flood_protect == "1"} {
		set get_seconds [iceradio:get:flood_time $host $chan]
		set replace(%get_seconds%) $get_seconds
		putserv "NOTICE $nick :$iceradio(banner_radio) \002$nick\002: [string map [array get replace] $iceradio(flood_text)]"
		return
	}
}
	set set [lindex [split $arg] 0]
	switch $set {
		-version {
		putserv "PRIVMSG $chan :\002$iceradio(projectName) $iceradio(version)\002 coded by\002 $iceradio(author)\002 ($iceradio(email)) --\002 $iceradio(website)\002. PRIVATE TCL available only on donations."
		}
		rules {
		putserv "PRIVMSG $chan :\002$iceradio(banner_radio)\002 $chan rules:  (Language:\002 ENGLISH\002) (No Swearing, Politics, Religion, Trolling, Racism, Sex Talk, Harassment, Abuse, Flooding)"
		}
		help {
		putserv "NOTICE $nick :\002$iceradio(banner_radio)\002 Commands: \002$iceradio(char)radio\002 \[?|help\] ; \002$iceradio(char)links\002 ; \002$iceradio(char)radio\002 ; \002$iceradio(char)radio\002 rules ; \002$iceradio(char)radio\002 -version"
		}
		\? {
		putserv "NOTICE $nick :\002$iceradio(banner_radio)\002 Commands: \002$iceradio(char)radio\002 \[?|help\] ; \002$iceradio(char)links\002 ; \002$iceradio(char)radio\002 ; \002$iceradio(char)radio\002 rules ; \002$iceradio(char)radio\002 -version"
		}
		default {
		iceradio:radio_cmd $nick $host $hand $chan $arg
		}
	}
}

###
# Thanks to speechless
# http://forum.egghelp.org/viewtopic.php?t=11277&start=179
proc maketiny {url} {
	set ua "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5"
	set http [::http::config -useragent $ua -useragent "utf-8"]
	set token [http::geturl "http://tinyurl.com/api-create.php?[http::formatQuery url $url]" -timeout 3000]
	upvar #0 $token state
if {[string length $state(body)]} { return $state(body) }
	return $url
}

###
# Credits
set iceradio(projectName) "iceRadio"
set iceradio(author) "BLaCkShaDoW"
set iceradio(website) "wWw.TCLScriptS.NeT"
set iceradio(email) "blackshadow\[at\]tclscripts.net"
set iceradio(version) "v1.2"

putlog "\002$iceradio(projectName) $iceradio(version)\002 by\002 $iceradio(author)\002 ($iceradio(website)): Loaded & initialised.."

##################
#######################################################################################################
###                  *** END OF ICE RADIO TCL ***                                                   ###
#######################################################################################################
