From ee7a287b0f564671d100fa29ae0269c482ef4efe Mon Sep 17 00:00:00 2001 From: Vincent Le Gallic Date: Sun, 23 Nov 2014 02:13:07 +0100 Subject: [PATCH] Nouvelle gestion des utilisateurs --- basile.py | 44 +++++++++++----------- config.py | 2 +- users.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 22 deletions(-) create mode 100644 users.py diff --git a/basile.py b/basile.py index b6dd64a..0c6fdc7 100755 --- a/basile.py +++ b/basile.py @@ -29,6 +29,8 @@ import nk import isit #: Module définissant les erreurs import errors +#: Module de gestion des utilisateurs +import users # la partie qui réfère au fichier lui-même est mieux ici # sinon on réfère la config et pas le fichier lui-même @@ -91,10 +93,12 @@ class Basile(ircbot.SingleServerIRCBot): self.ops = self.overops + config.ops self.report_bugs_to = config.report_bugs_to self.chanlist = config.chanlist - self.identities = json.load(open(config.identities_file, "r")) self.stay_channels = config.stay_channels self.quiet_channels = config.quiet_channels self.last_perdu = 0 + # On charge la base de données d'utilisateurs + self.users = users.UserDB() + self.users.load() ### Communication NK def new_connection_NK(self, serv, username, password, typ="bdd"): @@ -158,10 +162,10 @@ class Basile(ircbot.SingleServerIRCBot): if self.last_perdu + config.time_between_perdu < time.time() or forced: if not channel in self.quiet_channels or forced: serv.privmsg(channel, "J'ai perdu !") - self.last_perdu=time.time() - delay=config.time_between_perdu_trigger - delta=config.time_between_perdu_trigger_delta - serv.execute_delayed(random.randrange(delay-delta,delay+delta),self.lost,(serv,channel)) + self.last_perdu = time.time() + delay = config.time_between_perdu_trigger + delta = config.time_between_perdu_trigger_delta + serv.execute_delayed(random.randrange(delay - delta, delay + delta), self.lost, (serv, channel)) def quitter(self, chan, leave_message=None): """Quitter un channel avec un message customisable.""" @@ -265,9 +269,9 @@ class Basile(ircbot.SingleServerIRCBot): serv.privmsg(auteur, ligne.encode("utf-8")) elif cmd == u"identify": if len(message) == 1: - if self.identities.has_key(auteur): + if self.users.has(auteur): serv.privmsg(auteur, "Je vous connais sous le pseudo note %s." % ( - self.identities[auteur]["pseudo"].encode("utf8"))) + self.users[auteur].pseudonote.encode("utf8"))) else: serv.privmsg(auteur, "Je ne connais pas votre pseudo note.") elif len(message) >= 3: @@ -275,9 +279,8 @@ class Basile(ircbot.SingleServerIRCBot): success, info, _ = self.new_connection_NK(serv, username, password) if success: log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") - serv.privmsg(auteur, "Identité enregistrée.") - self.identities[auteur] = info - json.dump(self.identities, open(config.identities_file,"w")) + self.users.add(auteur, info["idbde"]) + serv.privmsg(auteur, "Pseudo enregistré.") else: log(self.serveur, "priv", auteur, " ".join(message) + "[failed]") serv.privmsg(auteur, "Mot de passe invalide. (ou serveur down)") @@ -285,14 +288,13 @@ class Basile(ircbot.SingleServerIRCBot): serv.privmsg(auteur, "Syntaxe : IDENTIFY [ ]") elif cmd == u"drop": if len(message) > 1: - if self.identities.has_key(auteur): + if self.users.has(auteur): password = " ".join(message[1:]) - success, _, _ = self.new_connection_NK(serv, self.identities[auteur], password) + success, _, _ = self.new_connection_NK(serv, "#%s" % self.users[auteur].idbde, password) if success: - del self.identities[auteur] + self.users.drop(auteur) log(self.serveur, "priv", auteur, " ".join(message) + "[successful]") - json.dump(self.identities, open(config.identities_file, "w")) - serv.privmsg(auteur, "Identité oubliée.") + serv.privmsg(auteur, "Pseudo oublié.") else: log(self.serveur, "priv", auteur, " ".join(message) + "[failed]") serv.privmsg(auteur, "Mot de passe invalide. (ou serveur down)") @@ -449,8 +451,8 @@ class Basile(ircbot.SingleServerIRCBot): notunderstood = True elif cmd == u"solde": if len(message) == 1: - if self.identities.has_key(auteur): - success, solde, pseudo = nk.get_solde(self.nk, self.identities[auteur]["idbde"], serv, auteur) + if self.users.has(auteur): + success, solde, pseudo = nk.get_solde(self.nk, self.users[auteur].idbde, serv, auteur) if success: serv.privmsg(auteur, "%.2f (%s)" % (solde/100.0, pseudo.encode("utf8"))) log(self.serveur, "priv", auteur, " ".join(message) + ("[successful]" if success else "[failed]")) @@ -547,14 +549,14 @@ class Basile(ircbot.SingleServerIRCBot): serv.privmsg(canal, "%s: pong" % (auteur)) elif cmd in [u"solde", u"!solde", u"!coca"] or cmd.startswith("!"): - if self.identities.has_key(auteur): - idbde = self.identities[auteur]["idbde"] + if self.users.has(auteur): + idbde = self.users[auteur].idbde if cmd in [u"solde", u"!solde"]: - success, solde, pseudo = nk.get_solde(self.nk, self.identities[auteur]["idbde"], serv, canal) + success, solde, pseudo = nk.get_solde(self.nk, idbde, serv, canal) if success: serv.privmsg(canal, "%s: %s (%s)" % (auteur, float(solde)/100, pseudo.encode("utf8"))) elif cmd in [u"!coca"] or cmd.startswith("!"): - success = nk.consomme(self.nk, self.identities[auteur]["idbde"], message[1:], serv, canal) + success = nk.consomme(self.nk, idbde, message[1:], serv, canal) log(self.serveur, canal, auteur, message + ("[successful]" if success else "[failed]")) else: serv.privmsg(canal, "%s: Je ne connais pas votre pseudo note." % (auteur)) diff --git a/config.py b/config.py index e0ece95..a3dc293 100644 --- a/config.py +++ b/config.py @@ -29,7 +29,7 @@ nk_server = "bde2.crans.org" nk_port = 4242 #: Là où sont stockées les correspondances pseudo IRC → note -identities_file = "identities.json" +users_file = "users.json" #: Le template des noms de fichier de log logfile_template = "basile.%s.log" diff --git a/users.py b/users.py new file mode 100644 index 0000000..49ddf41 --- /dev/null +++ b/users.py @@ -0,0 +1,108 @@ +# -*- encoding: utf-8 -*- + +""" Gestion des utilisateurs par Basile. """ + +import json + +import config + +class User(object): + """ Un utilisateur. Peut avoir plusieurs pseudos IRC, un seul idbde. """ + def __init__(self, pseudosirc, idbde): + self.pseudosirc, self.idbde = pseudosirc, idbde + + def jsonize(self): + d = {"pseudosirc" : self.pseudosirc, "idbde" : self.idbde} + return d + + def __unicode__(self): + """ Retourne l'utilisateur affichable """ + return unicode(self.jsonize()) + def __str__(self): + return unicode(self).encode("utf-8") + def __repr__(self): + return repr(str(self)) + + def __eq__(self, otheruser): + """ Teste l'égalité entre deux utilisateurs (= ont un pseudo IRC commun). + Accepte aussi en deuxième une chaîne de caractères. """ + myset = set([p.lower() for p in self.pseudosirc]) + if isinstance(otheruser, User): + hisset = [p.lower() for p in otheruser.pseudosirc] + else: + hisset = [otheruser.lower()] + return myset.intersection(hisset) != set() + +def load_file(filename): + """ Récupère les utilisateurs depuis le fichier """ + with open(filename) as f: + jsonusers = json.load(f) + users = [User(**u) for u in jsonusers] + return users + +def save_file(users, filename): + """ Enregistre les utilisateurs dans le fichier """ + with open(filename, "w") as f: + raws = [u.jsonize() for u in users] + json.dump(raws, f) + +class UserDB(object): + """ Stocke et distribue des utilisateurs. """ + def __init__(self): + self.userlist = [] + + def load(self): + """ Charge le fichier d'utilisateurs dans la DB """ + self.userlist = load_file(config.users_file) + + def save(self): + """ Sauvegarde la DB dans le fichier d'utilisateurs """ + save_file(self.userlist, config.users_file) + + def add(self, pseudoirc, idbde): + """ Enregistre un nouvel utilisateur, sauf si il existe déjà. """ + if not self.has(pseudoirc): + newuser = User(pseudosirc=[pseudoirc], idbde=idbde) + self.userlist.append(newuser) + self.save() + return True + return False + create = add + + def group(self, newpseudoirc, oldpseudoirc): + """ Enregistre un autre pseudo IRC à un utilisateur existant. """ + user = self[oldpseudoirc] + if newpseudoirc.lower() in [p.lower() for p in user.pseudosirc]: + return + user.pseudosirc.append(newpseudoirc) + self.save() + + def drop(self, idbde): + """ Enlève un utilisateur, via son idbde. """ + idrop = [i for (i, u) in enumerate(self.userlist) if u.idbde == idbde] + if idrop: + self.userlist.pop(idrop[0]) + self.save() + else: + raise KeyError("Pas d'utilisateur d'idbde %s." % (idbde,)) + + def __getitem__(self, pseudoirc): + """ Récupère un utilisateur par son pseudo IRC. """ + pseudo = pseudoirc.lower() + match = [u for u in self.userlist if pseudo in [p.lower() for p in u.pseudosirc]] + if match: + return match[0] + else: + raise KeyError("Utilisateur inexistant : %r" % pseudoirc) + + def has(self, pseudoirc): + """ Vérifie si cet utilisateur existe dans la base (case-insensitive). """ + try: + user = self[pseudoirc] + except KeyError: + return False + else: + return True + + def __repr__(self): + return repr(self.userlist) -- 2.39.2