/mobile/forums.py
Python | 193 lines | 150 code | 12 blank | 31 comment | 13 complexity | e1b756325b62936919cc2861a0ea3041 MD5 | raw file
Possible License(s): BSD-3-Clause
- #!/usr/bin/env python
- # -*- coding: utf8 -*-
- ###
- # Copyright (c) 2011, Alexandre `Zopieux` Macabies
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- #
- # * Redistributions of source code must retain the above copyright notice,
- # this list of conditions, and the following disclaimer.
- # * Redistributions in binary form must reproduce the above copyright notice,
- # this list of conditions, and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- # * Neither the name of the author of this software nor the name of
- # contributors to this software may be used to endorse or promote products
- # derived from this software without specific prior written consent.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- # POSSIBILITY OF SUCH DAMAGE.
- ###
- import re
- from annoying.decorators import render_to
- from sdzmoar.common.utils import *
- regex_forumid = re.compile(r'forum\-81\-(?P<id>\d+)', re.I)
- regex_topicid = re.compile(r'forum\-83\-(?P<id>\d+)', re.I)
- def _index():
- soup = get_soup_or_404('http://www.siteduzero.com/forum.html', timeout=Times.month)
- categories = []
- tmpcatname = None
- tmpforums = []
- for elem in soup.findall('//table[@class="liste_cat"]/tbody/tr'):
- if elem.get('class') == 'grosse_cat':
- if tmpforums:
- categories.append({'name': tmpcatname, 'forums': tmpforums})
- tmpforums = []
- tmpcatname = clean_text(elem.find('td/a').text)
- else:
- url = elem.find('td[@class="nom_forum"]/a').get('href')
- name = clean_text(elem.find('td[@class="nom_forum"]/a').text)
- try:
- description = clean_text(elem.find('td[@class="nom_forum"]/span').text)
- except AttributeError:
- description = None
- parsed = regex_forumid.search(url)
- if parsed is None:
- tmpforums.append({
- 'redirection': url,
- 'name': name,
- 'description': description,
- })
- else:
- tmpforums.append({
- 'id': parsed.group('id'),
- 'name': name,
- 'description': description,
- 'count_topics': clean_int(elem.find('td[3]').text),
- 'count_messages': clean_int(elem.find('td[4]').text),
- })
- # final item
- if tmpforums:
- categories.append({'name': tmpcatname, 'forums': tmpforums})
- return {'categories': categories}
- @render_to('mobile/forums/index.html')
- def index(request):
- return _index()
- def _category(id, page=None):
- if page is None: # handles reversed page order
- url = 'http://www.siteduzero.com/forum-81-%s.html' % id
- else:
- url = 'http://www.siteduzero.com/forum-81-%s-p%i.html' % (id, page)
- soup = get_soup_or_404(url, timeout=Times.day)
- title = clean_text(soup.find('//h1').text)
- topics = []
- for elem in soup.findall('//table[@class="liste_cat"]/tbody/tr'):
- if u'postit' in elem.get('class', ''):
- continue
- meta = elem.find('td[2]')
- subtitle = elem.find('td[3]/span')
- moved = meta.find(u'img[@alt="Déplacé"]') is not None
- if subtitle is not None:
- subtitle = clean_text(subtitle.text)
- res = {
- 'id': regex_topicid.search(elem.find('td[3]/a').get('href')).group('id'),
- 'title': clean_text(elem.find('td[3]/a').text),
- 'created_on': sdz_datetime(elem.find('td[3]/a').get('title')[6:]), # Cree <date>
- 'subtitle': subtitle,
- 'author': sdz_member(elem.find('td[5]/a')),
- 'moved': moved,
- }
- if not moved:
- res.update({
- 'postit': meta.find(u'img[@alt="Post-it"]') is not None,
- 'closed': meta.find(u'img[@alt="Fermé"]') is not None,
- 'solved': meta.find(u'img[@alt="Résolu"]') is not None,
- 'messages': clean_int(elem.find('td[6]').text),
- })
- topics.append(res)
- pager = SdzPager.fromHtml(soup.find('//table[@class="liste_cat"]'))
- return {'topics': topics, 'pager': pager, 'title': title}
- @render_to('mobile/forums/category.html')
- def category(request, id):
- page = get_page(request, default=None)
- return _category(id, page)
- def _topic(id, page=None):
- soup = get_soup_or_404('http://www.siteduzero.com/forum-83-%s-p%i.html' % (id, page), timeout=10 * Times.minute)
- topic_title = clean_text(soup.find('//h1').text)
- messages = []
- tempmeta = {}
- for elem in soup.findall('//table[@class="liste_messages"]/tbody/tr'):
- if 'header_message' in elem.get('class', ''):
- author = sdz_member(elem.find('td[1]//a'))
- if clean_text(elem.find('td[2]//span/a').tail).lower().startswith(u'message supprimé'):
- reason = clean_text(elem.find('td[2]//span/em').text)
- messages.append({
- 'author': author,
- 'deleted': True,
- 'deleted_self': reason.lower() == u"cette réponse a été supprimée par l'utilisateur",
- 'deletion_reason': reason,
- })
- else:
- tempmeta = {
- 'author': author,
- 'posted_on': sdz_datetime(clean_text(elem.find('td[2]//span/a').tail)[6:]), # Posté <date>
- }
- else:
- res = {}
- message_td = elem.find('td[2]')
- helping_answer = message_td.get('class') == 'message_bonne_reponse'
- content = message_td.find('div[@class="boite_message"]')
- if helping_answer:
- notice_help = content.find('div[@class="info_bonne_reponse"]')
- content.remove(notice_help) # helping_answer bool is enough...
- edition = content.find('div[@class="message_edite"]')
- if edition is not None:
- span = edition.find('span')
- edition_by_other = span is not None
- if edition_by_other:
- parent = span
- else:
- parent = edition
- edition_author = sdz_member(parent.find('a'))
- date_edition = sdz_datetime(clean_text(parent.text)[6:-3].strip())
- content.remove(edition)
- res['edition_author'] = edition_author
- res['date_edition'] = date_edition
- res['edition_by_other'] = edition_by_other
- sig = content.find('div[@class="signature"]')
- if sig is not None:
- content.remove(sig)
- res['content'] = zcode_parser(html_string(content))
- res['helping'] = helping_answer
- res.update(tempmeta)
- messages.append(res)
- pager = SdzPager.fromHtml(soup.find('//table[@class="liste_messages"]'))
- return {'messages': messages, 'pager': pager, 'topic_title': topic_title}
- @render_to('mobile/forums/topic.html')
- def topic(request, id):
- page = get_page(request)
- return _topic(id, page)