Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """Evita que los nicks caduquen en un red IRC por falta de uso,
- activandolos cada cierto tiempo.
- Se ejecuta con un canal principal configurado,
- al cual entra al conectarse.
- Los comandos se obtienen con !ayuda.
- Se pueden ejecutar en privado, o en el canal principal.
- Algunos comandos tienen restringido su uso al canal principal,
- por motivos de seguridad.
- Debido a que al poner o quitar un nick hay que indicar la clave,
- se recomienda encarecidamente ejecutarlos en privado.
- Los nicks se guardan en el fichero nicks.db,
- codificada su clave con una almacenada en clave.crypt.
- Al iniciarse por primera vez, crea un nueva clave.
- Si pierde la clave, se generara una nueva,
- pero no podra acceder a las claves almacenadas.
- """
- ##### ---------- OPCIONES ---------- #####
- ## Servidor IRC (entre comillas) ##
- SERVIDOR = "irc.irc-hispano.org"
- ## Puerto para el servidor ##
- PUERTO = 6667
- ## Nick (entre comillas) ##
- NICK = "Parking"
- ## Canal principal (entre comillas) ##
- CANAL = "#pybot"
- ## Intervalo entre activaciones de nicks (en segundos) ##
- INTERVALO = 604800 # Una semana
- ## Modo debug, envia mas mensajes al canal (1 o 0) ##
- DEBUG = 1
- ##### ---------- OPCIONES ---------- #####
- import socket, os, time, threading, base64
- class IRC:
- def __init__(self):
- """Inicia variables"""
- self.version = 2
- self.servidor = SERVIDOR
- self.puerto = PUERTO
- self.nick = NICK
- self.user = ("parking", "bot", "bot", "Aparcamiento de nicks")
- self.canal = CANAL.lower()
- self.tiemposleep = INTERVALO
- self.ficheronicks = "nicks.db"
- self.ruta = os.path.dirname(__file__) + "/"
- self.hilovar = None
- self.iniciotiempo = 0
- self.ultimatiempo = 0
- self.comprobarencriptacion()
- def comprobarencriptacion(self):
- """Comprueba que exista el fichero con la clave, o lo crea"""
- clave = "clave.crypt"
- fichero = self.ruta + clave
- try:
- f = open(fichero)
- except:
- f = open(fichero, "w")
- import random
- self.clave = str(random.randint(int("1"*512), int("9"*512)))
- del random
- 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())
- f.close()
- else:
- self.clave = f.read(512)
- f.close()
- self.clave = "".join(reversed(list(self.clave)))
- try:
- int(self.clave)
- except:
- raise Exception("ERROR: 'clave.crpyt' corrupto. Borrelo para crear uno nuevo [perdera el acceso a todos los nicks ya guardados!!!]")
- def conectar(self):
- """Conecta al servidor e inicia el bucle de recepcion"""
- self.socket = socket.socket()
- self.socket.connect((self.servidor, self.puerto))
- self.socket.settimeout(300)
- self.enviarcomando("NICK", self.nick)
- self.enviarcomando("USER", *self.user)
- self.operativo = False
- try:
- self.recibir()
- finally:
- self.operativo = False
- def recibir(self):
- """Bucle de recepcion"""
- f = self.socket.makefile()
- while True:
- linea = f.readline()
- if not linea:
- raise self
- try:
- self.procesarlinearecibida(linea)
- except Exception, error:
- self.error("al procesar linea recibida: %s" % error)
- def procesarlinearecibida(self, linea):
- """Procesa una linea recibida"""
- parametros = self.dividirparametros(linea)
- if linea[0] == ":":
- comando = parametros[1]
- origen = parametros[0].split("!")[0]
- parametros = parametros[2:]
- else:
- comando = parametros[0]
- parametros = parametros[1:]
- if comando == "PING":
- self.enviarcomando("PONG", *parametros)
- elif comando == "001":
- self.enviarcomando("JOIN", self.canal)
- self.nick = parametros[0]
- elif comando == "433":
- if not self.operativo or parametros[1] == self.nick:
- self.nick = parametros[1] + "-"
- self.enviarcomando("NICK", self.nick)
- else:
- self.error("al cambiar a '%s': %s" % (parametros[1], parametros[-1]))
- elif comando == "438":
- try:
- tiempo = int(parametros[8])
- except:
- tiempo = 30
- self.nuevohilo(self.hilo2, tiempo, "NICK", parametros[1])
- elif comando == "JOIN" and origen == self.nick and parametros[0].lower() == self.canal:
- 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)))
- self.operativo = True
- if self.hilovar:
- self.debug("Hilo ya iniciado!!")
- else:
- self.hilovar = self.nuevohilo(self.hilo)
- self.iniciotiempo = time.time()
- elif comando == "PRIVMSG":
- self.procesarcomando(origen, parametros[0], parametros[1].split())
- def procesarcomando(self, origen, canal, parametros):
- """Procesa un comando del usuario"""
- enviar = canal if canal[0] in "#&+" else origen
- if parametros[0] == "!addnick":
- if canal[0] in "#&+":
- self.info("NO escriba sus claves en canales publicos, se RECOMIENDA que ejecute el comando en un mensaje PRIVADO", enviar)
- try:
- nick, passwd = parametros[1], parametros[2]
- except:
- self.error("Uso: !addnick user pass", enviar)
- else:
- c = self.encriptar(nick, passwd)
- f = open(self.ruta + self.ficheronicks, "a")
- f.write(c + "\n")
- f.close()
- self.info("Ok. Se activara '%s' cada %s" % (nick, self.conver(self.tiemposleep)), enviar)
- self.debug("Nuevo nick")
- elif parametros[0] == "!delnick":
- if canal[0] in "#&+":
- self.info("NO escriba sus claves en canales publicos, se RECOMIENDA que ejecute el comando en un mensaje PRIVADO", enviar)
- try:
- nick, passwd = parametros[1], parametros[2]
- except:
- self.error("Uso: !delnick user pass", enviar)
- else:
- try:
- f = open(self.ruta + self.ficheronicks)
- except:
- self.error("No hay usuarios", enviar)
- else:
- ls = f.readlines()
- f.close()
- for l in ls[:]:
- nick2, passwd2 = self.desencriptar(l, 0)
- if nick == nick2 and passwd == passwd2:
- ls.remove(l)
- self.info("Borrado '%s'" % nick, enviar)
- break
- else:
- self.error("No esta '%s' (o clave incorrecta)" % nick, enviar)
- return
- f = open(self.ruta + self.ficheronicks, "w")
- f.writelines(ls)
- f.close()
- elif parametros[0] == "!listanicks":
- if canal.lower() == self.canal:
- self.listarnicks(enviar)
- else:
- self.error("Permiso denegado", enviar)
- elif parametros[0] == "!activanicks":
- if canal.lower() == self.canal:
- self.info("Activando nicks AHORA!", enviar)
- self.nuevohilo(self.hilo3, self.activarnicks)
- else:
- self.error("Permiso denegado", enviar)
- elif parametros[0] == "!eliminacorruptos":
- if canal.lower() == self.canal:
- self.eliminarcorruptos(enviar)
- else:
- self.error("Permiso denegado", enviar)
- elif parametros[0] == "!ayuda":
- self.ayuda(enviar)
- def dividirparametros(self, linea):
- """Divide una linea en parametros"""
- if linea[0] == ":":
- # Quitar ":" iniciales
- linea = linea[1:]
- # Quitar fin de linea
- linea = linea.replace("\r", "").replace("\n", "")
- puntos = linea.find(":")
- if puntos == -1:
- return linea.split()
- else:
- return linea[:puntos].split() + [linea[puntos+1:]]
- def enviarcomando(self, comando, *parametros):
- """Envia un comando"""
- if parametros:
- for i in xrange(len(parametros)-1):
- comando += " " + parametros[i]
- comando += " :" + parametros[-1]
- self.socket.send(comando + "\r\n")
- def debug(self, texto):
- """Texto que enviar al debug"""
- if DEBUG:
- self.enviarcomando("PRIVMSG", self.canal, "DEBUG: " + texto)
- print "DEBUG:", texto
- def info(self, texto, canal):
- """Texto de informacion"""
- self.enviarcomando("PRIVMSG", canal, "INFO: " + texto)
- # print "INFO: ", texto # informacion sobre el comando
- def error(self, texto, canal=None):
- """Texto de error"""
- self.enviarcomando("PRIVMSG", self.canal if canal is None else canal, "ERROR: " + texto)
- print "ERROR:", texto
- def conver(self, tTemp, sMs=60):
- """Convierte el tiempo a un formato legible"""
- 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 = []
- if tA: tR.append("%sA" % puntos(tA))
- if tD: tR.append("%dD" % tD)
- if tH: tR.append("%dh" % tH)
- if tM: tR.append("%dm" % tM)
- if tS: tR.append("%ds" % tS)
- if (tMS or not tR) and (abs(tTemp) < sMs or sMs is -1):
- tR.append("%dms" % tMS)
- if not tR: tR.append("0s")
- return " ".join(tR)
- def nuevohilo(self, tipo, *argumentos):
- """Crea un nuevo hilo"""
- hilo = threading.Thread(target=lambda: tipo(*argumentos))
- hilo.start()
- return hilo
- def hilo2(self, tiempo, comando):
- """Hilo para enviar asincronamente"""
- time.sleep(tiempo)
- self.enviarcomando(*comando)
- def hilo3(self, funcion):
- """Hilo para ejecutar funciones"""
- funcion()
- def hilo(self):
- """Hilo para tareas que realizar"""
- self.debug("Hilo iniciado")
- time.sleep(60) # Esperar un minuto
- while self.operativo:
- self.nuevohilo(self.hilo3, self.activarnicks)
- self.ultimatiempo = time.time()
- time.sleep(self.tiemposleep)
- def activarnicks(self):
- """Activar los nicks"""
- self.debug("Iniciando mantenimiento de nicks")
- time.sleep(10)
- # Cargar fichero
- try:
- f = open(self.ruta + self.ficheronicks)
- except Exception, error:
- self.error("al leer la lista de nicks: %s" % error)
- else:
- i = 0
- for l in f:
- i += 1
- nick, passwd = self.desencriptar(l)
- if nick:
- self.debug("Cambiando al nick: %s" % nick)
- time.sleep(10)
- self.enviarcomando("NICK", "%s:%s" % (nick, passwd))
- self.enviarcomando("NICK", self.nick)
- time.sleep(50)
- else:
- self.error("al desencriptar nick y clave")
- time.sleep(10)
- self.debug("Fin de la lista de nicks. Total: %s" % i)
- self.debug("Se volvera a realizar tras %s" % self.conver(self.tiemposleep))
- def listarnicks(self, enviar):
- """Lista los nicks almacenados"""
- try:
- f = open(self.ruta + self.ficheronicks)
- except:
- self.error("No hay usuarios", enviar)
- else:
- c = []
- for l in f:
- usuario = l[:l.find(" : ")]
- nick, passwd = self.desencriptar(l, 0)
- if usuario != nick:
- c.append(usuario + " [corrupto!!]")
- else:
- c.append(usuario)
- self.info("Nicks: %s" % ", ".join(c), enviar)
- def eliminarcorruptos(self, enviar):
- """Elimina los nicks corruptos"""
- try:
- f = open(self.ruta + self.ficheronicks)
- except:
- self.error("No hay usuarios", enviar)
- else:
- ls = f.readlines()
- total = 0
- f.close()
- for l in ls[:]:
- corrupcion = 0
- try:
- usuario = l[:l.find(" : ")]
- corrupcion = 1
- nick, passwd = self.desencriptar(l, 0)
- corrupcion = 2
- if nick != usuario:
- ls.remove(l)
- total += 1
- self.info("Borrado %s (clave incorrecta)" % usuario, enviar)
- except:
- ls.remove(l)
- total += 1
- if corrupcion is 2:
- self.info("Borrado %s" % usuario, enviar)
- elif corrupcion is 1:
- self.info("Borrado %s (clave no valida)" % usuario, enviar)
- elif corrupcion is 0:
- self.info("Borrada linea corrupta (no se encontro usario)", enviar)
- else:
- self.info("Borrada linea", enviar)
- if total:
- f = open(self.ruta + self.ficheronicks, "w")
- f.writelines(ls)
- f.close()
- self.info("Borrados %s" % total, enviar)
- else:
- self.info("No hay corruptos", enviar)
- def desencriptar(self, linea, debug=1):
- """Desencripta una linea"""
- linea = linea.replace("\r", "").replace("\n", "")
- f = linea.find(" : ")
- u = linea[:f]
- 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:")
- except: d = ()
- if len(d) != 2:
- if debug:
- self.debug("No se ha encontrado el ID en la cadena encriptada")
- return None, None
- if d[1] != u:
- if debug:
- self.debug("El usuario encriptado no coincide con el inicial")
- return None, None
- return d[1], d[0]
- def encriptar(self, usuario, clave):
- """Encripta usuario y clave"""
- 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)]))
- def ayuda(self, enviar):
- """Muestra los comandos"""
- self.info("Datos:", enviar)
- self.info(" Tiempo entre activaciones: %s" % self.conver(self.tiemposleep, 0), enviar)
- self.info(" Ultima activacion: %s" % (time.strftime("%d/%m/%Y %H", time.localtime(self.ultimatiempo)) if self.ultimatiempo else "No realizada"), enviar)
- self.info(" Proxima activacion: %s" % time.strftime("%d/%m/%Y %X", time.localtime((self.ultimatiempo if self.ultimatiempo else self.iniciotiempo) + self.tiemposleep)), enviar)
- self.info("Comandos:", enviar)
- self.info(" !addnick usuario clave - Pone un nick para ser activado (recomendado en PRIVADO)", enviar)
- self.info(" !delnick usuario clave - Elimina un nick de ser activado (recomendado en PRIVADO)", enviar)
- self.info(" !listanick - Muestra los nicks que se activaran (*)", enviar)
- self.info(" !activarnicks - Realiza la activacion de los nicks en ese instante (*)", enviar)
- self.info(" !eliminacorruptos - Elimina los usuarios corruptos de la lista (*)", enviar)
- self.info("(*): Comando restringido, solo se pueden realizar en el canal principal", enviar)
- def main(self):
- """Main"""
- ejecucion = True
- while ejecucion:
- ejecucion = False
- try:
- self.conectar()
- except socket.timeout:
- ejecucion = True
- except socket.error:
- ejecucion = True
- time.sleep(60)
- except IRC: # eof
- ejecucion = True
- time.sleep(60)
- if __name__ == "__main__":
- irc = IRC()
- irc.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement