summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2011-07-11 02:23:45 +0200
committerFlorent Le Coz <louiz@louiz.org>2011-07-11 02:23:45 +0200
commit956bda066b683001b23f718bd5892440d03b5401 (patch)
tree7f09f39a1f97e0fc80e554ba7bc8f7a0eab3eaea
parentc03557efd75cd21a2798991b2729177294167842 (diff)
downloadpoezio-956bda066b683001b23f718bd5892440d03b5401.tar.gz
poezio-956bda066b683001b23f718bd5892440d03b5401.tar.bz2
poezio-956bda066b683001b23f718bd5892440d03b5401.tar.xz
poezio-956bda066b683001b23f718bd5892440d03b5401.zip
PUBSUB: publish items on node, with a text editor
-rw-r--r--src/core.py9
-rw-r--r--src/pubsub.py131
-rw-r--r--src/tabs.py3
3 files changed, 137 insertions, 6 deletions
diff --git a/src/core.py b/src/core.py
index 0d6bf6ea..c0e5f252 100644
--- a/src/core.py
+++ b/src/core.py
@@ -178,7 +178,7 @@ class Core(object):
self.timed_events = set()
def coucou(self):
- self.command_pubsub('psgxs.linkmauve.fr')
+ self.command_pubsub('pubsub.louiz.org')
def start(self):
"""
@@ -649,7 +649,8 @@ class Core(object):
Completely erase and redraw the screen
"""
self.stdscr.clear()
- self.call_for_resize()
+ self.stdscr.refresh()
+ self.refresh_window()
def call_for_resize(self):
"""
@@ -751,6 +752,8 @@ class Core(object):
"""
ncurses initialization
"""
+ self.background = False # Bool to know if curses can draw
+ # or be quiet while an other console app is running.
curses.curs_set(1)
curses.noecho()
curses.nonl()
@@ -1530,6 +1533,6 @@ class Core(object):
self.information(_("Unknown command (%s)") % (command), _('Error'))
def doupdate(self):
- if not self.running:
+ if not self.running or self.background is True:
return
curses.doupdate()
diff --git a/src/pubsub.py b/src/pubsub.py
index 54d950cd..498843cf 100644
--- a/src/pubsub.py
+++ b/src/pubsub.py
@@ -17,14 +17,101 @@
import logging
log = logging.getLogger(__name__)
+import os
import curses
+import tempfile
+import subprocess
import tabs
import windows
import atom_parser
+from config import config
+
+from datetime import datetime
from sleekxmpp.xmlstream import ElementBase, ET
+ATOM_XMLNS = "http://www.w3.org/2005/Atom"
+
+item_template = \
+"""
+-- About you
+-- Your name
+Author: %(author)s
+
+-- Your jid (e.g. xmpp:romeo@example.com) or website’s url (http://example.com)
+URI: xmpp:%(jid)s
+
+-- Your email address (e.g. romeo@mail.com)
+email:
+Title:
+
+-- Please use the form dd/mm/yyy hh:mm:ss, or leave empty
+-- If you leave the date empty it will automatically be filled with the current time and date (recommended)
+Date:
+
+--- body --- Until the end of file, this will be your item's body
+
+"""
+
+def parse_template(lines):
+ """
+ takes a template string (splitted by lines) and returns a dict with the correstponding values
+ """
+ lines = [line.lower() for line in lines]
+ res = {}
+ reading_body = False
+ body = []
+ for line in lines:
+ if line.startswith('--- body ---'):
+ reading_body = True
+ continue
+ if reading_body:
+ body.append(line)
+ continue
+ if line.startswith('-- '):
+ continue
+ for value in ('author', 'uri', 'email', 'title', 'date'):
+ if line.startswith('%s:' % (value,)):
+ res[value] = line.split(':', 1)[1].strip()
+ res['body'] = ''.join(body)
+ return res
+
+def create_entry_from_dict(dic):
+ """
+ Takes a dict with the correct values and returns an ET.Element
+ representing an Atom entry
+ """
+ entry_elem = ET.Element('entry', xmlns=ATOM_XMLNS)
+
+ author_elem = ET.Element('author', xmlns=ATOM_XMLNS)
+ if dic.get('author'):
+ name_elem = ET.Element('name', xmlns=ATOM_XMLNS)
+ name_elem.text = dic.get('author')
+ author_elem.append(name_elem)
+ if dic.get('uri'):
+ uri_elem = ET.Element('uri', xmlns=ATOM_XMLNS)
+ uri_elem.text = dic.get('uri')
+ author_elem.append(uri_elem)
+ if dic.get('email'):
+ email_elem = ET.Element('email', xmlns=ATOM_XMLNS)
+ email_elem.text = dic.get('email')
+ author_elem.append(email_elem)
+ entry_elem.append(author_elem)
+ if dic.get('title'):
+ title_elem = ET.Element('title', xmlns=ATOM_XMLNS)
+ title_elem.text = dic.get('title')
+ entry_elem.append(title_elem)
+ # TODO
+ # if dic.get('date'):
+ date_elem = ET.Element('published', xmlns=ATOM_XMLNS)
+ date_elem.text = '%s' % datetime.now()
+ entry_elem.append(date_elem)
+ summary_elem = ET.Element('summary', xmlns=ATOM_XMLNS)
+ summary_elem.text = dic.get('body') or ''
+ entry_elem.append(summary_elem)
+ return entry_elem
+
class PubsubNode(object):
node_type = None # unknown yet
def __init__(self, name, parent=None):
@@ -103,6 +190,7 @@ class PubsubBrowserTab(tabs.Tab):
self.input = self.default_help_message
self.key_func['c'] = self.command_create_node
+ self.key_func['p'] = self.command_publish_item
self.key_func["M-KEY_DOWN"] = self.scroll_node_down
self.key_func["M-KEY_UP"] = self.scroll_node_up
self.key_func["KEY_DOWN"] = self.item_listview.move_cursor_down
@@ -112,6 +200,38 @@ class PubsubBrowserTab(tabs.Tab):
self.get_nodes()
+ def command_publish_item(self):
+ self.core.background = True
+ editor = config.get('editor', '') or os.getenv('EDITOR') or 'vi'
+ log.debug('Starting item edition with command %s' % editor)
+ tmpfile = tempfile.NamedTemporaryFile(mode='r+')
+ tmpfile.write(item_template % {'author': self.core.xmpp.boundjid.user, 'jid': self.core.xmpp.boundjid.bare})
+ tmpfile.flush()
+ process = subprocess.call(editor.split() + [tmpfile.name])
+ tmpfile.flush()
+ tmpfile.seek(0)
+ item_dict = parse_template(tmpfile.readlines())
+ tmpfile.close()
+ log.debug('[%s]' % item_dict)
+
+ self.core.background = False
+ self.core.full_screen_redraw()
+ entry = create_entry_from_dict(item_dict)
+ self.publish_item(entry, self.get_selected_node_name())
+
+ def publish_item(self, content, node_name):
+ """
+ publish the given item on the given node
+ """
+ def callback(res):
+ if res:
+ self.set_info_message('Item published')
+ else:
+ self.set_info_message('Item not published')
+ self.force_refresh()
+
+ self.core.xmpp.plugin['xep_0060'].setItem(self.server, node_name, content, callback=callback)
+
def set_info_message(self, message):
"""
Set an informative message in the upper line, near the server name
@@ -281,9 +401,13 @@ class PubsubBrowserTab(tabs.Tab):
def callback(res):
if res:
self.node_listview.add_lines([{'name': '', 'node': node_name}])
+ self.set_info_message('Node created')
+ else:
+ self.set_info_message('Node not created')
self.reset_help_message()
+ self.force_refresh()
if node_name:
- self.core.xmpp.plugin['xep_0060'].create_node(self.server, node_name)
+ self.core.xmpp.plugin['xep_0060'].create_node(self.server, node_name, callback=callback)
return True
def reset_help_message(self, txt=None):
@@ -336,7 +460,10 @@ class PubsubBrowserTab(tabs.Tab):
return
log.debug('Content: %s'%ET.tostring(selected_item.content))
entry = atom_parser.parse_atom_entry(selected_item.content)
- self.item_viewer._text = \
+ if not entry:
+ self.item_viewer._text = str(ET.tostring(selected_item.content))
+ else:
+ self.item_viewer._text = \
"""\x193Title:\x19o %(title)s
\x193Author:\x19o %(author_name)s (%(author_uri)s)
%(dates)s\x193Link:\x19o %(link)s
diff --git a/src/tabs.py b/src/tabs.py
index 8d4e6447..96a59621 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -1051,7 +1051,8 @@ class PrivateTab(ChatTab):
empty_before = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
self.input.do_command(key)
empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
- if self.core.get_tab_by_name(JID(self.get_room().name).bare, MucTab).get_room().joined:
+ tab = self.core.get_tab_by_name(JID(self.get_room().name).bare, MucTab)
+ if tab and tab.get_room().joined:
self.send_composing_chat_state(empty_before, empty_after)
return False