Add the ability to talk with other nemubot over DCC

This commit is contained in:
Némunaire 2012-08-31 05:21:19 +02:00
parent 30da270557
commit a2d9757d06
8 changed files with 350 additions and 200 deletions

186
bot.py
View File

@ -20,17 +20,19 @@ from datetime import datetime
from queue import Queue from queue import Queue
import threading import threading
from botcaps import BotCaps
from consumer import Consumer from consumer import Consumer
import event import event
import hooks
from networkbot import NetworkBot from networkbot import NetworkBot
from server import Server from server import Server
ID_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" ID_letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
class Bot(BotCaps): class Bot:
def __init__(self, servers=dict(), modules=dict(), mp=list()): def __init__(self, servers=dict(), modules=dict(), mp=list()):
BotCaps.__init__(self, 3.2, "3.2-dev") # Bot general informations
self.version = 3.2
self.version_txt = "3.2-dev"
# Keep global context: servers and modules # Keep global context: servers and modules
self.servers = servers self.servers = servers
@ -44,8 +46,12 @@ class Bot(BotCaps):
self.events = list() self.events = list()
self.event_timer = None self.event_timer = None
# Own hooks
self.hooks = hooks.MessagesHook(self)
# Other known bots, making a bots network # Other known bots, making a bots network
self.network = dict() self.network = dict()
self.hooks_cache = dict()
# Messages to be treated # Messages to be treated
self.msg_queue = Queue() self.msg_queue = Queue()
@ -194,6 +200,180 @@ class Bot(BotCaps):
for srv in k: for srv in k:
self.servers[srv].disconnect() self.servers[srv].disconnect()
# Hooks cache
def create_cache(self, name):
if name not in self.hooks_cache:
if isinstance(self.hooks.__dict__[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_cache[name].append(tpl)
# Now, add extermal hooks
level = 0
while level == 0 or lvl_exist:
lvl_exist = False
for ext in self.network:
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,
self.network[ext].hooks[level].__dict__[name]))
level += 1
elif isinstance(self.hooks.__dict__[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.__dict__[name])
# Now, add extermal hooks
level = 0
while level == 0 or lvl_exist:
lvl_exist = False
for ext in self.network:
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])
level += 1
else:
raise Exception(name + " hook type unrecognized")
return self.hooks_cache[name]
# Treatment
def check_rest_times(self, store, hook):
"""Remove from store the hook if it has been executed given time"""
if hook.times == 0:
if isinstance(store, dict):
store[hook.name].remove(hook)
if len(store) == 0:
del store[hook.name]
elif isinstance(store, list):
store.remove(hook)
def treat_pre(self, msg):
"""Treat a message before all other treatment"""
for h, lvl, store in self.create_cache("all_pre"):
h.run(msg)
self.check_rest_times(store, h)
def treat_cmd(self, msg):
"""Treat a command message"""
treated = list()
# First, treat simple hook
cmd_hook = self.create_cache("cmd_hook")
if msg.cmd[0] in cmd_hook:
(hks, lvl, store) = cmd_hook[msg.cmd[0]]
for h in hks:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, h)
# Then, treat regexp based hook
cmd_rgxp = self.create_cache("cmd_rgxp")
for hook, lvl, store in cmd_rgxp:
if hook.is_matching(msg.cmd[0], msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
# Finally, treat default hooks if not catched before
cmd_default = self.create_cache("cmd_default")
for hook, lvl, store in cmd_default:
if treated:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
return treated
def treat_ask(self, msg):
"""Treat an ask message"""
treated = list()
# First, treat simple hook
ask_hook = self.create_cache("ask_hook")
if msg.content in ask_hook:
hks, lvl, store = ask_hook[msg.content]
for h in hks:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, h)
# Then, treat regexp based hook
ask_rgxp = self.create_cache("ask_rgxp")
for hook, lvl, store in ask_rgxp:
if hook.is_matching(msg.content, msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
# Finally, treat default hooks if not catched before
ask_default = self.create_cache("ask_default")
for hook, lvl, store in ask_default:
if treated:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
return treated
def treat_answer(self, msg):
"""Treat a normal message"""
treated = list()
# First, treat simple hook
msg_hook = self.create_cache("msg_hook")
if msg.content in msg_hook:
hks, lvl, store = msg_hook[msg.content]
for h in hks:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, h)
# Then, treat regexp based hook
msg_rgxp = self.create_cache("msg_rgxp")
for hook, lvl, store in msg_rgxp:
if hook.is_matching(msg.content, msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
# Finally, treat default hooks if not catched before
msg_default = self.create_cache("msg_default")
for hook, lvl, store in msg_default:
if len(treated) > 0:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(store, hook)
return treated
def hotswap(bak): def hotswap(bak):
return Bot(bak.servers, bak.modules, bak.modules_path) return Bot(bak.servers, bak.modules, bak.modules_path)

View File

@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
# Nemubot is a modulable IRC bot, built around XML configuration files.
# Copyright (C) 2012 Mercier Pierre-Olivier
#
# 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
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# 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/>.
import hooks
class BotCaps:
def __init__(self, version=None, version_txt=None):
# Bot general informations
self.version = version
self.version_txt = version_txt
# Hooks
self.hooks = hooks.MessagesHook()

View File

@ -38,7 +38,7 @@ class Consumer(threading.Thread):
# Create, parse and treat the message # Create, parse and treat the message
try: try:
msg = Message(srv, raw, time, prvt) msg = Message(srv, raw, time, prvt)
res = msg.treat(self.context.hooks) res = msg.treat()
except: except:
print ("\033[1;31mERROR:\033[0m occurred during the " print ("\033[1;31mERROR:\033[0m occurred during the "
"processing of the message: %s" % raw) "processing of the message: %s" % raw)
@ -56,6 +56,9 @@ class Consumer(threading.Thread):
elif isinstance(res, Response): elif isinstance(res, Response):
srv.send_response(res, data) srv.send_response(res, data)
# Inform that the message has been treated
srv.msg_treated(data)
except queue.Empty: except queue.Empty:
pass pass
finally: finally:

145
hooks.py
View File

@ -19,7 +19,9 @@
from response import Response from response import Response
class MessagesHook: class MessagesHook:
def __init__(self): def __init__(self, context):
self.context = context
# Store specials hook # Store specials hook
self.all_pre = list() # Treated before any parse self.all_pre = list() # Treated before any parse
#self.all_post = list() # Treated before send message to user #self.all_post = list() # Treated before send message to user
@ -42,25 +44,30 @@ class MessagesHook:
def add_hook(self, store, hook): def add_hook(self, store, hook):
"""Insert in the right place a hook into the given store""" """Insert in the right place a hook into the given store"""
if isinstance(store, dict) and hook.name is not None: if store in self.context.hooks_cache:
if hook.name not in store: del self.context.hooks_cache[store]
store[hook.name] = list()
store[hook.name].append(hook) attr = getattr(self, store)
elif isinstance(store, list): if attr is None:
store.append(hook) print ("Warning: unrecognized hook store type")
return
if isinstance(attr, dict) and hook.name is not None:
if hook.name not in attr:
attr[hook.name] = list()
attr[hook.name].append(hook)
elif isinstance(attr, list):
attr.append(hook)
else: else:
print ("Warning: unrecognized hook store type") print ("Warning: unrecognized hook store type")
def register_hook_attributes(self, store, module, node): def register_hook_attributes(self, store, module, node):
if node.hasAttribute("name"): if node.hasAttribute("name"):
self.add_hook(getattr(self, store + "_hook"), Hook(getattr(module, self.add_hook(store + "_hook", Hook(getattr(module, node["call"]),
node["call"]), node["name"]))
node["name"]))
elif node.hasAttribute("regexp"): elif node.hasAttribute("regexp"):
self.add_hook(getattr(self, store + "_rgxp"), Hook(getattr(module, self.add_hook(store + "_rgxp", Hook(getattr(module, node["call"]),
node["call"]), None, None, node["regexp"]))
None, None,
node["regexp"]))
def register_hook(self, module, node): def register_hook(self, module, node):
"""Create a hook from configuration node""" """Create a hook from configuration node"""
@ -75,116 +82,6 @@ class MessagesHook:
node["type"] == "all"): node["type"] == "all"):
self.register_hook_attributes("answer", module, node) self.register_hook_attributes("answer", module, node)
def check_rest_times(self, store, hook):
"""Remove from store the hook if it has been executed given time"""
if hook.times == 0:
if isinstance(store, dict):
store[hook.name].remove(hook)
if len(store) == 0:
del store[hook.name]
elif isinstance(store, list):
store.remove(hook)
def treat_pre(self, msg):
"""Treat a message before all other treatment"""
for h in self.all_pre:
h.run(msg)
self.check_rest_times(self.all_pre, h)
def treat_cmd(self, msg):
"""Treat a command message"""
treated = list()
# First, treat simple hook
if msg.cmd[0] in self.cmd_hook:
for h in self.cmd_hook[msg.cmd[0]]:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.cmd_hook, h)
# Then, treat regexp based hook
for hook in self.cmd_rgxp:
if hook.is_matching(msg.cmd[0], msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.cmd_rgxp, hook)
# Finally, treat default hooks if not catched before
for hook in self.cmd_default:
if treated:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.cmd_default, hook)
return treated
def treat_ask(self, msg):
"""Treat an ask message"""
treated = list()
# First, treat simple hook
if msg.content in self.ask_hook:
for h in self.ask_hook[msg.content]:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.ask_hook, h)
# Then, treat regexp based hook
for hook in self.ask_rgxp:
if hook.is_matching(msg.content, msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.ask_rgxp, hook)
# Finally, treat default hooks if not catched before
for hook in self.ask_default:
if treated:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.ask_default, hook)
return treated
def treat_answer(self, msg):
"""Treat a normal message"""
treated = list()
# First, treat simple hook
if msg.content in self.msg_hook:
for h in self.msg_hook[msg.content]:
res = h.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.msg_hook, h)
# Then, treat regexp based hook
for hook in self.msg_rgxp:
if hook.is_matching(msg.content, msg.channel):
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.msg_rgxp, hook)
# Finally, treat default hooks if not catched before
for hook in self.msg_default:
if len(treated) > 0:
break
res = hook.run(msg)
if res is not None and res != False:
treated.append(res)
self.check_rest_times(self.msg_default, hook)
return treated
class Hook: class Hook:
"""Class storing hook informations""" """Class storing hook informations"""

