• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

news4 - RSS aggrigation system


Commit MetaInfo

Révision04b45a09f84e27ebe0abbab369f7ee2d1ba7ae99 (tree)
l'heure2012-11-07 05:31:45
Auteurhylom <hylom@hylo...>
Commiterhylom

Message de Log

implement plugin system

Change Summary

Modification

--- a/css/gnews.css
+++ b/css/gnews.css
@@ -22,17 +22,21 @@ a {
2222 margin-bottom: 1em;
2323 }
2424 .entry-footer{
25- color: gray;
25+ color: #888;
2626 }
2727
2828 #site-header {
29- border-bottom: 1px solid gray;
29+ border-bottom: 1px solid #888;
3030 margin-bottom: 10px;
3131 }
3232
33+#site-header .last-update {
34+ color: #888;
35+}
36+
3337 #site-footer {
3438 margin-top: 10px;
35- color: gray;
39+ color: #888;
3640 text-align: center;
3741 }
3842
--- a/fetcher.py
+++ b/fetcher.py
@@ -21,7 +21,7 @@ class FeedFetcher(object):
2121 entry = {
2222 # 'title': e.title.decode('utf8') if isinstance(e.title, str) else e.title,
2323 'title': e.title,
24- 'link': e.link,
24+ 'url': e.link,
2525 'body': e.description,
2626 'date': dateutil.parser.parse(e.updated),
2727 'feed': self._feed,
--- a/gnews.py
+++ b/gnews.py
@@ -15,7 +15,6 @@ def main():
1515 "gnews's main function"
1616 # TODO: argv check
1717
18-
1918 # fetch RSS feed
2019 entries = []
2120 for feed in sources:
@@ -49,8 +48,14 @@ def main():
4948 for e in entries:
5049 log(e["date"])
5150
51+ call_plugin('pre_render', entries)
52+
5253 # do rendering
53- params = {'tags':tags, 'page':{}, 'sorted_tags':sorted_tags}
54+ params = {
55+ 'tags':tags,
56+ 'page':{},
57+ 'sorted_tags':sorted_tags
58+ }
5459
5560 # render index page
5661 do_rendering('index', 'index%s.html', entries, params)
@@ -61,6 +66,38 @@ def main():
6166 do_rendering('tags', tag + '%s.html', subentries, params)
6267
6368
69+def call_plugin(function_name, entries):
70+ "call plugin"
71+ for plugin in config['plugins']:
72+ mod = _get_plugin(plugin)
73+ f = mod.__getattribute__(function_name)
74+ f(entries)
75+
76+class PluginError(Exception):
77+ def __init__(self, value):
78+ self.value = value
79+ def __str__(self):
80+ return 'plugin "' + self.value + '" is not found.'
81+
82+def _get_plugin(plugin_name):
83+ 'load plugin by config settings'
84+
85+ # fallback when filter isn't defined
86+ if plugin_name is None:
87+ return lambda x:x
88+
89+ # import module
90+ mods = __import__(config['plugin_directory'],
91+ globals(),
92+ locals(),
93+ [plugin_name,])
94+ try:
95+ mod = mods.__getattribute__(plugin_name)
96+ except AttributeError:
97+ raise PluginError(plugin_name)
98+
99+ return mod
100+
64101
65102 def do_rendering(page_type, filename, entries, params):
66103 "rendering page"
--- /dev/null
+++ b/plugins/hatebu_counter.py
@@ -0,0 +1,40 @@
1+#!/usr/bin/python
2+# -*- coding: utf-8
3+'plugin for hatena bookmark counter'
4+
5+#from __future__ import with_statement
6+
7+import xmlrpclib
8+import datetime
9+import time
10+import sys
11+
12+# see http://d.hatena.ne.jp/keyword/%a4%cf%a4%c6%a4%ca%a5%d6%a5%c3%a5%af%a5%de%a1%bc%a5%af%b7%ef%bf%f4%bc%e8%c6%c0API?kid=146686
13+
14+urls = []
15+counts = {}
16+
17+def pre_fetch():
18+ pass
19+
20+def pre_tag_aggregate(entries):
21+ pass
22+
23+def pre_render(entries):
24+ counts = []
25+ for i in range(0, len(entries), 50):
26+ urls = [x['url'] for x in entries[i:i+50]]
27+ c = _get_count(urls)
28+ for j in range(0, len(c)):
29+ entries[i+j]['url'] = c[j]
30+
31+def pre_quit(entries):
32+ pass
33+
34+def _get_count(urls):
35+ # urls can have max 50 items
36+ uri = "http://b.hatena.ne.jp/xmlrpc"
37+ server = xmlrpclib.ServerProxy(uri)
38+ t = server.bookmark.getCount(*urls)
39+ return t
40+
--- a/renderer.py
+++ b/renderer.py
@@ -12,7 +12,6 @@ from propertizer import propertize
1212 from logger import log
1313
1414 def date_format(date):
15- #dt = dateutil.parser.parse(date)
1615 return date.strftime('%Y/%m/%d %H:%M')
1716
1817 class Renderer(object):
@@ -41,6 +40,7 @@ class Renderer(object):
4140 'site': config['site_parameter'],
4241 'sources': self._sources,
4342 }
43+ kwargs['site']['last_update'] = datetime.datetime.utcnow()
4444 for key in kwargs:
4545 d = propertize(kwargs[key])
4646 kwargs[key] = d
--- a/templates/index.tmpl.html
+++ b/templates/index.tmpl.html
@@ -12,14 +12,17 @@
1212 <div class="container">
1313
1414 <!-- タイトル -->
15- <div class="row">
16- <div class="span12">
17- <header id="site-header">
15+ <div class="row" id="site-header">
16+ <div class="span9">
17+ <header>
1818 <a href="${site.root}">
1919 <img id="sitelogo" src="${site.img_directory}/themesjp.png" alt="Themes.JP"> α
2020 </a>
2121 </header>
2222 </div>
23+ <div class="span3 last-update">
24+ last update: ${date_format(site.last_update)}
25+ </div>
2326 </div>
2427
2528 <!-- コンテンツ本体 -->
@@ -50,7 +53,7 @@
5053 <img class="thumbnail" src="${entry.images[0]}">
5154 % endif
5255 <h3>
53- <a href='${entry.link}' target="_blank_">${entry.title}</a>
56+ <a href='${entry.url}' target="_blank_">${entry.title}</a>
5457 </h3>
5558 </div>
5659
@@ -63,7 +66,7 @@
6366 <!-- フッタ -->
6467 <div class="entry-footer">
6568 <div class="entry-continue">
66- <a href='${entry.link}'>[続きを読む]</a>
69+ <a href='${entry.url}'>[続きを読む]</a>
6770 </div>
6871 <div class="information">
6972 <span>情報元:<a href='${entry.feed.url}'>${entry.feed.name}</a></span>