Response class is now part of 'more' module.
This commit prepare the new message flow based on protocol independent messages. This commit changes the module API: you need to import the Response class manually at the begining of our module.
This commit is contained in:
parent
8f620b9756
commit
41da1c0780
9
bot.py
9
bot.py
@ -36,7 +36,6 @@ from hooks.manager import HooksManager
|
|||||||
from networkbot import NetworkBot
|
from networkbot import NetworkBot
|
||||||
from server.IRC import IRCServer
|
from server.IRC import IRCServer
|
||||||
from server.DCC import DCC
|
from server.DCC import DCC
|
||||||
import response
|
|
||||||
|
|
||||||
logger = logging.getLogger("nemubot.bot")
|
logger = logging.getLogger("nemubot.bot")
|
||||||
|
|
||||||
@ -77,13 +76,14 @@ class Bot(threading.Thread):
|
|||||||
self.hooks = HooksManager()
|
self.hooks = HooksManager()
|
||||||
def in_ping(msg):
|
def in_ping(msg):
|
||||||
if re.match("^ *(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)", msg.text, re.I) is not None:
|
if re.match("^ *(m[' ]?entends?[ -]+tu|h?ear me|do you copy|ping)", msg.text, re.I) is not None:
|
||||||
return response.Response(message="pong", channel=msg.receivers, nick=msg.nick)
|
return "PRIVMSG %s :%s: pong" % (",".join(msg.receivers), msg.nick)
|
||||||
self.hooks.add_hook(MessageHook(in_ping), "in", "PRIVMSG", "ask")
|
self.hooks.add_hook(MessageHook(in_ping), "in", "PRIVMSG", "ask")
|
||||||
|
|
||||||
def _help_msg(msg):
|
def _help_msg(msg):
|
||||||
"""Parse and response to help messages"""
|
"""Parse and response to help messages"""
|
||||||
cmd = msg.cmds
|
cmd = msg.cmds
|
||||||
res = response.Response()
|
from more import Response
|
||||||
|
res = Response()
|
||||||
if len(cmd) > 1:
|
if len(cmd) > 1:
|
||||||
if cmd[1] in self.modules:
|
if cmd[1] in self.modules:
|
||||||
if len(cmd) > 2:
|
if len(cmd) > 2:
|
||||||
@ -470,9 +470,6 @@ def reload():
|
|||||||
import prompt.builtins
|
import prompt.builtins
|
||||||
imp.reload(prompt.builtins)
|
imp.reload(prompt.builtins)
|
||||||
|
|
||||||
import response
|
|
||||||
imp.reload(response)
|
|
||||||
|
|
||||||
import server
|
import server
|
||||||
rl,wl,xl = server._rlist,server._wlist,server._xlist
|
rl,wl,xl = server._rlist,server._wlist,server._xlist
|
||||||
imp.reload(server)
|
imp.reload(server)
|
||||||
|
26
consumer.py
26
consumer.py
@ -26,7 +26,6 @@ import sys
|
|||||||
import bot
|
import bot
|
||||||
from server.DCC import DCC
|
from server.DCC import DCC
|
||||||
from message import Message
|
from message import Message
|
||||||
from response import Response
|
|
||||||
import server
|
import server
|
||||||
|
|
||||||
logger = logging.getLogger("nemubot.consumer")
|
logger = logging.getLogger("nemubot.consumer")
|
||||||
@ -89,7 +88,7 @@ class MessageConsumer:
|
|||||||
if h.match(message=msg, server=self.srv):
|
if h.match(message=msg, server=self.srv):
|
||||||
res = h.run(msg)
|
res = h.run(msg)
|
||||||
if isinstance(res, list):
|
if isinstance(res, list):
|
||||||
for i in xrange(len(res)):
|
for i in range(len(res)):
|
||||||
if res[i] == msg:
|
if res[i] == msg:
|
||||||
res.pop(i)
|
res.pop(i)
|
||||||
break
|
break
|
||||||
@ -119,11 +118,11 @@ class MessageConsumer:
|
|||||||
res = h.run(msg)
|
res = h.run(msg)
|
||||||
if isinstance(res, list):
|
if isinstance(res, list):
|
||||||
for r in res:
|
for r in res:
|
||||||
if isinstance(r, Response):
|
if hasattr(r, "set_sender"):
|
||||||
r.set_sender(msg.sender)
|
r.set_sender(msg.sender)
|
||||||
self.responses += res
|
self.responses += res
|
||||||
elif res is not None:
|
elif res is not None:
|
||||||
if isinstance(res, Response):
|
if hasattr(res, "set_sender"):
|
||||||
res.set_sender(msg.sender)
|
res.set_sender(msg.sender)
|
||||||
self.responses.append(res)
|
self.responses.append(res)
|
||||||
|
|
||||||
@ -140,15 +139,20 @@ class MessageConsumer:
|
|||||||
self.responses = list()
|
self.responses = list()
|
||||||
|
|
||||||
while len(new_msg) > 0:
|
while len(new_msg) > 0:
|
||||||
msg = self.first_treat(new_msg.pop(0))
|
ff = new_msg.pop(0)
|
||||||
|
if isinstance(ff, str):
|
||||||
|
self.responses.append(ff)
|
||||||
|
continue
|
||||||
|
msg = self.first_treat(ff)
|
||||||
for h in hm.get_hooks("post"):
|
for h in hm.get_hooks("post"):
|
||||||
if h.match(message=msg, server=self.srv):
|
if h.match(message=msg, server=self.srv):
|
||||||
res = h.run(msg)
|
res = h.run(msg)
|
||||||
if isinstance(res, list):
|
if isinstance(res, list):
|
||||||
for i in xrange(len(res)):
|
for i in range(len(res)):
|
||||||
if res[i] == msg:
|
if isinstance(res[i], str):
|
||||||
res.pop(i)
|
self.responses.append(res.pop(i))
|
||||||
break
|
break
|
||||||
|
msg = None
|
||||||
new_msg += res
|
new_msg += res
|
||||||
elif res is not None and res != msg:
|
elif res is not None and res != msg:
|
||||||
new_msg.append(res)
|
new_msg.append(res)
|
||||||
@ -182,7 +186,9 @@ class MessageConsumer:
|
|||||||
|
|
||||||
for res in self.responses:
|
for res in self.responses:
|
||||||
to_server = None
|
to_server = None
|
||||||
if res.server is None:
|
if isinstance(res, str):
|
||||||
|
to_server = self.srv
|
||||||
|
elif res.server is None:
|
||||||
to_server = self.srv
|
to_server = self.srv
|
||||||
res.server = self.srv.id
|
res.server = self.srv.id
|
||||||
elif isinstance(res.server, str) and res.server in context.servers:
|
elif isinstance(res.server, str) and res.server in context.servers:
|
||||||
@ -194,7 +200,7 @@ class MessageConsumer:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# Sent the message only if treat_post authorize it
|
# Sent the message only if treat_post authorize it
|
||||||
to_server.send_response(res)
|
to_server.write(res)
|
||||||
|
|
||||||
class EventConsumer:
|
class EventConsumer:
|
||||||
"""Store a event before treating"""
|
"""Store a event before treating"""
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
# 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/>.
|
||||||
|
|
||||||
from response import Response
|
|
||||||
|
|
||||||
class IRCException(Exception):
|
class IRCException(Exception):
|
||||||
|
|
||||||
def __init__(self, message, personnal=True):
|
def __init__(self, message, personnal=True):
|
||||||
@ -26,4 +24,6 @@ class IRCException(Exception):
|
|||||||
self.personnal = personnal
|
self.personnal = personnal
|
||||||
|
|
||||||
def fill_response(self, msg):
|
def fill_response(self, msg):
|
||||||
|
# TODO: no more Response usable here
|
||||||
|
from more import Response
|
||||||
return Response(self.message, channel=msg.receivers, nick=(msg.nick if self.personnal else None))
|
return Response(self.message, channel=msg.receivers, nick=(msg.nick if self.personnal else None))
|
||||||
|
@ -20,7 +20,8 @@ import re
|
|||||||
|
|
||||||
from exception import IRCException
|
from exception import IRCException
|
||||||
import hooks
|
import hooks
|
||||||
from response import Response
|
|
||||||
|
from message import Message
|
||||||
|
|
||||||
class MessageHook(hooks.AbstractHook):
|
class MessageHook(hooks.AbstractHook):
|
||||||
|
|
||||||
@ -39,8 +40,8 @@ class MessageHook(hooks.AbstractHook):
|
|||||||
|
|
||||||
|
|
||||||
def match(self, message, server=None):
|
def match(self, message, server=None):
|
||||||
if isinstance(message, Response):
|
if not isinstance(message, Message):
|
||||||
return self.is_matching(None, message.channel, server)
|
return True
|
||||||
|
|
||||||
elif message.qual == "cmd":
|
elif message.qual == "cmd":
|
||||||
return self.is_matching(message.cmds[0], message.channel, server)
|
return self.is_matching(message.cmds[0], message.channel, server)
|
||||||
|
@ -28,7 +28,6 @@ from bot import __version__
|
|||||||
import event
|
import event
|
||||||
import exception
|
import exception
|
||||||
import hooks
|
import hooks
|
||||||
import response
|
|
||||||
import xmlparser
|
import xmlparser
|
||||||
|
|
||||||
logger = logging.getLogger("nemubot.importer")
|
logger = logging.getLogger("nemubot.importer")
|
||||||
@ -159,7 +158,7 @@ class ModuleLoader(SourceLoader):
|
|||||||
|
|
||||||
def send_response(server, res):
|
def send_response(server, res):
|
||||||
if server in self.context.servers:
|
if server in self.context.servers:
|
||||||
return self.context.servers[server].send_response(res)
|
return self.context.servers[server].write("PRIVMSG %s :%s" % (",".join(res.receivers), res.get_message()))
|
||||||
else:
|
else:
|
||||||
module.logger.error("Try to send a message to the unknown server: %s", server)
|
module.logger.error("Try to send a message to the unknown server: %s", server)
|
||||||
return False
|
return False
|
||||||
@ -205,7 +204,6 @@ class ModuleLoader(SourceLoader):
|
|||||||
|
|
||||||
module.ModuleEvent = event.ModuleEvent
|
module.ModuleEvent = event.ModuleEvent
|
||||||
module.ModuleState = xmlparser.module_state.ModuleState
|
module.ModuleState = xmlparser.module_state.ModuleState
|
||||||
module.Response = response.Response
|
|
||||||
module.IRCException = exception.IRCException
|
module.IRCException = exception.IRCException
|
||||||
|
|
||||||
# Load dependancies
|
# Load dependancies
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import shlex
|
import shlex
|
||||||
|
|
||||||
from response import Response
|
|
||||||
|
|
||||||
class Message:
|
class Message:
|
||||||
def __init__ (self, orig, private=False):
|
def __init__ (self, orig, private=False):
|
||||||
self.cmd = orig.cmd
|
self.cmd = orig.cmd
|
||||||
|
@ -10,6 +10,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
"""Load this module"""
|
"""Load this module"""
|
||||||
global DATAS
|
global DATAS
|
||||||
|
@ -14,6 +14,8 @@ from xmlparser.node import ModuleState
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
global DATAS
|
global DATAS
|
||||||
DATAS.setIndex("name", "birthday")
|
DATAS.setIndex("name", "birthday")
|
||||||
|
@ -9,6 +9,8 @@ from tools.countdown import countdown_format
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
yr = datetime.today().year
|
yr = datetime.today().year
|
||||||
yrn = datetime.today().year + 1
|
yrn = datetime.today().year + 1
|
||||||
|
|
||||||
|
@ -9,6 +9,8 @@ from tools import web
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
if not CONF or not CONF.hasNode("goodreadsapi") or not CONF.getNode("goodreadsapi").hasAttribute("key"):
|
if not CONF or not CONF.hasNode("goodreadsapi") or not CONF.getNode("goodreadsapi").hasAttribute("key"):
|
||||||
print ("You need a Goodreads API key in order to use this "
|
print ("You need a Goodreads API key in order to use this "
|
||||||
|
@ -14,6 +14,8 @@ from collections import defaultdict
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
s = [('present', '0'), ('présent', '0'), ('pr', '0'),
|
s = [('present', '0'), ('présent', '0'), ('pr', '0'),
|
||||||
('passé simple', '12'), ('passe simple', '12'), ('ps', '12'),
|
('passé simple', '12'), ('passe simple', '12'), ('ps', '12'),
|
||||||
('passé antérieur', '112'), ('passe anterieur', '112'), ('pa', '112'),
|
('passé antérieur', '112'), ('passe anterieur', '112'), ('pa', '112'),
|
||||||
|
@ -8,6 +8,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
from . import DDGSearch
|
from . import DDGSearch
|
||||||
from . import UrbanDictionnary
|
from . import UrbanDictionnary
|
||||||
from . import WFASearch
|
from . import WFASearch
|
||||||
|
@ -11,13 +11,15 @@ import time
|
|||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
nemubotversion = 3.4
|
|
||||||
|
|
||||||
from event import ModuleEvent
|
from event import ModuleEvent
|
||||||
from hooks import hook
|
from hooks import hook
|
||||||
from tools.date import extractDate
|
from tools.date import extractDate
|
||||||
from tools.countdown import countdown_format, countdown
|
from tools.countdown import countdown_format, countdown
|
||||||
|
|
||||||
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full ():
|
def help_full ():
|
||||||
return "This module store a lot of events: ny, we, " + (", ".join(DATAS.index.keys())) + "\n!eventslist: gets list of timer\n!start /something/: launch a timer"
|
return "This module store a lot of events: ny, we, " + (", ".join(DATAS.index.keys())) + "\n!eventslist: gets list of timer\n!start /something/: launch a timer"
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full ():
|
def help_full ():
|
||||||
return "!github /repo/: Display information about /repo/.\n!github_user /user/: Display information about /user/."
|
return "!github /repo/: Display information about /repo/.\n!github_user /user/: Display information about /user/."
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "Search a movie title with: !imdbs <approximative title> ; View movie details with !imdb <title>"
|
return "Search a movie title with: !imdbs <approximative title> ; View movie details with !imdb <title>"
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_tiny():
|
def help_tiny():
|
||||||
"""Line inserted in the response to the command !help"""
|
"""Line inserted in the response to the command !help"""
|
||||||
return "Read manual pages on IRC"
|
return "Read manual pages on IRC"
|
||||||
|
@ -7,6 +7,8 @@ from urllib.request import urlopen
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
if not CONF or not CONF.hasNode("mapquestapi") or not CONF.getNode("mapquestapi").hasAttribute("key"):
|
if not CONF or not CONF.hasNode("mapquestapi") or not CONF.getNode("mapquestapi").hasAttribute("key"):
|
||||||
print ("You need a MapQuest API key in order to use this "
|
print ("You need a MapQuest API key in order to use this "
|
||||||
|
@ -12,6 +12,8 @@ from tools.web import striphtml
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def get_raw_page(site, term, ssl=False):
|
def get_raw_page(site, term, ssl=False):
|
||||||
# Built IRL
|
# Built IRL
|
||||||
url = "http%s://%s/w/api.php?format=json&redirects&action=query&prop=revisions&rvprop=content&titles=%s" % (
|
url = "http%s://%s/w/api.php?format=json&redirects&action=query&prop=revisions&rvprop=content&titles=%s" % (
|
||||||
|
175
modules/more.py
175
modules/more.py
@ -18,22 +18,195 @@
|
|||||||
|
|
||||||
"""Progressive display of very long messages"""
|
"""Progressive display of very long messages"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
from hooks import hook
|
from hooks import hook
|
||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
logger = logging.getLogger("nemubot.response")
|
||||||
|
|
||||||
|
class Response:
|
||||||
|
def __init__(self, message=None, channel=None, nick=None, server=None,
|
||||||
|
nomore="No more message", title=None, more="(suite) ",
|
||||||
|
count=None, ctcp=False, shown_first_count=-1,
|
||||||
|
line_treat=None):
|
||||||
|
self.nomore = nomore
|
||||||
|
self.more = more
|
||||||
|
self.line_treat = line_treat
|
||||||
|
self.rawtitle = title
|
||||||
|
self.server = server
|
||||||
|
self.messages = list()
|
||||||
|
self.alone = True
|
||||||
|
self.is_ctcp = ctcp
|
||||||
|
if message is not None:
|
||||||
|
self.append_message(message, shown_first_count=shown_first_count)
|
||||||
|
self.elt = 0 # Next element to display
|
||||||
|
|
||||||
|
self.sender = None
|
||||||
|
self.channel = channel
|
||||||
|
self.nick = nick
|
||||||
|
self.count = count
|
||||||
|
|
||||||
|
@property
|
||||||
|
def receivers(self):
|
||||||
|
if self.channel is None:
|
||||||
|
if self.nick is not None:
|
||||||
|
return [ self.nick ]
|
||||||
|
return [ self.sender.split("!")[0] ]
|
||||||
|
elif isinstance(self.channel, list):
|
||||||
|
return self.channel
|
||||||
|
else:
|
||||||
|
return [ self.channel ]
|
||||||
|
|
||||||
|
def set_sender(self, sender):
|
||||||
|
if sender is None or sender.find("!") < 0:
|
||||||
|
if sender is not None:
|
||||||
|
logger.warn("Bad sender provided in Response, it will be ignored.", stack_info=True)
|
||||||
|
self.sender = None
|
||||||
|
else:
|
||||||
|
self.sender = sender
|
||||||
|
|
||||||
|
def append_message(self, message, title=None, shown_first_count=-1):
|
||||||
|
if type(message) is str:
|
||||||
|
message = message.split('\n')
|
||||||
|
if len(message) > 1:
|
||||||
|
for m in message:
|
||||||
|
self.append_message(m)
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
message = message[0]
|
||||||
|
if message is not None and len(message) > 0:
|
||||||
|
if shown_first_count >= 0:
|
||||||
|
self.messages.append(message[:shown_first_count])
|
||||||
|
message = message[shown_first_count:]
|
||||||
|
self.messages.append(message)
|
||||||
|
self.alone = self.alone and len(self.messages) <= 1
|
||||||
|
if isinstance(self.rawtitle, list):
|
||||||
|
self.rawtitle.append(title)
|
||||||
|
elif title is not None:
|
||||||
|
rawtitle = self.rawtitle
|
||||||
|
self.rawtitle = list()
|
||||||
|
for osef in self.messages:
|
||||||
|
self.rawtitle.append(rawtitle)
|
||||||
|
self.rawtitle.pop()
|
||||||
|
self.rawtitle.append(title)
|
||||||
|
|
||||||
|
def append_content(self, message):
|
||||||
|
if message is not None and len(message) > 0:
|
||||||
|
if self.messages is None or len(self.messages) == 0:
|
||||||
|
self.messages = list(message)
|
||||||
|
self.alone = True
|
||||||
|
else:
|
||||||
|
self.messages[len(self.messages)-1] += message
|
||||||
|
self.alone = self.alone and len(self.messages) <= 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def empty(self):
|
||||||
|
return len(self.messages) <= 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def title(self):
|
||||||
|
if isinstance(self.rawtitle, list):
|
||||||
|
return self.rawtitle[0]
|
||||||
|
else:
|
||||||
|
return self.rawtitle
|
||||||
|
|
||||||
|
def pop(self):
|
||||||
|
self.messages.pop(0)
|
||||||
|
self.elt = 0
|
||||||
|
if isinstance(self.rawtitle, list):
|
||||||
|
self.rawtitle.pop(0)
|
||||||
|
if len(self.rawtitle) <= 0:
|
||||||
|
self.rawtitle = None
|
||||||
|
|
||||||
|
def treat_ctcp(self, content):
|
||||||
|
if self.is_ctcp:
|
||||||
|
return "\x01" + content + "\x01"
|
||||||
|
else:
|
||||||
|
return content
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
if self.alone and len(self.messages) > 1:
|
||||||
|
self.alone = False
|
||||||
|
|
||||||
|
if self.empty:
|
||||||
|
return self.treat_ctcp(self.nomore)
|
||||||
|
|
||||||
|
if self.line_treat is not None and self.elt == 0:
|
||||||
|
self.messages[0] = self.line_treat(self.messages[0]).replace("\n", " ").strip()
|
||||||
|
|
||||||
|
msg = ""
|
||||||
|
if self.channel is not None and self.nick is not None:
|
||||||
|
msg += self.nick + ": "
|
||||||
|
|
||||||
|
if self.title is not None:
|
||||||
|
if self.elt > 0:
|
||||||
|
msg += self.title + " " + self.more + ": "
|
||||||
|
else:
|
||||||
|
msg += self.title + ": "
|
||||||
|
|
||||||
|
if self.elt > 0:
|
||||||
|
msg += "[…] "
|
||||||
|
|
||||||
|
elts = self.messages[0][self.elt:]
|
||||||
|
if isinstance(elts, list):
|
||||||
|
for e in elts:
|
||||||
|
if len(msg) + len(e) > 430:
|
||||||
|
msg += "[…]"
|
||||||
|
self.alone = False
|
||||||
|
return self.treat_ctcp(msg)
|
||||||
|
else:
|
||||||
|
msg += e + ", "
|
||||||
|
self.elt += 1
|
||||||
|
self.pop()
|
||||||
|
return self.treat_ctcp(msg[:len(msg)-2])
|
||||||
|
|
||||||
|
else:
|
||||||
|
if len(elts.encode()) <= 432:
|
||||||
|
self.pop()
|
||||||
|
if self.count is not None:
|
||||||
|
return self.treat_ctcp(msg + elts + (self.count % len(self.messages)))
|
||||||
|
else:
|
||||||
|
return self.treat_ctcp(msg + elts)
|
||||||
|
|
||||||
|
else:
|
||||||
|
words = elts.split(' ')
|
||||||
|
|
||||||
|
if len(words[0].encode()) > 432 - len(msg.encode()):
|
||||||
|
self.elt += 432 - len(msg.encode())
|
||||||
|
return self.treat_ctcp(msg + elts[:self.elt] + "[…]")
|
||||||
|
|
||||||
|
for w in words:
|
||||||
|
if len(msg.encode()) + len(w.encode()) > 431:
|
||||||
|
msg += "[…]"
|
||||||
|
self.alone = False
|
||||||
|
return self.treat_ctcp(msg)
|
||||||
|
else:
|
||||||
|
msg += w + " "
|
||||||
|
self.elt += len(w) + 1
|
||||||
|
self.pop()
|
||||||
|
return self.treat_ctcp(msg)
|
||||||
|
|
||||||
|
|
||||||
SERVERS = dict()
|
SERVERS = dict()
|
||||||
|
|
||||||
@hook("all_post")
|
@hook("all_post")
|
||||||
def parseresponse(res):
|
def parseresponse(res):
|
||||||
# TODO: handle inter-bot communication NOMORE
|
# TODO: handle inter-bot communication NOMORE
|
||||||
# TODO: check that the response is not the one already saved
|
# TODO: check that the response is not the one already saved
|
||||||
|
rstr = res.get_message()
|
||||||
|
|
||||||
if not res.alone:
|
if not res.alone:
|
||||||
if res.server not in SERVERS:
|
if res.server not in SERVERS:
|
||||||
SERVERS[res.server] = dict()
|
SERVERS[res.server] = dict()
|
||||||
for receiver in res.receivers:
|
for receiver in res.receivers:
|
||||||
SERVERS[res.server][receiver] = res
|
SERVERS[res.server][receiver] = res
|
||||||
return res
|
|
||||||
|
ret = list()
|
||||||
|
for channel in res.receivers:
|
||||||
|
ret.append("%s %s :%s" % ("NOTICE" if res.is_ctcp else "PRIVMSG", channel, rstr))
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@hook("cmd_hook", "more")
|
@hook("cmd_hook", "more")
|
||||||
|
@ -14,6 +14,8 @@ from tools import web
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
if not CONF or not CONF.hasNode("whoisxmlapi") or not CONF.getNode("whoisxmlapi").hasAttribute("username") or not CONF.getNode("whoisxmlapi").hasAttribute("password"):
|
if not CONF or not CONF.hasNode("whoisxmlapi") or not CONF.getNode("whoisxmlapi").hasAttribute("username") or not CONF.getNode("whoisxmlapi").hasAttribute("password"):
|
||||||
print ("You need a WhoisXML API account in order to use the "
|
print ("You need a WhoisXML API account in order to use the "
|
||||||
|
@ -9,6 +9,7 @@ import urllib
|
|||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
from hooks import hook
|
from hooks import hook
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "!subreddit /subreddit/: Display information on the subreddit."
|
return "!subreddit /subreddit/: Display information on the subreddit."
|
||||||
|
@ -8,6 +8,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
@hook("cmd_hook", "choice")
|
@hook("cmd_hook", "choice")
|
||||||
def cmd_choice(msg):
|
def cmd_choice(msg):
|
||||||
if len(msg.cmds) > 1:
|
if len(msg.cmds) > 1:
|
||||||
|
@ -12,6 +12,8 @@ from tools.web import striphtml
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full ():
|
def help_full ():
|
||||||
return "!tcode <transaction code|keywords>"
|
return "!tcode <transaction code|keywords>"
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "If you would like to sleep soon, use !sleepytime to know the best time to wake up; use !sleepytime hh:mm if you want to wake up at hh:mm"
|
return "If you would like to sleep soon, use !sleepytime to know the best time to wake up; use !sleepytime hh:mm if you want to wake up at hh:mm"
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
global DATAS
|
global DATAS
|
||||||
DATAS.setIndex("name", "phone")
|
DATAS.setIndex("name", "phone")
|
||||||
|
@ -12,6 +12,8 @@ from .pyaspell import AspellError
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "!spell [<lang>] <word>: give the correct spelling of <word> in <lang=fr>."
|
return "!spell [<lang>] <word>: give the correct spelling of <word> in <lang=fr>."
|
||||||
|
|
||||||
|
@ -12,6 +12,8 @@ from tools import web
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "!syno <word>: give a list of synonyms for <word>."
|
return "!syno <word>: give a list of synonyms for <word>."
|
||||||
|
|
||||||
|
@ -11,6 +11,8 @@ from urllib.request import urlopen
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
import xmlparser
|
import xmlparser
|
||||||
|
|
||||||
LANG = ["ar", "zh", "cz", "en", "fr", "gr", "it",
|
LANG = ["ar", "zh", "cz", "en", "fr", "gr", "it",
|
||||||
|
@ -9,6 +9,8 @@ from tools import web
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
global DATAS
|
global DATAS
|
||||||
DATAS.setIndex("name", "station")
|
DATAS.setIndex("name", "station")
|
||||||
|
@ -15,10 +15,11 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
from hooks import hook
|
from hooks import hook
|
||||||
|
|
||||||
|
nemubotversion = 3.4
|
||||||
|
|
||||||
from networking import w3m
|
from networking import w3m
|
||||||
from .atom import Atom
|
from .atom import Atom
|
||||||
|
from more import Response
|
||||||
nemubotversion = 3.4
|
|
||||||
|
|
||||||
def help_full ():
|
def help_full ():
|
||||||
return "This module is autonomous you can't interract with it."
|
return "This module is autonomous you can't interract with it."
|
||||||
|
@ -14,6 +14,8 @@ import mapquest
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def load(context):
|
def load(context):
|
||||||
global DATAS
|
global DATAS
|
||||||
DATAS.setIndex("name", "city")
|
DATAS.setIndex("name", "city")
|
||||||
|
@ -10,6 +10,8 @@ from urllib.request import urlopen
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
from hooks import hook
|
from hooks import hook
|
||||||
|
|
||||||
API_URL="http://worldcup.sfg.io/%s"
|
API_URL="http://worldcup.sfg.io/%s"
|
||||||
|
@ -11,6 +11,8 @@ from hooks import hook
|
|||||||
|
|
||||||
nemubotversion = 3.4
|
nemubotversion = 3.4
|
||||||
|
|
||||||
|
from more import Response
|
||||||
|
|
||||||
def help_full():
|
def help_full():
|
||||||
return "!ycc [<url>]: with an argument, reduce the given <url> thanks to ycc.fr; without argument, reduce the last URL said on the current channel."
|
return "!ycc [<url>]: with an argument, reduce the given <url> thanks to ycc.fr; without argument, reduce the last URL said on the current channel."
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ import zlib
|
|||||||
|
|
||||||
from server.DCC import DCC
|
from server.DCC import DCC
|
||||||
import hooks
|
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):
|
||||||
|
185
response.py
185
response.py
@ -1,185 +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 logging
|
|
||||||
import traceback
|
|
||||||
import sys
|
|
||||||
|
|
||||||
logger = logging.getLogger("nemubot.response")
|
|
||||||
|
|
||||||
class Response:
|
|
||||||
def __init__(self, message=None, channel=None, nick=None, server=None,
|
|
||||||
nomore="No more message", title=None, more="(suite) ",
|
|
||||||
count=None, ctcp=False, shown_first_count=-1,
|
|
||||||
line_treat=None):
|
|
||||||
self.nomore = nomore
|
|
||||||
self.more = more
|
|
||||||
self.line_treat = line_treat
|
|
||||||
self.rawtitle = title
|
|
||||||
self.server = server
|
|
||||||
self.messages = list()
|
|
||||||
self.alone = True
|
|
||||||
self.is_ctcp = ctcp
|
|
||||||
if message is not None:
|
|
||||||
self.append_message(message, shown_first_count=shown_first_count)
|
|
||||||
self.elt = 0 # Next element to display
|
|
||||||
|
|
||||||
self.sender = None
|
|
||||||
self.channel = channel
|
|
||||||
self.nick = nick
|
|
||||||
self.count = count
|
|
||||||
|
|
||||||
@property
|
|
||||||
def receivers(self):
|
|
||||||
if self.channel is None:
|
|
||||||
if self.nick is not None:
|
|
||||||
return [ self.nick ]
|
|
||||||
return [ self.sender.split("!")[0] ]
|
|
||||||
elif isinstance(self.channel, list):
|
|
||||||
return self.channel
|
|
||||||
else:
|
|
||||||
return [ self.channel ]
|
|
||||||
|
|
||||||
def set_sender(self, sender):
|
|
||||||
if sender is None or sender.find("!") < 0:
|
|
||||||
if sender is not None:
|
|
||||||
logger.warn("Bad sender provided in Response, it will be ignored.", stack_info=True)
|
|
||||||
self.sender = None
|
|
||||||
else:
|
|
||||||
self.sender = sender
|
|
||||||
|
|
||||||
def append_message(self, message, title=None, shown_first_count=-1):
|
|
||||||
if type(message) is str:
|
|
||||||
message = message.split('\n')
|
|
||||||
if len(message) > 1:
|
|
||||||
for m in message:
|
|
||||||
self.append_message(m)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
message = message[0]
|
|
||||||
if message is not None and len(message) > 0:
|
|
||||||
if shown_first_count >= 0:
|
|
||||||
self.messages.append(message[:shown_first_count])
|
|
||||||
message = message[shown_first_count:]
|
|
||||||
self.messages.append(message)
|
|
||||||
self.alone = self.alone and len(self.messages) <= 1
|
|
||||||
if isinstance(self.rawtitle, list):
|
|
||||||
self.rawtitle.append(title)
|
|
||||||
elif title is not None:
|
|
||||||
rawtitle = self.rawtitle
|
|
||||||
self.rawtitle = list()
|
|
||||||
for osef in self.messages:
|
|
||||||
self.rawtitle.append(rawtitle)
|
|
||||||
self.rawtitle.pop()
|
|
||||||
self.rawtitle.append(title)
|
|
||||||
|
|
||||||
def append_content(self, message):
|
|
||||||
if message is not None and len(message) > 0:
|
|
||||||
if self.messages is None or len(self.messages) == 0:
|
|
||||||
self.messages = list(message)
|
|
||||||
self.alone = True
|
|
||||||
else:
|
|
||||||
self.messages[len(self.messages)-1] += message
|
|
||||||
self.alone = self.alone and len(self.messages) <= 1
|
|
||||||
|
|
||||||
@property
|
|
||||||
def empty(self):
|
|
||||||
return len(self.messages) <= 0
|
|
||||||
|
|
||||||
@property
|
|
||||||
def title(self):
|
|
||||||
if isinstance(self.rawtitle, list):
|
|
||||||
return self.rawtitle[0]
|
|
||||||
else:
|
|
||||||
return self.rawtitle
|
|
||||||
|
|
||||||
def pop(self):
|
|
||||||
self.messages.pop(0)
|
|
||||||
self.elt = 0
|
|
||||||
if isinstance(self.rawtitle, list):
|
|
||||||
self.rawtitle.pop(0)
|
|
||||||
if len(self.rawtitle) <= 0:
|
|
||||||
self.rawtitle = None
|
|
||||||
|
|
||||||
def treat_ctcp(self, content):
|
|
||||||
if self.is_ctcp:
|
|
||||||
return "\x01" + content + "\x01"
|
|
||||||
else:
|
|
||||||
return content
|
|
||||||
|
|
||||||
def get_message(self):
|
|
||||||
if self.alone and len(self.messages) > 1:
|
|
||||||
self.alone = False
|
|
||||||
|
|
||||||
if self.empty:
|
|
||||||
return self.treat_ctcp(self.nomore)
|
|
||||||
|
|
||||||
if self.line_treat is not None and self.elt == 0:
|
|
||||||
self.messages[0] = self.line_treat(self.messages[0]).replace("\n", " ").strip()
|
|
||||||
|
|
||||||
msg = ""
|
|
||||||
if self.channel is not None and self.nick is not None:
|
|
||||||
msg += self.nick + ": "
|
|
||||||
|
|
||||||
if self.title is not None:
|
|
||||||
if self.elt > 0:
|
|
||||||
msg += self.title + " " + self.more + ": "
|
|
||||||
else:
|
|
||||||
msg += self.title + ": "
|
|
||||||
|
|
||||||
if self.elt > 0:
|
|
||||||
msg += "[…] "
|
|
||||||
|
|
||||||
elts = self.messages[0][self.elt:]
|
|
||||||
if isinstance(elts, list):
|
|
||||||
for e in elts:
|
|
||||||
if len(msg) + len(e) > 430:
|
|
||||||
msg += "[…]"
|
|
||||||
self.alone = False
|
|
||||||
return self.treat_ctcp(msg)
|
|
||||||
else:
|
|
||||||
msg += e + ", "
|
|
||||||
self.elt += 1
|
|
||||||
self.pop()
|
|
||||||
return self.treat_ctcp(msg[:len(msg)-2])
|
|
||||||
|
|
||||||
else:
|
|
||||||
if len(elts.encode()) <= 432:
|
|
||||||
self.pop()
|
|
||||||
if self.count is not None:
|
|
||||||
return self.treat_ctcp(msg + elts + (self.count % len(self.messages)))
|
|
||||||
else:
|
|
||||||
return self.treat_ctcp(msg + elts)
|
|
||||||
|
|
||||||
else:
|
|
||||||
words = elts.split(' ')
|
|
||||||
|
|
||||||
if len(words[0].encode()) > 432 - len(msg.encode()):
|
|
||||||
self.elt += 432 - len(msg.encode())
|
|
||||||
return self.treat_ctcp(msg + elts[:self.elt] + "[…]")
|
|
||||||
|
|
||||||
for w in words:
|
|
||||||
if len(msg.encode()) + len(w.encode()) > 431:
|
|
||||||
msg += "[…]"
|
|
||||||
self.alone = False
|
|
||||||
return self.treat_ctcp(msg)
|
|
||||||
else:
|
|
||||||
msg += w + " "
|
|
||||||
self.elt += len(w) + 1
|
|
||||||
self.pop()
|
|
||||||
return self.treat_ctcp(msg)
|
|
@ -185,13 +185,6 @@ class IRCServer(SocketServer):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def send_response(self, res):
|
|
||||||
for channel in res.receivers:
|
|
||||||
if channel is not None and channel != self.nick:
|
|
||||||
self.write("%s %s :%s" % ("NOTICE" if res.is_ctcp else "PRIVMSG", channel, res.get_message()))
|
|
||||||
else:
|
|
||||||
raise Exception("Trying to send a message to an undefined channel: %s" % channel)
|
|
||||||
|
|
||||||
def _close(self):
|
def _close(self):
|
||||||
if self.socket is not None: self.write("QUIT")
|
if self.socket is not None: self.write("QUIT")
|
||||||
return SocketServer._close(self)
|
return SocketServer._close(self)
|
||||||
@ -219,17 +212,15 @@ class IRCServer(SocketServer):
|
|||||||
else:
|
else:
|
||||||
res = _ctcp_response("ERRMSG Unknown or unimplemented CTCP request")
|
res = _ctcp_response("ERRMSG Unknown or unimplemented CTCP request")
|
||||||
if res is not None:
|
if res is not None:
|
||||||
res.set_sender(mes.sender)
|
res = res % mes.nick
|
||||||
self.send_response(res)
|
self.write(res)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
yield mes
|
yield mes
|
||||||
|
|
||||||
|
|
||||||
from response import Response
|
|
||||||
|
|
||||||
def _ctcp_response(msg):
|
def _ctcp_response(msg):
|
||||||
return Response(msg, ctcp=True)
|
return "NOTICE %%s :\x01%s\x01" % msg
|
||||||
|
|
||||||
|
|
||||||
mgx = re.compile(b'''^(?:@(?P<tags>[^ ]+)\ )?
|
mgx = re.compile(b'''^(?:@(?P<tags>[^ ]+)\ )?
|
||||||
|
@ -64,10 +64,6 @@ class AbstractServer(io.IOBase):
|
|||||||
_xlist.remove(self)
|
_xlist.remove(self)
|
||||||
|
|
||||||
|
|
||||||
def send_response(self, res):
|
|
||||||
return NotImplemented
|
|
||||||
|
|
||||||
|
|
||||||
def write(self, message):
|
def write(self, message):
|
||||||
"""Send a message to the server using send_callback"""
|
"""Send a message to the server using send_callback"""
|
||||||
self._send_callback(message)
|
self._send_callback(message)
|
||||||
|
Loading…
Reference in New Issue
Block a user