import os.path
-import shutil,copy
-import tornado.auth
+import shutil,re
import tornado.escape
import tornado.web
+import tornado.httpserver
+import tornado.ioloop
+import tornado.options
+from tornado.options import define,options
from tinydb import TinyDB,Query,where
-from tinydb.storages import MemoryStorage
from tinydb.operations import delete
-from datetime import datetime
+from datetime import datetime,date
+import json
+
+define('port',default=8000,help='run on the given port',type=int)
class BaseHandler(tornado.web.RequestHandler):
def get_current_user(self):
params = self.application.db.get(where('kinds') == 'conf')
if params['mentenance'] == True:
self.render('mentenance.htm',title=params['title'],db=dbname)
+ return
if self.application.collection(dbname) == False:
if self.current_user == b'admin':
self.application.db.table(dbname)
else:
raise tornado.web.HTTPError(404)
return
+ key = self.get_argument('key','')
+ if key:
+ table = self.application.db.table(dbname)
+ rec = table.get(where('number') == int(key))
+ if rec:
+ self.render('article.htm',record=rec)
+ return
+ else:
+ raise tornado.web.HTTPError(404)
+ return
i = params['count']
+ rule = tornado.escape.url_unescape(self.get_cookie('aikotoba',''))
na = tornado.escape.url_unescape(self.get_cookie("username",u"誰かさん"))
pos = self.application.gpos(dbname,page)
table = self.application.db.table(dbname)
start = len(table)-i
if start < 0:
start = 0
+ bool = (dbname == params['info name'])
rec = sorted(table.all(),key=lambda x: x['number'])[start:start+i]
+ if bool == True:
+ rec = rec[::-1]
if len(table) >= 10*i:
self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)
return
- self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname)
+ if (bool == True)and(self.current_user != b'admin'):
+ self.render('modules/info.htm',position=pos,records=rec,data=params,db=dbname)
+ else:
+ self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname,aikotoba=rule)
class LoginHandler(BaseHandler):
def get(self):
- self.render('login.htm')
+ query = self.get_query_argument('next','')
+ i = query[1:].find('/')
+ if i == -1:
+ qs = query[1:]
+ else:
+ qs = query[1:i+1]
+ self.render('login.htm',db=qs)
def post(self):
pw = self.application.db.get(where('kinds') == 'conf')
if self.get_argument('password') == pw['password']:
self.set_current_user('admin')
dbname = self.get_argument('record')
- self.redirect('/'+dbname+'/admin/0/')
+ if dbname == 'master':
+ self.redirect('/master')
+ else:
+ self.redirect('/'+dbname+'/admin/0/')
class LogoutHandler(BaseHandler):
def get(self):
self.clear_current_user()
self.redirect('/login')
-class NaviHandler(tornado.web.RequestHandler):
+class NaviHandler(tornado.web.RequestHandler):
def get(self):
- self.render('top.htm',coll=sorted(self.name()),full=self.full)
+ col,na = self.name()
+ self.render('top.htm',coll=col,name=na,full=self.full)
def name(self):
- for x in self.application.db.tables():
- if x != '_default':
- yield x
+ names = self.application.db.tables()
+ na = self.application.db.get(where('kinds') == 'conf')['info name']
+ for s in ['_default','master','temp']:
+ if s in names:
+ names.remove(s)
+ if na in names:
+ names.remove(na)
+ else:
+ na = ''
+ return sorted(names),na
def full(self,dbname):
if dbname in self.application.db.tables():
self.render('title.htm',coll=rec,full=self.full)
def title(self):
- for x in self.name():
+ names = self.application.db.tables()
+ for s in ['_default','master','temp']:
+ if s in names:
+ names.remove(s)
+ for x in names:
item = {}
item['name'] = x
table = self.application.db.table(x)
rec = sorted(table.all(),key=lambda k: k['number'])
s = rec[i-1]['date']
item['date'] = s
- item['date2'] = datetime.strptime(s,'%Y/%m/%d %H:%M').day
+ i = datetime.strptime(s,'%Y/%m/%d %H:%M')
+ year = datetime.now().year-i.year
+ if year == 0:
+ j = 800
+ elif year == 1:
+ j = 400
+ else:
+ j = 0
+ item['date2'] = j+31*(i.month-1)+i.day
yield item
class RegistHandler(tornado.web.RequestHandler):
if self.application.collection(dbname) == False:
raise tornado.web.HTTPError(404)
return
+ self.database = dbname
rec = self.application.db.get(where('kinds') == 'conf')
words = rec['bad_words']
out = rec['out_words']
na = self.get_argument('name')
sub = self.get_argument('title')
- com = self.get_argument('comment')
+ com = self.get_argument('comment',None,False)
text = ''
i = 0
+ url = []
error = ''
for word in out:
if word in com:
error = error + u'禁止ワード.'
break
for line in com.splitlines(True):
+ if error != '':
+ break
for word in words:
- if word in line:
+ if word in line.lower():
error = error + u'タグ違反.('+word+')'
- i += len(line)
+ i += len(line)
+ obj = re.finditer('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', line)
+ for x in obj:
+ if x.group() not in url:
+ url.append(x.group())
+ if re.match(' ',line):
+ line = line.replace(' ',' ',1)
text = text+'<p>'+self.link(line)+'<br></p>'
+ s = ''
+ for x in url:
+ s = s+'<tr><td><a class=livepreview target=_blank href={0}>{0}</a></td></tr>'.format(x)
+ if s:
+ text = text+'<table><tr><td>検出URL:</td></tr>'+s+'</table>'
pw = self.get_argument('password')
- if sub == '':
- sub = u'タイトルなし.'
if i == 0:
error = error + u'本文がありません.'
elif i > 1000:
item = sorted(article.all(),key=lambda x: x['number'])[len(article)-1]
no = item['number']+1
if error == '':
+ if not na:
+ na = u'誰かさん'
+ if sub == '':
+ sub = u'タイトルなし.'
s = datetime.now()
reg = {'number':no,'name':na,'title':sub,'comment':text,'raw':com,'password':pw,'date':s.strftime('%Y/%m/%d %H:%M')}
article.insert(reg)
- restart()
self.set_cookie('username',tornado.escape.url_escape(na))
self.redirect('/'+dbname+'#article')
else:
self.render('regist.htm',content=error)
def link(self,command):
- y = ''
i = 0
text = ''
- for x in command.split():
- if (y == '>>')and(x.isdecimal() == True):
- s = '<a href=#'+x+'>'+x+'</a>'
- while -1 < command.find(x,i):
- j = command.find(x,i)
- tmp = command[i:j]
- i = j+len(x)
- k = tmp.rsplit(None,1)
- if ((len(k) > 1)and(k[1] == y))or(k[0] == y):
- text = text+tmp+s
- break
- else:
- text = text+tmp+x
- y = x
- if text == '':
- return command
+ obj = re.finditer('>>[0-9]+',command)
+ for x in obj:
+ s = '<a class=minpreview data-preview-url=/{0}?key={1} href=/{0}/userdel?job={1}>>>{1}</a>'.format(self.database,x.group()[2:])
+ text = text+command[i:x.start()]+s
+ i = x.end()
else:
- if len(command) > i:
- return text+command[i:]
- else:
- return text
+ text = text+command[i:]
+ return text
class AdminHandler(BaseHandler):
@tornado.web.authenticated
- def get(self,dbname,page='0'):
+ def get(self,dbname,page):
if dbname == '':
dbname = self.get_argument('record','')
if self.application.collection(dbname) == False:
start = len(table)-i
if start < 0:
start = 0
- restart()
- self.application.db = TinyDB(st.json)
self.render('modules/admin.htm',position=pos,records=rec[start:start+i],mente=check,password=mente['password'],db=dbname)
class AdminConfHandler(BaseHandler):
table = self.application.db.table(dbname)
for x in self.get_arguments('item'):
table.remove(where('number') == int(x))
- restart()
self.redirect('/'+dbname+'/admin/0/')
def store(self):
if x in bak.tables():
table = database.table(x)
table.insert_multiple(bak.table(x).all())
- restart()
class UserHandler(tornado.web.RequestHandler):
+ table = None
+ def get(self,dbname):
+ self.table = self.application.db.table(dbname)
+ q = self.get_query_argument('job','0',strip=True)
+ num = self.page(int(q))
+ if num == '':
+ self.redirect('/{0}#{1}'.format(dbname,q))
+ else:
+ self.redirect('/{0}{1}#{2}'.format(dbname,num,q))
+
def post(self,dbname):
- num = int(self.get_argument('number'))
- pas = self.get_argument('password')
- table = self.application.db.table(dbname)
- qwr = Query()
- obj = table.get(qwr.number == num)
- if obj and(obj['password'] == pas):
- table.remove(qwr.number == num)
- self.redirect('/'+dbname)
+ number = self.get_argument('number')
+ if number.isdigit() == True:
+ num = int(number)
+ pas = self.get_argument('password')
+ self.table = self.application.db.table(dbname)
+ qwr = Query()
+ obj = self.table.get(qwr.number == num)
+ if obj and(obj['password'] == pas):
+ self.table.update({'title':u'削除されました','name':'','comment':u'<i><b>投稿者により削除されました</b></i>'},qwr.number == num)
+ self.redirect('/{0}{1}#{2}'.format(dbname,self.page(num),number))
+ else:
+ self.redirect('/'+dbname)
+
+ def page(self,number):
+ if self.table != None:
+ rec = self.table.count(where('number') <= number)
+ conf = self.application.db.get(where('kinds') == 'conf')
+ if len(self.table)-rec >= conf['count']:
+ return '/'+str(1+rec//conf['count'])+'/'
+ else:
+ return ''
class SearchHandler(tornado.web.RequestHandler):
def post(self,dbname):
- self.word = tornado.escape.url_unescape(self.get_argument('word1'))
- self.radiobox = self.get_argument('filter')
- self.set_cookie('search',tornado.escape.url_escape(self.word))
- rec = self.search(dbname)
- self.render('modules/search.htm',records=rec,word1=self.word,db=dbname)
+ arg = self.get_argument('word1')
+ self.word = arg
+ self.radiobox = self.get_argument('filter')
+ rec = sorted(self.search(dbname),key=lambda x: x['number'])
+ self.render('modules/search.htm',records=rec,word1=arg,db=dbname)
def get(self,dbname):
if self.application.collection(dbname) == False:
raise tornado.web.HTTPError(404)
return
- word = self.get_cookie('search')
- if word == None:
- word = ''
- else:
- word = tornado.escape.url_unescape(word)
- self.render('modules/search.htm',records=[],word1=word,db=dbname)
+ self.render('modules/search.htm',records=[],word1='',db=dbname)
- def search(self,name):
- table = self.application.db.table(name)
+ def search(self,dbname):
+ table = self.application.db.table(dbname)
element = self.word.split()
if len(element) == 0:
element = ['']
query = (Query().raw.search(element[0])) | (Query().raw.search(element[1])) | (Query().raw.search(element[2]))
else:
query = (Query().name == element[0]) | (Query().name == element[1]) | (Query().name == element[2])
- if self.radiobox == 'comment':
- rec = []
- mem = TinyDB(storage=MemoryStorage)
+ if self.radiobox == 'comment':
for x in table.search(query):
- result = ''
+ com = ''
for text in x['raw'].splitlines(True):
- for word in self.word.split():
+ for word in element:
if text.find(word) > -1:
- result = result+'<p style=background-color:yellow>'+text+'<br></p>'
+ com = com +'<p style=background-color:yellow>'+text+'<br></p>'
break
else:
- result = result+'<p>'+text+'<br></p>'
- i = mem.insert(x)
- mem.update({'comment':result},eids=[i])
- rec = sorted(mem.all(),key=lambda x: x['number'])
- mem.close()
- return rec
+ com = com+'<p>'+text+'<br></p>'
+ x['comment'] = com
+ yield x
else:
- rec = table.search(query)
- return sorted(rec,key=lambda x: x['number'])
+ for x in table.search(query):
+ yield x
class FooterModule(tornado.web.UIModule):
def render(self,number,url,link):
return self.render_string('modules/footer.htm',index=number,url=url,link=link)
+class HeadlineApi(tornado.web.RequestHandler):
+ def get(self):
+ response = {}
+ for x in self.application.db.tables():
+ if x != '_default':
+ response[x] = self.get_data(x)
+ self.write(json.dumps(response,ensure_ascii=False))
+
+ def get_data(self,dbname):
+ table = self.application.db.table(dbname)
+ i = len(table)
+ if i == 0:
+ return {}
+ else:
+ rec = sorted(table.all(),key=lambda x: x['number'])[i-1]
+ return {'number':rec['number'],'title':rec['title'],'name':rec['name'],'comment':rec['raw'][0:19]}
+
+class ArticleApi(tornado.web.RequestHandler):
+ def get(self,dbname,number):
+ if self.application.collection(dbname) == True:
+ table = self.application.db.table(dbname)
+ response = table.get(where('number') == int(number))
+ if response == None:
+ response = {}
+ else:
+ del response['comment']
+ self.write(json.dumps(response,ensure_ascii=False))
+ else:
+ tornado.web.HTTPError(404)
+
+ def post(self,dbname):
+ name = self.get_argument('name',u'誰かさん')
+ title = self.get_argument('title',u'タイトルなし')
+ comment = self.get_argument('comment')
+ table = self.application.db.table(dbname)
+ table.insert({'name':name,'title':title,'comment':comment})
+
+class HelpHandler(tornado.web.RequestHandler):
+ def get(self):
+ self.render('help.htm',req='')
+
+ def post(self):
+ com = self.get_argument('help','')
+ text = ''
+ for line in com.splitlines():
+ text +='<p>'+line
+ table = self.application.db.table('master')
+ time = datetime.now()
+ table.insert({'comment':text,'time':time.strftime('%Y/%m/%d %H:%M')})
+ if com == '':
+ req = ''
+ else:
+ req = '送信しました'
+ self.render('help.htm',req=req)
+
+class MasterHandler(BaseHandler):
+ @tornado.web.authenticated
+ def get(self):
+ if self.current_user == b'admin':
+ com = self.application.db.table('master').all()
+ self.render('master.htm',com=com)
+ else:
+ raise tornado.web.HTTPError(404)
+
+class AlertHandler(UserHandler):
+ def get(self):
+ db = self.get_query_argument('db')
+ num = self.get_query_argument('num')
+ self.table = self.application.db.table(db)
+ tb = self.table.get(where('number') == int(num))
+ s = self.page(int(num))
+ jump = '/'+db+s+'#'+num
+ link = '<p><a href={0}>{0}</a>'.format(jump)
+ time = datetime.now()
+ data = {'comment':tb['comment']+link,'time':time.strftime('%Y/%m/%d'),
+ 'link':jump,'date':date.weekday(time)}
+ id = self.application.db.table('temp').insert(data)
+ self.render('alert.htm',com=data['comment'],num=id)
+
+ def post(self):
+ id = int(self.get_argument('num'))
+ table = self.application.db.table('temp')
+ tb = table.get(eid=id)
+ link = tb['link']
+ table.remove(eids=[id])
+ table.remove(where('date') != date.weekday(datetime.now()))
+ if self.get_argument('admit','') == 'ok':
+ com = self.get_argument('com')
+ tb['comment'] = com+tb['comment']
+ del tb['date']
+ table = self.application.db.table('master')
+ table.insert(tb)
+ self.redirect(link)
+
class Application(tornado.web.Application):
def __init__(self):
- self.db = TinyDB(st.json)
+ self.db = TinyDB(st.json)
handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
- (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/',IndexHandler),
- (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),
+ (r'/headline/api',HeadlineApi),(r'/read/api/([a-zA-Z0-9_]+)/([0-9]+)',ArticleApi),(r'/write/api/([a-zA-Z0-9_]+)',ArticleApi),
+ (r'/help',HelpHandler),(r'/master/*',MasterHandler),(r'/alert',AlertHandler),
+ (r'/([a-zA-Z0-9_]+)',IndexHandler),(r'/([a-zA-Z0-9_]+)/([0-9]+)/*',IndexHandler),
+ (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),
(r'/([a-zA-Z0-9_]+)/search',SearchHandler),(r'/([a-zA-Z0-9_]+)/regist',RegistHandler)]
- settings = {'template_path':os.path.join(os.path.dirname(__file__),'pybbs'),
+ settings = {'template_path':os.path.join(os.path.dirname(__file__),'templates'),
'static_path':os.path.join(os.path.dirname(__file__),'static'),
'ui_modules':{'Footer':FooterModule},
- 'cookie_secret':'bZJc2sWbQLKos6GkHn/VB9oXwQt8SOROkRvJ5/xJ89E=',
+ 'cookie_secret':'bZJc2sWbQLKo6GkHn/VB9oXwQt8SOROkRvJ5/xJ89Eo=',
'xsrf_cookies':True,
- #'debug':True,
+ 'debug':True,
'login_url':'/login'
}
tornado.web.Application.__init__(self,handlers,**settings)
return pos
def collection(self,name):
- for x in self.db.tables():
- if x == name:
- return True
+ if name in self.db.tables():
+ return True
else:
return False
bak = 'static/db/bak.json'
st = static()
-app = Application()
-
-def restart():
- pass
- #app.db.close()
- #app.db = TinyDB(st.json)
+if __name__ == '__main__':
+ tornado.options.parse_command_line()
+ http_server = tornado.httpserver.HTTPServer(Application())
+ http_server.listen(options.port)
+ tornado.ioloop.IOLoop.instance().start()