#!/usr/bin/python2 # -*-coding:Latin-1 -* import MySQLdb import error import zones import db import html import cgi import re import urllib import os import urlparse import account def printthread(parent = 0): """ Écrit la liste des threads d'une zone dont le code est spécifié par zonecode. """ global db # zone = zones.Zone() # zone.loadFromCode(zonecode) # print '<h2>%s</h2>' % zone['name'] print '<div ' if parent != 0: print 'style="margin:0px 16px" ' opennewpage = 'false' else: opennewpage = 'true' print 'id="post%s"><img id="loader%s" src="ajaxload.gif" style="height:0px"/></div>' % (parent, parent) print '<script>load(readData, %s, \'loadreplies\', \'b\', %s)</script>' % (parent, opennewpage) # for thread in zone.loadthreads(zone = zone['code']): # print thread.printhtml() def loadReplies(parent = 0, index = 0, count = 42, zone = ''): """ Retourne les réponses à un post/thread spécifié par parent. index : début de la liste. range : nombre de réponses à charger. order : ordre des réponses. conditions : autres conditions, au format MySQL. """ global db parent = int(parent) posts = [] if parent == 0: order = 'last_post_timestamp DESC' else: order = 'timestamp ASC' request = 'SELECT * FROM posts' # if parent != 0: request += ' WHERE parent=%s' % int(parent) if zone != '': request += ' AND zone=\'%s\'' % zone request += ' ORDER BY %s' % order if count > 0: request += ' LIMIT %s, %s' % (index, count) dcursor = db.db.dcursor() dcursor.execute(request) rows = dcursor.fetchall() for row in rows: post = Post() post.loadFromRow(row) posts.append(post) return posts class Post: """ Représente un post. """ def __init__(self): """ Initialise le post. """ self._loaded = False self._data = {} self.replycount = None def testloaded(self, crashif=True): """ Indique si le post a été chargé, et arrête avec une erreur si la valeur chargée est la même que crashif. """ if crashif and self._loaded: raise error.SavhonError('Post already loaded.') elif crashif == False and self._loaded == False: raise error.SavhonError('Post not loaded.') def loadFromId(self, id): """ Charge le post en fonction de l'id spécifié. """ self.testloaded() dcursor = db.db.dcursor() dcursor.execute('SELECT * FROM posts WHERE id=\'%s\'', int(id)) row = dcursor.fetchone() self._data = row self._loaded = True def loadFromConditions(self, conditions): """ Charge le post qui répond aux conditions spécifiées au format MySQL. Seul le premier élément est chargé. """ self.testloaded() dcursor.execute('SELECT * FROM posts WHERE %s' % conditions) row = dcursor.fetchone() self._data = row self._loaded = True def loadFromRow(self, row): """ Charge le post depuis une liste de valeurs. """ self.testloaded() self._data = row self._loaded = True def printhtml(self, showmaindiv = True, opennewpage = False): """ Retourne le code HTML du post. """ self.testloaded(False) render = '' if showmaindiv: render += '<div class="post" id="post%s">' % self._data['id'] render += '<p onclick="' if opennewpage: render += 'window.location = \'?thread=%s\'' % self._data['id'] else: render += 'load(readData, %s, \'loadreplies\', \'%s\', false)' % (self._data['id'], self._data['zone']) render +='" id="postauthor%s" class="postauthor"><strong>%s</strong> (%s)' % (self._data['id'], cgi.escape(self._data['author']), self._data['timestamp']) render += ' <span style="float:right"><strong>' if self.replyCount() == 0: render += 'no replies</strong>' else: render += '%s ' % self.replyCount() if self.replyCount() == 1: render += 'reply' else: render += 'replies' if self.replyCount() != 0: render += '</strong> (%s)' % self._data['last_post_timestamp'] render += '</p>' render += '<div id="postcontent%s" class="postcontent">' % self._data['id'] render += '<img class="avatar" src="%s" style="float:left"/>' % account.avatar(self._data['author']) render += self.attachmentAsHtml() render += '<p class="postcontenttext">%s</p>' % cgi.escape(self._data['content']) render += '</div>' render += '<img id="loader%s" src="ajaxload.gif" style="height:0px"/>' % self._data['id'] if showmaindiv: render += '</div>' return render def __getitem__(self, index): """ Surcharge de l'opérateur []. Retourne la valeur du post, spécifiée par l'index. """ self._data[index] def replyCount(self, forcerefresh = False): self.testloaded(False) if self.replycount == None or forcerefresh: global db cursor = db.db.cursor() cursor.execute('SELECT COUNT(*) AS entries FROM posts WHERE parent=%s', int(self._data['id'])) row = cursor.fetchone() self.replycount = row[0] return self.replycount def attachmentAsHtml(self): self.testloaded(False) global db if self._data['attachment'] == '' or self._data['attachment'] == 'None': return '' ext = os.path.splitext(urlparse.urlparse(self._data['attachment'])[2])[1][1:] cursor = db.db.dcursor() cursor.execute('SELECT COUNT(*) AS entries, thumbnail_template FROM attachment_types WHERE extension=%s', (ext.lower())) row = cursor.fetchone() if row['entries'] == 0: thumbnail = '<img class="thumbnail" src="unknowntype.png"/>' else: thumbnail = re.sub('%u', self._data['attachment'], row['thumbnail_template']); return '<a href="%s">%s</a>' % (cgi.escape(self._data['attachment']), thumbnail)