]>
git.ipfire.org Git - ipfire.org.git/blob - webapp/backend/planet.py
8 from misc
import Object
10 class PlanetEntry(Object
):
11 def __init__(self
, backend
, data
):
12 Object
.__init
__(self
, backend
)
16 def __cmp__(self
, other
):
17 return cmp(self
.published
, other
.published
)
27 def set_title(self
, title
):
28 if self
.title
== title
:
31 self
.db
.execute("UPDATE planet SET title = %s WHERE id = %s", title
, self
.id)
32 self
.data
["title"] = title
34 title
= property(lambda s
: s
.data
.title
, set_title
)
38 return "https://planet.ipfire.org/post/%s" % self
.slug
40 def set_published(self
, published
):
41 if self
.published
== published
:
44 self
.db
.execute("UPDATE planet SET published = %s WHERE id = %s",
46 self
.data
["published"] = published
48 published
= property(lambda s
: s
.data
.published
, set_published
)
52 return self
.published
.year
56 return self
.published
.month
60 return self
.data
.updated
62 def get_markdown(self
):
63 return self
.data
.markdown
65 def set_markdown(self
, markdown
):
66 if self
.markdown
== markdown
:
69 markup
= self
.render(markdown
)
70 self
.db
.execute("UPDATE planet SET markdown = %s, markup = %s WHERE id = %s",
71 markdown
, markup
, self
.id)
74 "markdown" : markdown
,
78 markdown
= property(get_markdown
, set_markdown
)
83 return self
.data
.markup
85 return self
.render(self
.markdown
)
89 return self
.render(self
.markdown
, 400)
91 def render(self
, text
, limit
=0):
92 return self
.planet
.render(text
, limit
)
101 if not hasattr(self
, "_author"):
102 self
._author
= self
.accounts
.get_by_uid(self
.data
.author_id
)
106 def set_status(self
, status
):
107 if self
.status
== status
:
110 self
.db
.execute("UPDATE planet SET status = %s WHERE id = %s", status
, self
.id)
111 self
.data
["status"] = status
113 status
= property(lambda s
: s
.data
.status
, set_status
)
116 return self
.status
== "draft"
118 def is_published(self
):
119 return self
.status
== "published"
121 def count_view(self
, referer
=None, location
=None):
122 self
.db
.execute("INSERT INTO planet_views(post_id, referer, location) \
123 VALUES(%s, %s, %s)", self
.id, referer
, location
)
125 if hasattr(self
, "_views"):
130 if not hasattr(self
, "_views"):
131 res
= self
.db
.get("SELECT COUNT(*) AS views FROM planet_views \
132 WHERE post_id = %s", self
.id)
134 self
._views
= res
.views
139 class Planet(Object
):
140 def get_authors(self
):
141 query
= self
.db
.query("SELECT DISTINCT author_id FROM planet WHERE status = %s \
142 AND published IS NOT NULL AND published <= NOW()", "published")
146 author
= self
.accounts
.search(author
.author_id
)
148 authors
.append(author
)
150 return sorted(authors
)
153 res
= self
.db
.query("SELECT DISTINCT EXTRACT(YEAR FROM published)::integer AS year \
154 FROM planet WHERE status = %s ORDER BY year DESC", "published")
156 return [row
.year
for row
in res
]
158 def get_entry_by_slug(self
, slug
):
159 entry
= self
.db
.get("SELECT * FROM planet WHERE slug = %s", slug
)
162 return PlanetEntry(self
.backend
, entry
)
164 def get_entry_by_id(self
, id):
165 entry
= self
.db
.get("SELECT * FROM planet WHERE id = %s", id)
168 return PlanetEntry(self
.backend
, entry
)
170 def get_entries(self
, limit
=3, offset
=None, status
="published", author_id
=None):
171 query
= "SELECT * FROM planet"
172 args
, clauses
= [], []
175 clauses
.append("status = %s")
178 if status
== "published":
179 clauses
.append("published <= NOW()")
182 clauses
.append("author_id = %s")
183 args
.append(author_id
)
186 query
+= " WHERE %s" % " AND ".join(clauses
)
188 query
+= " ORDER BY published DESC"
190 # Respect limit and offset
196 query
+= " OFFSET %s"
200 for entry
in self
.db
.query(query
, *args
):
201 entry
= PlanetEntry(self
.backend
, entry
)
202 entries
.append(entry
)
206 def get_entries_by_author(self
, author_id
, limit
=None, offset
=None):
207 return self
.get_entries(limit
=limit
, offset
=offset
, author_id
=author_id
)
209 def get_entries_by_year(self
, year
):
210 entries
= self
.db
.query("SELECT * FROM planet \
211 WHERE status = %s AND EXTRACT(YEAR FROM published) = %s \
212 ORDER BY published DESC", "published", year
)
214 return [PlanetEntry(self
.backend
, e
) for e
in entries
]
216 def get_hot_entries(self
, days
=30, limit
=8):
217 entries
= self
.db
.query("WITH hottest AS (SELECT post_id, COUNT(post_id) AS count \
218 FROM planet_views WHERE \"when\" >= NOW() - INTERVAL '%s days' \
219 GROUP BY post_id ORDER BY count DESC) SELECT * FROM planet \
220 LEFT JOIN hottest ON planet.id = hottest.post_id \
221 WHERE hottest.count IS NOT NULL \
222 ORDER BY hottest.count DESC LIMIT %s",
225 return [PlanetEntry(self
.backend
, e
) for e
in entries
]
227 def render(self
, text
, limit
=0):
228 if limit
and len(text
) >= limit
:
229 text
= text
[:limit
] + "..."
231 return textile
.textile(text
)
233 def _generate_slug(self
, title
):
234 slug
= unicodedata
.normalize("NFKD", title
).encode("ascii", "ignore")
235 slug
= re
.sub(r
"[^\w]+", " ", slug
)
236 slug
= "-".join(slug
.lower().strip().split())
242 e
= self
.db
.get("SELECT * FROM planet WHERE slug = %s", slug
)
249 def create(self
, title
, markdown
, author
, status
="published", published
=None):
250 slug
= self
._generate
_slug
(title
)
251 markup
= self
.render(markdown
)
253 if published
is None:
254 published
= datetime
.datetime
.utcnow()
256 id = self
.db
.execute("INSERT INTO planet(author_id, slug, title, status, \
257 markdown, markup, published) VALUES(%s, %s, %s, %s, %s, %s, %s) RETURNING id",
258 author
.uid
, slug
, title
, status
, markdown
, markup
, published
)
261 return self
.get_entry_by_id(id)
263 def update_entry(self
, entry
):
264 self
.db
.execute("UPDATE planet SET title = %s, markdown = %s WHERE id = %s",
265 entry
.title
, entry
.markdown
, entry
.id)
267 def save_entry(self
, entry
):
268 slug
= self
._generate
_slug
(entry
.title
)
270 id = self
.db
.execute("INSERT INTO planet(author_id, title, slug, markdown, published) \
271 VALUES(%s, %s, %s, %s, NOW())", entry
.author
.uid
, entry
.title
, slug
, entry
.markdown
)
275 def search(self
, what
):
276 res
= self
.db
.query("WITH \
277 q AS (SELECT plainto_tsquery(%s, %s) AS query), \
278 ranked AS (SELECT id, query, ts_rank_cd(to_tsvector(%s, markdown), query) AS rank \
279 FROM planet, q WHERE markdown @@ query ORDER BY rank DESC) \
280 SELECT *, ts_headline(markup, ranked.query, 'MinWords=100, MaxWords=110') AS markup FROM planet \
281 JOIN ranked ON planet.id = ranked.id \
282 WHERE status = %s AND published IS NOT NULL AND published <= NOW() \
283 ORDER BY ranked DESC LIMIT 25",
284 "english", what
, "english", "published")
286 return [PlanetEntry(self
.backend
, e
) for e
in res
]