PageRenderTime 36ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/phpbb/module.py

https://gitlab.com/phyks/weboob
Python | 196 lines | 171 code | 8 blank | 17 comment | 1 complexity | 46dfd797a2d236daea0743d06fd16638 MD5 | raw file
  1. # -*- coding: utf-8 -*-
  2. # Copyright(C) 2010-2011 Romain Bignon
  3. #
  4. # This file is part of weboob.
  5. #
  6. # weboob is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU Affero General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # weboob is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU Affero General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Affero General Public License
  17. # along with weboob. If not, see <http://www.gnu.org/licenses/>.
  18. from weboob.tools.backend import Module, BackendConfig
  19. from weboob.tools.newsfeed import Newsfeed
  20. from weboob.tools.value import Value, ValueInt, ValueBackendPassword
  21. from weboob.tools.misc import limit
  22. from weboob.capabilities.messages import CapMessages, CapMessagesPost, Message, Thread, CantSendMessage
  23. from .browser import PhpBB
  24. from .tools import rssid, url2id, id2url, id2topic
  25. __all__ = ['PhpBBModule']
  26. class PhpBBModule(Module, CapMessages, CapMessagesPost):
  27. NAME = 'phpbb'
  28. MAINTAINER = u'Romain Bignon'
  29. EMAIL = 'romain@weboob.org'
  30. VERSION = '1.3'
  31. LICENSE = 'AGPLv3+'
  32. DESCRIPTION = "phpBB forum"
  33. CONFIG = BackendConfig(Value('url', label='URL of forum', regexp='https?://.*'),
  34. Value('username', label='Username', default=''),
  35. ValueBackendPassword('password', label='Password', default=''),
  36. ValueInt('thread_unread_messages', label='Limit number of unread messages to retrieve for a thread', default=500)
  37. )
  38. STORAGE = {'seen': {}}
  39. BROWSER = PhpBB
  40. def create_default_browser(self):
  41. username = self.config['username'].get()
  42. if len(username) > 0:
  43. password = self.config['password'].get()
  44. else:
  45. password = None
  46. return self.create_browser(self.config['url'].get(),
  47. username, password)
  48. #### CapMessages ##############################################
  49. def _iter_threads(self, root_link=None):
  50. with self.browser:
  51. links = list(self.browser.iter_links(root_link.url if root_link else None))
  52. for link in links:
  53. if link.type == link.FORUM:
  54. link.title = '%s[%s]' % (root_link.title if root_link else '', link.title)
  55. for thread in self._iter_threads(link):
  56. yield thread
  57. if link.type == link.TOPIC:
  58. thread = Thread(url2id(link.url))
  59. thread.title = ('%s ' % root_link.title if root_link else '') + link.title
  60. thread.date = link.date
  61. thread.flags = thread.IS_DISCUSSION
  62. yield thread
  63. def iter_threads(self):
  64. return self._iter_threads()
  65. def get_thread(self, id):
  66. thread = None
  67. parent = None
  68. if isinstance(id, Thread):
  69. thread = id
  70. id = thread.id
  71. thread_id = url2id(id, nopost=True) or id
  72. try:
  73. last_seen_id = self.storage.get('seen', default={})[id2topic(thread_id)]
  74. except KeyError:
  75. last_seen_id = 0
  76. with self.browser:
  77. for post in self.browser.iter_posts(id):
  78. if not thread:
  79. thread = Thread(thread_id)
  80. thread.title = post.title
  81. m = self._post2message(thread, post)
  82. m.parent = parent
  83. if last_seen_id < post.id:
  84. m.flags |= Message.IS_UNREAD
  85. if parent:
  86. parent.children = [m]
  87. else:
  88. thread.root = m
  89. parent = m
  90. return thread
  91. def _post2message(self, thread, post):
  92. signature = post.signature
  93. if signature:
  94. signature += '<br />'
  95. signature += 'URL: %s' % self.browser.absurl(id2url('%s.%s' % (thread.id, post.id)))
  96. return Message(thread=thread,
  97. id=post.id,
  98. title=post.title,
  99. sender=post.author,
  100. receivers=None,
  101. date=post.date,
  102. parent=None,
  103. content=post.content,
  104. signature=signature,
  105. children=[],
  106. flags=Message.IS_HTML)
  107. def iter_unread_messages(self):
  108. with self.browser:
  109. url = self.browser.get_root_feed_url()
  110. for article in Newsfeed(url, rssid).iter_entries():
  111. id = url2id(article.link)
  112. thread = None
  113. try:
  114. last_seen_id = self.storage.get('seen', default={})[id2topic(id)]
  115. except KeyError:
  116. last_seen_id = 0
  117. child = None
  118. iterator = self.browser.riter_posts(id, last_seen_id)
  119. if self.config['thread_unread_messages'].get() > 0:
  120. iterator = limit(iterator, self.config['thread_unread_messages'].get())
  121. for post in iterator:
  122. if not thread:
  123. thread = Thread('%s.%s' % (post.forum_id, post.topic_id))
  124. message = self._post2message(thread, post)
  125. if child:
  126. message.children.append(child)
  127. child.parent = message
  128. if post.parent:
  129. message.parent = Message(thread=thread,
  130. id=post.parent)
  131. else:
  132. thread.root = message
  133. yield message
  134. def set_message_read(self, message):
  135. try:
  136. last_seen_id = self.storage.get('seen', default={})[id2topic(message.thread.id)]
  137. except KeyError:
  138. last_seen_id = 0
  139. if message.id > last_seen_id:
  140. self.storage.set('seen', id2topic(message.thread.id), message.id)
  141. self.storage.save()
  142. def fill_thread(self, thread, fields):
  143. return self.get_thread(thread)
  144. #### CapMessagesReply #########################################
  145. def post_message(self, message):
  146. assert message.thread
  147. forum = 0
  148. topic = 0
  149. if message.thread:
  150. try:
  151. if '.' in message.thread.id:
  152. forum, topic = [int(i) for i in message.thread.id.split('.', 1)]
  153. else:
  154. forum = int(message.thread.id)
  155. except ValueError:
  156. raise CantSendMessage('Thread ID must be in form "FORUM_ID[.TOPIC_ID]".')
  157. with self.browser:
  158. return self.browser.post_answer(forum,
  159. topic,
  160. message.title,
  161. message.content)
  162. OBJECTS = {Thread: fill_thread}