]>
Commit | Line | Data |
---|---|---|
940227cb MT |
1 | #!/usr/bin/python |
2 | ||
27066195 | 3 | import re |
940227cb | 4 | import textile |
27066195 MT |
5 | import tornado.database |
6 | import unicodedata | |
940227cb MT |
7 | |
8 | from accounts import Accounts | |
9 | from databases import Databases | |
10 | ||
11 | from misc import Singleton | |
12 | ||
13 | class PlanetEntry(object): | |
27066195 MT |
14 | def __init__(self, entry=None): |
15 | if entry: | |
16 | self.__entry = entry | |
17 | else: | |
18 | self.__entry = tornado.database.Row({ | |
19 | "id" : None, | |
20 | "title" : "", | |
21 | "markdown" : "", | |
22 | }) | |
23 | ||
24 | def set(self, key, val): | |
25 | self.__entry[key] = val | |
26 | ||
27 | @property | |
28 | def planet(self): | |
29 | return Planet() | |
940227cb MT |
30 | |
31 | @property | |
32 | def id(self): | |
33 | return self.__entry.id | |
34 | ||
35 | @property | |
36 | def slug(self): | |
37 | return self.__entry.slug | |
38 | ||
39 | @property | |
40 | def title(self): | |
41 | return self.__entry.title | |
42 | ||
43 | @property | |
44 | def published(self): | |
45 | return self.__entry.published | |
46 | ||
cc3b928d MT |
47 | @property |
48 | def year(self): | |
49 | return self.published.year | |
50 | ||
51 | @property | |
52 | def month(self): | |
53 | return self.published.month | |
54 | ||
940227cb MT |
55 | @property |
56 | def updated(self): | |
57 | return self.__entry.updated | |
58 | ||
59 | @property | |
60 | def markdown(self): | |
61 | return self.__entry.markdown | |
62 | ||
63 | @property | |
64 | def abstract(self): | |
65 | return self.render(self.markdown, 400) | |
66 | ||
67 | def render(self, text, limit=0): | |
27066195 | 68 | return self.planet.render(text, limit) |
940227cb MT |
69 | |
70 | @property | |
71 | def text(self): | |
72 | return self.render(self.markdown) | |
73 | ||
74 | @property | |
75 | def author(self): | |
76 | return Accounts().search(self.__entry.author_id) | |
77 | ||
78 | ||
79 | class Planet(object): | |
80 | __metaclass__ = Singleton | |
81 | ||
82 | @property | |
83 | def db(self): | |
84 | return Databases().webapp | |
85 | ||
86 | def get_authors(self): | |
87 | authors = [] | |
88 | for author in self.db.query("SELECT DISTINCT author_id FROM planet"): | |
89 | author = Accounts().search(author.author_id) | |
90 | if author: | |
91 | authors.append(author) | |
92 | ||
27066195 | 93 | return sorted(authors) |
940227cb | 94 | |
cc3b928d MT |
95 | def get_years(self): |
96 | res = self.db.query("SELECT DISTINCT YEAR(published) AS year \ | |
97 | FROM planet ORDER BY year DESC") | |
98 | ||
99 | return [row.year for row in res] | |
100 | ||
940227cb MT |
101 | def get_entry_by_slug(self, slug): |
102 | entry = self.db.get("SELECT * FROM planet WHERE slug = %s", slug) | |
103 | if entry: | |
104 | return PlanetEntry(entry) | |
105 | ||
27066195 MT |
106 | def get_entry_by_id(self, id): |
107 | entry = self.db.get("SELECT * FROM planet WHERE id = %s", id) | |
108 | if entry: | |
109 | return PlanetEntry(entry) | |
110 | ||
940227cb MT |
111 | def _limit_and_offset_query(self, limit=None, offset=None): |
112 | query = " " | |
113 | ||
114 | if limit: | |
115 | if offset: | |
116 | query += "LIMIT %d,%d" % (offset, limit) | |
117 | else: | |
118 | query += "LIMIT %d" % limit | |
119 | ||
120 | return query | |
121 | ||
122 | def get_entries(self, limit=3, offset=None): | |
14624b27 | 123 | query = "SELECT * FROM planet WHERE acknowledged='Y' ORDER BY published DESC" |
940227cb MT |
124 | |
125 | # Respect limit and offset | |
126 | query += self._limit_and_offset_query(limit=limit, offset=offset) | |
127 | ||
128 | entries = [] | |
129 | for entry in self.db.query(query): | |
130 | entries.append(PlanetEntry(entry)) | |
131 | ||
132 | return entries | |
133 | ||
134 | def get_entries_by_author(self, author_id, limit=None, offset=None): | |
135 | query = "SELECT * FROM planet WHERE author_id = '%s'" % author_id | |
14624b27 | 136 | query += " AND acknowledged='Y' ORDER BY published DESC" |
940227cb MT |
137 | |
138 | # Respect limit and offset | |
139 | query += self._limit_and_offset_query(limit=limit, offset=offset) | |
140 | ||
940227cb MT |
141 | entries = self.db.query(query) |
142 | ||
143 | return [PlanetEntry(e) for e in entries] | |
27066195 | 144 | |
cc3b928d MT |
145 | def get_entries_by_year(self, year): |
146 | entries = self.db.query("SELECT * FROM planet \ | |
147 | WHERE YEAR(published) = %s ORDER BY published DESC", year) | |
148 | ||
149 | return [PlanetEntry(e) for e in entries] | |
150 | ||
27066195 MT |
151 | def render(self, text, limit=0): |
152 | if limit and len(text) >= limit: | |
153 | text = text[:limit] + "..." | |
154 | return textile.textile(text) | |
155 | ||
156 | def _generate_slug(self, title): | |
157 | slug = unicodedata.normalize("NFKD", title).encode("ascii", "ignore") | |
158 | slug = re.sub(r"[^\w]+", " ", slug) | |
159 | slug = "-".join(slug.lower().strip().split()) | |
160 | ||
161 | if not slug: | |
162 | slug = "entry" | |
163 | ||
164 | while True: | |
165 | e = self.db.get("SELECT * FROM planet WHERE slug = %s", slug) | |
166 | if not e: | |
167 | break | |
168 | slug += "-" | |
169 | ||
170 | return slug | |
171 | ||
172 | def update_entry(self, entry): | |
173 | self.db.execute("UPDATE planet SET title = %s, markdown = %s WHERE id = %s", | |
174 | entry.title, entry.markdown, entry.id) | |
175 | ||
176 | def save_entry(self, entry): | |
177 | slug = self._generate_slug(entry.title) | |
178 | ||
179 | self.db.execute("INSERT INTO planet(author_id, title, slug, markdown, published) " | |
180 | "VALUES(%s, %s, %s, %s, UTC_TIMESTAMP())", entry.author.uid, entry.title, | |
181 | slug, entry.markdown) | |
182 | ||
2bdd073f MT |
183 | def search(self, what): |
184 | entries = self.db.query("SELECT *, MATCH(markdown, title) AGAINST(%s) AS score \ | |
185 | FROM planet WHERE MATCH(markdown, title) AGAINST(%s) ORDER BY score DESC", what, what) | |
186 | ||
187 | return [PlanetEntry(e) for e in entries] |