]> gitweb.pimeys.fr Git - bots/basile.git/blobdiff - nk.py
Meteo : bot mort et enterré depuis longtemps
[bots/basile.git] / nk.py
diff --git a/nk.py b/nk.py
index c80adfd0ff303adc7e0be438292e4a06d6f80869..0aafbc16aff64606b07b40e5d5ccf0e6a6ea6e69 100644 (file)
--- a/nk.py
+++ b/nk.py
@@ -8,6 +8,7 @@
 import socket
 import json
 import ssl
+import traceback
 
 #: Config de basile
 import config
@@ -15,7 +16,7 @@ import config
 class NKError(Exception):
     def __init__(self,msg):
         Exception.__init__(self)
-        self.msg=msg
+        self.msg = msg
     def __str__(self):
         return str(self.msg)
     def __unicode__(self):
@@ -30,43 +31,126 @@ class NKHelloFailed(NKError):
 class NKUnknownError(NKError):
     pass
 
+class NKDeadServer(NKError):
+    pass
+
+def full_read(socket):
+    # On récupère d'abord la taille du message
+    length_str = ''
+    char = socket.recv(1)
+    while char != '\n':
+        length_str += char
+        char = socket.recv(1)
+    total = int(length_str)
+    # On utilise une memoryview pour recevoir les données chunk par chunk efficacement
+    view = memoryview(bytearray(total))
+    next_offset = 0
+    while total - next_offset > 0:
+        recv_size = socket.recv_into(view[next_offset:], total - next_offset)
+        next_offset += recv_size
+    try:
+        msg = json.loads(view.tobytes())
+    except (TypeError, ValueError) as e:
+        raise NKNotJson("L'objet reçu n'est pas un JSON")
+    return msg
+
 def connect():
-    sock=socket.socket()
+    sock = socket.socket()
     try:
         # On établit la connexion sur port 4242
         sock.connect((config.nk_server, config.nk_port))
         # On passe en SSL
-        sock=ssl.wrap_socket(sock,ca_certs='../keys/ca_.crt')
+        sock = ssl.wrap_socket(sock, ca_certs='../keys/ca_.crt')
         # On fait un hello
-        sock.write('["hello", "Basile"]')
+        sock.write(json.dumps(["hello", "Basile"]))
         # On récupère la réponse du hello
-        out=sock.read()
-        out=json.loads(out)
+        out = full_read(sock)
     except Exception as exc:
         # Si on a foiré quelque part, c'est que le serveur est down
         raise NKRefused(str(exc))
-    if out["retcode"]==0:
+    if out["retcode"] == 0:
         return sock
-    elif out["retcode"]==11:
+    elif out["retcode"] == 11:
         raise NKHelloFailed(out["errmsg"])
     else:
         raise NKUnknownError(out["errmsg"])
 
 
-def login(username,password,typ="bdd"):
-    sock=connect()
-    if typ=="special": # ça c'est pour Basile lui-même
-        masque='[]'
-    elif typ=="bdd":
-        masque='[[], [], true]'
+def login(username, password, typ="bdd"):
+    sock = connect()
+    if typ == "special": # ça c'est pour Basile lui-même
+        masque = []
+    elif typ == "bdd":
+        masque = [[], [], True]
     try:
         # Basile a un compte special user
-        commande='["login", [%s,%s,"%s",%s]]'%(json.dumps(username),json.dumps(password),typ,masque)
-        sock.write(commande)
-        out=sock.read()
+        commande = ["login", [username, password, typ, masque]]
+        sock.write(json.dumps(commande))
+        out = full_read(sock)
     except Exception as exc:
         # Si on a foiré quelque part, c'est que le serveur est down
         raise NKRefused(str(exc))
-    # On vérifie ensuite que le login
-    return json.loads(out),sock
+    return out, sock
+
+def get_infos(sock, idbde, serv, canal):
+    """Récupère les données de l'utilisateur NK n°``idbde``"""
+    try:
+        sock.write(json.dumps(["compte", idbde]))
+        ret = full_read(sock)
+        retcode = ret["retcode"]
+        if retcode == 0:
+            return ret["msg"]
+        else:
+            serv.privmsg(canal, ret["errmsg"].encode("utf-8"))
+    except Exception as exc:
+        trace = traceback.format_exc()
+        msg = "failed\n%s" % trace
+        for l in msg.split("\n"):
+            serv.privmsg(canal, l)
+        #log(self.serveur, "priv", auteur, " ".join(message) + "[failed]")
+
+def get_solde(sock, idbde, serv, canal):
+    """Récupère le (success, solde, pseudo) de l'utilisateur NK n°``idbde``"""
+    infos = get_infos(sock, idbde, serv, canal)
+    if infos:
+        return (True, infos["solde"], infos["pseudo"])
+    else:
+        return (False, None, None)
+
+def consomme(sock, idbde, conso, serv, canal):
+    """Fais consommer une conso à l'utilisateur NK n°``idbde``"""
+    try:
+        sock.write(json.dumps(["get_boutons", ["", ""]]))
+        ret = full_read(sock)
+        retcode = ret["retcode"]
+        if retcode == 0:
+            boutons = ret["msg"]
+            boutons = [b for b in boutons if b["label"].lower() == conso.lower()]
+            if len(boutons) == 0:
+                serv.privmsg(canal, (u"Impossible de trouver la conso %s" % (conso)).encode("utf-8"))
+                return False
+            bouton = boutons[0]
+            sock.write(json.dumps(["consos", [[bouton["id"], idbde, 1]]]))
+            ret = full_read(sock)
+            if ret["retcode"] == 0:
+                [[retcode, [idbouton, idbde], errmsg]] = ret["msg"]
+                if retcode != 0:
+                    serv.privmsg(canal, errmsg.encode("utf-8"))
+                else:
+                    success, solde, pseudo = get_solde(sock, idbde, serv, canal)
+                    if success:
+                        serv.privmsg(canal, (u"%s consomme 1 %s (nouveau solde : %.2f)" % (pseudo, bouton["label"], solde/100.0)).encode("utf-8"))
+                    else:
+                        serv.privmsg(canal, (u"%s consommé mais impossible de récupérer le solde après transaction." % (bouton["label"])).encode("utf-8"))
+                    return True # on a réussi à consommer la conso
+            else:
+                serv.privmsg(canal, ret["errmsg"].encode("utf-8"))
+                return False
+        else:
+            serv.privmsg(canal, ret["errmsg"])
+    except Exception as exc:
+        trace = traceback.format_exc()
+        msg = "failed\n%s" % trace
+        for l in msg.split("\n"):
+            serv.privmsg(canal, l)