#
# goear.tcl 1.0.1 --
# This script for eggdrop gets the mp3 path file from a goear.com link
# It also creates a tinyurl to download it
#
# Copyright (c) 2007-2009 Eggdrop Spain 12-april-2009
#   HackeMate (Sentencia) Sentencia@eggdrop.es
#
# This program is free software; you can redistribute it and/or
# modify it _only for your own use_
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
#
# Please, use the email to contact with the author for let him know about all
# what you could do. Everyone wants develop his software as well.
#
#                   Thank you for feed my empiric life.
#
# If you like, you can contact with the author to suggest him features. By the
# way, do not ask him to make Login, he is working on that.

#   -*- IMPORTANT -*-
#       Auto Update checker: You can verify if your goear copy is the lastest
#       version available typing .goear update [yes for auto download] in partyline
#
#       FeedBack feature. Type in partyline .goear feedback [your email] <message>
#       to send the author any suggestion or comment. Insults are not welcome.

# This is what you need to get this script work:
# Type in partyline: .chanset #channel +goear
# or channel !goear enable

global goear
setudef flag goear
setudef flag goearcolors

# Should I create a tinyurl to show the download link?
# (1) Enable (0) Disable
set goear(tinyurl) 1

# Do you want auto update this file when it is possible?
# (1) Yes (0) No - It is recommended, if youtube changes his tags probably this script will broke
set goear(autoupdate) 1

# Do you want see all matches at one line? (0) Yes (1) No
set goear(multiline) 1

# Time in seconds to prevent flood
set goear(rest) 10

# Limit of links at same time
set goear(max) 5

# This is the final output message what you will read in your channel.
# You can configure all fields that your eggdrop will show.
# <title>       will return the title of the song
# <artist>      will return the artist of the song
# <file>        will return the link or tinyurl link for download it directly

set goear(output) "Download the mp3 file at \037\00312<file>\003\037 (<artist> - <title>)"


bind pub - !goear goearPub
bind pub - !googear googearPub

set goear(author) "HackeMate"
set goear(contact) "HackeMate <Sentencia@eggdrop.es>"
set goear(fileName) [info script]
set goear(projectName) "LeechGoear"
set goear(name) "Goear"
set goear(version) "1.0.1"
set goear(package.http) [package require http]
set goear(protection) ""

proc goearPub {nick uhost hand chan text} {
	if {![channel get $chan goear]} {
		if {$text eq "enable"} {
			channel set $chan +goear
			goearLog $chan "Usage: !googear <search string> To see a list of matches. !goear <weblink | id (if  you know what it is)> to get the direct download link for mp3"
			putserv "NOTICE $nick :You also can use .goear update and .goear feedback in partyline to upgrade your script or send a feedback to author of this script."
			return
		} else {
			putserv "NOTICE $nick :$chan has this command disabled."
		}
		if {[matchattr $hand n]} {
			putserv "NOTICE $nick :You can enable it directly typing: /msg $chan !goear enable"
		}
        return
    }
    global goear
    if {$text eq ""} {
        return
    }
	if {![info exists goear(protection)]} {
		set goear(protection) [clock seconds]
	} else {
		if {![string is digit -strict $goear(protection)]} {
			set goear(protection) [clock seconds]
		} else {
			set time [expr [clock seconds]-$goear(protection)]
			if {$time >= $goear(rest)} {
				set goear(protection) [clock seconds]
			} else {
				goearLog log "Flood protection in $chan from $nick\."
				return
			}
		}
	}
    set info [goearSong $chan $text]
    if {$info eq ""} {
        return 
    }
    set file [lindex $info 0]
    set artist [lindex $info 1]
    set title [lindex $info 2]
    putserv "PRIVMSG $chan :[string map [list "<artist>" $artist "<title>" $title "<file>" $file] $goear(output)]"
}

