Réalisation d'un script pour XCHAT

Publié le par Satellite

Pourquoi cet article ? Parce que tout d'abord, face à MIRC, les autres clients, bien que meilleurs, sont délaissés et on trouve difficilement des scripts interessant pour Xchat. Ensuite parce que je déconseille totalement l'emploi d'un script IRC que vous n'avez pas compris ou pas codé vous même. Pourquoi ? Parce qu'il est facile de créer un script permettant le controle de votre ordinateur, ou autre. Voici donc comment j'ai réalisé un script python, certes basique, mais bien pratique pour les utilisateurs fréquents d'IRC.

Un script Xchat en python nécessite tout d'abord l'emploi du module xchat

import xchat

Ensuite, il est nécessaire de préciser certaines variables indiquant certaines version à Xchat:

__module_name__ = 'iPsilon-Script'
__module_version__ = '1.0 Alpha'
__module_description__ = 'Réalisé par iZy_TeH_PariaH'

Bien. Une fois que c'est fait, voici les commandes les plus courantes :

xchat.command( <comande>) permet de réaliser la comande précisée en paramètre. Par exemple xchat.command('KICK iZy_TeH_PariaH') effectuera la même chose que si vous tappez /KICK iZy_TeH_PariaH

xchat.hook_print(evenement,fonction) permet de réaliser un lien entre un évenement et une fonction. Par exemple xchat.hook_print('You Join',on_join) appelera la fonction on_join à chaque fois que vous rejoignez un salon. La liste des evenements textuels se trouve dans le menu Paramètre/Avancé/Evenements textuels. La fonction que vous appelez doit prendre en compte trois paramètres à savoir word, word_eol et userdata . Word contient les differentes informations (vous le voyez dans les evenements textuels). Word_eol effectue la même chose, mais en partant de la fin (je suppose, je l'utilise jamais), et userdata constitue les paramètres supplémentaires.

xchat.hook_command(commande,fonction) permet d'appeler une fonction chaque fois que l'utilisateur tape une commande. Par exemple xchat.hook_command('/salut',saluer) appellera la fonction saluer chaque fois que l'utilisateur tape /salut. La fonction appelée doit prendre en compte les trois paramètres précédents.

Pour plus d'informations sur les autres fonctions, je vous redirige vers le guide de programmation xchat en python.

Passons au script que nous allons réaliser. Je vais essayer d'etre clair. Il contiendra quelques remotes ainsi qu'un détecteur de clones.

Tout d'abord, le detecteur de clone. Un utilisateur utilise des clones quand il se connecte plusieurs fois a partir de la même IP. Les clones se caractèrisent par le fait qu'ils possèdent le même host @host.domaine
 Il se divise en deux fonctions. L'une sera appelée par l'utilisateur par la comande &c et scannera les host des utilisateurs présents sur le salon. La seconde sera appelée à chaque fois qu'un utilisateur rejoint le salon, et comparera son host avec ceux déjà présents.  C'est parti ! Tout d'abord,la fonction comparant les host lorsque qu'un utilisateur arrive :

def scanHost(host): #Scanner de clones
    a = xchat.get_list('users')
    hostS = host[2].split('@')[1]

Alors la fonction xchat.get_list('users') retourne une liste d'objets users possedant les attributs  nick (pseudo), host(le host complet) et le préfixe (+ : voice, etc...)
La fonction prend comme paramètre un host (celui qui rejoint le salon). Cependant, un host est de la forme *!*@*, et uniquement la partie @* nous interesse. On travaille donc la chaine de caractères pour l'obtenir. On continue !


for user in a:
        hostP = user.host.split('@')[1]
        if hostP == hostS:
            print '**************************************************************************'
            print 'Détéction d\'un clone sur le salon ! ' + host[0] + ' = ' + user.nick
            print '**************************************************************************'

Pour chaque utilisateur, on récupère le host et on le travaille pour obtenir la chaine qui nous interesse. Puis on la compare avec celui de l'arrivant. Si il correspond, on affiche que c'est un clone. Facile non ? La fonction est donc :

def scanHost(host): #Scanner de clones
    a = xchat.get_list('users')
    hostS = host[2].split('@')[1]
    for user in a:
        hostP = user.host.split('@')[1]
        if hostP == hostS:
            print '**************************************************************************'
            print 'Détéction d\'un clone sur le salon ! ' + host[0] + ' = ' + user.nick
            print '**************************************************************************'



Il suffit de relier cette fonction par un hook_print. Pour ma part, chaque fosi qu'une personne rejoint le salon, la fonction on_join est appelée, puis cette fonction apelle les differentes fonctions (en l'occurence le scanner). Pour coder plus proprement quoi !

def on_newJoin(word,word_eol,userdata):
    """Quand quelqu'un rejoint le salon"""
    scanHost(word) #On vérifie si ce n'est pas un clone

Puis, dans le main :

xchat.hook_print('Join',on_newJoin)

Et voila !

Etudions maintenant le scanner On DemanD !