View File

@ -214,11 +214,11 @@ def register_hooks(module, context, prompt):
# Register legacy hooks # Register legacy hooks
if hasattr(module, "parseanswer"): if hasattr(module, "parseanswer"):
context.hooks.add_hook(context.hooks.cmd_default, Hook(module.parseanswer)) context.hooks.add_hook("cmd_default", Hook(module.parseanswer))
if hasattr(module, "parseask"): if hasattr(module, "parseask"):
context.hooks.add_hook(context.hooks.ask_default, Hook(module.parseask)) context.hooks.add_hook("ask_default", Hook(module.parseask))
if hasattr(module, "parselisten"): if hasattr(module, "parselisten"):
context.hooks.add_hook(context.hooks.msg_default, Hook(module.parselisten)) context.hooks.add_hook("msg_default", Hook(module.parselisten))
########################## ##########################
# # # #

View File

@ -43,6 +43,7 @@ def save():
class Message: class Message:
def __init__ (self, srv, line, timestamp, private = False): def __init__ (self, srv, line, timestamp, private = False):
self.raw = line
self.srv = srv self.srv = srv
self.time = timestamp self.time = timestamp
self.channel = None self.channel = None
@ -136,14 +137,14 @@ class Message:
return False return False
return self.srv.accepted_channel(self.channel) return self.srv.accepted_channel(self.channel)
def treat(self, hooks): def treat(self):
"""Parse and treat the message""" """Parse and treat the message"""
if self.cmd == "PING": if self.cmd == "PING":
self.srv.send_pong(self.content) self.srv.send_pong(self.content)
elif self.cmd == "PRIVMSG" and self.ctcp: elif self.cmd == "PRIVMSG" and self.ctcp:
self.parsectcp() self.parsectcp()
elif self.cmd == "PRIVMSG" and self.authorize(): elif self.cmd == "PRIVMSG" and self.authorize():
return self.parsemsg (hooks) return self.parsemsg()
elif self.channel in self.srv.channels: elif self.channel in self.srv.channels:
if self.cmd == "353": if self.cmd == "353":
self.srv.channels[self.channel].parse353(self) self.srv.channels[self.channel].parse353(self)
@ -191,13 +192,10 @@ class Message:
self.srv.send_ctcp(self.sender, "ERRMSG Unknown or unimplemented CTCP request") self.srv.send_ctcp(self.sender, "ERRMSG Unknown or unimplemented CTCP request")
def reparsemsg(self): def reparsemsg(self):
if self.hooks is not None: self.parsemsg()
self.parsemsg(self.hooks)
else:
print ("Can't reparse message")
def parsemsg (self, hooks): def parsemsg (self):
hooks.treat_pre(self) self.srv.context.treat_pre(self)
#Treat all messages starting with 'nemubot:' as distinct commands #Treat all messages starting with 'nemubot:' as distinct commands
if self.content.find("%s:"%self.srv.nick) == 0: if self.content.find("%s:"%self.srv.nick) == 0:
#Remove the bot name #Remove the bot name
@ -211,7 +209,7 @@ class Message:
# Ask hooks # Ask hooks
else: else:
return hooks.treat_ask(self) return self.srv.context.treat_ask(self)
#Owner commands #Owner commands
elif self.content[0] == '`' and self.sender == self.srv.owner: elif self.content[0] == '`' and self.sender == self.srv.owner:
@ -236,7 +234,6 @@ class Message:
#Messages stating with ! #Messages stating with !
elif self.content[0] == '!' and len(self.content) > 1: elif self.content[0] == '!' and len(self.content) > 1:
self.hooks = hooks
try: try:
self.cmd = shlex.split(self.content[1:]) self.cmd = shlex.split(self.content[1:])
except ValueError: except ValueError:
@ -277,13 +274,13 @@ class Message:
conn = DCC(self.srv, self.sender) conn = DCC(self.srv, self.sender)
conn.send_file("bot_sample.xml") conn.send_file("bot_sample.xml")
else: else:
return hooks.treat_cmd(self) return self.srv.context.treat_cmd(self)
else: else:
res = hooks.treat_answer(self) res = self.srv.context.treat_answer(self)
# Assume the message starts with nemubot: # Assume the message starts with nemubot:
if res is None and self.private: if res is None and self.private:
return hooks.treat_ask(self) return self.srv.context.treat_ask(self)
return res return res
# def parseOwnerCmd(self, cmd): # def parseOwnerCmd(self, cmd):