proc googearPub {nick uhost hand chan text} {
    
    if {![channel get $chan goear]} {
		if {$text eq "enable"} {
			channel set $chan +goear
            channel set $chan +goearcolors
			goearLog $chan "Usage: !googear <search string> To see a list of matches. !goear <weblink | id (if you know what it is)> to get the direct download link for mp3"
			putserv "NOTICE $nick :You also can use .goear update and .goear feedback in partyline to upgrade your script or send a feedback to author of this script."
			return
		} else {
			putserv "NOTICE $nick :$chan has this command disabled."
		}
		if {[matchattr $hand n]} {
			putserv "NOTICE $nick :You can enable it directly typing: /msg $chan !goear enable"
		}
        return
    }
    regsub -all -- {\017|\002|\037|\026|\003(\d{1,2})?(,\d{1,2})?} $text "" arg
	global goear
	# This is a generic protection to prevent flood goear.com
    # No utimer required
	#
	if {![info exists goear(protection)]} {
		set goear(protection) [clock seconds]
	} else {
		if {![string is digit -strict $goear(protection)]} {
			set goear(protection) [clock seconds]
		} else {
			set time [expr [clock seconds]-$goear(protection)]
			if {$time >= $goear(rest)} {
				set goear(protection) [clock seconds]
			} else {
				goearLog log "Flood protection in $chan from $nick\."
				return
			}
		}
	}

	if {$arg eq ""} {
		putserv "NOTICE $nick :Tell me what to search."
		return
	}
    set data [googearGet $arg]
    
    if {![channel get $chan goearcolors]} {
		regsub -all -- {\017|\002|\037|\026|\003(\d{1,2})?(,\d{1,2})?} $data "" data
	}
	if {[string length $data] == 0} {
		set data "I was unable to connect to that website. Probably I get timeout."
        return
	}
	if {$goear(multiline) != "1"} {
		putserv "PRIVMSG $chan :$data"
	} else {
		foreach line $data {
			putserv "PRIVMSG $chan :$line"
		}
	}  
}

