youtube script
#16
11:06:52am / * <iRoc> http://youtu.be/YIBo4yvLkfU
11:06:53am / * <iB0T> Raanjhanaa - Title Track ft. Dhanush & Sonam Kapoor - YouTube' ( 2 minutes 22 seconds ) Viewed 1.018.908
11:06:57am / * <iRoc> http://www.youtube.com/watch?v=69HNy2r7f-M
11:06:58am / * <iB0T> Let's Battle Minecraft S4 #3 [Battlemap/HD/German] - Geht weg :( - YouTube' ( 16 minutes 28 seconds ) Viewed 5.372



tcl
package require http 2.4
bind PUBM - * mu
proc mu {nick uhost hand chan text} {
	set web(page) http://www.youtube.com
	set watch [regexp -nocase -- {\/watch\?v\=([^\s]{11})} $text youtubeid]
	if { $watch == 0 } {
		set watch [regexp -nocase -- {youtu\.be\/([^\s]{11})} $text a youtubeid]
		if { $watch == 0 } return
		set youtubeid "/watch?v=$youtubeid"
	}
 
	set logoo "\002\00301,00You\00300,04Tube\002\017"
 
	if {$watch && $youtubeid != ""} {
		putlog "$web(page)$youtubeid"
		set agent "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1"     
		set t [::http::config -useragent $agent]
		set t [::http::geturl "$web(page)$youtubeid" -timeout 30000]
		set data [::http::data $t]
		::http::cleanup $t
 
		set l [regexp -all -inline -- {<title>(.*?)</title>.*?<span class="watch-view-count " >(.*?)</span>} $data]
 
		regexp {"length_seconds": (\d+),} $data "" length
 
		foreach {black a b c d e} $l {
 
			set a [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $a]
			set b [string map [list \n ""] $b]
			set c [string map [list \n ""] $c]
			set d [string map [list \n ""] $d]
			set e [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $e]
 
			regsub -all {<.*?>} $a {} a
			regsub -all {<.*?>} $b {} b
			regsub -all {<.*?>} $c {} c
			regsub -all {<.*?>} $d {} d
			regsub -all {<.*?>} $e {} e			
 
			putserv "PRIVMSG $chan :$a' ( [duration $length] ) Viewed $b"
 
			    proc duration {s} {
				variable etube
				set hours [expr {$s / 3600}]
				set minutes [expr {($s / 60) % 60}]
				set seconds [expr {$s % 60}]
				set res ""
 
				if {$hours != 0} {append res "$hours hours"}				
				if {$minutes != 0} {append res " $minutes minutes"}
				if {$seconds != 0} {append res " $seconds seconds"}
				return $res
 
			}	
		}
	}
}


Répondre Avertir
#17
tcl
package require http 2.4
bind PUBM - * mu
proc mu {nick uhost hand chan text} {
   set web(page) http://www.youtube.com
   set watch [regexp -nocase -- {\/watch\?v\=([^\s]{11})} $text youtubeid]
   if { $watch == 0 } {
      set watch [regexp -nocase -- {youtu\.be\/([^\s]{11})} $text a youtubeid]
      if { $watch == 0 } return
      set youtubeid "/watch?v=$youtubeid"
   }
 
   set logoo "\002\00301,00You\00300,04Tube\002\017"
 
   if {$watch && $youtubeid != ""} {
      putlog "$web(page)$youtubeid"
      set agent "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1"    
      set t [::http::config -useragent $agent]
      set t [::http::geturl "$web(page)$youtubeid" -timeout 30000]
      set data [::http::data $t]
      ::http::cleanup $t
 
      set l [regexp -all -inline -- {<title>(.*?)</title>.*?<span class="watch-view-count " >(.*?)</span>} $data]
 
      regexp {"length_seconds": (\d+),} $data "" length
 
      foreach {black a b c d e} $l {
 
         set a [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $a]
         set b [string map [list \n ""] $b]
         set c [string map [list \n ""] $c]
         set d [string map [list \n ""] $d]
         set e [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $e]
 
         regsub -all {<.*?>} $a {} a
         regsub -all {<.*?>} $b {} b
         regsub -all {<.*?>} $c {} c
         regsub -all {<.*?>} $d {} d
         regsub -all {<.*?>} $e {} e         
 
         putserv "PRIVMSG $chan :$a ( [duration $length] ) Viewed $b"
 
             proc duration {s} {
            variable etube
            set hours [expr {$s / 3600}]
            set minutes [expr {($s / 60) % 60}]
            set seconds [expr {$s % 60}]
            set res ""
 
            if {$hours != 0} {append res "$hours hours"}            
            if {$minutes != 0} {append res " $minutes minutes"}
            if {$seconds != 0} {append res " $seconds seconds"}
            return $res
 
         }   
      }
   }
}



