mon test script assisté par une ia
#1
salut la  communauté ,
vais vous proposer un petit travail assisté par une ia , vous pouvez s'en servir ou ça nous sert pour discuter et à le développer aussi

tcl
# -----------------------------------------------------------------------------
# Script YouTube pour Eggdrop Bot IRC
# Version : 1.1.16
# Description : Ce script permet d'intégrer des fonctionnalités YouTube dans un bot IRC.
#               Il permet de rechercher des vidéos YouTube, de détecter automatiquement
#               les liens YouTube partagés dans le chat, et d'afficher des informations
#               détaillées sur les vidéos.
#
# Prérequis :
# - Tcl 8.6 ou supérieur
# - Packages Tcl : http, json, tls
# - Clé API YouTube valide (à configurer par l'utilisateur)
#
# Commandes :
# - !yt <terme> : Recherche une vidéo YouTube basée sur le terme de recherche fourni.
#
# Fonctionnalités :
# - Détection automatique des liens YouTube et affichage des détails des vidéos.
# - Mise en cache des résultats de recherche pour optimiser les appels API.
# - Formatage des messages pour une présentation claire des informations.
# -----------------------------------------------------------------------------

# ---------------------------------------------------------------------
# Configuration Utilisateur
# ---------------------------------------------------------------------
# Veuillez entrer votre clé API YouTube ci-dessous
namespace eval ::youtube {
    # Clé API YouTube (à configurer par l'utilisateur)
    variable api_key "VOTRE_CLE_ICI"
}

# ---------------------------------------------------------------------
# Script Principal (Ne modifiez rien ci-dessous)
# ---------------------------------------------------------------------
 
namespace eval ::youtube {
    # Version du script
    variable script_version "1.1.16"
    # Préfixe pour les messages YouTube
    variable yt_prefix "\002\00301,00You\00300,04Tube\017"
    # Cache pour stocker les résultats de recherche
    variable cache
    # Cache pour stocker les résultats automatiques
    variable auto_cache

    # S'assurer que la version de Tcl est 8.6 ou supérieure pour le support Unicode
    if {[catch {package require Tcl 8.6}]} {
        putlog "Attention : Tcl < 8.6 détecté - Unicode limité"
    }

    # Procédure d'initialisation
    proc init {} {
        # Packages requis
        foreach pkg {http json tls} {
            if {[catch {package require $pkg} err]} {
                error "Package requis manquant : $pkg"
            }
        }
        # Initialiser les caches
        array set ::youtube::cache {}
        array set ::youtube::auto_cache {}
        # Définir le flag YouTube s'il n'est pas déjà défini
        if {![info exists ::youtube_flag_defined]} {
            setudef flag youtube
            set ::youtube_flag_defined 1
        }
        # Lier les commandes à leurs procédures respectives
        bind pub - "!yt" ::youtube::pub:youtube
        bind pubm - "*youtube*" ::youtube::pubm:youtube_auto
        bind pubm - "*youtu.be*" ::youtube::pubm:youtube_auto
        
        # Message de confirmation du chargement du script
        putlog "Script YouTube version $::youtube::script_version chargé. Pour l'activer, utilisez la commande : .chanset #channel +youtube"
    }

    # Procédure pour envoyer un message YouTube
    proc send_youtube_message {target message {type "PRIVMSG"}} {
        variable yt_prefix
        if {$type eq "PRIVMSG"} {
            puthelp "PRIVMSG $target :${yt_prefix}\003 $message"
        } elseif {$type eq "NOTICE"} {
            puthelp "NOTICE $target :$message\003"
        }
    }

    # Procédure pour vérifier si YouTube est activé pour un canal
    proc check_youtube_enabled {chan {silent 0}} {
        set enabled [channel get $chan youtube]
        if {!$enabled && !$silent} {
            send_youtube_message $chan "Erreur : YouTube non activé (activer via DCC chat)"
        }
        return $enabled
    }