proc googearGet {ask} {
    
    global goear
    regsub -all -- {\s+} $ask " " search
    set search [http::formatQuery $search]
    http::config -useragent "Mozilla/5.0 (Windows NT; U; Windows NT x86; en-ES; rv:1.9.0.3) Firefox 3.0.7" -accept "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    set token [http::geturl http://www.goear.com/search.php?q=$search -timeout 10000]
    upvar #0 $token state
    set ncode ""
    regexp {[0-9]{3}} $state(http) ncode
    if {$ncode eq ""} {
        set ncode $state(http)
    }
    set list {}
    switch -- $ncode {
        "200" {
            set songs [regexp -all -inline {<strong><a title=(.*?) class="escuchar">} $state(body)]
            set total [expr [llength $songs] /2]
            if {$total > $goear(max)} {
                set list [list "Showing $goear(max) of $total."]
            }
            set i 2
            foreach {id line} $songs {
                #set map {}
                #foreach {entity number} [regexp -all -inline {&#(\d+);} $line] {
                #    lappend map $entity [format \\u%04x [scan $number %d]]
                #}
                #set line [string map [subst -nocomm -novar $map] $line]
                set line [split $line {"}]
                set song [lindex $line 1]
                set id [lindex [split [lindex $line 3] "/"] 1]
                set link "http://www.goear.com/listenwin.php?v=$id"
                lappend list "\($song\) \00312\037$link\003\037"
                if {$i > $goear(max)} {
                    break
                }
                incr i
            }


            return $list
        }
        "404" {
            goearLog log "No such file or webpage."
            http::cleanup $token
            return [list "No such file or webpage."]
        }
        default {
            goearLog log "unforeseen circumstance. Server responded: $ncode"
            http::cleanup $token
            return [list "unforeseen circumstance. Server responded: $ncode"]
        }

    }
    
    
}
proc goearXml {chan id} {
    
    # http://www.goear.com/files/xmlfiles/9/secm9ec21f3.xml
    set i [string index $id 0]
    http::config -useragent "Mozilla/5.0 (Windows NT; U; Windows NT x86; en-ES; rv:1.9.0.3) Firefox 3.0.7" -accept "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
    set token [http::geturl http://www.goear.com/files/xmlfiles/$i/secm$id.xml]
    upvar #0 $token state
    set data $state(body)
    regexp {[0-9]{3}} $state(http) ncode
    if {$ncode eq ""} {
        set ncode $state(http)
    }
    switch -- $ncode {
        "200" {
            regexp {<song path="(.*?)"} $data "" file
            regexp {artist="(.*?)"} $data "" artist
            regexp {title="(.*?)"} $data "" title
            http::cleanup $token
            return [list 200 $file $artist $title]
        }
        default {
            return $ncode
        }
    }
}

proc goearId {chan url} {
    
    set isId [lindex [split $url "="] end]
    if {[string length $isId] != 7} {
        set isId [lindex [split $url "/"] 4]
    }
    if {[string length $isId] != 7} {
        set isId $url
    }
    if {[string length $isId] != 7} {
        return -1
    }
    return $isId
}

proc goearSong {chan url} {
    
    global goear
    set xml [goearXml $chan [goearId $chan $url]]
    set ncode [lindex $xml 0]
    set file [lindex $xml 1]
    set artist [lindex $xml 2]
    set title [lindex $xml 3]
    
    if {$ncode == 200} {
        if {$goear(tinyurl)} {
            set file [goearTinyurl $file]
        }
    } else {
        goearLog $chan "unforeseen circumstances. Server responded: ERROR $ncode"
        return 
    }
    return [list $file $artist $title]
}

proc goearTinyurl {url} {
    
    if {![regexp -nocase {^(http://)?([^/:]+)(:([0-9]+))?(/.*)?$} $url]} {
        return -1
    }
    set token [http::geturl http://tinyurl.com/create.php -query [http::formatQuery url $url]]
    upvar #0 $token state
    regexp {<small>\[<a href="(.*?)" target} $state(body) "" link; puts $link
    http::cleanup $token
    return $link
}

proc goearLog {target string} {
    global goear
    if {![validchan $target]} {
        putlog "$goear(name)\: $string"
    } else {
        putserv "PRIVMSG $target :$goear(name)\: $string"
    }
}

bind dcc n goear communication::welcome

namespace eval communication {
	
	# communication.tcl --
	# 	This is a little library for eggdrop as internal use
	# 	It is done to portablility - You cannot use it without a file.cgi in your
	# 	http server. If you really want that, contact me.	
	variable version 1.0
	variable feedback {http://www.eggdrop.es/cgi-bin/feedback.cgi}
	variable update {http://www.eggdrop.es/cgi-bin/update.cgi}
	
	proc welcome {hand ipx text} {
		global goear
		set arg [lindex [split $text] 0]
		switch -- $arg {
			"feedback" {
				set contact [lindex [split $text] 1]
				set message [join [lrange [split $text] 1 end]]
				if {($contact eq "") || ($message eq "")} {
					putdcc $ipx "$goear(projectName) - FeedBack"
					putdcc $ipx "Thank you for tell what you think."
					putdcc $ipx "This command sends to author an message with your suggestion, you are able to send one feedback per day (aprox)"
					putdcc $ipx "Usage: .webfeedback <your email (put it if you may want a reply or conversation with author, if not, put anything)> <tell me in english or spanish what you want say>"
				} else {
					set result [[namespace current]::Feedback $contact $goear(projectName) $message]
					if {$result eq ""} {
						putdcc $ipx "The server responded nothing. Did you sent a previous feedback already?"
						return
					}
					putdcc $ipx "The server responded:"
					foreach line [split $result \n] {
						putdcc $ipx $line
					}
				}
			}
			"update" {
				set download [lindex [split $text] 1]
				putdcc $ipx [join [lrange [split [[namespace current]::Update $goear(fileName) $goear(projectName) $goear(version) $download]] 1 end]]
			}
			default {
				putdcc $ipx "You can use '.goear update' to verify the last version and '.goear feedback' to send to author a suggestion"
			}
		}
	}
	
	proc Feedback {reporter projectName message} {
		variable feedback
		http::config -useragent "$reporter $projectName"
		set token [http::geturl "$feedback\?suggest=[http::formatQuery $message]" -timeout 4000]
		set data [http::data $token]
		http::cleanup $token
		return $data
	}
	
	proc Update {fileName projectName version {download ""}} {
		variable update
		set fs [open $fileName]
		set data [read $fs]
		close $fs
		set md5 [md5 $data]
		set query [http::formatQuery project $projectName version $version md5 $md5 download $download]
		set token [http::geturl "$update\?$query" -timeout 4000]
		set data [http::data $token]
		http::cleanup $token
        set result ""
        set info ""
        set url ""
		regexp {<!-- result -->(.*?)<!-- /result -->} $data "" result
		regexp {<!-- info -->(.*?)<!-- /info -->} $data "" info
		if {($download ne "") && ($download ne "no") && ($result == 1)} {
			regexp {<!-- data -->(.*?)<!-- /data -->} $data "" url
			if {![regexp -nocase {^(http://)?([^/:]+)(:([0-9]+))?(/.*)?$} $url]} {
				return "0 Invalid URL target file link."
			}
			set token [http::geturl $url -binary 1 -timeout 4000]
			set fileData [http::data $token]
            file rename -force -- $fileName $fileName\.bak
			set fs [open $fileName w]
			puts -nonewline $fs $fileData
			close $fs
            rehash
			set info "$projectName was (purged) downloaded and sourced succesfully, now you are using the lastest version available. There is a backup in $fileName\.bak"        
        }
		return "$result $info"
	}
}
if {![info exists goear(loaded)]} {
    set goear(status) [communication::Update $goear(fileName) $goear(projectName) $goear(version) $goear(autoupdate)]
    set goear(result) [lindex [split $goear(status)] 0]
    set goear(info) [join [lrange [split $goear(status)] 1 end]]
    goearLog log $goear(info)
} 
goearLog log "[file tail $goear(fileName)] $goear(version) Loaded - by $goear(author) (Feedback and update commands available, type .goear in partyline)"
set goear(loaded) 1