Comme ça plutôt ?
Répondre Avertir
#18
Hello,

avez-vous tenté de passer une URL en https ?

Car du coup ça ne marche pas ;)
Répondre Avertir
#19
Peux-tu être plus explicite ?
Ca ne marche pas lorsqu'on annonce une url youtube en https sur le canal, ou lorsqu'on modifie le script pour mettre:
tcl
set web(page) https://www.youtube.com


Pour le premier cas, ça m'étonne un peu vu qu'on se base sur la chaîne de caractère "watch?v=xxxxxxx" ou "youtu.be/xxxxxxx".
Après, si la vidéo est privée et donc accessible seulement pour un utilisateur logué, c'est normal.
Répondre
#20
C'est une erreur de ma part, je n'avais pas la bonne version du youtube.tcl du coup j'avais une erreur quand je postais une vidéo en https... Désolé ! ça fonctionne très bien !

[10:32] <Hitsu> https://www.youtube.com/watch?v=A16VcQdTL80
[10:32] <%Seireitei> Asaf Avidan // Reckoning Song (One Day) - YouTube ( 3 minutes 25 seconds ) Viewed 11 507 944
Répondre Avertir
#21
bonjour,

ou est ce que je peux télécharger le youtube script? (dernière version)

merci
Répondre
#22
Salut,

J'viens vous présenter Zurl-0.01.tcl. Ce script fusionne la fonctionnalité d'un urltitle et d'un youtubetitle.

Les derniers posts de ce topic m'ont servi à personnaliser ce script. Les liens vers les sources sont dans la description. C'est le fruit de votre travail. = )