View File

@ -16,20 +16,27 @@
# You should have received a copy of the GNU Affero General Public License # 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/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import json
import random import random
import shlex import shlex
import urllib.parse
import zlib
from botcaps import BotCaps
from DCC import DCC from DCC import DCC
import hooks
from response import Response
class NetworkBot: class NetworkBot:
def __init__(self, context, srv, dest, dcc=None): def __init__(self, context, srv, dest, dcc=None):
# General informations
self.context = context self.context = context
self.srv = srv self.srv = srv
self.dcc = dcc
self.dest = dest self.dest = dest
self.infos = None
self.dcc = dcc # DCC connection to the other bot
self.hooks = list()
# Tags monitor
self.my_tag = random.randint(0,255) self.my_tag = random.randint(0,255)
self.inc_tag = 0 self.inc_tag = 0
self.tags = dict() self.tags = dict()
@ -52,39 +59,64 @@ class NetworkBot:
return self.dcc.realname return self.dcc.realname
return None return None
def isDCC(self, someone):
"""Abstract implementation"""
return True
def send_cmd(self, cmd, data=None): def send_cmd(self, cmd, data=None):
"""Create a tag and send the command""" """Create a tag and send the command"""
# First, define a tag # First, define a tag
self.inc_tag = (self.inc_out + 1) % 256 self.inc_tag = (self.inc_tag + 1) % 256
while self.inc_tag in self.tags: while self.inc_tag in self.tags:
self.inc_tag = (self.inc_out + 1) % 256 self.inc_tag = (self.inc_tag + 1) % 256
tag = ("%c%c" % (self.my_tag, self.inc_tag)).encode() tag = ("%c%c" % (self.my_tag, self.inc_tag)).encode()
if data is not None: self.tags[tag] = (cmd, data)
self.tags[tag] = data
else:
self.tags[tag] = cmd
# Send the command with the tag # Send the command with the tag
self.send_response(tag, cmd) self.send_response_final(tag, cmd)
def send_response(self, tag, msg): def send_response(self, res, tag):
self.send_response_final(tag, [res.sender, res.channel, res.nick, res.nomore, res.title, res.more, res.count, json.dumps(res.messages)])
def msg_treated(self, tag):
self.send_ack(tag)
def send_response_final(self, tag, msg):
"""Send a response with a tag""" """Send a response with a tag"""
for line in msg.split("\n"): if isinstance(msg, list):
self.dcc.send_dcc_raw(tag + b' ' + line.encode()) cnt = b''
for i in msg:
if i is None:
cnt += b' ""'
elif isinstance(i, int):
cnt += (' %d' % i).encode()
elif isinstance(i, float):
cnt += (' %f' % i).encode()
else:
cnt += b' "' + urllib.parse.quote(i).encode() + b'"'
if False and len(cnt) > 10:
cnt = b' Z ' + zlib.compress(cnt)
print (cnt)
self.dcc.send_dcc_raw(tag + cnt)
else:
for line in msg.split("\n"):
self.dcc.send_dcc_raw(tag + b' ' + line.encode())
def send_ack(self, tag): def send_ack(self, tag):
"""Acknowledge a command""" """Acknowledge a command"""
if tag in self.tags: if tag in self.tags:
del self.tags[tag] del self.tags[tag]
self.send_response(tag, "ACK") self.send_response_final(tag, "ACK")
def connect(self): def connect(self):
"""Making the connexion with dest through srv""" """Making the connexion with dest through srv"""
if self.dcc is None: if self.dcc is None or not self.dcc.connected:
self.dcc = DCC(self.srv, self.dest) self.dcc = DCC(self.srv, self.dest)
self.dcc.treatement = self.hello self.dcc.treatement = self.hello
self.dcc.send_dcc("NEMUBOT###") self.dcc.send_dcc("NEMUBOT###")
else:
self.send_cmd("FETCH")
def disconnect(self, reason=""): def disconnect(self, reason=""):
"""Close the connection and remove the bot from network list""" """Close the connection and remove the bot from network list"""
@ -101,24 +133,89 @@ class NetworkBot:
self.disconnect("Sorry, I think you were a bot") self.disconnect("Sorry, I think you were a bot")
def treat_msg(self, line, cmd=None): def treat_msg(self, line, cmd=None):
print (line)
words = line.split(b' ') words = line.split(b' ')
# Ignore invalid commands # Ignore invalid commands
if len(words) >= 2: if len(words) >= 2:
tag = words[0] tag = words[0]
cmd = words[1]
if len(words) > 2: # Is it a response?
args = shlex.split(line[len(tag) + len(cmd) + 2:].decode()) if tag in self.tags:
# Is it compressed content?
if words[1] == b'Z':
#print (line)
line = zlib.decompress(line[len(tag) + 3:])
self.response(line, tag, [urllib.parse.unquote(arg) for arg in shlex.split(line[len(tag) + 1:].decode())], self.tags[tag])
else: else:
args = list() cmd = words[1]
if len(words) > 2:
args = shlex.split(line[len(tag) + len(cmd) + 2:].decode())
args = [urllib.parse.unquote(arg) for arg in args]
else:
args = list()
#print ("request:", line)
self.request(tag, cmd, args)
# Parse def response(self, line, tag, args, t):
if cmd == b'ACK': (cmds, data) = t
if tag in self.tags: #print ("response for", cmds, ":", args)
del self.tags[tag]
elif cmd == b'MYTAG' and len(args) > 0: if isinstance(cmds, list):
while args[0] == self.my_tag: cmd = cmds[0]
self.my_tag = random.randint(0,255) else:
self.send_ack(tag) cmd = cmds
cmds = list(cmd)
if args[0] == 'ACK': # Acknowledge a command
del self.tags[tag]
elif cmd == "FETCH" and len(args) >= 5:
level = int(args[1])
while len(self.hooks) <= level:
self.hooks.append(hooks.MessagesHook(self.context))
if args[2] == "": args[2] = None
if args[3] == "": args[3] = None
if args[4] == "": args[4] = list()
else: args[4] = args[4].split(',')
self.hooks[level].add_hook(args[0], hooks.Hook(self.exec_hook, args[2], None, args[3], args[4]))
elif cmd == "HOOK" and len(args) >= 8:
# Rebuild the response
if args[1] == '': args[1] = None
if args[2] == '': args[2] = None
if args[3] == '': args[3] = None
if args[4] == '': args[4] = None
if args[5] == '': args[5] = None
if args[6] == '': args[6] = None
res = Response(args[0], channel=args[1], nick=args[2], nomore=args[3], title=args[4], more=args[5], count=args[6])
for msg in json.loads(args[7]):
res.append_message(msg)
if len(res.messages) <= 1:
res.alone = True
self.srv.send_response(res, None)
def request(self, tag, cmd, args):
# Parse
if cmd == b'MYTAG' and len(args) > 0: # Inform about choosen tag
while args[0] == self.my_tag:
self.my_tag = random.randint(0,255)
self.send_ack(tag)
elif cmd == b'FETCH': # Get known commands
for name in ["cmd_hook", "ask_hook", "msg_hook"]:
elts = self.context.create_cache(name)
for elt in elts:
(hooks, lvl, store) = elts[elt]
for h in hooks:
self.send_response_final(tag, [name, lvl, elt, h.regexp, ','.join(h.channels)])
self.send_ack(tag)
elif (cmd == b'HOOK' or cmd == b'"HOOK"') and len(args) > 0: # Action requested
self.context.receive_message(self, args[0].encode(), True, tag)
def exec_hook(self, msg):
self.send_cmd(["HOOK", msg.raw])

View File

@ -110,6 +110,10 @@ class Server(threading.Thread):
def send_pong(self, cnt): def send_pong(self, cnt):
self.s.send(("PONG %s\r\n" % cnt).encode ()) self.s.send(("PONG %s\r\n" % cnt).encode ())
def msg_treated(self, origin):
"""Do nothing, here for implement abstract class"""
pass
def send_response(self, res, origin): def send_response(self, res, origin):
if res.channel is not None and res.channel != self.nick: if res.channel is not None and res.channel != self.nick:
self.send_msg(res.channel, res.get_message()) self.send_msg(res.channel, res.get_message())