8 import wsgiref.simple_server
9 from tinydb import TinyDB,Query,where
10 from tinydb.operations import delete
11 from datetime import datetime
13 class BaseHandler(tornado.web.RequestHandler):
14 def get_current_user(self):
15 user = self.get_secure_cookie('admin_user')
16 return tornado.escape.utf8(user)
18 def set_current_user(self,username):
19 self.set_secure_cookie('admin_user',username)
21 def clear_current_user(self):
22 self.clear_cookie('admin_user')
24 class IndexHandler(BaseHandler):
25 def get(self,dbname,page='0'):
26 params = self.application.db.get(where('kinds') == 'conf')
27 if params['mentenance'] == True:
28 self.render('mentenance.htm',title=params['title'],db=dbname)
29 if self.application.collection(dbname) == False:
30 if self.current_user == b'admin':
31 self.application.db.table(dbname)
33 raise tornado.web.HTTPError(404)
36 na = tornado.escape.url_unescape(self.get_cookie("username",u"誰かさん"))
37 pos = self.application.gpos(dbname,page)
38 table = self.application.db.table(dbname)
44 rec = sorted(table.all(),key=lambda x: x['number'])[start:start+i]
45 if len(table) >= 10*i:
46 self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)
48 self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname)
50 class LoginHandler(BaseHandler):
52 self.render('login.htm')
55 pw = self.application.db.get(where('kinds') == 'conf')
56 if self.get_argument('password') == pw['password']:
57 self.set_current_user('admin')
58 dbname = self.get_argument('record')
59 self.redirect('/'+dbname+'/admin/0/')
61 class LogoutHandler(BaseHandler):
63 self.clear_current_user()
64 self.redirect('/login')
66 class NaviHandler(tornado.web.RequestHandler):
68 self.render('top.htm',coll=sorted(self.name()),full=self.full)
71 for x in self.application.db.tables():
75 def full(self,dbname):
76 if dbname in self.application.db.tables():
77 i = 10*self.application.db.get(where('kinds') == 'conf')['count']
78 table = self.application.db.table(dbname)
83 class TitleHandler(NaviHandler):
85 rec = sorted(self.title(),key=lambda x: x['date2'])
86 self.render('title.htm',coll=rec,full=self.full)
92 table = self.application.db.table(x)
95 if table.contains(where('number') == 1) == True:
96 s = table.get(where('number') == 1)['title']
104 rec = sorted(table.all(),key=lambda k: k['number'])
107 i = datetime.strptime(s,'%Y/%m/%d %H:%M')
108 year = datetime.now().year-i.year
115 item['date2'] = j+31*(i.month-1)+i.day
118 class RegistHandler(tornado.web.RequestHandler):
119 def post(self,dbname):
120 if self.application.collection(dbname) == False:
121 raise tornado.web.HTTPError(404)
123 rec = self.application.db.get(where('kinds') == 'conf')
124 words = rec['bad_words']
125 out = rec['out_words']
126 na = self.get_argument('name')
127 sub = self.get_argument('title')
128 com = self.get_argument('comment')
134 error = error + u'禁止ワード.'
136 for line in com.splitlines(True):
138 if word in line.lower():
139 error = error + u'タグ違反.('+word+')'
141 text = text+'<p>'+self.link(line)+'<br></p>'
142 pw = self.get_argument('password')
144 error = error + u'本文がありません.'
146 error = error +u'文字数が1,000をこえました.'
151 article = self.application.db.table(dbname)
152 if len(article) == 0:
155 item = sorted(article.all(),key=lambda x: x['number'])[len(article)-1]
156 no = item['number']+1
159 reg = {'number':no,'name':na,'title':sub,'comment':text,'raw':com,'password':pw,'date':s.strftime('%Y/%m/%d %H:%M')}
161 self.set_cookie('username',tornado.escape.url_escape(na))
162 self.redirect('/'+dbname+'#article')
164 self.render('regist.htm',content=error)
166 def link(self,command):
170 for x in command.split():
171 if (y == '>>')and(x.isdecimal() == True):
172 s = '<a href=#'+x+'>'+x+'</a>'
173 while -1 < command.find(x,i):
174 j = command.find(x,i)
177 k = tmp.rsplit(None,1)
178 if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
188 return text+command[i:]
192 class AdminHandler(BaseHandler):
193 @tornado.web.authenticated
194 def get(self,dbname,page='0'):
196 dbname = self.get_argument('record','')
197 if self.application.collection(dbname) == False:
198 raise tornado.web.HTTPError(404)
200 table = self.application.db.table(dbname)
201 rec = sorted(table.all(),key=lambda x: x['number'])
202 mente = self.application.db.get(where('kinds') == 'conf')
203 if mente['mentenance'] == True:
204 check = 'checked=checked'
207 pos = self.application.gpos(dbname,page)
214 self.render('modules/admin.htm',position=pos,records=rec[start:start+i],mente=check,password=mente['password'],db=dbname)
216 class AdminConfHandler(BaseHandler):
217 @tornado.web.authenticated
218 def post(self,dbname,func):
220 param = self.application.db.get(where('kinds') == 'conf')['mentenance']
221 if self.get_argument('mente','') == 'on':
229 word = self.get_argument('pass','')
231 self.render('regist.htm',content='パスワードを設定してください')
234 self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')
236 table = self.application.db.table(dbname)
237 for x in self.get_arguments('item'):
238 table.remove(where('number') == int(x))
239 self.redirect('/'+dbname+'/admin/0/')
242 self.application.db.close()
243 shutil.copy(st.json,st.bak)
244 self.application.db = TinyDB(st.json)
247 database = self.application.db
249 for x in database.tables():
250 if self.application.collection(x) == True:
251 database.purge_table(x)
252 if x in bak.tables():
253 table = database.table(x)
254 table.insert_multiple(bak.table(x).all())
256 class UserHandler(tornado.web.RequestHandler):
257 def post(self,dbname):
258 num = self.get_argument('number')
259 if num.isdigit() == True:
261 pas = self.get_argument('password')
262 table = self.application.db.table(dbname)
264 obj = table.get(qwr.number == num)
265 if obj and(obj['password'] == pas):
266 table.remove(qwr.number == num)
267 self.redirect('/'+dbname)
269 class SearchHandler(tornado.web.RequestHandler):
270 def post(self,dbname):
271 self.word = tornado.escape.url_unescape(self.get_argument('word1'))
272 self.radiobox = self.get_argument('filter')
273 self.set_cookie('search',tornado.escape.url_escape(self.word))
274 rec = sorted(self.search(dbname),key=lambda x: x['number'])
275 self.render('modules/search.htm',records=rec,word1=self.word,db=dbname)
277 def get(self,dbname):
278 if self.application.collection(dbname) == False:
279 raise tornado.web.HTTPError(404)
281 word = self.get_cookie('search','')
282 word = tornado.escape.url_unescape(word)
283 self.render('modules/search.htm',records=[],word1=word,db=dbname)
285 def search(self,dbname):
286 table = self.application.db.table(dbname)
287 element = self.word.split()
288 if len(element) == 0:
290 while len(element) < 3:
291 element.append(element[0])
292 if self.radiobox == 'comment':
293 query = (Query().raw.search(element[0])) | (Query().raw.search(element[1])) | (Query().raw.search(element[2]))
295 query = (Query().name == element[0]) | (Query().name == element[1]) | (Query().name == element[2])
296 if self.radiobox == 'comment':
297 for x in table.search(query):
299 for text in x['raw'].splitlines(True):
300 for word in self.word.split():
301 if text.find(word) > -1:
302 com = com +'<p style=background-color:yellow>'+text+'<br></p>'
305 com = com+'<p>'+text+'<br></p>'
309 for x in table.search(query):
312 class FooterModule(tornado.web.UIModule):
313 def render(self,number,url,link):
314 return self.render_string('modules/footer.htm',index=number,url=url,link=link)
316 class Application(tornado.web.Application):
318 self.db = TinyDB(st.json)
319 handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
320 (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
321 (r'/([a-zA-Z0-9_]+)/admin/([0-9]+)/',AdminHandler),(r'/([a-zA-Z0-9_]+)/admin/([a-z]+)/',AdminConfHandler),(r'/([a-zA-Z0-9_]+)/userdel',UserHandler),
322 (r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
323 settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
324 'static_path':os.path.join(os.path.dirname(__file__),'static'),
325 'ui_modules':{'Footer':FooterModule},
326 'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
331 tornado.web.Application.__init__(self,handlers,**settings)
333 def gpos(self,dbname,page):
334 params = self.db.get(where('kinds') == 'conf')
338 elif (pos-1)*params['count'] >= len(self.db.table(dbname)):
342 def collection(self,name):
343 if name in self.db.tables():
349 json = 'static/db/db.json'
350 bak = 'static/db/bak.json'
353 app = tornado.wsgi.WSGIAdapter(Application())
354 if __name__ == '__main__':
355 server = wsgiref.simple_server.make_server('',8888,app)
356 server.serve_forever()