J'suis encore très novice et je n'ai fait qu'adapter les scripts à mes besoins en recherchant des codes simples et légés. Il y a encore quelques bugs que je n'arrive pas à corriger comme:
- La traduction des urls https pour le urltitle (ceux de youtube sont traduits mais pas toutes les autres)
- Empêcher le flood de la PL par le proc [mu] de youtitle (cela vient de la ligne
"set youtubeid "/watch?v=$youtubeid".

A part ça, le script est fonctionnel.

tcl
###############
#    Zurl     #
###############

############### Zurl.tcl is based on two grabbers urls titles scripts: 
############### -The first one is a classic grabber who describe all (or most) of urls.
############### (http://forum.eggdrop.fr/Titre-des-urls-diffusees-t-1331.html)
############### - The second one is a youtube grabber. 
############### (http://forum.eggdrop.fr/youtube-tiltle-t-1393.html)

############### So, the youtube (with rating, views, etc) and the classic grabber on 
############### the same script was the point. Hope it'll be usefull.

############### JazZ (jazz@epiknet.org)

 
############### Easy to use; you only need to add the Zurl.tcl file to ../scripts/, 
############### add the source path to the script in the eggdrop.conf and enjoy. 
 
set Zurlversion "0.01"

############### Packages & binding ############### 
 
package require http
package require uri
 
bind PUBM - "*?://*?" check_url
bind PUBM - * mu

############### Proc "classic" ############### 
 
proc check_url {nick uhost handle chan text} {
   if {[regexp -- {([a-z0-9\-]+\://[a-z0-9\-]+\.[a-z0-9\-\.]+(?:/|(?:/[a-zA-Z0-9!#\$%&'\*\+,\-\.:;=\?@\[\]_~]+)*))} $text match url]} {
   set url [string map -nocase { "&amp;" "&" } $url]
      set token [geturl $url]
      set html_data [::http::data $token]
      ::http::cleanup $token
      regexp -all -nocase -- "<title>(.*)</title>" $html_data match title
	if {![string match -nocase "*?/watch?v=*?" $url] && ![string match -nocase "*?://youtu.be*?" $url]} {   ;# than the classic grabber doesn't work on youtube's urls
 
                  putserv "PRIVMSG $chan :.:\[\002URL\002\]:. | $title | "

############### Uncomment the following lines to save titles, urls and linkers in your ../eggdrop/classics file 
############### (classics will be automatically create)   	
	
# set bc [open classics a] 
# set classics ".:\[$a\] \($web(page)$youtubeid\) by \[$nick\]:." 
# puts $bc classics 
# close $bc
      }   
   }
   return 0
}
 
proc geturl {url args} {
    array set URI [::uri::split $url];
    while {1} {
       set token [eval [list http::geturl $url] $args]
       if {![string match {30[1237]} [::http::ncode $token]]} {return $token}
       array set meta [set ${token}(meta)]
       if {![info exist meta(Location)]} {
            return $token
       }
       array set uri [::uri::split $meta(Location)]
       unset meta
       if {$uri(host) == ""} { set uri(host) $URI(host) }
       set url [eval ::uri::join [array get uri]]
    }
}

############### Proc Youtube ############### 
 
proc mu {nick uhost hand chan text} {
   set web(page) http://www.youtube.com
   set watch [regexp -nocase -- {\/watch\?v\=([^\s]{11})} $text youtubeid]
   if { $watch == 0 } {
      set watch [regexp -nocase -- {youtu\.be\/([^\s]{11})} $text a youtubeid]
 
      set youtubeid "/watch?v=$youtubeid" ;# the way this line was write is good but sends mistakes in PL. You can try with {} or something, 
                                       ;# it won't get urls from youtube like https or youtu.be anymore. If you find a solution, 
                                       ;# share your tips. By the way, it's almost perfect the way it is.   
   }
 
   if {$watch && $youtubeid != ""} {
      putlog "$web(page)$youtubeid"
      set agent "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.1) Gecko/2008070208 Firefox/3.0.1"   
      set t [::http::config -useragent $agent]
      set t [::http::geturl "$web(page)$youtubeid" -timeout 30000]
      set data [::http::data $t]
      ::http::cleanup $t
 
      set l [regexp -all -inline -- {<meta name="title" content="(.*?)">.*?<span class="watch-view-count " >(.*?)</span>.*?<span class="likes-count">(.*?)</span>.*?\
<span class="dislikes-count">(.*?)</span>} $data] 
 
 
	regexp {"length_seconds": (\d+),} $data "" length
 
      foreach {black a b c d e} $l {
 
         set a [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $a]
         set b [string map [list \n ""] $b]
         set c [string map [list \n ""] $c]
         set d [string map [list \n ""] $d]
         set e [string map -nocase {\&\#39; \x27 &amp; \x26 &quot; \x22} $e]
 
         regsub -all {<.*?>} $a {} a
         regsub -all {<.*?>} $b {} b
         regsub -all {<.*?>} $c {} c
         regsub -all {<.*?>} $d {} d
         regsub -all {<.*?>} $e {} e         
 
	 set b [string trim $b] ;# Some scotch to keep view at the right place
 
	proc duration {s} {
            variable etube
            set hours [expr {$s / 3600}]
            set minutes [expr {($s / 60) % 60}]
            set seconds [expr {$s % 60}]
            set res ""
 
            if {$hours != 0} {append res "$hours hrs "}            
            if {$minutes != 0} {append res "$minutes\min "}
            if {$seconds != 0} {append res "$seconds\sec"}
            return $res
         }   
 
         putserv "PRIVMSG $chan :.:\[\002YouTube\002\]:. | $a | [duration $length] | $b vues | + $c / - $d | " 

############### Uncomment the following lines to save titles, urls and linkers in the ../eggdrop/backlistube file 
############### (backlistube will be automatically create)   	
	
# set mt [open backlistube a] 
# set backlistube ".:\[$a\] \($web(page)$youtubeid\) by \[$nick\]:." 
# puts $mt $backlistube 
# close $mt     
      }
   }
}
 
putlog "\0033Zurl-$Zurlversion.tcl\003 loaded"



J'attends vos conseilles et critiques.

Enjoy guys.

--
JazZ
Répondre Avertir
#23
(18/02/2014, 15:24)JazZ a écrit : Salut,

J'viens vous présenter Zurl-0.01.tcl. Ce script fusionne la fonctionnalité d'un urltitle et d'un youtubetitle.

Bonjour,
J'ai un message d'erreur en partyline qui me dit :
[/code][04:28:19] Tcl error [mu]: can't read "youtubeid": no such variable
Répondre Avertir
#24
(18/02/2014, 15:24)JazZ a écrit : J'attends vos conseilles et critiques.

J'ai apporté une correction et des optimisations suite à Youtube tcl (Zurl.tcl) ne fonctionne plus, le code est à http://tools.eggdrop.fr/pasteme/view/81a8950b

Correction
La regexp qui extrait les infos youtube

Optimisations
- Suppression d'un bind (il est illogique d'avoir de binds qui vont réagir à la même chose),
- C'est la procédure principale qui "choisit" le traitement approprié,
- l'affichage des infos youtube est sorti du foreach,
- la procédure duration est sortie de la procédure youtube
Répondre
#25
Bonjour, perso j'obtiens cela comme erreur ....

Tcl error [check_url]: can't read "a": no such variable
Répondre Avertir
#26
Le code html de youtube a du changer.
Répondre
#27
ah ok, et il n'y a pas de nouvelle version du script ?
Répondre Avertir
#28
Vu que tu as signalé l'erreur il y a 56 minutes, et que tu es le seul à l'avoir signalée, pour l'instant non, il n'y a pas de nouvelle version.
Répondre
#29
Ok je te remercie pour ta réponse en espérant que quelqu'un ce lance dans le correctif, je l'aurais bien fais mais je ne pense pas avoir le niveau nécessaire pour cela.
Répondre Avertir
#30
je viens de trouver une version qui fonctionne avec l API ils expliquent même comment obtenir le code API.
Mais j'obtiens une erreur. voici l'erreur :

[11:30:13] Tcl error [youtube_query]: wrong # args: should be "matchattr handle flags ?channel?"

et voici le code

tcl
###############################################################################
 #  Name:                  Youtube Title V2
 #  Author:                Jan Milants <viper@anope.org>
 #  Version:               2.0     (28/08/2014)
 #  Eggdrop Version:       1.6.x
 #  Requires TCL version:  8.5
 #  Package dependencies:  http, tls, json
 #  Credits:               Based on original YouTube Script
 #                             by jotham.read@gmail.com
 #                         Design inspiration from
 #                             youtube.tcl by Mookie.
 ###############################################################################
 # Description
 # -------------
 # The script monitors text channels for links to Youtube.
 # When found, it will query the google server for details such as video title
 # and number of views of the youtube video and advertise the results in the channel.
 # The script also supports searching youtube with the command "!youtube <search text>"
 # or "!yt <search text>". In response, the search query will be passed on to the
 # youtube API and the best ranking result will be linked in channel.
 #
 # This script will be active on any channel it resides in with the "youtube" flag.
 # The flag can be set in the console with ".chanset #chan  youtube" or with the 
 # in channel command "!youtube on". Both commands only work for users with flag mno.
 #
 # Getting your own Google API key
 # ---------------------------------
 # This script uses the Google Youtube Data API V3, which requires an API key to
 # authorize access to the API and is used as basis for limiting request per day etc.
 # Instructions can be found on 
 #     https://developers.google.com/youtube/registering_an_application
 # Required steps in short:
 #     1. Go to the Google developers console https://console.developers.google.com
 #     2. Create a new project. Give it a name like 'eggdrop', doesn't matter much.
 #     3. When the project is loaded, select menu "APIs" under "APIs & auth"
 #     4. In the list of APIs, enable the "YouTube Data API v3".
 #     5. Select menu "Credentials" and click "Create new key".
 #     6. Select key type "server".
 #     7. Fill in the IP(s) or IP range from which the eggdrop bot will send
 #        requests to google's servers. This is a whitelist, if the request
 #        comes from a different IP, it will be rejected.
 #        Note: If my-ip or my-hostname is configured in eggdrop.conf, they should
 #              be entered here.
 #     8. You now have an API KEY; copy it to the config section below.
 #
 # !!! IMPORTANT !!!
 # When loading this script alongside other scripts which initiate web service calls,
 # ensure this script is loaded last! The script creates a handr for HTTPS connection
 # and sets the source IP to the my-ip or my-hostname from eggdrop.conf.
 # Most other scripts will not correctly enforce the source IP of requests and 
 # can overwrite this scripts HTTPS handr. This results in connections coming from another
 # IP on the machine and may thus be rejected by the Google API Servers. 
 # The typical error message logged would be "Error processing web service reply".
 #
 ###############################################################################
 #  Changes:
 #  2.00 28/08/14
 #    Started development (Jan).
 #    Almost complete rewrite most notable changes:
 #        * Use the YouTube Data API V3. (Requires TLS support!)
 #        * Strip out flat_json_decoder and use json & dict packages instead.
 #        * Strip out tinyurl support. Better to use youtu.be in the response.
 #        * Many more data elements supported in response format (possible by new API).
 #        * Added possiblity to turn the script on/off on a channel by channel basis.
 #        * Added ability to search youtube and return the first result.
 #  0.51 09/30/13
 #    Small correction for caps in url (but not video id)
 #  0.5 01/02/09
 #    Added better error reporting for restricted youtube content.
 #  0.4 10/11/09
 #    Changed title scraping method to use the oembed api.
 #    Added crude JSON decoder library.
 #  0.3 02/03/09
 #    Fixed entity decoding problems in return titles.
 #    Added customisable response format.
 #    Fixed rare query string bug.
 ###############################################################################
 #
 #  Configuration
 #
 ###############################################################################
 
 # API key assigned to your Google account.
 # Sadly, everyone will have to register with Google and request their own API key.
 # An API key is linked to an IP or mask, so you will need to register one for your own.
 # Find detailed instructions above.
 set youtube(api_key)           ""
 
 # Base URI for links to youtube videos.
 # Either use the normal youtube link or youtu.be for shorter URLs.
 # I'd recommend keeping the HTTPS to avoid exposing user data.
 set youtube(base_url)          "https://www.youtube.com/watch?v="
 #set youtube(base_url)          "https://www.youtu.be/"
 
 # Date/time format
 # The format to be used when showing dates, for example in publish date.
 # All times are in UTC.
 #
 # Available tokens:
 #   %year%          4 digit year notation
 #   %month%         2 digit month notation
 #   %day%           2 digit day of the month notation
 #   %hours%          2 digit hour notation on a 24hours basis
 #   %minutes%       2 digit minutes notation
 #   %seconds%       2 digit seconds notation
 #
 # Example:
 #     "%day%/%month%/%year% %hours%:%minutes% UTC"
 set youtube(date_format)   "%day%/%month%/%year% %hours%:%minutes% UTC"
 
 
 # Response Formats
 # Template of the reply to be send to the channel showing the youtube video details.
 # A separate response can be set for replies to a pasted URL or to a query.
 #
 # Available tokens in the response format:
 #   %botnick%       Nickname of bot
 #   %poster%        Nickname of person who posted the youtube link
 #   %youtube_url%   URL to the youtube link (This may not be the exact same
 #                   URL that was posted since it's rewritten based on the format
 #                   above to ensure all links posted by the bot are HTTPS.)
 #   %id%            ID of the linked youtube video.
 #   %author%        Author/Uploader/channel of the video.
 #   %title%         Title of youtube link
 #   %description%   Description of the video.
 #                   (Note that this is generally a VERY long text!)
 #   %published%     Date & time the video was published.
 #   %views%         The number of times the video has been viewed.
 #   %likes%         The number of users who have "liked" the video.
 #   %dislikes%      The number of users who have "disliked" the video.
 #   %length%        Length of the video.
 # Tokens only available in the response to searches (q_resp_format):
 #   %query%         The original search string.
 #
 # Example:
 #     "\002YouTube\002: %poster%: %youtube_url% - \"\002%title%\002\" (Uploaded by \"%author%\" on %published%) - Length: %length% - Views: %views%  - Likes / Dislikes: %likes% / %dislikes%"
 # The template used when looking up a URL found in the channel
 set youtube(response_format)   "\002YouTube\002: %poster%: %youtube_url% - \"\002%title%\002\" (Uploaded by \"%author%\" on %published%) - Length: %length% - Views: %views%  - Likes / Dislikes: %likes% / %dislikes%"
 # The template used when replying to a search query.
 set youtube(q_resp_format)     "\002YouTube\002: %poster%: Top result for searching '%query%': %youtube_url% - \"\002%title%\002\" (Uploaded by \"%author%\" on %published%) - Length: %length% - Views: %views%  - Likes / Dislikes: %likes% / %dislikes%"
 
 # The maximum number of characters from a youtube title to print
 set youtube(max_title_length)  64
 
 # The maximum number of characters from a youtube description to print
 set youtube(max_desc_length)   128
 
 ###############################################################################
 #
 #  Advanced Configuration
 #  !!! DO NOT CHANGE UNLESS YOU KNOW WHAT YOU'RE DOING !!!
 #
 ###############################################################################
 
 # URLs of the youtube V3 API
 set youtube(api_get)           "https://www.googleapis.com/youtube/v3/videos"
 set youtube(api_search)        "https://www.googleapis.com/youtube/v3/search"
 
 # The groups of properties to be fetched
 set youtube(api_part)          "snippet,statistics,contentDetails"
 
 # The fields from the selected property groups that are to be returned
 set youtube(api_fields)        "items(id,snippet(publishedAt,title,description,channelTitle),statistics,contentDetails(duration))"
 
 # Maximum time in milliseconds to wait for youtube to respond
 set youtube(api_timeout)       "30000"
 
 # Pattern used to patch youtube links in channel public text
 set youtube(pattern)           {https{0,1}://.*youtu(?:\.be/|be\..*/watch\?(?:.*)v=)([A-Za-z0-9_\-] )}
 
 ###############################################################################
 
 package require Tcl 8.5
 package require http 2.7
 package require tls
 package require json
 
 # We need HTTPS support for the Google APIs..
 # If local IP or host is configured in the main config, use it as the source
 # of the outgoing connections.
 if { [info exists {my-ip}] == 1 && [string length ${my-ip}] > 0} {
        http::register https 443 [list tls::socket -myaddr ${my-ip}]
 } elseif { [info exists {my-hostname}] == 1 && [string length ${my-hostname}] > 0} {
        http::register https 443 [list tls::socket -myaddr ${my-hostname}]
 } else {
        http::register https 443 tls::socket
 }
 
 set YoutubeTitleVersion "2.0"
 
 setudef flag youtube
 bind pubm - * public_youtube
 bind pub - !youtube youtube_query
 bind pub - !yt youtube_query
 
 ###############################################################################
 
 proc note {msg} {
   putlog "% $msg"
 }
 
 # Ensure strings are no longer then given length. This will cutoff the string
 # at the desired length and append '...'.
 proc shorten {text maxlen} {
        if { [string length $text] > [expr $maxlen - 1] } {
                set text [string range $text 0 [expr $maxlen - 4]]"..."
        }
        return $text
 }
 
 # Convert an ISO8601 date into a more readable format..
 proc conv_iso8601_date {orig_date} {
        global youtube
        set pattern {(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d{1}|3[012])[T\s](?:(?:([01]\d|2[0-3]):([0-5]\d))|(24):(00)):(?:([0-5]\d)(?:[\.,](\d ))?|(60)(?:[\.,](0 ))?)Z}
        if { [regexp $pattern $orig_date match year month day hours minutes hours_2 minutes_2 seconds milliseconds seconds_2 milliseconds_2] } {
                # The hour and hour_2 variables are mutually exclusive, so we append the _2 variables to
                # the original ones to have fewer variables to work with.
                append hours $hours_2
                append minutes $minutes_2
                append seconds $seconds_2
 
                # Put everything in a dictionary so we can have a configurable time format.
                set tokens [dict create]
                dict set tokens %year% $year
                dict set tokens %month% $month
                dict set tokens %day% $day
                dict set tokens %hours% $hours
                dict set tokens %minutes% $minutes
                dict set tokens %seconds% $seconds
 
                return [string map $tokens $youtube(date_format)]
        } else {
                error "Unable to process date value ($orig_date) returned by web service."
        }
 }
 
 # Convert an ISO8601 duration into a more readable format..
 proc conv_iso8601_duration {duration} {
        set length ""
        set pattern {P(?:(\d )Y)?(?:(\d )M)?(?:(\d )D)?(?:T(?:(\d )H)?(?:(\d )M)?(?:(\d (?:\.\d )?)S)?)}
        if { [regexp $pattern $duration match years months days hours minutes seconds] } {
                if { [string length $years] > 0 } {
                        append length $years Y " "
                }
                if { [string length $months] > 0 } {
                        append length $months M " "
                }
                if { [string length $days] > 0 } {
                        append length $days D " "
                }
                if { [string length $hours] > 0 } {
                        append length $hours h " "
                }
                if { [string length $minutes] > 0 } {
                        append length $minutes m " "
                }
                if { [string length $seconds] > 0 } {
                        append length $seconds s " "
                }
        } else {
                error "Unable to process duration value ($duration) returned by web service."
        }
        return [string trim $length]
 }
 
 ###############################################################################
 
 # Process the reply string of a video lookup from the Youtube API (JSON) and add the
 # data to a dictionary containing all tokens the user will be able to use in the template.
 proc read_props {json_blob} {
        global youtube
        # Create an empty dictionary for the variables supported in the response format.
        set properties [dict create]
 
        # Convert the JSON response to a dictionary.
        set reply [json::json2dict $json_blob]
 
        # The web service returns a list of results, even though our query will always get 1.
        # So we have to take the first element from the list..
        if { ![dict exists $reply items] } {
                error "Error processing web service reply."
        } else {
                set video [lindex [dict get $reply items] 0]
 
                # Check whether the variables we support in the response are present in the
                # reply from the web service. We check this one by one instead of assuming
                # they exist in case the API changes or someone messes with the requested fields.
                # Properties of the view we extract from reply..
                if { [dict exists $video id] } {
                        dict set properties %id% [dict get $video id]
                } else {
                        dict set properties %id% ""
                }
                if { [dict exists $video snippet channelTitle] } {
                        dict set properties %author% [dict get $video snippet channelTitle]
                } else {
                        dict set properties %author% ""
                }
                if { [dict exists $video snippet title] } {
                        dict set properties %title% [shorten "[dict get $video snippet title]" $youtube(max_title_length)]
                } else {
                        dict set properties %title% ""
                }
                if { [dict exists $video snippet description] } {
                        dict set properties %description% [shorten "[dict get $video snippet description]" $youtube(max_desc_length)]]
                } else {
                        dict set properties %description% ""
                }
                if { [dict exists $video snippet publishedAt] } {
                        dict set properties %published% [conv_iso8601_date [dict get $video snippet publishedAt]]
                } else {
                        dict set properties %published% ""
                }
                if { [dict exists $video statistics viewCount] } {
                        dict set properties %views% [dict get $video statistics viewCount]
                } else {
                        dict set properties %views% ""
                }
                if { [dict exists $video statistics likeCount] } {
                        dict set properties %likes% [dict get $video statistics likeCount]
                } else {
                        dict set properties %likes% ""
                }
                if { [dict exists $video statistics dislikeCount] } {
                        dict set properties %dislikes% [dict get $video statistics dislikeCount]
                } else {
                        dict set properties %dislikes% ""
                }
                if { [dict exists $video contentDetails duration] } {
                        dict set properties %length% [conv_iso8601_duration [dict get $video contentDetails duration]]
                } else {
                        dict set properties %length% ""
                }
        }
 
        return $properties
 }
 
 # Process the reply string of a search query to the Youtube API (JSON) and extract the 
 # video id of the first result from the reply.
 proc read_searchres {json_blob} {
        global youtube
        # Create an empty dictionary for the variables supported in the response format.
        set video_id ""
 
        # Convert the JSON response to a dictionary.
        set reply [json::json2dict $json_blob]
 
        # The web service returns a list of results, even though our query will always get 1.
        # So we have to take the first element from the list..
        if { ![dict exists $reply items] } {
                error "Error processing web service reply."
        } else {
                set res [lindex [dict get $reply items] 0]
                if { [dict exists $res id videoId] } {
                        set video_id [dict get $res id videoId]
                }
        }
 
        return $video_id
 }
 
 # Send a request to the youtube API to fetch the video details for
 # the video with the given ID.
 proc fetch_props {youtube_id} {
        global youtube
        # Ensure an API key has been configured..
        if { [info exists youtube(api_key)] == 0 || [string length $youtube(api_key)] == 0 } {
                error "An API key must be configured to access the Google web API!"
        } else {
                set query [http::formatQuery id $youtube_id key $youtube(api_key) \
                        part $youtube(api_part) fields $youtube(api_fields)]
                set response [http::geturl "$youtube(api_get)?$query" -timeout $youtube(api_timeout)]
                upvar #0 $response state
                if [expr [http::ncode $response] == 401] {
                        error "Location contained restricted embed data."
                } else {
                        set response_body [http::data $response]
                        http::cleanup $response
                        return [read_props $response_body]
                }
        }
 }
 
 # Find the video ID of the first match for the given search.
 proc search_video {criteria} {
        global youtube
        # Ensure an API key has been configured..
        if { [info exists youtube(api_key)] == 0 || [string length $youtube(api_key)] == 0 } {
                error "An API key must be configured to access the Google web API!"
        } else {
                set query [http::formatQuery type "video" q $criteria key $youtube(api_key) \
                        part "id" fields "items(id(videoId))" maxResults "1"]
                set response [http::geturl "$youtube(api_search)?$query" -timeout $youtube(api_timeout)]
                upvar #0 $response state
                if [expr [http::ncode $response] == 401] {
                        error "Location contained restricted embed data."
                } else {
                        set response_body [http::data $response]
                        http::cleanup $response
                        return [read_searchres $response_body]
                }
        }
 }
 
 ###############################################################################
 
 # This is triggered to analyse ever channel message for the presence of the youtube URL.
 # When one is found, the ID is extracted and passed on to get a list of the video properties.
 # Finally, this list is used to fill in the tokens in the user defined reply template.
 proc public_youtube {nick host hand chan args} {
        global youtube botnick
 
        if { [channel get $chan youtube] && [regexp -nocase -- $youtube(pattern) $args match video_id] } {
                if { [catch {set tokens [fetch_props $video_id]} error] } {
                        note "Failed to get video details: $error (querying '$video_id')"
                # If the reply contained an empty ID, we assume we found no video..
                } elseif { [string length [dict get $tokens %id%]] == 0 } {
                        putserv "PRIVMSG $chan :Unable to find a youtube video with ID '$video_id'."
                } else {
                        dict set tokens %botnick% $botnick
                        dict set tokens %poster% $nick
                        # Rebuild the URL so we use a url shortener or force SSL
                        # in all messages coming from us
                        dict set tokens %youtube_url% "$youtube(base_url)$video_id"
 
                        set result [string map $tokens $youtube(response_format)]
                        putserv "PRIVMSG $chan :$result" 
                }
        }
 }
 
 # This is triggered on !youtube commands.
 # Allows turning monitoring on or off by admins.
 # All other queries are interpreted as a youtube search.
 proc youtube_query {nick host hand chan args} {
        global youtube botnick
 
        # We get a list of arguments, join it to get rid of the curly braces..
        set args [join $args]
        if  { [string length $args] == 0 } {
                if { [channel get $chan youtube] } {
                        putserv "PRIVMSG $chan :Syntax: \002!youtube <search criteria>\002 - Search for a video."
                }
                if { [matchattr $hand  mno| mno $chan] } {
                        putserv "NOTICE $nick :Syntax: \002!youtube <on/off>\002 - Turn youtube link lookups on/off."
                }
        } elseif { [matchattr $hand  mno| mno $chan] && ([string compare $args "on"] == 0 \
                        || [string compare $args "off"] == 0) } {
                if { ![channel get $chan youtube] && [string compare $args "on"] == 0 } {
                        channel set $chan  youtube
                        putserv "NOTICE $nick :YoutubeTitleV2: enabled on $chan"
                        note "YoutubeTitleV2: Monitoring enabled by $nick for $chan."
                } elseif { [channel get $chan youtube] && [string compare $args "off"] == 0 } {
                        channel set $chan -youtube
                        putserv "NOTICE $nick :YoutubeTitleV2: disabled on $chan"
                        note "YoutubeTitleV2: Monitoring disabled by $nick for $chan."
                }
        # The magic number comes from the length of the string "cat".. ;)
        } elseif { [channel get $chan youtube] && [string length $args] < 3 } {
                putserv "PRIVMSG $chan :Search criteria must be at least 3 characters long."
        } elseif { [channel get $chan youtube] } {
                # Search a video...
                # Note that we have to do 2 requests: one to fetch search results (id)
                # and a second to get video details. This is caused by the youtube API 
                # not being capable of returning details in the search functions.
                if { [catch { set video_id [search_video $args] } error ] } {
                        note "Failed to find a video: $error (searching for '$args')."
                # If the reply contained an empty ID, we assume we found no video..
                } elseif { [string length $video_id] == 0 } {
                        putserv "PRIVMSG $chan :Unable to find a youtube video matching search '$args'" 
                # We have the video id, now find the properties..
                } elseif { [catch {set tokens [fetch_props $video_id]} error] } {
                        note "Failed to get video details: $error (searching for '$args' and found '$video_id')."
                # If the reply contained an empty ID, we assume we found no video..
                } elseif { [string length [dict get $tokens %id%]] == 0 } {
                        putserv "PRIVMSG $chan :Unable to fetch the video details of '$video_id' for the search result '$args'"
                } else {
                        dict set tokens %botnick% $botnick
                        dict set tokens %poster% $nick
                        dict set tokens %query% $args
                        # Rebuild the URL so we use a url shortener or force SSL
                        # in all messages coming from us
                        dict set tokens %youtube_url% "$youtube(base_url)$video_id"
 
                        set result [string map $tokens $youtube(q_resp_format)]
                        putserv "PRIVMSG $chan :$result" 
                }
        }
 }
 
 ###############################################################################
 
 note "YoutubeTitleV2 Version $YoutubeTitleVersion: loaded";


Répondre Avertir


Atteindre :


Utilisateur(s) parcourant ce sujet : 2 visiteur(s)
Tchat 100% gratuit -Discutez en toute liberté