OSDN Git Service

初期データベースファイルの更新
[pybbs/pybbs.git] / index.py
1
2 import os.path
3 import shutil,copy
4 import tornado.auth
5 import tornado.escape
6 import tornado.web
7 import tornado.wsgi
8 from tinydb import TinyDB,Query,where
9 from tinydb.storages import MemoryStorage
10 from tinydb.operations import delete
11 from datetime import datetime
12
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)
17     
18     def set_current_user(self,username):
19         self.set_secure_cookie('admin_user',username)
20         
21     def clear_current_user(self):
22         self.clear_cookie('admin_user')
23
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)
32             else:
33                 raise tornado.web.HTTPError(404)
34                 return
35         i = params['count']      
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)
39         start = (pos-1)*i
40         if start < 0:
41             start = len(table)-i
42             if start < 0:
43                 start = 0
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)
47             return
48         self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname)
49         
50 class LoginHandler(BaseHandler):
51     def get(self):
52         self.render('login.htm')
53         
54     def post(self):
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/')
60         
61 class LogoutHandler(BaseHandler):
62     def get(self):
63         self.clear_current_user()
64         self.redirect('/login')
65         
66 class NaviHandler(tornado.web.RequestHandler):
67     def get(self):
68         self.render('top.htm',coll=sorted(self.name()),full=self.full)
69         
70     def name(self):
71         for x in self.application.db.tables():
72             if x != '_default':
73                 yield x
74                 
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)
79             if len(table) >= i:
80                 return True
81         return False
82
83 class TitleHandler(NaviHandler):
84     def get(self):
85         rec = sorted(self.title(),key=lambda x: x['date2'])
86         self.render('title.htm',coll=rec,full=self.full)  
87         
88     def title(self):
89         for x in self.name():
90             item = {}
91             item['name'] = x
92             table = self.application.db.table(x)
93             i = len(table)
94             item['count'] = i            
95             if table.contains(where('number') == 1) == True:
96                 s = table.get(where('number') == 1)['title']
97             else:
98                 s = ''
99             item['title'] = s   
100             if i == 0:
101                 item['date'] = ''
102                 item['date2'] = 0
103             else:
104                 rec = sorted(table.all(),key=lambda k: k['number'])
105                 s = rec[i-1]['date']
106                 item['date'] = s
107                 i = datetime.strptime(s,'%Y/%m/%d %H:%M')
108                 year = datetime.now().year-i.year
109                 if year == 0:
110                     j = 800
111                 elif year == 1:
112                     j = 400
113                 else:
114                     j = 0
115                 item['date2'] = j+31*(i.month-1)+i.day
116             yield item
117         
118 class RegistHandler(tornado.web.RequestHandler):
119     def post(self,dbname):
120         if self.application.collection(dbname) == False:
121             raise tornado.web.HTTPError(404)
122             return
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')
129         text = ''
130         i = 0
131         error = ''
132         for word in out:
133             if word in com:
134                 error = error + u'禁止ワード.'
135                 break
136         for line in com.splitlines(True):
137             for word in words:
138                 if word in line:
139                     error = error + u'タグ違反.('+word+')'       
140             i += len(line)
141             text = text+'<p>'+self.link(line)+'<br></p>'
142         pw = self.get_argument('password')
143         if sub == '':
144             sub = u'タイトルなし.'
145         if i == 0:
146             error = error + u'本文がありません.'
147         elif i > 1000:
148             error = error +u'文字数が1,000をこえました.'
149         article = self.application.db.table(dbname)
150         if len(article) == 0:
151             no = 1
152         else:
153             item = sorted(article.all(),key=lambda x: x['number'])[len(article)-1]
154             no = item['number']+1
155         if error == '':
156             s = datetime.now()
157             reg = {'number':no,'name':na,'title':sub,'comment':text,'raw':com,'password':pw,'date':s.strftime('%Y/%m/%d %H:%M')}
158             article.insert(reg)
159             restart()
160             self.set_cookie('username',tornado.escape.url_escape(na))
161             self.redirect('/'+dbname+'#article')
162         else:
163             self.render('regist.htm',content=error)
164     
165     def link(self,command):
166         y = ''
167         i = 0
168         text = ''
169         for x in command.split():
170             if (y == '>>')and(x.isdecimal() == True):
171                 s = '<a href=#'+x+'>'+x+'</a>'
172                 while -1 < command.find(x,i):
173                     j = command.find(x,i)
174                     tmp = command[i:j]
175                     i = j+len(x)
176                     k = tmp.rsplit(None,1)
177                     if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
178                         text = text+tmp+s                                                                       
179                         break
180                     else:
181                         text = text+tmp+x                        
182             y = x    
183         if text == '':
184             return command
185         else:
186             if len(command) > i:
187                 return text+command[i:]
188             else:
189                 return text
190     
191 class AdminHandler(BaseHandler):
192     @tornado.web.authenticated               
193     def get(self,dbname,page='0'):
194         if dbname == '':
195             dbname = self.get_argument('record','')
196         if self.application.collection(dbname) == False:
197             raise tornado.web.HTTPError(404)
198             return
199         table = self.application.db.table(dbname) 
200         rec = sorted(table.all(),key=lambda x: x['number'])                   
201         mente = self.application.db.get(where('kinds') == 'conf')
202         if mente['mentenance'] == True:
203             check = 'checked=checked'
204         else:
205             check = ''
206         pos = self.application.gpos(dbname,page)
207         i = mente['count']
208         start = (pos-1)*i
209         if start < 0:
210             start = len(table)-i
211             if start < 0:
212                 start = 0
213         restart()
214         self.render('modules/admin.htm',position=pos,records=rec[start:start+i],mente=check,password=mente['password'],db=dbname)
215
216 class AdminConfHandler(BaseHandler):
217     @tornado.web.authenticated
218     def post(self,dbname,func):
219         if func == 'set':
220             param = self.application.db.get(where('kinds') == 'conf')['mentenance']
221             if self.get_argument('mente','') == 'on':
222                 mente = True
223                 if param != mente:
224                     self.store()
225             else:
226                 mente = False  
227                 if param != mente:
228                     self.restore()
229             word = self.get_argument('pass','')
230             if word == '':
231                 self.render('regist.htm',content='パスワードを設定してください')
232                 return
233             else:
234                 self.application.db.update({'mentenance':mente,'password':word},where('kinds') == 'conf')  
235         elif func == 'del':
236             table = self.application.db.table(dbname)
237             for x in self.get_arguments('item'):
238                 table.remove(where('number') == int(x))
239         restart()
240         self.redirect('/'+dbname+'/admin/0/')
241         
242     def store(self):
243         self.application.db.close()
244         shutil.copy(st.json,st.bak)
245         self.application.db = TinyDB(st.json)
246         
247     def restore(self):
248         database = self.application.db
249         bak = TinyDB(st.bak)
250         for x in database.tables():
251             if self.application.collection(x) == True:
252                 database.purge_table(x)
253                 if x in bak.tables():
254                     table = database.table(x)
255                     table.insert_multiple(bak.table(x).all())
256         restart()
257           
258 class UserHandler(tornado.web.RequestHandler):
259     def post(self,dbname):
260         num = self.get_argument('number')
261         if num.isdigit() == True:
262             pas = self.get_argument('password')
263             table = self.application.db.table(dbname)
264             qwr = Query()
265             obj = table.get(qwr.number == num)
266             if obj and(obj['password'] == pas):
267                 table.remove(qwr.number == num)
268         self.redirect('/'+dbname)
269       
270 class SearchHandler(tornado.web.RequestHandler):       
271     def post(self,dbname):
272         self.word = tornado.escape.url_unescape(self.get_argument('word1'))
273         self.radiobox = self.get_argument('filter')
274         self.set_cookie('search',tornado.escape.url_escape(self.word))         
275         rec = sorted(self.search(dbname),key=lambda x: x['number'])
276         self.render('modules/search.htm',records=rec,word1=self.word,db=dbname)
277     
278     def get(self,dbname):
279         if self.application.collection(dbname) == False:
280             raise tornado.web.HTTPError(404)
281             return
282         word = self.get_cookie('search','')
283         word = tornado.escape.url_unescape(word)
284         self.render('modules/search.htm',records=[],word1=word,db=dbname)
285         
286     def search(self,dbname):
287         table = self.application.db.table(dbname)    
288         element = self.word.split()
289         if len(element) == 0:
290             element = ['']
291         while len(element) < 3:
292             element.append(element[0])
293         if self.radiobox == 'comment':
294             query = (Query().raw.search(element[0])) | (Query().raw.search(element[1])) | (Query().raw.search(element[2]))
295         else:
296             query = (Query().name == element[0]) | (Query().name == element[1]) | (Query().name == element[2])
297         if self.radiobox == 'comment':    
298             for x in table.search(query):
299                 com = ''
300                 for text in x['raw'].splitlines(True):                  
301                     for word in self.word.split():                        
302                         if text.find(word) > -1:
303                             com = com +'<p style=background-color:yellow>'+text+'<br></p>'  
304                             break                          
305                     else:
306                         com = com+'<p>'+text+'<br></p>'
307                 x['comment'] = com
308                 yield x       
309         else:
310             for x in table.search(query):
311                 yield x
312                                         
313 class FooterModule(tornado.web.UIModule):
314     def render(self,number,url,link):
315         return self.render_string('modules/footer.htm',index=number,url=url,link=link)
316     
317 class Application(tornado.web.Application):    
318     def __init__(self):
319         self.db = TinyDB(st.json)
320         handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
321                     (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
322                     (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),
323                     (r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
324         settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
325                         'static_path':os.path.join(os.path.dirname(__file__),'static'),
326                         'ui_modules':{'Footer':FooterModule},
327                         'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
328                         'xsrf_cookies':True,
329                         #'debug':True,
330                         'login_url':'/login'
331                         }
332         tornado.web.Application.__init__(self,handlers,**settings)
333  
334     def gpos(self,dbname,page):
335         params = self.db.get(where('kinds') == 'conf')
336         pos = int(page)
337         if pos <= 0:
338             pos = 0
339         elif (pos-1)*params['count'] >= len(self.db.table(dbname)):
340             pos = 0
341         return pos
342     
343     def collection(self,name):
344         if name in self.db.tables():
345             return True
346         else:
347             return False
348
349 class static():
350     json = 'static/db/db.json'
351     bak = 'static/db/bak.json'
352
353 st = static()
354 app = tornado.wsgi.WSGIAdapter(Application())
355
356 def restart():
357     pass
358     #app.db.close()
359     #app.db = TinyDB(st.json)