include forum in messages ID, and ability to create new topic

This commit is contained in:
Romain Bignon 2011-08-29 19:48:54 +02:00
commit b8c3501ff5
4 changed files with 104 additions and 29 deletions

View file

@ -24,10 +24,10 @@ from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.newsfeed import Newsfeed
from weboob.tools.value import Value, ValueInt, ValueBackendPassword
from weboob.tools.misc import limit
from weboob.capabilities.messages import ICapMessages, ICapMessagesPost, Message, Thread
from weboob.capabilities.messages import ICapMessages, ICapMessagesPost, Message, Thread, CantSendMessage
from .browser import PhpBB
from .tools import rssid, url2id, id2url
from .tools import rssid, url2id, id2url, id2topic
__all__ = ['PhpBBBackend']
@ -87,9 +87,9 @@ class PhpBBBackend(BaseBackend, ICapMessages, ICapMessagesPost):
thread = id
id = thread.id
thread_id = url2id(id) or id
thread_id = url2id(id, nopost=True) or id
try:
last_seen_id = self.storage.get('seen', default={})[url2id(thread_id)]
last_seen_id = self.storage.get('seen', default={})[id2topic(thread_id)]
except KeyError:
last_seen_id = 0
@ -135,11 +135,10 @@ class PhpBBBackend(BaseBackend, ICapMessages, ICapMessagesPost):
url = self.browser.get_root_feed_url()
for article in Newsfeed(url, rssid).iter_entries():
id = url2id(article.link)
thread_id, message_id = [int(v) for v in id.split('.')]
thread = Thread(thread_id)
thread = None
try:
last_seen_id = self.storage.get('seen', default={})[thread.id]
last_seen_id = self.storage.get('seen', default={})[id2topic(id)]
except KeyError:
last_seen_id = 0
@ -148,6 +147,8 @@ class PhpBBBackend(BaseBackend, ICapMessages, ICapMessagesPost):
if self.config['thread_unread_messages'].get() > 0:
iterator = limit(iterator, self.config['thread_unread_messages'].get())
for post in iterator:
if not thread:
thread = Thread('%s.%s' % (post.forum_id, post.topic_id))
message = self._post2message(thread, post)
if child:
@ -163,12 +164,12 @@ class PhpBBBackend(BaseBackend, ICapMessages, ICapMessagesPost):
def set_message_read(self, message):
try:
last_seen_id = self.storage.get('seen', default={})[message.thread.id]
last_seen_id = self.storage.get('seen', default={})[id2topic(message.thread.id)]
except KeyError:
last_seen_id = 0
if message.id > last_seen_id:
self.storage.set('seen', int(message.thread.id), message.id)
self.storage.set('seen', id2topic(message.thread.id), message.id)
self.storage.save()
def fill_thread(self, thread, fields):
@ -178,8 +179,20 @@ class PhpBBBackend(BaseBackend, ICapMessages, ICapMessagesPost):
def post_message(self, message):
assert message.thread
forum = 0
topic = 0
if message.thread:
try:
if '.' in message.thread.id:
forum, topic = [int(i) for i in message.thread.id.split('.', 1)]
else:
forum = int(message.thread.id)
except ValueError:
raise CantSendMessage('Thread ID must be in form "FORUM_ID[.TOPIC_ID]".')
with self.browser:
return self.browser.post_answer(message.thread.id if message.thread else 0,
return self.browser.post_answer(forum,
topic,
message.title,
message.content)

View file

@ -18,6 +18,7 @@
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
import re
import urllib
from urlparse import urlsplit
@ -28,6 +29,10 @@ from .pages.index import LoginPage
from .pages.forum import ForumPage, TopicPage, PostingPage
from .tools import id2url, url2id
__all__ = ['PhpBB']
# Browser
class PhpBB(BaseBrowser):
PAGES = {'https?://.*/index.php': ForumPage,
@ -93,7 +98,7 @@ class PhpBB(BaseBrowser):
parent = 0
while 1:
for post in self.page.iter_posts():
if post.id >= stop_id:
if stop_id and post.id >= stop_id:
return
post.parent = parent
@ -145,11 +150,39 @@ class PhpBB(BaseBrowser):
return post
def post_answer(self, topic, title, content):
if topic == 0:
raise CantSendMessage('Unable to create new topic for now')
def get_forums(self):
self.home()
return dict(self.page.iter_all_forums())
def post_answer(self, forum_id, topic_id, title, content):
if topic_id == 0:
if not forum_id:
forums = self.get_forums()
forums_prompt = 'Forums list:\n%s' % ('\n'.join(['\t- %s' % f for f in forums.itervalues()]))
m = re.match('\[(.*)\] (.*)', title or '')
if not m:
raise CantSendMessage('Please enter a title formatted like that:\n\t"[FORUM] SUBJECT"\n\n%s' % forums_prompt)
forum_id = None
for k,v in forums.iteritems():
if v.lower() == m.group(1).lower():
forum_id = k
break
if not forum_id:
raise CantSendMessage('Forum "%s" not found.\n\n%s' % (m.group(1), forums_prompt))
self.location('%s/posting.php?mode=post&f=%d' % (self.BASEPATH, forum_id))
assert self.is_on_page(PostingPage)
self.page.post(title, content)
assert self.is_on_page(PostingPage)
error = self.page.get_error_message()
if error:
raise CantSendMessage(u'Unable to send message: %s' % error)
else:
self.location('%s/%s' % (self.BASEPATH, id2url(topic)))
self.location('%s/%s' % (self.BASEPATH, id2url(topic_id)))
assert self.is_on_page(TopicPage)
self.page.go_reply()
@ -158,7 +191,7 @@ class PhpBB(BaseBrowser):
# Don't send title because it isn't needed in real use case
# and with monboob title is something like:
# Re: [Forum Name] Re: Topic Name
if title is not None and title.startswith('Re: '):
if title is not None and title.startswith('Re:'):
title = None
self.page.post(title, content)

View file

@ -67,10 +67,19 @@ class ForumPage(PhpBBPage):
link.nb_messages = int(li.cssselect('dd.posts')[0].text.strip()) + 1
yield link
def iter_all_forums(self):
for option in self.parser.select(self.document.getroot(), 'select#f', 1).findall('option'):
value = int(option.attrib['value'])
if value < 0 or not option.text:
continue
yield value, option.text.strip(u'» \xa0\n\r')
class Post(object):
def __init__(self, topic, id):
def __init__(self, forum_id, topic_id, id):
self.id = int(id)
self.topic = topic
self.forum_id = forum_id
self.topic_id = topic_id
self.title = u''
self.author = u''
self.date = None
@ -85,9 +94,14 @@ class TopicPage(PhpBBPage):
self.cur_page = int(strongs[0].text.strip())
self.tot_pages = int(strongs[1].text.strip())
v = urlsplit(self.url)
try:
url = self.parser.select(self.document.getroot(), 'h2 a', 1).attrib['href']
except BrokenPageError, e:
url = self.url
v = urlsplit(url)
args = parse_qs(v.query)
self.topic_id = int(args['t'][0])
self.forum_id = int(args['f'][0]) if 'f' in args else 0
self.forum_title = u''
nav = self.parser.select(self.document.getroot(), 'li.icon-home')
@ -143,15 +157,15 @@ class TopicPage(PhpBBPage):
profile = div.cssselect('dl.postprofile')[0]
id = div.attrib['id'][1:]
post = Post(self.topic_id, id)
post = Post(self.forum_id, self.topic_id, id)
title = u''
title_tags = body.cssselect('h3 a')
if len(title_tags) == 0:
title_tags = self.document.getroot().cssselect('h2 a')
if len(title_tags) == 0:
title = u''
self.logger.warning('Unable to parse title')
elif title_tags[0].text:
else:
title = title_tags[0].text.strip()
post.title = self.forum_title + title

View file

@ -24,13 +24,19 @@ from urlparse import urlsplit, parse_qs
from weboob.tools.misc import local2utc
def url2id(url):
def url2id(url, nopost=False):
v = urlsplit(url)
pagename = v.path.split('/')[-1]
args = parse_qs(v.query)
if pagename == 'viewforum.php':
return '%d' % int(args['f'][0])
if pagename == 'viewtopic.php':
s = '%d' % int(args['t'][0])
if 'p' in args:
if 'f' in args:
s = '%d' % int(args['f'][0])
else:
s = '0'
s += '.%d' % int(args['t'][0])
if 'p' in args and not nopost:
s += '.%d' % int(args['p'][0])
return s
@ -39,11 +45,20 @@ def url2id(url):
def id2url(id):
v = id.split('.')
if len(v) == 1:
return 'viewtopic.php?t=%d' % int(v[0])
return 'viewforum.php?f=%d' % int(v[0])
if len(v) == 2:
return 'viewtopic.php?t=%d&p=%d#p%d' % (int(v[0]),
int(v[1]),
int(v[1]))
return 'viewtopic.php?f=%d&t=%d' % (int(v[0]), int(v[1]))
if len(v) == 3:
return 'viewtopic.php?f=%d&t=%d&p=%d#p%d' % (int(v[0]),
int(v[1]),
int(v[2]),
int(v[2]))
def id2topic(id):
try:
return int(id.split('.')[1])
except IndexError:
return None
def rssid(id):
return id