Un peu d'algorithmique : pour comparer deux a deux des objets (chaines de carractères en l'ocurence), on prend le premier element, puis on le compare avec tous les autres. Puis on prend le second, et on le compare avec tous les autres, sauf le premier (parce qu'on les a déjà comparés). Puis on prend le troisième et on le compare avec les autres sauf le premier et le second. Etc... Voici donc comment on va procéder. Si vous avez compris l'algorithme, ça ne devrait pas être un problème.

#Scanners
def scanClones():
    listeClone = []
    a = xchat.get_list('users') #On récupere la liste des users
    i = 0 #On prend un élement
    for user in a:
        host = user.host.split('@')[1]
        j = len(a) - 1 #On le compare avec les suivants
        while j > i:
            comp = a[j].host.split('@')[1]
            if comp == host:
                listeClone.append([user.nick,a[j].nick]) #On rajoute dans la variable listeClone la liste [utilisateur, son clone]
            j -= 1
        i += 1
    return listeClone

Bien. Maintenant, on passe aux remotes. Déjà on crée un lien dans le main entre l'evenement "vous ecrivez un message sur un canal" et la fonction qu'on va créer.

xchat.hook_print('Your Message',on_youPubmsg)
La fonction commencera ainsi :


def on_youPubmsg(word,word_eol,userdata):
    votrePseudo = word[0]
    votreTexte = word[1]
    listeTexte = votreTexte.split(' ')

On récupère les arguments. Cette fonction sera utile pour les remotes (juste après). Pour le moment, juste les messages que nous tappons ne contenant exclusivement qu'un mot nous interessent. On rajoute donc ça:

if len(listeTexte) == 1:
        if listeTexte[0] == '&c': #Scanner de clones
            print 'Scan des clones .... '
            print '**************************************************************************'
            a = scanClones()
            for user, clone in a:
                print 'Clones détéctés ! ' + user + ' = ' + clone
            print '**************************************************************************'

Le code est suffisament clair. On récupere la liste retournée par la fonction scanClones() et on affiche le résultat.

Passons maintenant aux remotes. On va créer une remote kickant le pseudo si on tape &k <pseudo>. Ainsi on commence ainsi.
elif len(listeTexte) == 2:
        if listeTexte[0] == '&k':
                xchat.command('KICK ' + listeTexte[1])

 Assez simple non ?

A vous de réaliser vos propres scripts a présent. Pour les interessés, voici le script que j'ai codé (un peu tard dans la nuit, donc pas très bien optimisé) permettant de réaliser les actions suivantes:

&k / &b / &kb  <pseudo> : Kick, ban ou kick/ban le pseudo
&k/&b/&kb -a : Kick, ban ou kickban tout le monde (sauf vous)
&k/&b/&kb -c : Kick, ban ou kickban tous les clones
Scanner de clone
&c scan les clones
AutoJoin lors d'un kick
&a : change votre pseudo de la forme iZy_`afk
&me : rétablit votre pseudo d'origine (défini dans la variable _name)

Si on vous attaque en floodant vos notice, vous prendrez immediatement un pseudo de la forme iZy_***** avec ***** un nombre aléatoire de cinq caractères (permettant ainsi d'empecher l'attaque). Voici le script (n'oubliez pas de changer les variables au début selon vos préferences)


#-*-coding:Utf-8-*-
import xchat,time
from threading import Thread
from random import randint
#---------------------
# -AutoJoin
# -Anti TakeOver
# -Remotes
# -Scan de host
# -Détection clones
#-----------------------
__module_name__ = 'iPsilon-Script'
__module_version__ = '1.0 Alpha'
__module_description__ = 'Réalisé par iZy_TeH_PariaH'

#Attribut de sécurité
_spamNotice = 0
_timer = None
_timerPseudo = None
#Attribut de configuration
_autoJoin = 1
_nick = 'iZy_TeH_PariaH'


def autoJoin(word,word_eol,userdata):
    if _autoJoin == 1:
        print 'Auto-joining ' + word[1]
        xchat.command('JOIN ' + word[1])
#----------------------------------------------
# Sécurité

def recupPseudo(word):
    xchat.command('NICK ' + _nick)
    global _timerPseudo
    if _timerPseudo != None:
        xchat.unhook(_timerPseudo)
        _timerPseudo = None
    
def antiNotice(word):
    """Change de pseudo si on flood de notice"""
    global _spamNotice
    global _timer
    if _spamNotice > 0 and _spamNotice < 5:
        _spamNotice -= 1
    elif _spamNotice > 5:
        print 'Attention : vous subissez un bombardement de messages Notice ! Sécurité activée'
        _spamNotice = 0
        xchat.command('NICK ' + xchat.get_info('nick')[:4] + str(randint(1,99999)))
        global _timerPseudo
        _timerPseudo = xchat.hook_timer(60000,recupPseudo)
    if _timer != None:
        xchat.unhook(_timer)
        _timer = None
        
def on_notice(word,word_eol,userdata):
    global _spamNotice
    global _timer
    _spamNotice += 1
    _timer = xchat.hook_timer(1000,antiNotice)
    
#------------------------------------------------
#Remote
        
def on_youPubmsg(word,word_eol,userdata):
    votrePseudo = word[0]
    votreTexte = word[1]
    listeTexte = votreTexte.split(' ')
    #Remotes
    if len(listeTexte) == 1:
        if listeTexte[0] == '&me':
            xchat.command('NICK ' + _nick)
        if listeTexte[0] == '&a':
            xchat.command('NICK ' + _nick[:4] + '`afk')
        if listeTexte[0] == '&c': #Scanner de clones
            print 'Scan des clones .... '
            print '**************************************************************************'
            a = scanClones()
            for user, clone in a:
                print 'Clones détéctés ! ' + user + ' = ' + clone
            print '**************************************************************************'
                    
                    
    elif len(listeTexte) == 2:
        if listeTexte[0] == '&k':
            if listeTexte[1] == '-a': # -a = all
                for user in xchat.get_list('users'):
                    if user.nick != xchat.get_info('nick'):
                        xchat.command('KICK ' + user.nick)
            elif listeTexte[1] == '-c': #-c = clones
                for user, clone in scanClones():
                    xchat.command('KICK ' + user + ' clones interdits !')
                    xchat.command('KICK ' + clone + ' clones interdits !')
            else:
                xchat.command('KICK ' + listeTexte[1])
                
        if listeTexte[0] == '&b':
            if listeTexte[1] == '-a': # -a = all
                for user in xchat.get_list('users'):
                    if user.nick != xchat.get_info('nick'):
                        xchat.command('BAN ' + user.nick)
            elif listeTexte[1] == '-c': #-c = clones
                for user, clone in scanClones():
                    xchat.command('BAN ' + user + ' clones interdits !')
            else:
                xchat.command('BAN ' + listeTexte[1])
        
        if listeTexte[0] == '&kb':
            if listeTexte[1] == '-a': # -a = all
                for user in xchat.get_list('users'):
                    if user.nick != xchat.get_info('nick'):
                        xchat.command('BAN ' + user.nick)
                        xchat.command('KICK ' + user.nick)
            elif listeTexte[1] == '-c': #-c = clones
                for user, clone in scanClones():
                    xchat.command('BAN ' + user + ' clones interdits !')
                    xchat.command('KICK ' + user + ' clones interdits !')
                    xchat.command('KICK ' + clone + ' clones interdits !')
            else:
                xchat.command('BAN ' + listeTexte[1])
                xchat.command('KICK ' + listeTexte[1])
        if listeTexte[0] == '&op':
            if listeTexte[1] == '-a': # -a = all
                for user in xchat.get_list('users'):
                    if user.nick != xchat.get_info('nick'):
                        xchat.command('OP ' + user.nick)
            else:
                xchat.command('OP ' + listeTexte[1])
#Scanners
def scanClones():
    listeClone = []
    a = xchat.get_list('users')
    i = 0
    for user in a:
        host = user.host.split('@')[1]
        j = len(a) - 1
        while j > i:
            comp = a[j].host.split('@')[1]
            if comp == host:
                listeClone.append([user.nick,a[j].nick])
            j -= 1
        i += 1
    return listeClone
    


#------------------------------------------------
#BOT
def scanHost(host): #Scanner de clones
    a = xchat.get_list('users')
    hostS = host[2].split('@')[1]
    for user in a:
        hostP = user.host.split('@')[1]
        if hostP == hostS:
            print '**************************************************************************'
            print 'Détéction d\'un clone sur le salon ! ' + host[0] + ' = ' + user.nick
            print '**************************************************************************'
        
def antiTO(word): #Anti take-over
    auteur = word[0]
    target = word[1]
    if target == '*!*@*':
        print '**************************************************************************'
        print 'Tentative de TAKING OVER détéctée'
        print '**************************************************************************'
        xchat.command('KICK ' + auteur)
        xchat.command('UNBAN ' + target)
#------------------------------------------------
def on_newJoin(word,word_eol,userdata):
    """Quand quelqu'un rejoint le salon"""
    scanHost(word) #On vérifie si ce n'est pas un clone
def on_join(word,word_eol,userdata):
    """Quand vous rejoignez le salon """
def on_channelBan(word,word_eol,userdata):
    """Si on pose un ban """
    antiTO(word) #On vérifie si ce n'est pas un TakingOver

def printConf(word,word_eol,userdata):
    print 'Auto join : ' + str(_autoJoin)
    print 'Nick par défaut : ' + _nick
    
if __name__ == '__main__':
    print 'Démarrage du script'
    print '/conf pour voir la liste des configurations'
    #Création des connections
    xchat.hook_print("You Kicked",autoJoin)
    xchat.hook_print('Your Message',on_youPubmsg)
    xchat.hook_print('Notice',on_notice)
    xchat.hook_print('You Join',on_join)
    xchat.hook_print('Join',on_newJoin)
    xchat.hook_print('Channel Ban',on_channelBan)
    #Création des nouvelles commandes
    xchat.hook_command('conf',printConf)



Publié dans Python

Pour être informé des derniers articles, inscrivez vous :
Commenter cet article