    # Gestionnaire pour la commande !yt
    proc pub:youtube {nick host hand chan arg} {
        variable cache
        if {![check_youtube_enabled $chan]} { return }
        set query [string trim $arg]
        if {$query eq ""} {
            send_youtube_message $chan "Utilisation : !yt <terme>"
            return
        }
        if {[info exists cache($query)]} {
            send_youtube_message $chan $cache($query)
            return
        }
        upvar #0 ::youtube::title title
        upvar #0 ::youtube::video_id video_id
        if {[catch {search_youtube $nick $chan $query} err]} {
            send_youtube_message $chan "Erreur : $err"
            return
        }
        upvar #0 ::youtube::channel_title channel_title
        upvar #0 ::youtube::duration duration
        upvar #0 ::youtube::views views
        upvar #0 ::youtube::published_at published_at
        upvar #0 ::youtube::video_link video_link
        if {[catch {process_youtube_url $nick $chan $video_id $query} err]} {
            send_youtube_message $chan "Erreur lors de la récupération des détails : $err"
            return
        }
        set message [format_yt_message [list $title $channel_title $duration $views $published_at $video_link]]
        set cache($query) $message
        utimer 300 [list unset ::youtube::cache($query)]
        send_youtube_message $chan $message
    }

    # Gestionnaire pour la détection automatique des liens YouTube dans les messages
    proc pubm:youtube_auto {nick host hand chan text} {
        variable auto_cache
        if {![check_youtube_enabled $chan 1]} { return }
        if {[string match "!yt*" $text]} { return }
        set youtube_pattern {(?:https?://)?(?:www\.|m\.)?(?:youtube\.com/(?:watch\?v=|shorts/|embed/|live/)|youtu\.be/)([^&\s\?]+)}
        set music_pattern {(?:https?://)?(?:www\.|m\.)?music\.youtube\.com/watch\?v=([^&\s\?]+)}
        if {![regexp $youtube_pattern $text] && ![regexp $music_pattern $text]} { return }
 
        set ids [regexp -all -inline $youtube_pattern $text]
        set music_ids [regexp -all -inline $music_pattern $text]
        foreach {match id} $ids {
            if {[info exists auto_cache($id)]} {
                send_youtube_message $chan $auto_cache($id)
                continue
            }
            if {[catch {process_youtube_url $nick $chan $id $text "" 0} err]} {
                continue
            }
            upvar #0 ::youtube::title title
            upvar #0 ::youtube::channel_title channel_title
            upvar #0 ::youtube::duration duration
            upvar #0 ::youtube::views views
            upvar #0 ::youtube::published_at published_at
            if {$title eq ""} {
                continue
            }
            set message [format_yt_message [list $title $channel_title $duration $views $published_at]]
            set auto_cache($id) $message
            utimer 300 [list unset ::youtube::auto_cache($id)]
            send_youtube_message $chan $message
        }
        foreach {match music_id} $music_ids {
            if {[info exists auto_cache($music_id)]} {
                send_youtube_message $chan $auto_cache($music_id)
                continue
            }
            if {[catch {process_youtube_url $nick $chan $music_id $text "music" 0} err]} {
                continue
            }
            upvar #0 ::youtube::title title
            upvar #0 ::youtube::channel_title channel_title
            upvar #0 ::youtube::duration duration
            upvar #0 ::youtube::views views
            upvar #0 ::youtube::published_at published_at
            if {$title eq ""} {
                continue
            }
            set message [format_yt_message [list $title $channel_title $duration $views $published_at]]
            set auto_cache($music_id) $message
            utimer 300 [list unset ::youtube::auto_cache($music_id)]
            send_youtube_message $chan $message
        }
    }

    # Procédure pour encoder une requête URL
    proc url_encode {query} {
        set encoded ""
        foreach char [split $query ""] {
            if {[regexp {^[a-zA-Z0-9]$} $char]} {
                append encoded $char
            } else {
                scan $char %c code
                append encoded [format "%%%02X" $code]
            }
        }
        return $encoded
    }

    # Procédure pour nettoyer et formater les titres des vidéos
    proc clean_title {title {keep_emojis 0}} {
        set cleaned $title
        if {!$keep_emojis} {
            set cleaned [string map {
                "í ¼í·©í ¼í·¿" "" "í ¼í·²í ¼í·¦" "" "í ¼í·¨" "" "í ¼í·§" "" 
                "í ¼í·ª" "" "í ¼í·«" "" "í ¼í·¬" "" "í ¼í·­" "" 
                "í ¼í·®" "" "í ¼í·¯" "" "í ¼í·°" "" "í ¼í·±" "" 
                "í ¼í¸" "" "í ¼í¹" "" "í ¼íº" "" "í ¼í»" "" 
                "í" "" "¼" "" "ÿ" "" "\n" " "
            } $cleaned]
            regsub -all {[^[:alnum:][:space:][:punct:]\u4e00-\u9FFF]} $cleaned "" cleaned
        }
        return [string trim $cleaned]
    }

    # Procédure pour récupérer les données YouTube avec des tentatives répétées
    proc fetch_youtube_data {url chan} {
        catch {package require tls}
        ::http::register https 443 [list ::tls::socket -tls1 1]
        set token ""
        for {set i 1} {$i <= 5} {incr i} {
            if {[catch {set token [::http::geturl $url -timeout 5000]} err]} {
                if {$i == 5} {
                    ::http::unregister https
                    send_youtube_message $chan "Erreur HTTP après 5 tentatives : $err"
                    return ""
                }
                after 1000
                continue
            }
            if {[::http::status $token] eq "ok"} { break }
            set err_msg [::http::error $token]
            switch -exact [::http::ncode $token] {
                429 {
                    send_youtube_message $chan "Erreur : Limite de requêtes atteinte, réessayez plus tard."
                    ::http::cleanup $token
                    ::http::unregister https
                    return ""
                }
                403 {
                    set raw_response [::http::data $token]
                    putlog "Erreur YouTube API (HTTP 403): $raw_response"
                    ::http::cleanup $token
                    ::http::unregister https
                    send_youtube_message $chan "Erreur : Vidéo privée ou restrictions activées."
                    return ""
                }
                404 {
                    set raw_response [::http::data $token]
                    putlog "Erreur YouTube API (HTTP 404): $raw_response"
                    ::http::cleanup $token
                    ::http::unregister https
                    send_youtube_message $chan "Erreur : Vidéo supprimée ou introuvable."
                    return ""
                }
            }
            ::http::cleanup $token
            if {$i == 5} {
                ::http::unregister https
                send_youtube_message $chan "Erreur HTTP après 5 tentatives : $err_msg"
                return ""
            }
            after 1000
        }
        set data [::http::data $token]
        ::http::cleanup $token
        ::http::unregister https
        if {[string trim $data] eq ""} {
            send_youtube_message $chan "Erreur : Réponse vide de l’API"
            return ""
        }
        if {[catch {set json_data [::json::json2dict $data]} err]} {
            send_youtube_message $chan "Erreur JSON : $err"
            return ""
        }
        return $json_data
    }

    # Procédure pour récupérer les données de chaîne depuis l'API YouTube
    proc fetch_channel_data {url chan type} {
        set json_data [fetch_youtube_data $url $chan]
        if {$json_data eq ""} {
            return ""
        }
        if {![dict exists $json_data items] || [llength [dict get $json_data items]] == 0} {
            return ""
        }
        return [lindex [dict get $json_data items] 0]
    }

    # Procédure pour formater un message YouTube
    proc format_yt_message {parts {separator "|"}} {
        set message ""
        set first 1
        foreach part $parts {
            if {$first} {
                append message "\002$part\002 "
                set first 0
            } else {
                append message "\00304${separator}\003 $part"
            }
        }
        append message " \00304${separator}\003"
        return [string trim $message]
    }

    # Procédure pour rechercher des vidéos YouTube
    proc search_youtube {nick chan query} {
        variable api_key
        upvar #0 ::youtube::title title
        upvar #0 ::youtube::video_id video_id
        set formatted_query [url_encode $query]
        set url "https://www.googleapis.com/youtube/v3/search?part=snippet&q=$formatted_query&type=video&key=$api_key"
        set json_data [fetch_youtube_data $url $chan]
        if {$json_data eq ""} { 
            error "Échec de la recherche"
        }
        set video [lindex [dict get $json_data items] 0]
        if {![dict exists $video id] || ![dict exists $video snippet]} { 
            error "Aucune vidéo trouvée pour cette recherche"
        }
        set id_dict [dict get $video id]
        set snippet_dict [dict get $video snippet]
        if {![dict exists $id_dict videoId] || ![dict exists $snippet_dict title]} { 
            error "ID ou titre manquant"
        }
        set title [clean_title [dict get $snippet_dict title]]
        set video_id [dict get $id_dict videoId]
    }

    # Procédure pour formater la durée d'une vidéo
    proc format_duration {duration} {
        if {$duration eq "P0D" || $duration eq "PT0S" || $duration eq ""} {
            return "Live"
        }
        if {![regexp {PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?} $duration _ hours minutes seconds]} {
            return "En cours de traitement"
        }
        set hours [expr {$hours ne "" ? $hours : 0}]
        set minutes [expr {$minutes ne "" ? $minutes : 0}]
        set seconds [expr {$seconds ne "" ? $seconds : 0}]
        if {$hours > 0} { return "${hours}h ${minutes}mn ${seconds}s" }
        if {$minutes > 0} { return "${minutes}mn ${seconds}s" }
        return "${seconds}s"
    }

    # Procédure pour formater le nombre de vues d'une vidéo
    proc format_views {views} {
        if {![string is integer -strict $views]} { return "N/A" }
        if {$views >= 1000000} { return [format "%.1fM" [expr {$views / 1000000.0}]] }
        if {$views >= 1000} { return [format "%.1fK" [expr {$views / 1000.0}]] }
        return $views
    }

    # Procédure pour formater la date de publication
    proc format_published_date {published_at} {
        regsub {\.\d+Z$} $published_at "Z" clean_date
        if {[catch {set timestamp [clock scan $clean_date -format "%Y-%m-%dT%H:%M:%SZ"]} err]} {
            return "Date inconnue"
        }
        return [clock format $timestamp -format "%d-%m-%Y"]
    }

    # Procédure pour traiter l'URL d'une vidéo YouTube
    proc process_youtube_url {nick chan id text {source ""} {include_link 1}} {
        variable api_key
        upvar #0 ::youtube::title title
        upvar #0 ::youtube::channel_title channel_title
        upvar #0 ::youtube::duration duration
        upvar #0 ::youtube::views views
        upvar #0 ::youtube::published_at published_at
        upvar #0 ::youtube::video_link video_link
        set title ""
        set channel_title ""
        set duration ""
        set views ""
        set published_at ""
        set video_link ""
 
        set url "https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails,statistics&id=$id&key=$api_key"
        set video [fetch_channel_data $url $chan "Vidéo"]
        if {$video eq ""} { 
            send_youtube_message $chan "Erreur : Vidéo invalide ou introuvable"
            return
        }
        set title [clean_title [dict get $video snippet title]]
        set channel_title [clean_title [dict get $video snippet channelTitle]]
        set raw_duration [dict get $video contentDetails duration]
        set duration [expr {$raw_duration eq "P0D" ? "Live" : [format_duration $raw_duration]}]
        set views [format_views [dict get $video statistics viewCount]]
        set published_at [format_published_date [dict get $video snippet publishedAt]]
        set video_link "https://youtu.be/$id"
    }

    # Initialisation
    init
}


Répondre Avertir
#2
J'ai jeté un oeil vite fait...
Le code pourrait probablement être optimisé, il y a beaucoup d'upvar, les appels de procédures n'intègrent pas le NS, certaines variables sont déclarées dans le NS global, d'autres locales.

Après, le code semble fonctionnel, mais je pense que si je cherche un peu, je trouverai des choses venant de m00nie et de BlackShadow :)
Répondre


Atteindre :


Utilisateur(s) parcourant ce sujet : 2 visiteur(s)
Tchat 100% gratuit -Discutez en toute liberté Tchatte avec Axelle Tchatte avec ta banquière