Salve a tutti. Sto scrivendo un Bot IRC in Python, e sono arrivato a un bot completamente funzionante, così volevo migliorare la struttura, in modo che fosse più facilmente estendibile. Ora, come potete vedere nello script allegato, nella classe Rule ho tante funzioni, una per ogni tipo di regola (e quindi di azione da compiere). Ad esempio, c'è una funzione per una risposta random, una per eseguire comandi shell, una per il bruteforce di hash md5 e così via. Ora, se voglio aggiungere una nuova funzionalità, devo modificare il sorgente aggiungendo la funzione desiderata, ed aggiungerla nel dizionario "self.internal_rules". Per maggiore comodità ed estendibilità pensavo di mettere tutte queste funzioni dentro una cartella come moduli, ad esempio random.py, shell.py, bruteforce.py e cosi via, e il bot all'avvio controlla tutti i moduli presenti e crea in base al nome del file il dizionario internal_rules. il mio problema è che in base al tipo di regola devo importare il modulo corrispondente, se ad esempio deve compiere un processo shell deve usare il modulo shell.py, ma dato che non posso fare import <variabile> poichè dopo import viene sempre considerato come stringa (o no? =|) come posso fare? Cercando in giro ho trovato il modulo imp e funzioni come imp.load_source ma non ho capito bene. Quindi mi sarebbe d'aiuto un buon metodo per importare moduli a seconda di una variabile, o altri modo per definire ed utilizzare funzioni in files esterni al "cuore" del programma. Grazie per le eventuali risposte :)
#! /usr/bin/python # -*- coding: UTF-8 -*-
""" PyBOT: Bot IRC in python. Creato da Learts This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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. See the GNU General Public License for more details. Dedicato al grande, l'inimitabile, l'incesurabile, l'imbannabile, l'invincibile, l'inbattibile, l'indistruttibile, l'inimitabile Chuck Norris! """ __module_name__ = "PyBOT" __module_version__ = __revision__ = "1.0Alpha2" __module_description__ = "Bot IRC scritto in Python" """ TODO: - Accetta comandi solo se all'inizio del messaggio o, se in mezzo al messaggio, il messaggio deve contenere il nick del bot. Utile nel caso di più bot presenti contemporaneamente" - Elimina punto di domanda da si/no (ancora qualche dubbio se sia da fare o meno) - Strutturare lo script in modo che siano facilmente aggiungibili altre regole - Funzione per salvare/caricare delle regole - Interazione con l'utente per la creazione di regole pre-bot Si pensava di strutturare così il tutto: un modulo con le funzioni necessarie al bot (comune per tutte le istanze dei bot), un modulo con tutte le funzioni delle regole (comune a tutti i bot) , un file con le regole (diverso per ogni istanza del bot), uno script per creare/salvare/ caricare e modificare files di regole (unico) """ import socket import random class Rule: autorizzati = [] negati = [] def __init__(self, name, keys, mode, help, response=None, variables=None): self.name = name self.keys = keys self.func = mode self.help = help print response and setattr(self, 'response', response) or '0' #Crea l'attributo solo se esiste, per non crearlo con valore None print variables and setattr(self, 'variables', variables) or '0' self.internal_rules = {'normal' : self.normal, 'random' : self.random, 'oneof' : self.one_of, 'auth' : self.auth, 'randomauth' : self.random_auth, 'checkauth' : self.check_auth, 'kick' : self.kick, 'disconnect' : self.disconnect, 'rejoin' : self.rejoin, 'say' : self.say, 'help' : self.send_help, 'join' : self.join, 'sys' : self.sys, 'leave' : self.leave, 'md5dec': self.find_md5} def __str__(self): return self.name def is_verified(self, server_response): for groupkey in self.keys: for key in groupkey: if key in server_response: self.written_key = key break else: return 0 return 1 def compile_rule(self, server_response): return self.internal_rules[self.func](server_response) def get_params(self, server_response): server_response = server_response.split(':', 2) try: user = server_response[1].split('!', 1)[0] except: user = 'gino' try: mode = server_response[1].split()[1] except: mode = '' try: chan = server_response[1].split()[2] except: chan = '' try: request = server_response[2].split(self.written_key, 1)[1].lstrip() except: request = '' return user, mode, chan, request def compile_message(self, message, user, request): return message.replace('$user', user).replace('$request', request) def kick(self): try: self.Bot.Socket.send("KICK %s %s :%s" % (self.chan, self.user, self.Params)) except: pass def send(self, message, chan): self.Bot.Socket.send('PRIVMSG %s :%s\n' % (chan, message)) return 'Message sent' def normal(self, server_response): user, mode, chan, request = self.get_params(server_response) message = self.compile_message(self.response, user, request) return self.send(message, chan) def one_of(self, server_response): user, mode, chan, request = self.get_params(server_response) message = self.compile_message(self.response[int(request) - 1], user, request) return self.send(message, chan) def auth(self): pass def random_auth(self, server_response): user, mode, chan, request = self.get_params(server_response) a, me = self.random(server_response) if self.variables in me: self.negati.append(user) print '%s è stato negato' % user else: self.autorizzati.append(user) print '%s è stato autorizzato' % user def check_auth(self, server_response): user, mode, chan, request = self.get_params(server_response) if user in self.autorizzati: print 'Autorizzato' return self.send(self.compile_message(self.response[0], user, request), chan) elif user in self.negati: print 'Negato' return self.send(self.compile_message(self.response[1], user, request), chan) else: print 'Niente' return self.send(self.compile_message(self.response[2], user, request), chan) def random(self, server_response): user, mode, chan, request = self.get_params(server_response) message = self.compile_message(self.response[random.randrange(len(self.response))], user, request) return self.send(message, chan), message def disconnect(self, server_response): user, mode, chan, request = self.get_params(server_response) print "Ricevuto comando di disconnessione da " + user if user == self.Bot.owner: self.Bot.disconnect(request) def rejoin(self, server_response): user, mode, chan, request = self.get_params(server_response) if self.Bot.nick in server_response: print "Sono stato kikkato!" self.Bot.join(chan) self.send(self.response, chan) def say(self, server_response): user, mode, chan, request = self.get_params(server_response) canale, text = request.split(' ', 1) if user == self.Bot.owner: return self.send(text, canale) def join(self, server_response): user, mode, chan, request = self.get_params(server_response) if user == self.Bot.owner: self.Bot.join(request) def leave(self, server_response): user, mode, chan, request = self.get_params(server_response) request = request and request or chan print request if user == self.Bot.owner: self.Bot.Socket.send("PART %s \n" % request) else: self.send("Accetto ordini solo da %s" % self.Bot.owner, chan) def sys(self, server_response): import os user, mode, chan, request = self.get_params(server_response) if user == self.Bot.owner: f = os.popen(request) for line in f: self.send(line, chan) return self.send("End of %s" % request, chan) else: return self.send("Non sei autorizzato", chan) def find_md5(self, server_response): import md5dec user, mode, chan, request = self.get_params(server_response) m = md5dec.md5_bruteforcer(33, 127, 3) try: if user == self.Bot.owner: res = m.complete_check(request) if res == None: return self.send("Stringa originaria non trovata, probabilmente è più lunga di %i caratteri" % m.max_chars, chan) return self.send("%s è l'hash di: %s" % (request, res), chan) else: return self.send("Non sei autorizzato a fondermi la CPU", chan) except: return self.send("Hash md5 non valido", chan) def send_help(self, server_response): user, mode, chan, request = self.get_params(server_response) if request: for rule in self.Bot.rules: if rule.name == request: self.send(rule.help, chan) break else: message = self.compile_message("Nessun comando/regola con nome '$request'", user, request) self.send(message, chan) else: text = ', '.join(map(str, self.Bot.rules)) self.send(text, chan) class Bot: def __init__(self, nick, owner, password = 0,): self.nick = nick self.owner = owner self.password = password self.rules = [] self.connected = 0 self.channels = [] def connect(self, server, porta=6667): """utilizzo: nomebot.connect(server, porta)\n Connette il bot al server specificato, passando dalla porta specificata.""" self.Socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.Socket.connect((server, porta)) self.Socket.send('USER %s "desktop" "freenode" :%s\n' % (self.nick, self.nick)) self.Socket.send("NICK %s\n" % self.nick) print 'Connesso' print self.password and self.Socket.send("NS IDENTIFY %s\n" % self.password) or 'Nessuna password specificata, identificazione non effettuata\n' self.connected = 1 def disconnect(self, message='Bye'): """Disconnette il bot""" if not self.connected: print "Non sei connesso" else: self.Socket.send("QUIT :%s \n" % message) for channel in self.channels: self.channels.remove(channel) self.connected = 0 def join(self, canale): """joina il canale specificato""" print self.connected and (self.Socket.send("JOIN %s\n" % canale), self.channels.append(canale)) or "Devi prima connetterti!" def add_rule(self, rule): self.rules.append(rule) rule.Bot = self def apply_rules(self): while self.connected: server_response = self.Socket.recv(4096).rstrip('\r\n') print server_response print try: for rule in self.rules: if rule.is_verified(server_response): print 'Regola verificata' print rule.compile_rule(server_response) break except: pass if __name__ == '__main__': permesso = Rule('permesso', [['!permesso']], 'randomauth', "Da o nega il permesso per la richiesta. Usage: !permesso richiesta", ['$user, hai il mio permesso per $request', '$user, NON hai il mio permesso'], 'NON') grazie = Rule('grazie', [['grazie', 'Grazie'], ['Chuck', 'chuck']], 'normal', "Ringraziarmi è giusto", "Ringraziare Chuck Norris è cosa buona e giusta") say = Rule('say', [['!say']], 'say', "Dico quello richiesto nel canale specificato. Al momento bisogna avere dei permessi speciali per usare !say. Usage: !say canale richiesta") sino = Rule('si/no', [['!sino']], 'random', "Random: Si o No", ['SI, sicuramente $request', 'Può darsi che $request', 'No, non penso che $request']) help = Rule('help', [['!help']], 'help', "Funzione d'aiuto. Se chiamata semplicemente '!help' mostra tutti i possibili comandi, se chiamata come !help nomecomando mostra l'help specifico del comando") join = Rule('join', [['!join']], 'join', "Joino il canale specificato.B isogna avere dei permessi speciali per usare !join. Usage: !join canale") sys = Rule('sys', [['!sys']], 'sys', "Eseguo il comando in una shell e mando l'output. Al momento bisogna avere dei permessi speciali per usare !sys. Usage: !sys comando") leave = Rule('leave', [['!leave']], 'leave', "Lascio il canale specificato. Al momento bisogna avere dei permessi speciali per usare !leave. Usage: leave channel. Se channel non è specificato lascio il canale corrente") bruteforce = Rule('bruteforce', [['!bruteforce']], 'md5dec', "Trova la stringa originaria di un hash md5 con la tecnica del bruteforcing. Stringhe originarie di massimo 3 caratteri. Usage: !bruteforce hash_md5") disconnect = Rule('disconnect', [['!disconnect']], 'disconnect', "Mi disconnetto. Al momento bisogna avere dei permessi speciali per usare !disconnect. Usage: !disconnect messaggio_uscita (il messaggio d'uscita è momentaneamente non funzionante)") kick = Rule('auto-rejoin', [['KICK']], 'rejoin', "Funzione automatica per l'auto-rejoin") C = Bot('|Chuck_Norris|', '_Learts_') C.add_rule(permesso) C.add_rule(grazie) C.add_rule(say) C.add_rule(sino) C.add_rule(help) C.add_rule(sys) C.add_rule(leave) C.add_rule(bruteforce) C.add_rule(disconnect) C.add_rule(kick) C.add_rule(join) C.connect('irc.freenode.org') C.join('#PTA') C.join('#tremulous.ita') C.apply_rules()
_______________________________________________ Python mailing list Python@lists.python.it http://lists.python.it/mailman/listinfo/python