174 lines
5.9 KiB
Python
174 lines
5.9 KiB
Python
# coding=utf-8
|
|
|
|
import json
|
|
import re
|
|
|
|
from nemubot import context
|
|
from nemubot.exception import IMException
|
|
from nemubot.hooks import hook
|
|
from nemubot.tools.xmlparser.node import ModuleState
|
|
|
|
nemubotversion = 3.4
|
|
|
|
from nemubot.module.more import Response
|
|
from nemubot.module.networking.page import headers
|
|
|
|
PASSWD_FILE = None
|
|
# You can get one with: curl -b "sessionid=YOURSESSIONID" 'https://accounts.cri.epita.net/api/users/?limit=10000' > users.json
|
|
APIEXTRACT_FILE = None
|
|
|
|
def load(context):
|
|
global PASSWD_FILE
|
|
if not context.config or "passwd" not in context.config:
|
|
print("No passwd file given")
|
|
else:
|
|
PASSWD_FILE = context.config["passwd"]
|
|
print("passwd file loaded:", PASSWD_FILE)
|
|
|
|
global APIEXTRACT_FILE
|
|
if not context.config or "apiextract" not in context.config:
|
|
print("No passwd file given")
|
|
else:
|
|
APIEXTRACT_FILE = context.config["apiextract"]
|
|
print("JSON users file loaded:", APIEXTRACT_FILE)
|
|
|
|
if PASSWD_FILE is None and APIEXTRACT_FILE is None:
|
|
return None
|
|
|
|
if not context.data.hasNode("aliases"):
|
|
context.data.addChild(ModuleState("aliases"))
|
|
context.data.getNode("aliases").setIndex("from", "alias")
|
|
|
|
if not context.data.hasNode("pics"):
|
|
context.data.addChild(ModuleState("pics"))
|
|
context.data.getNode("pics").setIndex("login", "pict")
|
|
|
|
import nemubot.hooks
|
|
context.add_hook(nemubot.hooks.Command(cmd_whois, "whois", keywords={"lookup": "Perform a lookup of the begining of the login instead of an exact search."}),
|
|
"in","Command")
|
|
|
|
class Login:
|
|
|
|
def __init__(self, line=None, login=None, uidNumber=None, firstname=None, lastname=None, promo=None, **kwargs):
|
|
if line is not None:
|
|
s = line.split(":")
|
|
self.login = s[0]
|
|
self.uid = s[2]
|
|
self.gid = s[3]
|
|
self.cn = s[4]
|
|
self.home = s[5]
|
|
else:
|
|
self.login = login
|
|
self.uid = uidNumber
|
|
self.promo = promo
|
|
self.cn = firstname + " " + lastname
|
|
try:
|
|
self.gid = "epita" + str(int(promo))
|
|
except:
|
|
self.gid = promo
|
|
|
|
def get_promo(self):
|
|
if hasattr(self, "promo"):
|
|
return self.promo
|
|
if hasattr(self, "home"):
|
|
try:
|
|
return self.home.split("/")[2].replace("_", " ")
|
|
except:
|
|
return self.gid
|
|
|
|
def get_photo(self):
|
|
if self.login in context.data.getNode("pics").index:
|
|
return context.data.getNode("pics").index[self.login]["url"]
|
|
for url in [ "https://photos.cri.epita.fr/%s", "https://intra-bocal.epitech.eu/trombi/%s.jpg" ]:
|
|
url = url % self.login
|
|
try:
|
|
_, status, _, _ = headers(url)
|
|
if status == 200:
|
|
return url
|
|
except:
|
|
logger.exception("On URL %s", url)
|
|
return None
|
|
|
|
|
|
def login_lookup(login, search=False):
|
|
if login in context.data.getNode("aliases").index:
|
|
login = context.data.getNode("aliases").index[login]["to"]
|
|
|
|
if APIEXTRACT_FILE:
|
|
with open(APIEXTRACT_FILE, encoding="utf-8") as f:
|
|
api = json.load(f)
|
|
for l in api["results"]:
|
|
if (not search and l["login"] == login) or (search and (("login" in l and l["login"].find(login) != -1) or ("cn" in l and l["cn"].find(login) != -1) or ("uid" in l and str(l["uid"]) == login))):
|
|
yield Login(**l)
|
|
|
|
login_ = login + (":" if not search else "")
|
|
lsize = len(login_)
|
|
|
|
if PASSWD_FILE:
|
|
with open(PASSWD_FILE, encoding="iso-8859-15") as f:
|
|
for l in f.readlines():
|
|
if l[:lsize] == login_:
|
|
yield Login(l.strip())
|
|
|
|
def cmd_whois(msg):
|
|
if len(msg.args) < 1:
|
|
raise IMException("Provide a name")
|
|
|
|
def format_response(t):
|
|
srch, l = t
|
|
if type(l) is Login:
|
|
pic = l.get_photo()
|
|
return "%s is %s (%s %s): %s%s" % (srch, l.cn.capitalize(), l.login, l.uid, l.get_promo(), " and looks like %s" % pic if pic is not None else "")
|
|
else:
|
|
return l % srch
|
|
|
|
res = Response(channel=msg.channel, count=" (%d more logins)", line_treat=format_response)
|
|
for srch in msg.args:
|
|
found = False
|
|
for l in login_lookup(srch, "lookup" in msg.kwargs):
|
|
found = True
|
|
res.append_message((srch, l))
|
|
if not found:
|
|
res.append_message((srch, "Unknown %s :("))
|
|
return res
|
|
|
|
@hook.command("nicks")
|
|
def cmd_nicks(msg):
|
|
if len(msg.args) < 1:
|
|
raise IMException("Provide a login")
|
|
nick = login_lookup(msg.args[0])
|
|
if nick is None:
|
|
nick = msg.args[0]
|
|
else:
|
|
nick = nick.login
|
|
|
|
nicks = []
|
|
for alias in context.data.getNode("aliases").getChilds():
|
|
if alias["to"] == nick:
|
|
nicks.append(alias["from"])
|
|
if len(nicks) >= 1:
|
|
return Response("%s is also known as %s." % (nick, ", ".join(nicks)), channel=msg.channel)
|
|
else:
|
|
return Response("%s has no known alias." % nick, channel=msg.channel)
|
|
|
|
@hook.ask()
|
|
def parseask(msg):
|
|
res = re.match(r"^(\S+)\s*('s|suis|est|is|was|were)\s+([a-zA-Z0-9_-]{3,8})$", msg.message, re.I)
|
|
if res is not None:
|
|
nick = res.group(1)
|
|
login = res.group(3)
|
|
if nick == "my" or nick == "I" or nick == "i" or nick == "je" or nick == "mon" or nick == "ma":
|
|
nick = msg.frm
|
|
if nick in context.data.getNode("aliases").index:
|
|
context.data.getNode("aliases").index[nick]["to"] = login
|
|
else:
|
|
ms = ModuleState("alias")
|
|
ms.setAttribute("from", nick)
|
|
ms.setAttribute("to", login)
|
|
context.data.getNode("aliases").addChild(ms)
|
|
context.save()
|
|
return Response("ok, c'est noté, %s est %s"
|
|
% (nick, login),
|
|
channel=msg.channel,
|
|
nick=msg.frm)
|