OSDN Git Service

うまくいってなかったらしいhttpの正規表現を変更
[pybbs/pybbs.git] / pybbs.py
index 5d36c27..a6dee93 100644 (file)
--- a/pybbs.py
+++ b/pybbs.py
@@ -2,7 +2,7 @@
 import os,re,glob
 from tornado import escape,web,ioloop,httpserver,httpclient
 import pymongo, urllib
-from datetime import datetime
+from datetime import datetime,timedelta
 import json
 from bson.objectid import ObjectId #don't remove
 from linebot.api import LineBotApi
@@ -22,13 +22,12 @@ class BaseHandler(web.RequestHandler):
         self.clear_cookie('admin_user')
 
 class IndexHandler(BaseHandler):
-    def get(self,dbname,page='0'):
-        dbname = escape.url_unescape(dbname)
+    def main(self,dbname,page):
         params = self.application.db['params'].find_one({'app':'bbs'})
         if params['mentenance'] is True:
             self.render('mentenance.htm',title=params['title'],db=dbname)
             return
-        if dbname not in self.application.coll():
+        if dbname not in self.application.mylist():
             if self.current_user == b'admin':
                 coll = self.application.db[dbname]
                 coll.insert({})
@@ -44,30 +43,45 @@ class IndexHandler(BaseHandler):
                 return
             else:
                 raise web.HTTPError(404)
-        i = params['count']      
-        rule = escape.url_unescape(self.get_cookie('aikotoba',''))
-        na = escape.url_unescape(self.get_cookie('username',u'誰かさん'))
-        pos = self.application.gpos(dbname,page)
+        self.rule = escape.url_unescape(self.get_cookie('aikotoba',''))
+        self.na = escape.url_unescape(self.get_cookie('username',u'誰かさん'))
+        self.pos = self.application.gpos(dbname,page)
         table = self.application.db[dbname]
-        start = (pos-1)*i
+        i = params['count']
+        start = (self.pos-1)*i
         if start < 0:
             start = table.count()-i
             if start < 0:
                 start = 0
         rec = table.find()
-        bool = (dbname == params['info name']) 
-        if bool is True:
+        self.bool = (dbname == params['info name'])
+        if self.bool is True:
             rec.sort('number',-1)
         else:
             rec.sort('number')
-        rec.skip(start).limit(i)
-        if table.count() >= 10*i:
-            self.render('modules/full.htm',position=pos,records=rec,data=params,db=dbname)
-            return
-        if bool is True and self.current_user != b'admin':
-            self.render('modules/info.htm',position=pos,records=rec,data=params,db=dbname)
+        self.rec = rec.skip(start).limit(i)
+
+    def get(self,dbname,page='0'):
+        self.main(dbname,page)
+        db = self.application.db
+        table = db[dbname].find()
+        params = db['params'].find_one({'app':'bbs'})
+        if table.count() >= 10*params['count']:
+            self.render('modules/full.htm',position=self.pos,records=self.rec,data=params,db=dbname)
+        if self.bool is True and self.current_user != b'admin':
+            self.render('modules/info.htm',position=self.pos,records=self.rec,data=params,db=dbname,error='')
         else:
-            self.render('modules/index.htm',position=pos,records=rec,data=params,username=na,db=dbname,aikotoba=rule)
+            self.render_admin(dbname)
+
+    def render_admin(self,dbname,title='',com='',er='',img='',ch='checked'):
+        t = self.get_argument('img','')
+        params = self.application.db['params'].find_one({'app':'bbs'})
+        if self.current_user == b'admin':
+            s = '<label><p>URL </p><input name="img" placeholder="src=http://~" value=' + t + '></label>'
+        else:
+            s = '<input type=hidden>'
+        self.render('modules/index.htm',position=self.pos,records=self.rec,data=params,username=self.na,title=title,
+            comment=com,db=dbname,aikotoba=self.rule,error=er+img,check=ch,admin=s)
 
 class LoginHandler(BaseHandler):
     def get(self):
@@ -105,31 +119,23 @@ class JumpHandler(BaseHandler):
         
 class NaviHandler(web.RequestHandler):
     def get(self):
-        if 'params' not in self.application.coll():
+        if 'params' not in self.application.mylist():
             item = {"mentenance":False,"out_words":[u"阿保",u"馬鹿",u"死ね"],"password":"admin",
-                    "title2":"<h1 style=color:gray;text-align:center>pybbs</h1>",
-                    "bad_words":["<style","<link","<script","<img"],"count":30,
-                    "title":"pybbs","info name":"info",'app':'bbs'}       
+                    "title2":"<h1 style=color:maroon;font-style:italic;text-align:center>とるね~ど号</h1>",
+                    "bad_words":["<style","<link","<script","<img","<a"],"count":30,
+                    "title":u"とるね~ど号","info name":"info",'app':'bbs'}
             self.application.db['params'].insert(item)
-            self.application.db['info']
+            self.application.db['info'].find()
         table = self.application.db['params'].find_one({'app':'bbs'})
         if table['mentenance'] is True:
             self.render('mentenance.htm',title=table['title'],db=table['info name'])
             return
-        coll,na = self.name()                
+        coll = self.application.coll()
+        na = table['info name']
         self.render('top.htm',coll=coll,name=na,full=self.full)
-                  
-    def name(self):
-        coll = sorted(self.application.coll(),key=str.lower)
-        na = self.application.db['params'].find_one({'app':'bbs'})['info name']
-        if na in coll:
-            coll.remove(na)
-        else:
-            na = ''
-        return coll,na
-            
+
     def full(self,dbname):
-        if dbname in self.application.db.collection_names():
+        if dbname in self.application.coll():
             i = 10*self.application.db['params'].find_one({'app':'bbs'})['count']
             table = self.application.db[dbname]
             if table.count() >= i:
@@ -142,8 +148,7 @@ class TitleHandler(NaviHandler):
         self.render('title.htm',coll=rec,full=self.full)  
         
     def title(self):
-        name = self.application.coll()
-        for x in name:
+        for x in self.application.coll():
             item = {}
             item['name'] = x
             table = self.application.db[x]
@@ -173,13 +178,14 @@ class TitleHandler(NaviHandler):
                 item['date2'] = j+31*(i.month-1)+i.day
             yield item
         
-class RegistHandler(web.RequestHandler):
+class RegistHandler(IndexHandler):
     def post(self,dbname):
-        if dbname not in self.application.coll():
+        self.main(dbname,'0')
+        if dbname not in self.application.coll(info=True):
             raise web.HTTPError(404)
-        rec = self.application.db['params'].find_one({'app':'bbs'})
-        words = rec['bad_words']
-        out = rec['out_words']
+        params = self.application.db['params'].find_one({'app':'bbs'})
+        words = params['bad_words']
+        out = params['out_words']
         rule = self.get_argument('aikotoba')
         na = self.get_argument('name')
         sub = self.get_argument('title')
@@ -188,20 +194,20 @@ class RegistHandler(web.RequestHandler):
         i = 0
         url = []
         error = ''
-        if rule != u'げんき':
-            error = u'合言葉未入力.'
-        for word in out:
-            if word in com:
-                error += u'禁止ワード.'
-                break
+        kinsi = False
         for line in com.splitlines():
-            if error:
-                break
+            if kinsi is False:
+                for word in out:
+                    if word in line:
+                        error += u'禁止ワード.<br>'
+                        kinsi = True
+                        break
             for word in words:
                 if word in line.lower():
-                    error += u'タグ違反.('+word+')'       
+                    tag = escape.xhtml_escape(word)
+                    error += u'タグ違反.('+tag+')<br>'
             i += len(line)
-            obj = re.finditer('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', 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())
@@ -214,9 +220,11 @@ class RegistHandler(web.RequestHandler):
             if j > 0: 
                 line = line.replace(' ','&nbsp;',j)     
             if len(line) == 0:
-                text += '<br>'
+                text += '<p><br>\n</p>'
             else:
-                text += '<p>'+self.link(line)+'</p>'
+                text += '<p>'+self.link(line,dbname)+'\n</p>'
+        if rule != u'げんき':
+            error += u'合言葉未入力.<br>'
         s = ''
         for x in url:
             s = s+'<tr><td><a href={0} class=livepreview target=_blank>{0}</a></td></tr>'.format(x)
@@ -224,9 +232,12 @@ class RegistHandler(web.RequestHandler):
             text = text+'<table><tr><td>検出url:</td></tr>'+s+'</table>'
         pw = self.get_argument('password')
         if i > 1000:
-            error += u'文字数が1,000をこえました.'
+            error += u'文字数が1,000をこえました.<br>'
         if na == '':
-            na = u'誰かさん'
+            if self.current_user == b'admin':
+                na = u'管理人'
+            else:
+                na = u'誰かさん'
         if sub == '':
             sub = u'タイトルなし.'
         article = self.application.db[dbname]
@@ -236,22 +247,46 @@ class RegistHandler(web.RequestHandler):
             items = article.find()
             item = items.sort('number')[article.count()-1]
             no = item['number']+1
+        s = datetime.now()
+        k = '%Y%m%d%H%M%S'
+        if self.get_argument('show', 'false') == 'true':
+            ch = 'checked'
+        else:
+            ch = ''
+            t = self.get_cookie('time')
+            if t and s - datetime.strptime(escape.url_unescape(t),k) < timedelta(seconds=10):
+                error += u'二重送信.'
+        img = self.get_argument('img','')
+        if img:
+            img = '<div style=text-align:center><img src="' + escape.url_unescape(img) + '"/></div>'
         if error == '':
-            self.set_cookie('aikotoba',escape.url_escape(rule))
-            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)
-            self.set_cookie('username',escape.url_escape(na))
-            self.redirect('/'+dbname+'#article')
+            if ch == 'checked':
+                error = '<p style=font-size:2.5em;color:blue>↓↓プレビュー↓↓</p>\n' + text
+                ch = ''
+            else:
+                com += img
+                text += img
+                reg = {'number': no, 'name': na, 'title': sub, 'comment': text, 'raw': com, 'password': pw,
+                    'date': s.strftime('%Y/%m/%d %H:%M')}
+                article.insert(reg)
+                self.set_cookie('aikotoba', escape.url_escape(rule))
+                self.set_cookie('username', escape.url_escape(na))
+                self.set_cookie('time',escape.url_escape(s.strftime(k)))
+                self.redirect('/' + dbname + '#article')
+                return
         else:
-            self.render('regist.htm',content=error)
-    
-    def link(self,command):
+            error = '<p style=color:red>' + error + '</p>'
+        self.na = na
+        self.rule = rule
+        self.pos = 0
+        self.render_admin(dbname,title=sub,com=com,er=error,ch=ch,img=img)
+
+    def link(self,command,database):
         i = 0
         text = ''
         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:])
+            s = '<a class=minpreview data-preview-url=/{0}?key={1} href=/{0}/userdel?job={1}>>>{1}</a>'.format(database,x.group()[2:])
             text = text+command[i:x.start()]+s
             i = x.end()
         else:
@@ -263,9 +298,7 @@ class AdminHandler(BaseHandler):
     def get(self,dbname,page='0'):
         if dbname == '':
             dbname = self.get_argument('record','')
-        if dbname not in self.application.coll():
-            raise web.HTTPError(404)
-        table = self.application.db[dbname] 
+        table = self.application.db[dbname]
         rec = table.find().sort('number')                   
         mente = self.application.db['params'].find_one({'app':'bbs'})
         if mente['mentenance'] is True:
@@ -346,7 +379,7 @@ class SearchHandler(web.RequestHandler):
         self.render('modules/search.htm',records=rec,word1=arg,db=dbname)
 
     def get(self,dbname=''):
-        if dbname not in self.application.coll() and dbname != '':
+        if dbname not in self.application.coll(info=True) and dbname != '':
             raise web.HTTPError(404)
         self.render('modules/search.htm',records=[],word1='',db=dbname)
     
@@ -522,7 +555,7 @@ class ListApi(web.RequestHandler):
             response = {}
         self.write(json.dumps(response,ensure_ascii=False))
 
-class WebHookHandler(web.RequestHandler):        
+class WebHookHandler(web.RequestHandler):
     def main(self, no):
         #pz = pytz.timezone('Asia/Tokyo')
         now = datetime.now()#pz)
@@ -561,14 +594,14 @@ class WebHookHandler(web.RequestHandler):
     def help(self):
         s = '-*-database names-*-\n'
         out = ['objectlabs-system','objectlabs-system.admin.collections','users_bot']
-        for x in self.application.db.collection_names(include_system_collections=False):
-            if not x in out and x[-4:] == '_bot' and x != '_bot':
+        for x in self.application.mylist():
+            if x not in out and x[-4:] == '_bot' and x != '_bot':
                 s += x[:-4]+'\n'
         return s
     
     def setting(self, dbname):
         dbname = dbname.lower()+'_bot'
-        ca = self.application.db.collection_names(include_system_collections=False)
+        ca = self.application.mylist()
         if 'users_bos' in ca:
             ca.remove('users_bot')
         if dbname in ca:
@@ -617,7 +650,7 @@ class WebHookHandler(web.RequestHandler):
                     token = item['access_token']
                 else:      
                     token =self.application.tk
-                if not bot in self.application.db.collection_names() or not self.application.db[bot].find_one({'name':self.uid}):
+                if bot not in self.application.mylist() or not self.application.db[bot].find_one({'name':self.uid}):
                     db = self.application.db[bot]
                     db.insert({'name':self.uid, 'dbname':de})
                 x = event['message']['text']     
@@ -634,7 +667,7 @@ class InitHandler(web.RequestHandler):
     def get(self):        
         de = self.get_argument('default', '')     
         if de == '':
-            names = self.application.db.collection_names()
+            names = self.application.mylist()
             db = []
             for x in names:
                 if x[-4:] == '_bot' and x != 'users_bot':
@@ -692,15 +725,14 @@ class TokenHandler(web.RequestHandler):
         http.fetch(req, callback=self.on_response)
 
 class Application(web.Application):
-    id = os.environ['Bot_Id']  
     ch = os.environ['Channel_Secret']
     uri = os.environ['MONGODB_URI']
-    ac = os.environ['ACCOUNT']   
-    tk = os.environ['long_token']
+    ac = os.environ['ACCOUNT']
+    tk = os.environ['Access_Token']
     db = pymongo.MongoClient(uri)[ac]
     def __init__(self):
         handlers = [(r'/',NaviHandler),(r'/login',LoginHandler),(r'/logout',LogoutHandler),(r'/title',TitleHandler),
-                    (r'/headline/api',HeadlineApi),(r'/read/api/([a-zA-Z0-9_]+)/([0-9]+)',ArticleApi),
+                    (r'/headline/api',HeadlineApi),(r'/read/api/([a-zA-Z0-9_%]+)/([0-9]+)',ArticleApi),
                     (r'/write/api/([a-zA-Z0-9_%]+)/()/()/()',ArticleApi),(r'/list/api/([a-zA-Z0-9_%]+)',ListApi),
                     (r'/help',HelpHandler),(r'/master',MasterHandler),(r'/alert',AlertHandler),(r'/jump',JumpHandler),
                     (r'/callback',WebHookHandler),(r'/init',InitHandler),(r'/search',SearchHandler),(r'/clean',CleanHandler),(r'/token',TokenHandler),
@@ -736,12 +768,18 @@ class Application(web.Application):
         else:
             return '/'+dbname+'#'+number
 
-    def coll(self):
-        name = self.db.collection_names()
-        for x in ['objectlabs-system.admin.collections','objectlabs-system','system.indexes',
-                  'params','master','temp']:
-            if x in name:
-                name.remove(x)
+    def mylist(self):
+        return self.db.list_collection_names()[:]
+
+    def coll(self,info=False):
+        name = self.mylist()
+        item = self.db['params'].find_one({'app':'bbs'})
+        target = ['objectlabs-system', 'objectlabs-system.admin.collections', 'system.indexes',
+            'params', 'master', 'temp']
+        if info is False:
+            target.append(item['info name'])
+        for x in target:
+            name.remove(x)
         for x in name:
             if x[-4:] == '_bot':
                 name.remove(x)