summaryrefslogtreecommitdiff
path: root/poezio/mam.py
diff options
context:
space:
mode:
authorroot <madhurgarg96@gmail.com>2019-09-05 15:40:46 +0530
committerroot <madhurgarg96@gmail.com>2019-09-05 17:42:27 +0530
commit17e7f0768a1ae2eceae78dca677d165d86a067d6 (patch)
tree4b0ecf38b0ba759f4c4c0b54e4dadf4030a7909c /poezio/mam.py
parent5e81fe276058f9ad884b76789ae52797057d3788 (diff)
downloadpoezio-17e7f0768a1ae2eceae78dca677d165d86a067d6.tar.gz
poezio-17e7f0768a1ae2eceae78dca677d165d86a067d6.tar.bz2
poezio-17e7f0768a1ae2eceae78dca677d165d86a067d6.tar.xz
poezio-17e7f0768a1ae2eceae78dca677d165d86a067d6.zip
Reorganize MAM
Diffstat (limited to 'poezio/mam.py')
-rw-r--r--poezio/mam.py157
1 files changed, 93 insertions, 64 deletions
diff --git a/poezio/mam.py b/poezio/mam.py
index 08bab727..919bb6dd 100644
--- a/poezio/mam.py
+++ b/poezio/mam.py
@@ -9,12 +9,20 @@
import asyncio
import random
from datetime import datetime, timedelta, timezone
+from slixmpp import JID
from slixmpp.exceptions import IqError, IqTimeout
from poezio.theming import get_theme
from poezio import tabs
from poezio import xhtml, colors
from poezio.config import config
from poezio.text_buffer import Message, TextBuffer
+from typing import List, Optional, Callable
+
+
+class DiscoInfoException(Exception): pass
+class MAMQueryException(Exception): pass
+class NoMAMSupportException(Exception): pass
+
def add_line(tab, text_buffer: TextBuffer, text: str, str_time: str, nick: str, top: bool):
"""Adds a textual entry in the TextBuffer"""
@@ -62,63 +70,68 @@ def add_line(tab, text_buffer: TextBuffer, text: str, str_time: str, nick: str,
jid=None,
)
-async def query(tab, remote_jid, action, amount, top, start=None, end=None, before=None):
- text_buffer = tab._text_buffer
+async def query(
+ core,
+ groupchat: bool,
+ remote_jid: JID,
+ amount: int,
+ reverse: bool,
+ start: Optional[datetime] = None,
+ end: Optional[datetime] = None,
+ before: Optional[str] = None,
+ callback: Optional[Callable] = None,
+ ) -> None:
try:
- iq = await tab.core.xmpp.plugin['xep_0030'].get_info(jid=remote_jid)
+ iq = await core.xmpp.plugin['xep_0030'].get_info(jid=remote_jid)
except (IqError, IqTimeout):
- if action is 'scroll':
- return tab.core.information('%s : Failed to retrieve messages' % remote_jid, 'Error')
- if 'urn:xmpp:mam:2' not in iq['disco_info'].get_features() and action is 'scroll':
- return tab.core.information("%s doesn't support MAM." % remote_jid, "Info")
- if top:
- if isinstance(tab, tabs.MucTab):
- try:
- if before is not None:
- results = tab.core.xmpp['xep_0313'].retrieve(jid=remote_jid,
- iterator=True, reverse=top, rsm={'before':before, 'max':amount})
- else:
- results = tab.core.xmpp['xep_0313'].retrieve(jid=remote_jid,
- iterator=True, reverse=top, end=end, rsm={'max':amount})
- except (IqError, IqTimeout):
- if action is 'scroll':
- return tab.core.information('%s : Failed to retrieve messages' % remote_jid, 'Error')
- else:
- try:
- if before is not None:
- results = tab.core.xmpp['xep_0313'].retrieve(with_jid=remote_jid,
- iterator=True, reverse=top, rsm={'before':before, 'max':amount})
- else:
- results = tab.core.xmpp['xep_0313'].retrieve(with_jid=remote_jid,
- iterator=True, reverse=top, end=end, rsm={'max':amount})
- except (IqError, IqTimeout):
- if action is 'scroll':
- return tab.core.information('%s : Failed to retrieve messages' % remote_jid, 'Error')
+ raise DiscoInfoException
+ if 'urn:xmpp:mam:2' not in iq['disco_info'].get_features():
+ raise NoMAMSupportException
+
+ args = {
+ 'iterator': True,
+ 'reverse': reverse,
+ }
+
+ if groupchat:
+ args['jid'] = remote_jid
else:
- if 'conference' in list(iq['disco_info']['identities'])[0]:
- try:
- results = tab.core.xmpp['xep_0313'].retrieve(jid=remote_jid,
- iterator=True, reverse=top, start=start, end=end)
- except (IqError, IqTimeout):
- return tab.core.information('%s : Failed to retrieve messages' % remote_jid, 'Error')
+ args['with_jid'] = remote_jid
+
+ args['rsm'] = {'max': amount}
+ if reverse:
+ if before is not None:
+ args['rsm']['before'] = before
else:
- try:
- results = tab.core.xmpp['xep_0313'].retrieve(with_jid=remote_jid,
- iterator=True, reverse=top, start=start, end=end)
- except (IqError, IqTimeout):
- return tab.core.information('%s : Failed to retrieve messages' % remote_jid, 'Error')
+ args['end'] = end
+ else:
+ args['rsm']['start'] = start
+ if before is not None:
+ args['rsm']['end'] = end
+ try:
+ results = core.xmpp['xep_0313'].retrieve(**args)
+ except (IqError, IqTimeout):
+ raise MAMQueryException
+ if callback is not None:
+ callback(results)
+
+ return results
+
+async def add_messages_to_buffer(tab, top: bool, results, amount: int) -> None:
+ """Prepends or appends messages to the tab text_buffer"""
+
+ text_buffer = tab._text_buffer
msg_count = 0
msgs = []
async for rsm in results:
if top:
for msg in rsm['mam']['results']:
- if msg['mam_result']['forwarded']['stanza'].xml.find(
- '{%s}%s' % ('jabber:client', 'body')) is not None:
+ if msg['mam_result']['forwarded']['stanza'] \
+ .xml.find('{%s}%s' % ('jabber:client', 'body')) is not None:
msgs.append(msg)
if msg_count == amount:
- tab.query_status = False
tab.core.refresh_window()
- return
+ return False
msg_count += 1
msgs.reverse()
for msg in msgs:
@@ -136,31 +149,47 @@ async def query(tab, remote_jid, action, amount, top, start=None, end=None, befo
nick = str(message['from'])
add_line(tab, text_buffer, message['body'], timestamp, nick, top)
tab.core.refresh_window()
- tab.query_status = False
+ return False
-def mam_scroll(tab, action):
+async def fetch_history(tab, end: Optional[datetime] = None, amount: Optional[int] = None):
remote_jid = tab.jid
- text_buffer = tab._text_buffer
before = tab.last_stanza_id
- end = datetime.now()
- if isinstance(tab, tabs.MucTab) is False:
- for message in text_buffer.messages:
- time = message.time
- if time < end:
- end = time
- end = end + timedelta(seconds=-1)
+ if end is None:
+ end = datetime.now()
tzone = datetime.now().astimezone().tzinfo
end = end.replace(tzinfo=tzone).astimezone(tz=timezone.utc)
end = end.replace(tzinfo=None)
end = datetime.strftime(end, '%Y-%m-%dT%H:%M:%SZ')
- if action is 'scroll':
- amount = tab.text_win.height
- else:
- amount = 2 * tab.text_win.height
+
if amount >= 100:
amount = 99
- if before is None:
- asyncio.ensure_future(query(tab, remote_jid, action, amount, top=True, end=end))
- else:
- asyncio.ensure_future(query(tab, remote_jid, action, amount, top=True, before=before))
- tab.query_status = True
+
+ groupchat = isinstance(tab, tabs.MucTab)
+
+ results = await query(tab.core, groupchat, remote_jid, amount, reverse=True, end=end, before=before)
+ query_status = await add_messages_to_buffer(tab, True, results, amount)
+ tab.query_status = query_status
+
+async def on_tab_open(tab) -> None:
+ amount = 2 * tab.text_win.height
+ end = datetime.now()
+ for message in tab._text_buffer.messages:
+ time = message.time
+ if time < end:
+ end = time
+ end = end + timedelta(seconds=-1)
+ try:
+ await fetch_history(tab, end=end, amount=amount)
+ except (NoMAMSupportException, MAMQueryException, DiscoInfoException):
+ return None
+
+async def on_scroll_up(tab) -> None:
+ amount = tab.text_win.height
+ try:
+ await fetch_history(tab, amount=amount)
+ except NoMAMSupportException:
+ tab.core.information('MAM not supported for %r' % tab.jid, 'Info')
+ return None
+ except (MAMQueryException, DiscoInfoException):
+ tab.core.information('An error occured when fetching MAM for %r' % tab.jid, 'Error')
+ return None