Standardize Bot class names
This commit is contained in:
parent
f9970cba42
commit
26faed014f
14
bin/nemubot
14
bin/nemubot
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Nemubot is a modulable IRC bot, built around XML configuration files.
|
||||
# Copyright (C) 2012 Mercier Pierre-Olivier
|
||||
# Nemubot is a smart and modulable IM bot.
|
||||
# Copyright (C) 2012-2014 nemunaire
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as published by
|
||||
@ -22,14 +22,14 @@ import os
|
||||
import imp
|
||||
import traceback
|
||||
|
||||
from nemubot import Bot
|
||||
import nemubot
|
||||
from nemubot import prompt
|
||||
from nemubot.prompt.builtins import load_file
|
||||
from nemubot import importer
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Create bot context
|
||||
context = Bot(0, "FIXME")
|
||||
context = nemubot.Bot()
|
||||
|
||||
# Load the prompt
|
||||
prmpt = prompt.Prompt()
|
||||
@ -50,7 +50,7 @@ if __name__ == "__main__":
|
||||
else:
|
||||
load_file(arg, context)
|
||||
|
||||
print ("Nemubot v%s ready, my PID is %i!" % (context.version_txt,
|
||||
print ("Nemubot v%s ready, my PID is %i!" % (nemubot.__version__,
|
||||
os.getpid()))
|
||||
while prmpt.run(context):
|
||||
try:
|
||||
@ -63,7 +63,7 @@ if __name__ == "__main__":
|
||||
# Reload all other modules
|
||||
bot.reload()
|
||||
print ("\033[1;32mContext reloaded\033[0m, now in Nemubot %s" %
|
||||
context.version_txt)
|
||||
nemubot.__version__)
|
||||
except:
|
||||
print ("\033[1;31mUnable to reload the prompt due to errors.\033[0"
|
||||
"m Fix them before trying to reload the prompt.")
|
||||
|
@ -16,12 +16,14 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from ipaddress import ip_address
|
||||
import logging
|
||||
from queue import Queue
|
||||
import threading
|
||||
import time
|
||||
import re
|
||||
import uuid
|
||||
|
||||
__version__ = '4.0.dev0'
|
||||
__author__ = 'nemunaire'
|
||||
|
||||
from nemubot import consumer
|
||||
from nemubot import event
|
||||
@ -31,28 +33,30 @@ from nemubot.IRCServer import IRCServer
|
||||
from nemubot.DCC import DCC
|
||||
from nemubot import response
|
||||
|
||||
ID_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
|
||||
class Bot:
|
||||
def __init__(self, ip, realname, mp=list()):
|
||||
# Bot general informations
|
||||
self.version = 4.0
|
||||
self.version_txt = '4.0.dev0'
|
||||
|
||||
# Save various informations
|
||||
self.ip = ip
|
||||
self.realname = realname
|
||||
self.ctcp_capabilities = dict()
|
||||
self.init_ctcp_capabilities()
|
||||
"""Class containing the bot context and ensuring key goals"""
|
||||
|
||||
def __init__(self, ip="127.0.0.1", modules_paths=list(), data_path="./datas/"):
|
||||
"""Initialize the bot context
|
||||
|
||||
Keyword arguments:
|
||||
ip -- The external IP of the bot (default: 127.0.0.1)
|
||||
modules_paths -- Paths to all directories where looking for module
|
||||
data_path -- Path to directory where store bot context data
|
||||
"""
|
||||
|
||||
# External IP for accessing this bot
|
||||
self.ip = ip_address(ip)
|
||||
|
||||
# Context paths
|
||||
self.modules_paths = modules_paths
|
||||
self.data_path = data_path
|
||||
|
||||
# Keep global context: servers and modules
|
||||
self.servers = dict()
|
||||
self.modules = dict()
|
||||
|
||||
# Context paths
|
||||
self.modules_path = mp
|
||||
self.datas_path = './datas/'
|
||||
|
||||
# Events
|
||||
self.events = list()
|
||||
self.event_timer = None
|
||||
@ -62,13 +66,16 @@ class Bot:
|
||||
|
||||
# Other known bots, making a bots network
|
||||
self.network = dict()
|
||||
self.hooks_cache = dict()
|
||||
self._hooks_cache = dict()
|
||||
|
||||
# Messages to be treated
|
||||
self.cnsr_queue = Queue()
|
||||
self.cnsr_thrd = list()
|
||||
self.cnsr_thrd_size = -1
|
||||
|
||||
# Stop the class thread
|
||||
self.stop = False
|
||||
|
||||
self.hooks.add_hook("irc_hook",
|
||||
hooks.Hook(self.treat_prvmsg, "PRIVMSG"),
|
||||
self)
|
||||
@ -80,13 +87,13 @@ class Bot:
|
||||
self.ctcp_capabilities["CLIENTINFO"] = self._ctcp_clientinfo
|
||||
self.ctcp_capabilities["DCC"] = self._ctcp_dcc
|
||||
self.ctcp_capabilities["NEMUBOT"] = lambda srv, msg: _ctcp_response(
|
||||
msg.sender, "NEMUBOT %f" % self.version)
|
||||
msg.sender, "NEMUBOT %f" % __version__)
|
||||
self.ctcp_capabilities["TIME"] = lambda srv, msg: _ctcp_response(
|
||||
msg.sender, "TIME %s" % (datetime.now()))
|
||||
self.ctcp_capabilities["USERINFO"] = lambda srv, msg: _ctcp_response(
|
||||
msg.sender, "USERINFO %s" % self.realname)
|
||||
self.ctcp_capabilities["VERSION"] = lambda srv, msg: _ctcp_response(
|
||||
msg.sender, "VERSION nemubot v%s" % self.version_txt)
|
||||
msg.sender, "VERSION nemubot v%s" % __version__)
|
||||
|
||||
def _ctcp_clientinfo(self, srv, msg):
|
||||
"""Response to CLIENTINFO CTCP message"""
|
||||
@ -104,6 +111,8 @@ class Bot:
|
||||
print ("DCC: unable to connect to %s:%s" % (ip, msg.cmds[4]))
|
||||
|
||||
|
||||
# Events methods
|
||||
|
||||
def add_event(self, evt, eid=None, module_src=None):
|
||||
"""Register an event and return its identifiant for futur update"""
|
||||
if eid is None:
|
||||
@ -125,7 +134,7 @@ class Bot:
|
||||
break
|
||||
self.events.insert(i + 1, evt)
|
||||
if i == -1:
|
||||
self.update_timer()
|
||||
self._update_event_timer()
|
||||
if len(self.events) <= 0 or self.events[i+1] != evt:
|
||||
return None
|
||||
|
||||
@ -138,7 +147,7 @@ class Bot:
|
||||
"""Find and remove an event from list"""
|
||||
if len(self.events) > 0 and id == self.events[0].id:
|
||||
self.events.remove(self.events[0])
|
||||
self.update_timer()
|
||||
self._update_event_timer()
|
||||
if module_src is not None:
|
||||
module_src.REGISTERED_EVENTS.remove(evt.id)
|
||||
return True
|
||||
@ -152,7 +161,7 @@ class Bot:
|
||||
return True
|
||||
return False
|
||||
|
||||
def update_timer(self):
|
||||
def _update_event_timer(self):
|
||||
"""Relaunch the timer to end with the closest event"""
|
||||
# Reset the timer if this is the first item
|
||||
if self.event_timer is not None:
|
||||
@ -180,9 +189,11 @@ class Bot:
|
||||
self.cnsr_queue.put_nowait(consumer.EventConsumer(evt))
|
||||
self.update_consumers()
|
||||
|
||||
self.update_timer()
|
||||
self._update_event_timer()
|
||||
|
||||
|
||||
# Server methods
|
||||
|
||||
def addServer(self, node, nick, owner, realname, ssl=False):
|
||||
"""Add a new server to the context"""
|
||||
srv = IRCServer(node, nick, owner, realname, ssl)
|
||||
@ -199,6 +210,8 @@ class Bot:
|
||||
return False
|
||||
|
||||
|
||||
# Modules methods
|
||||
|
||||
def add_module(self, module):
|
||||
"""Add a module to the context, if already exists, unload the
|
||||
old one before"""
|
||||
@ -218,8 +231,8 @@ class Bot:
|
||||
if path[len(path)-1] != "/":
|
||||
path = path + "/"
|
||||
|
||||
if path not in self.modules_path:
|
||||
self.modules_path.append(path)
|
||||
if path not in self.modules_paths:
|
||||
self.modules_paths.append(path)
|
||||
return True
|
||||
|
||||
return False
|
||||
@ -243,6 +256,9 @@ class Bot:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Consumers methods
|
||||
|
||||
def update_consumers(self):
|
||||
"""Launch new consumer thread if necessary"""
|
||||
if self.cnsr_queue.qsize() > self.cnsr_thrd_size:
|
||||
@ -292,14 +308,14 @@ class Bot:
|
||||
# Hooks cache
|
||||
|
||||
def create_cache(self, name):
|
||||
if name not in self.hooks_cache:
|
||||
if name not in self._hooks_cache:
|
||||
if isinstance(self.hooks.__dict__[name], list):
|
||||
self.hooks_cache[name] = list()
|
||||
self._hooks_cache[name] = list()
|
||||
|
||||
# Start by adding locals hooks
|
||||
for h in self.hooks.__dict__[name]:
|
||||
tpl = (h, 0, self.hooks.__dict__[name], self.hooks.bot)
|
||||
self.hooks_cache[name].append(tpl)
|
||||
self._hooks_cache[name].append(tpl)
|
||||
|
||||
# Now, add extermal hooks
|
||||
level = 0
|
||||
@ -309,17 +325,17 @@ class Bot:
|
||||
if len(self.network[ext].hooks) > level:
|
||||
lvl_exist = True
|
||||
for h in self.network[ext].hooks[level].__dict__[name]:
|
||||
if h not in self.hooks_cache[name]:
|
||||
self.hooks_cache[name].append((h, level + 1,
|
||||
if h not in self._hooks_cache[name]:
|
||||
self._hooks_cache[name].append((h, level + 1,
|
||||
self.network[ext].hooks[level].__dict__[name], self.network[ext].hooks[level].bot))
|
||||
level += 1
|
||||
|
||||
elif isinstance(self.hooks.__dict__[name], dict):
|
||||
self.hooks_cache[name] = dict()
|
||||
self._hooks_cache[name] = dict()
|
||||
|
||||
# Start by adding locals hooks
|
||||
for h in self.hooks.__dict__[name]:
|
||||
self.hooks_cache[name][h] = (self.hooks.__dict__[name][h], 0,
|
||||
self._hooks_cache[name][h] = (self.hooks.__dict__[name][h], 0,
|
||||
self.hooks.__dict__[name],
|
||||
self.hooks.bot)
|
||||
|
||||
@ -331,14 +347,14 @@ class Bot:
|
||||
if len(self.network[ext].hooks) > level:
|
||||
lvl_exist = True
|
||||
for h in self.network[ext].hooks[level].__dict__[name]:
|
||||
if h not in self.hooks_cache[name]:
|
||||
self.hooks_cache[name][h] = (self.network[ext].hooks[level].__dict__[name][h], level + 1, self.network[ext].hooks[level].__dict__[name], self.network[ext].hooks[level].bot)
|
||||
if h not in self._hooks_cache[name]:
|
||||
self._hooks_cache[name][h] = (self.network[ext].hooks[level].__dict__[name][h], level + 1, self.network[ext].hooks[level].__dict__[name], self.network[ext].hooks[level].bot)
|
||||
level += 1
|
||||
|
||||
else:
|
||||
raise Exception(name + " hook type unrecognized")
|
||||
|
||||
return self.hooks_cache[name]
|
||||
return self._hooks_cache[name]
|
||||
|
||||
# Treatment
|
||||
|
||||
@ -603,7 +619,7 @@ def _help_msg(sndr, modules, cmd):
|
||||
return res
|
||||
|
||||
def hotswap(bak):
|
||||
return Bot(bak.servers, bak.modules, bak.modules_path)
|
||||
return Bot(bak.servers, bak.modules, bak.modules_paths)
|
||||
|
||||
def reload():
|
||||
import imp
|
||||
|
@ -56,8 +56,8 @@ class MessagesHook:
|
||||
"add_hook function, please fix it in order to be "
|
||||
"compatible with unload feature")
|
||||
|
||||
if store in self.context.hooks_cache:
|
||||
del self.context.hooks_cache[store]
|
||||
if store in self.context._hooks_cache:
|
||||
del self.context._hooks_cache[store]
|
||||
|
||||
if not hasattr(self, store):
|
||||
print ("\033[1;35mWarning:\033[0m unrecognized hook store")
|
||||
@ -143,8 +143,8 @@ class MessagesHook:
|
||||
|
||||
def del_hook(self, store, hook, module_src=None):
|
||||
"""Remove a registered hook from a given store"""
|
||||
if store in self.context.hooks_cache:
|
||||
del self.context.hooks_cache[store]
|
||||
if store in self.context._hooks_cache:
|
||||
del self.context._hooks_cache[store]
|
||||
|
||||
if not hasattr(self, store):
|
||||
print ("Warning: unrecognized hook store type")
|
||||
|
@ -16,12 +16,14 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from distutils.version import StrictVersion
|
||||
from importlib.abc import Finder
|
||||
from importlib.abc import SourceLoader
|
||||
import imp
|
||||
import os
|
||||
import sys
|
||||
|
||||
import nemubot
|
||||
from nemubot import event
|
||||
from nemubot import exception
|
||||
from nemubot.hooks import Hook
|
||||
@ -37,7 +39,7 @@ class ModuleFinder(Finder):
|
||||
#print ("looking for", fullname, "in", path)
|
||||
# Search only for new nemubot modules (packages init)
|
||||
if path is None:
|
||||
for mpath in self.context.modules_path:
|
||||
for mpath in self.context.modules_paths:
|
||||
#print ("looking for", fullname, "in", mpath)
|
||||
if os.path.isfile(mpath + fullname + ".xml"):
|
||||
return ModuleLoader(self.context, self.prompt, fullname,
|
||||
@ -137,7 +139,7 @@ class ModuleLoader(SourceLoader):
|
||||
if not hasattr(module, "nemubotversion"):
|
||||
raise ImportError("Module `%s' is not a nemubot module."%self.name)
|
||||
# Check module version
|
||||
if module.nemubotversion != self.context.version:
|
||||
if StrictVersion(module.nemubotversion) != StrictVersion(nemubot.__version__):
|
||||
raise ImportError("Module `%s' is not compatible with this "
|
||||
"version." % self.name)
|
||||
|
||||
|
2
setup.py
2
setup.py
@ -12,7 +12,7 @@ except ImportError:
|
||||
with open(os.path.join(os.path.dirname(__file__),
|
||||
'lib',
|
||||
'__init__.py')) as f:
|
||||
version = re.search("self.version_txt = '([^']+)'", f.read()).group(1)
|
||||
version = re.search("__version__ = '([^']+)'", f.read()).group(1)
|
||||
|
||||
with open('requirements.txt', 'r') as f:
|
||||
requires = [x.strip() for x in f if x.strip()]
|
||||
|
Loading…
x
Reference in New Issue
Block a user