Advertisement
Guest User

Untitled

a guest
Aug 17th, 2017
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.73 KB | None | 0 0
  1. """Evita que los nicks caduquen en un red IRC por falta de uso,
  2. activandolos cada cierto tiempo.
  3. Se ejecuta con un canal principal configurado,
  4. al cual entra al conectarse.
  5. Los comandos se obtienen con !ayuda.
  6. Se pueden ejecutar en privado, o en el canal principal.
  7. Algunos comandos tienen restringido su uso al canal principal,
  8. por motivos de seguridad.
  9. Debido a que al poner o quitar un nick hay que indicar la clave,
  10. se recomienda encarecidamente ejecutarlos en privado.
  11. Los nicks se guardan en el fichero nicks.db,
  12. codificada su clave con una almacenada en clave.crypt.
  13. Al iniciarse por primera vez, crea un nueva clave.
  14. Si pierde la clave, se generara una nueva,
  15. pero no podra acceder a las claves almacenadas.
  16. """
  17.  
  18. ##### ---------- OPCIONES ---------- #####
  19. ## Servidor IRC (entre comillas) ##
  20. SERVIDOR = "irc.irc-hispano.org"
  21. ## Puerto para el servidor ##
  22. PUERTO = 6667
  23. ## Nick (entre comillas) ##
  24. NICK = "Parking"
  25. ## Canal principal (entre comillas) ##
  26. CANAL = "#pybot"
  27. ## Intervalo entre activaciones de nicks (en segundos) ##
  28. INTERVALO = 604800  # Una semana
  29. ## Modo debug, envia mas mensajes al canal (1 o 0) ##
  30. DEBUG = 1
  31. ##### ---------- OPCIONES ---------- #####
  32.  
  33. import socket, os, time, threading, base64
  34.  
  35. class IRC:
  36.     def __init__(self):
  37.         """Inicia variables"""
  38.         self.version = 2
  39.         self.servidor = SERVIDOR
  40.         self.puerto = PUERTO
  41.         self.nick = NICK
  42.         self.user = ("parking", "bot", "bot", "Aparcamiento de nicks")
  43.         self.canal = CANAL.lower()
  44.         self.tiemposleep = INTERVALO
  45.         self.ficheronicks = "nicks.db"
  46.         self.ruta = os.path.dirname(__file__) + "/"
  47.         self.hilovar = None
  48.         self.iniciotiempo = 0
  49.         self.ultimatiempo = 0
  50.         self.comprobarencriptacion()
  51.  
  52.  
  53.     def comprobarencriptacion(self):
  54.         """Comprueba que exista el fichero con la clave, o lo crea"""
  55.         clave = "clave.crypt"
  56.         fichero = self.ruta + clave
  57.         try:
  58.             f = open(fichero)
  59.         except:
  60.             f = open(fichero, "w")
  61.             import random
  62.             self.clave = str(random.randint(int("1"*512), int("9"*512)))
  63.             del random
  64.             f.write(self.clave + "\r\n\r\n## ## ## Clave generada en '%s' v1\r\n\r\n## ## ## No modifiques la primera linea del fichero, o no se podran leer las claves guardadas.\r\n\r\n## ## ## Guarda este fichero SIEMPRE junto con 'nicks.db'.\r\n" % time.asctime())
  65.             f.close()
  66.         else:
  67.             self.clave = f.read(512)
  68.             f.close()
  69.         self.clave = "".join(reversed(list(self.clave)))
  70.         try:
  71.             int(self.clave)
  72.         except:
  73.             raise Exception("ERROR: 'clave.crpyt' corrupto. Borrelo para crear uno nuevo [perdera el acceso a todos los nicks ya guardados!!!]")
  74.  
  75.  
  76.     def conectar(self):
  77.         """Conecta al servidor e inicia el bucle de recepcion"""
  78.         self.socket = socket.socket()
  79.         self.socket.connect((self.servidor, self.puerto))
  80.         self.socket.settimeout(300)
  81.         self.enviarcomando("NICK", self.nick)
  82.         self.enviarcomando("USER", *self.user)
  83.         self.operativo = False
  84.         try:
  85.             self.recibir()
  86.         finally:
  87.             self.operativo = False
  88.  
  89.  
  90.     def recibir(self):
  91.         """Bucle de recepcion"""
  92.         f = self.socket.makefile()
  93.         while True:
  94.             linea = f.readline()
  95.             if not linea:
  96.                 raise self
  97.             try:
  98.                 self.procesarlinearecibida(linea)
  99.             except Exception, error:
  100.                 self.error("al procesar linea recibida: %s" % error)
  101.  
  102.  
  103.     def procesarlinearecibida(self, linea):
  104.         """Procesa una linea recibida"""
  105.         parametros = self.dividirparametros(linea)
  106.         if linea[0] == ":":
  107.             comando = parametros[1]
  108.             origen = parametros[0].split("!")[0]
  109.             parametros = parametros[2:]
  110.         else:
  111.             comando = parametros[0]
  112.             parametros = parametros[1:]
  113.         if comando == "PING":
  114.             self.enviarcomando("PONG", *parametros)
  115.         elif comando == "001":
  116.             self.enviarcomando("JOIN", self.canal)
  117.             self.nick = parametros[0]
  118.         elif comando == "433":
  119.             if not self.operativo or parametros[1] == self.nick:
  120.                 self.nick = parametros[1] + "-"
  121.                 self.enviarcomando("NICK", self.nick)
  122.             else:
  123.                 self.error("al cambiar a '%s': %s" % (parametros[1], parametros[-1]))
  124.         elif comando == "438":
  125.             try:
  126.                 tiempo = int(parametros[8])
  127.             except:
  128.                 tiempo = 30
  129.             self.nuevohilo(self.hilo2, tiempo, "NICK", parametros[1])
  130.         elif comando == "JOIN" and origen == self.nick and parametros[0].lower() == self.canal:
  131.                 self.debug("Bot parking iniciado. Version %s. En [1 minuto] se activara el proceso. Se volvera a activar cada %s" % (self.version, self.conver(self.tiemposleep)))
  132.                 self.operativo = True
  133.                 if self.hilovar:
  134.                     self.debug("Hilo ya iniciado!!")
  135.                 else:
  136.                     self.hilovar = self.nuevohilo(self.hilo)
  137.                     self.iniciotiempo = time.time()
  138.         elif comando == "PRIVMSG":
  139.             self.procesarcomando(origen, parametros[0], parametros[1].split())
  140.  
  141.  
  142.     def procesarcomando(self, origen, canal, parametros):
  143.         """Procesa un comando del usuario"""
  144.         enviar = canal if canal[0] in "#&+" else origen
  145.         if parametros[0] == "!addnick":
  146.             if canal[0] in "#&+":
  147.                 self.info("NO escriba sus claves en canales publicos, se RECOMIENDA que ejecute el comando en un mensaje PRIVADO", enviar)
  148.             try:
  149.                 nick, passwd = parametros[1], parametros[2]
  150.             except:
  151.                 self.error("Uso: !addnick user pass", enviar)
  152.             else:
  153.                 c = self.encriptar(nick, passwd)
  154.                 f = open(self.ruta + self.ficheronicks, "a")
  155.                 f.write(c + "\n")
  156.                 f.close()
  157.                 self.info("Ok. Se activara '%s' cada %s" % (nick, self.conver(self.tiemposleep)), enviar)
  158.                 self.debug("Nuevo nick")
  159.         elif parametros[0] == "!delnick":
  160.             if canal[0] in "#&+":
  161.                 self.info("NO escriba sus claves en canales publicos, se RECOMIENDA que ejecute el comando en un mensaje PRIVADO", enviar)
  162.             try:
  163.                 nick, passwd = parametros[1], parametros[2]
  164.             except:
  165.                 self.error("Uso: !delnick user pass", enviar)
  166.             else:
  167.                 try:
  168.                     f = open(self.ruta + self.ficheronicks)
  169.                 except:
  170.                     self.error("No hay usuarios", enviar)
  171.                 else:
  172.                     ls = f.readlines()
  173.                     f.close()
  174.                     for l in ls[:]:
  175.                         nick2, passwd2 = self.desencriptar(l, 0)
  176.                         if nick == nick2 and passwd == passwd2:
  177.                             ls.remove(l)
  178.                             self.info("Borrado '%s'" % nick, enviar)
  179.                             break
  180.                     else:
  181.                         self.error("No esta '%s' (o clave incorrecta)" % nick, enviar)
  182.                         return
  183.                     f = open(self.ruta + self.ficheronicks, "w")
  184.                     f.writelines(ls)
  185.                     f.close()
  186.         elif parametros[0] == "!listanicks":
  187.             if canal.lower() == self.canal:
  188.                 self.listarnicks(enviar)
  189.             else:
  190.                 self.error("Permiso denegado", enviar)
  191.         elif parametros[0] == "!activanicks":
  192.             if canal.lower() == self.canal:
  193.                 self.info("Activando nicks AHORA!", enviar)
  194.                 self.nuevohilo(self.hilo3, self.activarnicks)
  195.             else:
  196.                 self.error("Permiso denegado", enviar)
  197.         elif parametros[0] == "!eliminacorruptos":
  198.             if canal.lower() == self.canal:
  199.                 self.eliminarcorruptos(enviar)
  200.             else:
  201.                 self.error("Permiso denegado", enviar)
  202.         elif parametros[0] == "!ayuda":
  203.             self.ayuda(enviar)
  204.  
  205.  
  206.     def dividirparametros(self, linea):
  207.         """Divide una linea en parametros"""
  208.         if linea[0] == ":":
  209.             # Quitar ":" iniciales
  210.             linea = linea[1:]
  211.         # Quitar fin de linea
  212.         linea = linea.replace("\r", "").replace("\n", "")
  213.         puntos = linea.find(":")
  214.         if puntos == -1:
  215.             return linea.split()
  216.         else:
  217.             return linea[:puntos].split() + [linea[puntos+1:]]
  218.  
  219.  
  220.     def enviarcomando(self, comando, *parametros):
  221.         """Envia un comando"""
  222.         if parametros:
  223.             for i in xrange(len(parametros)-1):
  224.                 comando += " " + parametros[i]
  225.             comando += " :" + parametros[-1]
  226.         self.socket.send(comando + "\r\n")
  227.  
  228.  
  229.     def debug(self, texto):
  230.         """Texto que enviar al debug"""
  231.         if DEBUG:
  232.             self.enviarcomando("PRIVMSG", self.canal, "DEBUG: " + texto)
  233.             print "DEBUG:", texto
  234.  
  235.  
  236.     def info(self, texto, canal):
  237.         """Texto de informacion"""
  238.         self.enviarcomando("PRIVMSG", canal, "INFO: " + texto)
  239.         # print "INFO: ", texto # informacion sobre el comando
  240.  
  241.  
  242.     def error(self, texto, canal=None):
  243.         """Texto de error"""
  244.         self.enviarcomando("PRIVMSG", self.canal if canal is None else canal, "ERROR: " + texto)
  245.         print "ERROR:", texto
  246.  
  247.  
  248.     def conver(self, tTemp, sMs=60):
  249.         """Convierte el tiempo a un formato legible"""
  250.         sM = 60; mH = 60; hS = mH * sM; hD = 24; dS = hD * hS; dA = 365; aS = dA * dS; tI = int(tTemp); tA = tI//aS; tD = tI//dS%dA; tH = tI//hS%hD; tM = tI//sM%mH; tS = tI%sM; tMS = (tTemp%1)*1000; tR = []
  251.         if tA: tR.append("%sA" % puntos(tA))
  252.         if tD: tR.append("%dD" % tD)
  253.         if tH: tR.append("%dh" % tH)
  254.         if tM: tR.append("%dm" % tM)
  255.         if tS: tR.append("%ds" % tS)
  256.         if (tMS or not tR) and (abs(tTemp) < sMs or sMs is -1):
  257.             tR.append("%dms" % tMS)
  258.         if not tR: tR.append("0s")
  259.         return " ".join(tR)
  260.  
  261.  
  262.  
  263.     def nuevohilo(self, tipo, *argumentos):
  264.         """Crea un nuevo hilo"""
  265.         hilo = threading.Thread(target=lambda: tipo(*argumentos))
  266.         hilo.start()
  267.         return hilo
  268.  
  269.  
  270.     def hilo2(self, tiempo, comando):
  271.         """Hilo para enviar asincronamente"""
  272.         time.sleep(tiempo)
  273.         self.enviarcomando(*comando)
  274.  
  275.  
  276.     def hilo3(self, funcion):
  277.         """Hilo para ejecutar funciones"""
  278.         funcion()
  279.  
  280.  
  281.     def hilo(self):
  282.         """Hilo para tareas que realizar"""
  283.         self.debug("Hilo iniciado")
  284.         time.sleep(60) # Esperar un minuto
  285.         while self.operativo:
  286.             self.nuevohilo(self.hilo3, self.activarnicks)
  287.             self.ultimatiempo = time.time()
  288.             time.sleep(self.tiemposleep)
  289.  
  290.  
  291.     def activarnicks(self):
  292.         """Activar los nicks"""
  293.         self.debug("Iniciando mantenimiento de nicks")
  294.         time.sleep(10)
  295.         # Cargar fichero
  296.         try:
  297.             f = open(self.ruta + self.ficheronicks)
  298.         except Exception, error:
  299.             self.error("al leer la lista de nicks: %s" % error)
  300.         else:
  301.             i = 0
  302.             for l in f:
  303.                 i += 1
  304.                 nick, passwd = self.desencriptar(l)
  305.                 if nick:
  306.                     self.debug("Cambiando al nick: %s" % nick)
  307.                     time.sleep(10)
  308.                     self.enviarcomando("NICK", "%s:%s" % (nick, passwd))
  309.                     self.enviarcomando("NICK", self.nick)
  310.                     time.sleep(50)
  311.                 else:
  312.                     self.error("al desencriptar nick y clave")
  313.                     time.sleep(10)
  314.             self.debug("Fin de la lista de nicks. Total: %s" % i)
  315.         self.debug("Se volvera a realizar tras %s" % self.conver(self.tiemposleep))
  316.  
  317.  
  318.     def listarnicks(self, enviar):
  319.         """Lista los nicks almacenados"""
  320.         try:
  321.             f = open(self.ruta + self.ficheronicks)
  322.         except:
  323.             self.error("No hay usuarios", enviar)
  324.         else:
  325.             c = []
  326.             for l in f:
  327.                 usuario = l[:l.find(" : ")]
  328.                 nick, passwd = self.desencriptar(l, 0)
  329.                 if usuario != nick:
  330.                     c.append(usuario + " [corrupto!!]")
  331.                 else:
  332.                     c.append(usuario)
  333.             self.info("Nicks: %s" % ", ".join(c), enviar)
  334.  
  335.  
  336.     def eliminarcorruptos(self, enviar):
  337.         """Elimina los nicks corruptos"""
  338.         try:
  339.             f = open(self.ruta + self.ficheronicks)
  340.         except:
  341.             self.error("No hay usuarios", enviar)
  342.         else:
  343.             ls = f.readlines()
  344.             total = 0
  345.             f.close()
  346.             for l in ls[:]:
  347.                 corrupcion = 0
  348.                 try:
  349.                     usuario = l[:l.find(" : ")]
  350.                     corrupcion = 1
  351.                     nick, passwd = self.desencriptar(l, 0)
  352.                     corrupcion = 2
  353.                     if nick != usuario:
  354.                         ls.remove(l)
  355.                         total += 1
  356.                         self.info("Borrado %s (clave incorrecta)" % usuario, enviar)
  357.                 except:
  358.                     ls.remove(l)
  359.                     total += 1
  360.                     if corrupcion is 2:
  361.                         self.info("Borrado %s" % usuario, enviar)
  362.                     elif corrupcion is 1:
  363.                         self.info("Borrado %s (clave no valida)" % usuario, enviar)
  364.                     elif corrupcion is 0:
  365.                         self.info("Borrada linea corrupta (no se encontro usario)", enviar)
  366.                     else:
  367.                         self.info("Borrada linea", enviar)
  368.             if total:
  369.                 f = open(self.ruta + self.ficheronicks, "w")
  370.                 f.writelines(ls)
  371.                 f.close()
  372.                 self.info("Borrados %s" % total, enviar)
  373.             else:
  374.                 self.info("No hay corruptos", enviar)
  375.  
  376.  
  377.     def desencriptar(self, linea, debug=1):
  378.         """Desencripta una linea"""
  379.         linea = linea.replace("\r", "").replace("\n", "")
  380.         f = linea.find(" : ")
  381.         u = linea[:f]
  382.         try: d = "".join([chr((ord(j) - int(i) - int(self.clave[-10:])) % 256) for i, j in zip(self.clave, base64.b64decode(linea[f+3:]))]).split(":botParking:")
  383.         except: d = ()
  384.         if len(d) != 2:
  385.             if debug:
  386.                 self.debug("No se ha encontrado el ID en la cadena encriptada")
  387.             return None, None
  388.         if d[1] != u:
  389.             if debug:
  390.                 self.debug("El usuario encriptado no coincide con el inicial")
  391.             return None, None
  392.         return d[1], d[0]
  393.  
  394.  
  395.     def encriptar(self, usuario, clave):
  396.         """Encripta usuario y clave"""
  397.         return usuario + " : " + base64.b64encode("".join([chr((int(i) + ord(j) + int(self.clave[-10:])) % 256) for i, j in zip(self.clave, clave + ":botParking:" + usuario)]))
  398.  
  399.  
  400.     def ayuda(self, enviar):
  401.         """Muestra los comandos"""
  402.         self.info("Datos:", enviar)
  403.         self.info(" Tiempo entre activaciones: %s" % self.conver(self.tiemposleep, 0), enviar)
  404.         self.info(" Ultima activacion: %s" % (time.strftime("%d/%m/%Y %H", time.localtime(self.ultimatiempo)) if self.ultimatiempo else "No realizada"), enviar)
  405.         self.info(" Proxima activacion: %s" % time.strftime("%d/%m/%Y %X", time.localtime((self.ultimatiempo if self.ultimatiempo else self.iniciotiempo) + self.tiemposleep)), enviar)
  406.         self.info("Comandos:", enviar)
  407.         self.info(" !addnick usuario clave  - Pone un nick para ser activado (recomendado en PRIVADO)", enviar)
  408.         self.info(" !delnick usuario clave  - Elimina un nick de ser activado (recomendado en PRIVADO)", enviar)
  409.         self.info(" !listanick      - Muestra los nicks que se activaran (*)", enviar)
  410.         self.info(" !activarnicks       - Realiza la activacion de los nicks en ese instante (*)", enviar)
  411.         self.info(" !eliminacorruptos   - Elimina los usuarios corruptos de la lista (*)", enviar)
  412.         self.info("(*): Comando restringido, solo se pueden realizar en el canal principal", enviar)
  413.  
  414.  
  415.     def main(self):
  416.         """Main"""
  417.         ejecucion = True
  418.         while ejecucion:
  419.             ejecucion = False
  420.             try:
  421.                 self.conectar()
  422.             except socket.timeout:
  423.                 ejecucion = True
  424.             except socket.error:
  425.                 ejecucion = True
  426.                 time.sleep(60)
  427.             except IRC: # eof
  428.                 ejecucion = True
  429.                 time.sleep(60)
  430.  
  431.  
  432.  
  433.  
  434. if __name__ == "__main__":
  435.     irc = IRC()
  436.     irc.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement