Selaa lähdekoodia

Merge branch 'master' of https://github.com/2DU/opennamu

Surplus_Up (2DU) 7 vuotta sitten
vanhempi
sitoutus
fb5d535416
12 muutettua tiedostoa jossa 673 lisäystä ja 634 poistoa
  1. 3 3
      Docker-Install.md
  2. 12 630
      app.py
  3. 1 1
      language/ko-KR.json
  4. 69 0
      route/close_topic_list.py
  5. 83 0
      route/manager.py
  6. 45 0
      route/other.py
  7. 72 0
      route/title_index.py
  8. 201 0
      route/topic.py
  9. 77 0
      route/topic_admin.py
  10. 55 0
      route/topic_stop.py
  11. 23 0
      route/topic_top.py
  12. 32 0
      route/user_tool.py

+ 3 - 3
Docker-Install.md

@@ -1,10 +1,10 @@
 ## Installation
 ```
-docker pull opennamu/opennamu
+docker pull opennamu/stable
 ```
 
 ## Start
 ```
-docker run -p 3000:3000 -v data:/app/data --name opennamu opennamu/opennamu
-docker run -p <host-port>:3000 -v <host-data_directory>:/app/data --name <docker-containername> opennamu/opennamu
+docker run -p 3000:3000 -v data:/app/data --name opennamu opennamu/stable
+docker run -p <host-port>:3000 -v <host-data_directory>:/app/data --name <docker-containername> opennamu/stable
 ```

+ 12 - 630
app.py

@@ -408,664 +408,46 @@ def move(name = None):
 
 @app.route('/other')
 def other():
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [load_lang('other_tool'), wiki_set(), custom(), other2([0, 0])],
-        data =  '''
-                <h2>''' + load_lang('record') + '''</h2>
-                <ul>
-                    <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
-                    <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('list') + '''</h2>
-                <ul>
-                    <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
-                    <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
-                    <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
-                    <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
-                    <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
-                    <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
-                    <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
-                    <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
-                    <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('other') + '''</h2>
-                <ul>
-                    <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
-                    <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('admin') + '''</h2>
-                <ul>
-                    <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('version') + '''</h2>
-                <ul>
-                    <li>''' + load_lang('version') + ' : <a id="out_link" href="https://github.com/2DU/opennamu/blob/master/version.md">' + r_ver + '''</a></li>
-                </ul>
-                ''',
-        menu = 0
-    ))
+    return other_2(conn)
     
 @app.route('/manager', methods=['POST', 'GET'])
 @app.route('/manager/<int:num>', methods=['POST', 'GET'])
 def manager(num = 1):
-    title_list = {
-        0 : [load_lang('document_name'), 'acl'], 
-        1 : [0, 'check'], 
-        2 : [0, 'ban'], 
-        3 : [0, 'admin'], 
-        4 : [0, 'record'], 
-        5 : [0, 'topic_record'], 
-        6 : [load_lang('name'), 'admin_plus'], 
-        7 : [load_lang('name'), 'plus_edit_filter'], 
-        8 : [load_lang('document_name'), 'search'], 
-        9 : [0, 'block_user'], 
-        10 : [0, 'block_admin'], 
-        11 : [load_lang('document_name'), 'watch_list'], 
-        12 : [load_lang('compare_target'), 'check'], 
-        13 : [load_lang('document_name'), 'edit']
-    }
-    
-    if num == 1:
-        return easy_minify(flask.render_template(skin_check(), 
-            imp = [load_lang('admin_tool'), wiki_set(), custom(), other2([0, 0])],
-            data =  '''
-                    <h2>''' + load_lang('admin') + '''</h2>
-                    <ul>
-                        <li><a href="/manager/2">''' + load_lang('acl_document_list') + '''</a></li>
-                        <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
-                        <li><a href="/manager/4">''' + load_lang('ban') + '''</a></li>
-                        <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
-                        <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
-                    </ul>
-                    <br>
-                    <h2>''' + load_lang('owner') + '''</h2>
-                    <ul>
-                        <li><a href="/manager/8">''' + load_lang('admin_group_add') + '''</a></li>
-                        <li><a href="/setting">''' + load_lang('setting') + '''</a></li>
-                    </ul>
-                    <h3>''' + load_lang('filter') + '''</h3>
-                    <ul>
-                        <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
-                        <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
-                        <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
-                    </ul>
-                    <br>
-                    <h2>''' + load_lang('server') + '''</h2>
-                    <ul>
-                        <li><a href="/indexing">''' + load_lang('indexing') + '''</a></li>
-                        <li><a href="/restart">''' + load_lang('wiki_restart') + '''</a></li>
-                        <li><a href="/update">''' + load_lang('update') + '''</a></li>
-                        <li><a href="/oauth_setting">''' + load_lang('oauth_setting') + '''</a></li>
-                        <li><a href="/adsense_setting">''' + load_lang('adsense_setting') + '''</a></li>
-                    </ul>
-                    ''',
-            menu = [['other', load_lang('return')]]
-        ))
-    elif not num - 1 > len(title_list):
-        if flask.request.method == 'POST':
-            if flask.request.args.get('plus', None):
-                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.args.get('plus', None)) + '?plus=' + flask.request.form.get('name', None))
-            else:
-                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.form.get('name', None)))
-        else:
-            if title_list[(num - 2)][0] == 0:
-                placeholder = load_lang('user_name')
-            else:
-                placeholder = title_list[(num - 2)][0]
-
-            return easy_minify(flask.render_template(skin_check(), 
-                imp = ['Redirect', wiki_set(), custom(), other2([0, 0])],
-                data =  '''
-                        <form method="post">
-                            <input placeholder="''' + placeholder + '''" name="name" type="text">
-                            <hr class=\"main_hr\">
-                            <button type="submit">''' + load_lang('go') + '''</button>
-                        </form>
-                        ''',
-                menu = [['manager', load_lang('return')]]
-            ))
-    else:
-        return redirect()
+    return manager_2(conn, num)
         
 @app.route('/title_index')
 def title_index():
-    page = int(number_check(flask.request.args.get('page', '1')))
-    num = int(number_check(flask.request.args.get('num', '100')))
-    if page * num > 0:
-        sql_num = page * num - num
-    else:
-        sql_num = 0
-
-    all_list = sql_num + 1
-
-    if num > 1000:
-        return re_error('/error/3')
-
-    data = '<a href="/title_index?num=250">(250)</a> <a href="/title_index?num=500">(500)</a> <a href="/title_index?num=1000">(1000)</a>'
-
-    curs.execute("select title from data order by title asc limit ?, ?", [str(sql_num), str(num)])
-    title_list = curs.fetchall()
-    if title_list:
-        data += '<hr class=\"main_hr\"><ul>'
-
-    for list_data in title_list:
-        data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + list_data[0] + '</a></li>'        
-        all_list += 1
-
-    if page == 1:
-        count_end = []
-
-        curs.execute("select count(title) from data")
-        count = curs.fetchall()
-        if count:
-            count_end += [count[0][0]]
-        else:
-            count_end += [0]
-
-        sql_list = [load_lang('template', 1).lower() + ':', 'category:', 'user:', 'file:']
-        for sql in sql_list:
-            curs.execute("select count(title) from data where title like ?", [sql + '%'])
-            count = curs.fetchall()
-            if count:
-                count_end += [count[0][0]]
-            else:
-                count_end += [0]
-
-        count_end += [count_end[0] - count_end[1]  - count_end[2]  - count_end[3]  - count_end[4]]
-        
-        data += '''
-                </ul>
-                <hr class=\"main_hr\">
-                <ul>
-                    <li>all : ''' + str(count_end[0]) + '''</li>
-                </ul>
-                <hr class=\"main_hr\">
-                <ul>
-                    <li>''' + load_lang('template') + ' : ' + str(count_end[1]) + '''</li>
-                    <li>''' + load_lang('category') + ' : ' + str(count_end[2]) + '''</li>
-                    <li>''' + load_lang('user') + ' : ' + str(count_end[3]) + '''</li>
-                    <li>''' + load_lang('file') + ' : ' + str(count_end[4]) + '''</li>
-                    <li>other : ''' + str(count_end[5]) + '''</li>
-                '''
-
-    data += '</ul>' + next_fix('/title_index?num=' + str(num) + '&page=', page, title_list, num)
-    sub = ' (' + str(num) + ')'
-    
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [load_lang('all_document_list'), wiki_set(), custom(), other2([sub, 0])],
-        data = data,
-        menu = [['other', load_lang('return')]]
-    ))
-        
+    return title_index_2(conn)
+                
 @app.route('/topic/<everything:name>/sub/<sub>/b/<int:num>')
 def topic_block(name = None, sub = None, num = 1):
-    if admin_check(3, 'blind (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
-        return re_error('/error/3')
-
-    curs.execute("select block from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-    block = curs.fetchall()
-    if block:
-        if block[0][0] == 'O':
-            curs.execute("update topic set block = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-        else:
-            curs.execute("update topic set block = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-        
-        rd_plus(name, sub, get_time())
-        
-        conn.commit()
-        
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))
+    return topic_block_2(conn, name, sub, num)
         
 @app.route('/topic/<everything:name>/sub/<sub>/notice/<int:num>')
 def topic_top(name = None, sub = None, num = 1):
-    if admin_check(3, 'notice (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
-        return re_error('/error/3')
-
-    curs.execute("select title from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-    if curs.fetchall():
-        curs.execute("select top from topic where id = ? and title = ? and sub = ?", [str(num), name, sub])
-        top_data = curs.fetchall()
-        if top_data:
-            if top_data[0][0] == 'O':
-                curs.execute("update topic set top = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-            else:
-                curs.execute("update topic set top = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-        
-        rd_plus(name, sub, get_time())
-
-        conn.commit()
-
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))        
-        
+    return topic_top_2(conn, name, sub, num)
+                
 @app.route('/topic/<everything:name>/sub/<sub>/tool/<regex("close|stop|agree"):tool>')
 def topic_stop(name = None, sub = None, tool = None):
-    if tool == 'close':
-        set_list = [
-            'O', 
-            'S', 
-            load_lang('close', 1), 
-            load_lang('open', 1)
-        ]
-    elif tool == 'stop':
-        set_list = [
-            '', 
-            'O', 
-            load_lang('stop', 1), 
-            load_lang('restart', 1)
-        ]
-    elif tool == 'agree':
-        pass
-    else:
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
-
-    if admin_check(3, 'topic ' + tool + ' (' + name + ' - ' + sub + ')') != 1:
-        return re_error('/error/3')
-
-    ip = ip_check()
-    time = get_time()
-    
-    curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
-    topic_check = curs.fetchall()
-    if topic_check:
-        if tool == 'agree':
-            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
-            if curs.fetchall():
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " X', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
-                curs.execute("update rd set agree = '' where title = ? and sub = ?", [name, sub])
-            else:
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " O', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
-                curs.execute("update rd set agree = 'O' where title = ? and sub = ?", [name, sub])
-        else:
-            curs.execute("select title from rd where title = ? and sub = ? and stop = ?", [name, sub, set_list[0]])
-            if curs.fetchall():
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[3], time, ip])
-                curs.execute("update rd set stop = '' where title = ? and sub = ?", [name, sub])
-            else:
-                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[2], time, ip])
-                curs.execute("update rd set stop = ? where title = ? and sub = ?", [set_list[0], name, sub])
-        
-        rd_plus(name, sub, time)
-        
-        conn.commit()
-        
-    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))    
+    return topic_stop_2(conn, name, sub, tool)
 
 @app.route('/topic/<everything:name>/sub/<sub>/admin/<int:num>')
 def topic_admin(name = None, sub = None, num = 1):
-    curs.execute("select block, ip, date from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
-    data = curs.fetchall()
-    if not data:
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
-
-    ban = ''
-
-    if admin_check(3) == 1:
-        ban +=  '''
-                </ul>
-                <br>
-                <h2>''' + load_lang('admin_tool') + '''</h2>
-                <ul>
-                '''
-        is_ban = '<li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(num) + '">'
-
-        if data[0][0] == 'O':
-            is_ban += load_lang('hide_release')
-        else:
-            is_ban += load_lang('hide')
-        
-        is_ban +=   '''
-                        </a>
-                    </li>
-                    <li>
-                        <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/notice/' + str(num) + '''">
-                    '''
-
-        curs.execute("select id from topic where title = ? and sub = ? and id = ? and top = 'O'", [name, sub, str(num)])
-        if curs.fetchall():
-            is_ban += load_lang('notice_release')
-        else:
-            is_ban += load_lang('notice') + ''
-        
-        is_ban += '</a></li></ul>'
-        ban += '<li><a href="/ban/' + url_pas(data[0][1]) + '">'
-
-        curs.execute("select end from ban where block = ?", [data[0][1]])
-        if curs.fetchall():
-            ban += load_lang('ban_release')
-        else:
-            ban += load_lang('ban')
-        
-        ban += '</a></li>' + is_ban
-
-    ban +=  '''
-            </ul>
-            <br>
-            <h2>''' + load_lang('other_tool') + '''</h2>
-            <ul>
-                <li>
-                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/raw/' + str(num) + '''">raw</a>
-                </li>
-            '''
-    ban = '<li>' + load_lang('time') + ' : ' + data[0][2] + '</li>' + ban
-    
-    if ip_or_user(data[0][1]) == 1:
-        ban = '<li>' + load_lang('writer') + ' : ' + data[0][1] + ' <a href="/record/' + url_pas(data[0][1]) + '">(' + load_lang('record') + ')</a></li>' + ban
-    else:
-        ban =   '''
-                <li>
-                    ''' + load_lang('writer') + ' : <a href="/w/user:' + data[0][1] + '">' + data[0][1] + '</a> <a href="/record/' + url_pas(data[0][1]) + '">(' + load_lang('record') + ''')</a>
-                </li>
-                ''' + ban
-
-    ban = '<h2>' + load_lang('state') + '</h2><ul>' + ban
-
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [load_lang('discussion_tool'), wiki_set(), custom(), other2([' (' + str(num) + ')', 0])],
-        data = ban,
-        menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num), load_lang('return')]]
-    ))
+    return topic_admin_2(conn, name, sub, num)
 
 @app.route('/topic/<everything:name>/sub/<sub>', methods=['POST', 'GET'])
 def topic(name = None, sub = None):
-    ban = topic_check(name, sub)
-    admin = admin_check(3)
-    
-    if flask.request.method == 'POST':
-        if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
-            return re_error('/error/13')
-        else:
-            captcha_post('', 0)
-
-        ip = ip_check()
-        today = get_time()
-        
-        if ban == 1:
-            return re_error('/ban')
-        
-        curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
-        old_num = curs.fetchall()
-        if old_num:
-            num = int(old_num[0][0]) + 1
-        else:
-            num = 1
-
-        match = re.search('^user:([^/]+)', name)
-        if match:
-            curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [match.groups()[0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + load_lang('user_discussion', 1) + '</a>', today])
-        
-        data = re.sub('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', '[br]', flask.request.form.get('content', None))
-        for rd_data in re.findall("(?:#([0-9]+))", data):
-            curs.execute("select ip from topic where title = ? and sub = ? and id = ?", [name, sub, rd_data])
-            ip_data = curs.fetchall()
-            if ip_data and ip_or_user(ip_data[0][0]) == 0:
-                curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [ip_data[0][0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num) + '">' + load_lang('discussion', 1) + '</a>', today])
-            
-        data = re.sub("(?P<in>#(?:[0-9]+))", '[[\g<in>]]', data)
-
-        data = savemark(data)
-
-        rd_plus(name, sub, today)
-
-        curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '')", [str(num), name, sub, data, today, ip])
-        conn.commit()
-        
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#reload')
-    else:
-        curs.execute("select title from rd where title = ? and sub = ? and stop = 'O'", [name, sub])
-        close_data = curs.fetchall()
-        
-        curs.execute("select title from rd where title = ? and sub = ? and stop = 'S'", [name, sub])
-        stop_data = curs.fetchall()
-        
-        curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub])
-        topic_exist = curs.fetchall()
-        
-        display = ''
-        all_data = ''
-        data = ''
-        number = 1
-        
-        if admin == 1 and topic_exist:
-            if close_data:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('open') + ')</a> '
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('close') + ')</a> '
-            
-            if stop_data:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('restart') + ')</a> '
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('stop') + ')</a> '
-
-            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
-            if curs.fetchall():
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('destruction') + ')</a>'
-            else:
-                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('agreement') + ')</a>'
-            
-            all_data += '<hr class=\"main_hr\">'
-        
-        if (close_data or stop_data) and admin != 1:
-            display = 'display: none;'
-        
-        curs.execute("select data, id, date, ip, block, top from topic where title = ? and sub = ? order by id + 0 asc", [name, sub])
-        topic = curs.fetchall()
-        
-        curs.execute("select data, id, date, ip from topic where title = ? and sub = ? and top = 'O' order by id + 0 asc", [name, sub])
-        for topic_data in curs.fetchall():                   
-            who_plus = ''
-            
-            curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['notice (' + name + ' - ' + sub + '#' + topic_data[1] + ')'])
-            topic_data_top = curs.fetchall()
-            if topic_data_top:
-                who_plus += ' <span style="margin-right: 5px;">@' + topic_data_top[0][0] + ' </span>'
-                                
-            all_data += '''
-                        <table id="toron">
-                            <tbody>
-                                <tr>
-                                    <td id="toron_color_red">
-                                        <a href="#''' + topic_data[1] + '''">
-                                            #''' + topic_data[1] + '''
-                                        </a> ''' + ip_pas(topic_data[3]) + who_plus + ''' <span style="float: right;">''' + topic_data[2] + '''</span>
-                                    </td>
-                                </tr>
-                                <tr>
-                                    <td>''' + render_set(data = topic_data[0]) + '''</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                        <br>
-                        '''    
-
-        for topic_data in topic:
-            user_write = topic_data[0]
-
-            if number == 1:
-                start = topic_data[3]
-
-            if topic_data[4] == 'O':
-                blind_data = 'id="toron_color_grey"'
-                
-                if admin != 1:
-                    curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['blind (' + name + ' - ' + sub + '#' + str(number) + ')'])
-                    who_blind = curs.fetchall()
-                    if who_blind:
-                        user_write = '[[user:' + who_blind[0][0] + ']] ' + load_lang('hide')
-                    else:
-                        user_write = load_lang('hide')
-            else:
-                blind_data = ''
-
-            user_write = render_set(data = user_write)
-            ip = ip_pas(topic_data[3])
-            
-            curs.execute('select acl from user where id = ?', [topic_data[3]])
-            user_acl = curs.fetchall()
-            if user_acl and user_acl[0][0] != 'user':
-                ip += ' <a href="javascript:void(0);" title="' + load_lang('admin') + '">★</a>'
-
-            if admin == 1 or blind_data == '':
-                ip += ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/admin/' + str(number) + '">(' + load_lang('discussion_tool') + ')</a>'
-
-            curs.execute("select end from ban where block = ?", [topic_data[3]])
-            if curs.fetchall():
-                ip += ' <a href="javascript:void(0);" title="' + load_lang('blocked') + '">†</a>'
-                    
-            if topic_data[5] == '1':
-                color = '_blue'
-            elif topic_data[3] == start:
-                color = '_green'
-            else:
-                color = ''
-                
-            if user_write == '':
-                user_write = '<br>'
-                         
-            all_data += '''
-                        <table id="toron">
-                            <tbody>
-                                <tr>
-                                    <td id="toron_color''' + color + '''">
-                                        <a href="javascript:void(0);" id="''' + str(number) + '">#' + str(number) + '</a> ' + ip + '''</span>
-                                    </td>
-                                </tr>
-                                <tr ''' + blind_data + '''>
-                                    <td>''' + user_write + '''</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                        <br>
-                        '''
-            number += 1
-
-        if ban != 1 or admin == 1:
-            data += '''
-                    <div id="plus"></div>
-                    <script type="text/javascript" src="/views/main_css/topic_reload.js"></script>
-                    <script>topic_load("''' + name + '''", "''' + sub + '''");</script>
-                    <a id="reload" href="javascript:void(0);" onclick="location.href.endsWith(\'#reload\')? location.reload(true):location.href=\'#reload\'">(''' + load_lang('reload') + ''')</a>
-                    <form style="''' + display + '''" method="post">
-                    <br>
-                    <textarea style="height: 100px;" name="content"></textarea>
-                    <hr class=\"main_hr\">
-                    ''' + captcha_get()
-            
-            if display == '':
-                data += ip_warring()
-
-            data += '''
-                        <button type="submit">''' + load_lang('send') + '''</button>
-                    </form>
-                    '''
-
-        return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2([' (' + load_lang('discussion') + ')', 0])],
-            data = '<h2 id="topic_top_title">' + sub + '</h2>' + all_data + data,
-            menu = [['topic/' + url_pas(name), load_lang('list')]]
-        ))
+    return topic_2(conn, name, sub)
 
 @app.route('/tool/<name>')
 def user_tool(name = None):
-    data =  '''
-            <h2>''' + load_lang('tool') + '''</h2>
-            <ul>
-                <li><a href="/record/''' + url_pas(name) + '''">''' + load_lang('record') + '''</a></li>
-            </ul>
-            '''
-            
-    if admin_check(1) == 1:
-        curs.execute("select block from ban where block = ?", [name])
-        if curs.fetchall():
-            ban_name = load_lang('ban_release')
-        else:
-            ban_name = load_lang('ban')
-    
-        data += '''
-                <h2>''' + load_lang('admin') + '''</h2>
-                <ul>
-                    <li><a href="/ban/''' + url_pas(name) + '''">''' + ban_name + '''</a></li>
-                    <li><a href="/check/''' + url_pas(name) + '''">''' + load_lang('check') + '''</a></li>
-                </ul>
-                '''
-
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [name, wiki_set(), custom(), other2([' (' + load_lang('tool') + ')', 0])],
-        data = data,
-        menu = 0
-    ))
+    return user_tool_2(conn, name)
         
 @app.route('/topic/<everything:name>', methods=['POST', 'GET'])
 @app.route('/topic/<everything:name>/<regex("close|agree"):tool>', methods=['GET'])
 def close_topic_list(name = None, tool = None):
-    div = ''
-    
-    if flask.request.method == 'POST':
-        t_num = ''
-        
-        while 1:
-            curs.execute("select title from topic where title = ? and sub = ? limit 1", [name, flask.request.form.get('topic', None) + t_num])
-            if curs.fetchall():
-                if t_num == '':
-                    t_num = ' 2'
-                else:
-                    t_num = ' ' + str(int(t_num.replace(' ', '')) + 1)
-            else:
-                break
-
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(flask.request.form.get('topic', None) + t_num))
-    else:
-        plus = ''
-        menu = [['topic/' + url_pas(name), load_lang('return')]]
-        
-        if tool == 'close':
-            curs.execute("select sub from rd where title = ? and stop = 'O' order by sub asc", [name])
-            
-            sub = load_lang('close') + ''
-        elif tool == 'agree':
-            curs.execute("select sub from rd where title = ? and agree = 'O' order by sub asc", [name])
-            
-            sub = load_lang('agreement') + ''
-        else:
-            curs.execute("select sub from rd where title = ? order by date desc", [name])
-            
-            sub = load_lang('discussion_list')
+    return close_topic_list_2(conn, name, tool)
             
-            menu = [['w/' + url_pas(name), load_lang('document')]]
-            
-            plus =  '''
-                    <a href="/topic/''' + url_pas(name) + '''/close">(''' + load_lang('close') + ''')</a> <a href="/topic/''' + url_pas(name) + '''/agree">(''' + load_lang('agreement') + ''')</a>
-                    <hr class=\"main_hr\">
-                    <input placeholder="''' + load_lang('discussion_name') + '''" name="topic" type="text">
-                    <hr class=\"main_hr\">
-                    <button type="submit">''' + load_lang('go') + '''</button>
-                    '''
-
-        for data in curs.fetchall():
-            curs.execute("select data, date, ip, block from topic where title = ? and sub = ? and id = '1'", [name, data[0]])
-            if curs.fetchall():                
-                it_p = 0
-                
-                if sub == load_lang('discussion_list'):
-                    curs.execute("select title from rd where title = ? and sub = ? and stop = 'O' order by sub asc", [name, data[0]])
-                    if curs.fetchall():
-                        it_p = 1
-                
-                if it_p != 1:
-                    div += '<h2><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(data[0]) + '">' + data[0] + '</a></h2>'
-
-        if div == '':
-            plus = re.sub('^<br>', '', plus)
-        
-        return easy_minify(flask.render_template(skin_check(), 
-            imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
-            data =  '<form method="post">' + div + plus + '</form>',
-            menu = menu
-        ))
-        
 @app.route('/login', methods=['POST', 'GET'])
 def login():
     if custom()[2] != 0:

+ 1 - 1
language/ko-KR.json

@@ -105,7 +105,7 @@
         "recent_change" : "최근 수정",
         "edit_filter" : "편집 필터",
         "recent_ban" : "최근 차단",
-        "load" : "다른 문서 연결",
+        "load" : "다른 문서 불러오기",
         "edit_filter_rule" : "편집 필터 규칙",
         "move_history" : "이동 기록",
         "other_tool" : "기타 도구",

+ 69 - 0
route/close_topic_list.py

@@ -0,0 +1,69 @@
+from .tool.func import *
+
+def close_topic_list_2(conn, name, tool):
+    curs = conn.cursor()
+    
+    div = ''
+    
+    if flask.request.method == 'POST':
+        t_num = ''
+        
+        while 1:
+            curs.execute("select title from topic where title = ? and sub = ? limit 1", [name, flask.request.form.get('topic', None) + t_num])
+            if curs.fetchall():
+                if t_num == '':
+                    t_num = ' 2'
+                else:
+                    t_num = ' ' + str(int(t_num.replace(' ', '')) + 1)
+            else:
+                break
+
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(flask.request.form.get('topic', None) + t_num))
+    else:
+        plus = ''
+        menu = [['topic/' + url_pas(name), load_lang('return')]]
+        
+        if tool == 'close':
+            curs.execute("select sub from rd where title = ? and stop = 'O' order by sub asc", [name])
+            
+            sub = load_lang('close') + ''
+        elif tool == 'agree':
+            curs.execute("select sub from rd where title = ? and agree = 'O' order by sub asc", [name])
+            
+            sub = load_lang('agreement') + ''
+        else:
+            curs.execute("select sub from rd where title = ? order by date desc", [name])
+            
+            sub = load_lang('discussion_list')
+            
+            menu = [['w/' + url_pas(name), load_lang('document')]]
+            
+            plus =  '''
+                    <a href="/topic/''' + url_pas(name) + '''/close">(''' + load_lang('close') + ''')</a> <a href="/topic/''' + url_pas(name) + '''/agree">(''' + load_lang('agreement') + ''')</a>
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('discussion_name') + '''" name="topic" type="text">
+                    <hr class=\"main_hr\">
+                    <button type="submit">''' + load_lang('go') + '''</button>
+                    '''
+
+        for data in curs.fetchall():
+            curs.execute("select data, date, ip, block from topic where title = ? and sub = ? and id = '1'", [name, data[0]])
+            if curs.fetchall():                
+                it_p = 0
+                
+                if sub == load_lang('discussion_list'):
+                    curs.execute("select title from rd where title = ? and sub = ? and stop = 'O' order by sub asc", [name, data[0]])
+                    if curs.fetchall():
+                        it_p = 1
+                
+                if it_p != 1:
+                    div += '<h2><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(data[0]) + '">' + data[0] + '</a></h2>'
+
+        if div == '':
+            plus = re.sub('^<br>', '', plus)
+        
+        return easy_minify(flask.render_template(skin_check(), 
+            imp = [name, wiki_set(), custom(), other2([' (' + sub + ')', 0])],
+            data =  '<form method="post">' + div + plus + '</form>',
+            menu = menu
+        ))

+ 83 - 0
route/manager.py

@@ -0,0 +1,83 @@
+from .tool.func import *
+
+def manager_2(conn, num):
+    curs = conn.cursor()
+    
+    title_list = {
+        0 : [load_lang('document_name'), 'acl'], 
+        1 : [0, 'check'], 
+        2 : [0, 'ban'], 
+        3 : [0, 'admin'], 
+        4 : [0, 'record'], 
+        5 : [0, 'topic_record'], 
+        6 : [load_lang('name'), 'admin_plus'], 
+        7 : [load_lang('name'), 'plus_edit_filter'], 
+        8 : [load_lang('document_name'), 'search'], 
+        9 : [0, 'block_user'], 
+        10 : [0, 'block_admin'], 
+        11 : [load_lang('document_name'), 'watch_list'], 
+        12 : [load_lang('compare_target'), 'check'], 
+        13 : [load_lang('document_name'), 'edit']
+    }
+    
+    if num == 1:
+        return easy_minify(flask.render_template(skin_check(), 
+            imp = [load_lang('admin_tool'), wiki_set(), custom(), other2([0, 0])],
+            data =  '''
+                    <h2>''' + load_lang('admin') + '''</h2>
+                    <ul>
+                        <li><a href="/manager/2">''' + load_lang('acl_document_list') + '''</a></li>
+                        <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
+                        <li><a href="/manager/4">''' + load_lang('ban') + '''</a></li>
+                        <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
+                        <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
+                    </ul>
+                    <br>
+                    <h2>''' + load_lang('owner') + '''</h2>
+                    <ul>
+                        <li><a href="/manager/8">''' + load_lang('admin_group_add') + '''</a></li>
+                        <li><a href="/setting">''' + load_lang('setting') + '''</a></li>
+                    </ul>
+                    <h3>''' + load_lang('filter') + '''</h3>
+                    <ul>
+                        <li><a href="/inter_wiki">''' + load_lang('interwiki_list') + '''</a></li>
+                        <li><a href="/email_filter">''' + load_lang('email_filter_list') + '''</a></li>
+                        <li><a href="/name_filter">''' + load_lang('id_filter_list') + '''</a></li>
+                    </ul>
+                    <br>
+                    <h2>''' + load_lang('server') + '''</h2>
+                    <ul>
+                        <li><a href="/indexing">''' + load_lang('indexing') + '''</a></li>
+                        <li><a href="/restart">''' + load_lang('wiki_restart') + '''</a></li>
+                        <li><a href="/update">''' + load_lang('update') + '''</a></li>
+                        <li><a href="/oauth_setting">''' + load_lang('oauth_setting') + '''</a></li>
+                        <li><a href="/adsense_setting">''' + load_lang('adsense_setting') + '''</a></li>
+                    </ul>
+                    ''',
+            menu = [['other', load_lang('return')]]
+        ))
+    elif not num - 1 > len(title_list):
+        if flask.request.method == 'POST':
+            if flask.request.args.get('plus', None):
+                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.args.get('plus', None)) + '?plus=' + flask.request.form.get('name', None))
+            else:
+                return redirect('/' + title_list[(num - 2)][1] + '/' + url_pas(flask.request.form.get('name', None)))
+        else:
+            if title_list[(num - 2)][0] == 0:
+                placeholder = load_lang('user_name')
+            else:
+                placeholder = title_list[(num - 2)][0]
+
+            return easy_minify(flask.render_template(skin_check(), 
+                imp = ['Redirect', wiki_set(), custom(), other2([0, 0])],
+                data =  '''
+                        <form method="post">
+                            <input placeholder="''' + placeholder + '''" name="name" type="text">
+                            <hr class=\"main_hr\">
+                            <button type="submit">''' + load_lang('go') + '''</button>
+                        </form>
+                        ''',
+                menu = [['manager', load_lang('return')]]
+            ))
+    else:
+        return redirect()

+ 45 - 0
route/other.py

@@ -0,0 +1,45 @@
+from .tool.func import *
+
+def other_2(conn):
+    curs = conn.cursor()
+    
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [load_lang('other_tool'), wiki_set(), custom(), other2([0, 0])],
+        data =  '''
+                <h2>''' + load_lang('record') + '''</h2>
+                <ul>
+                    <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
+                    <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
+                </ul>
+                <br>
+                <h2>''' + load_lang('list') + '''</h2>
+                <ul>
+                    <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
+                    <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
+                    <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
+                    <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
+                    <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
+                    <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
+                    <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
+                    <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
+                    <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
+                </ul>
+                <br>
+                <h2>''' + load_lang('other') + '''</h2>
+                <ul>
+                    <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
+                    <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
+                </ul>
+                <br>
+                <h2>''' + load_lang('admin') + '''</h2>
+                <ul>
+                    <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
+                </ul>
+                <br>
+                <h2>''' + load_lang('version') + '''</h2>
+                <ul>
+                    <li>''' + load_lang('version') + ' : <a id="out_link" href="https://github.com/2DU/opennamu/blob/master/version.md">' + r_ver + '''</a></li>
+                </ul>
+                ''',
+        menu = 0
+    ))

+ 72 - 0
route/title_index.py

@@ -0,0 +1,72 @@
+from .tool.func import *
+
+def title_index_2(conn):
+    curs = conn.cursor()
+    
+    page = int(number_check(flask.request.args.get('page', '1')))
+    num = int(number_check(flask.request.args.get('num', '100')))
+    if page * num > 0:
+        sql_num = page * num - num
+    else:
+        sql_num = 0
+
+    all_list = sql_num + 1
+
+    if num > 1000:
+        return re_error('/error/3')
+
+    data = '<a href="/title_index?num=250">(250)</a> <a href="/title_index?num=500">(500)</a> <a href="/title_index?num=1000">(1000)</a>'
+
+    curs.execute("select title from data order by title asc limit ?, ?", [str(sql_num), str(num)])
+    title_list = curs.fetchall()
+    if title_list:
+        data += '<hr class=\"main_hr\"><ul>'
+
+    for list_data in title_list:
+        data += '<li>' + str(all_list) + '. <a href="/w/' + url_pas(list_data[0]) + '">' + list_data[0] + '</a></li>'        
+        all_list += 1
+
+    if page == 1:
+        count_end = []
+
+        curs.execute("select count(title) from data")
+        count = curs.fetchall()
+        if count:
+            count_end += [count[0][0]]
+        else:
+            count_end += [0]
+
+        sql_list = [load_lang('template', 1).lower() + ':', 'category:', 'user:', 'file:']
+        for sql in sql_list:
+            curs.execute("select count(title) from data where title like ?", [sql + '%'])
+            count = curs.fetchall()
+            if count:
+                count_end += [count[0][0]]
+            else:
+                count_end += [0]
+
+        count_end += [count_end[0] - count_end[1]  - count_end[2]  - count_end[3]  - count_end[4]]
+        
+        data += '''
+                </ul>
+                <hr class=\"main_hr\">
+                <ul>
+                    <li>all : ''' + str(count_end[0]) + '''</li>
+                </ul>
+                <hr class=\"main_hr\">
+                <ul>
+                    <li>''' + load_lang('template') + ' : ' + str(count_end[1]) + '''</li>
+                    <li>''' + load_lang('category') + ' : ' + str(count_end[2]) + '''</li>
+                    <li>''' + load_lang('user') + ' : ' + str(count_end[3]) + '''</li>
+                    <li>''' + load_lang('file') + ' : ' + str(count_end[4]) + '''</li>
+                    <li>other : ''' + str(count_end[5]) + '''</li>
+                '''
+
+    data += '</ul>' + next_fix('/title_index?num=' + str(num) + '&page=', page, title_list, num)
+    sub = ' (' + str(num) + ')'
+    
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [load_lang('all_document_list'), wiki_set(), custom(), other2([sub, 0])],
+        data = data,
+        menu = [['other', load_lang('return')]]
+    ))

+ 201 - 0
route/topic.py

@@ -0,0 +1,201 @@
+from .tool.func import *
+
+def topic_2(conn, name, sub):
+    curs = conn.cursor()
+    
+    ban = topic_check(name, sub)
+    admin = admin_check(3)
+    
+    if flask.request.method == 'POST':
+        if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
+            return re_error('/error/13')
+        else:
+            captcha_post('', 0)
+
+        ip = ip_check()
+        today = get_time()
+        
+        if ban == 1:
+            return re_error('/ban')
+        
+        curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
+        old_num = curs.fetchall()
+        if old_num:
+            num = int(old_num[0][0]) + 1
+        else:
+            num = 1
+
+        match = re.search('^user:([^/]+)', name)
+        if match:
+            curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [match.groups()[0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + load_lang('user_discussion', 1) + '</a>', today])
+        
+        data = re.sub('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', '[br]', flask.request.form.get('content', None))
+        for rd_data in re.findall("(?:#([0-9]+))", data):
+            curs.execute("select ip from topic where title = ? and sub = ? and id = ?", [name, sub, rd_data])
+            ip_data = curs.fetchall()
+            if ip_data and ip_or_user(ip_data[0][0]) == 0:
+                curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [ip_data[0][0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num) + '">' + load_lang('discussion', 1) + '</a>', today])
+            
+        data = re.sub("(?P<in>#(?:[0-9]+))", '[[\g<in>]]', data)
+
+        data = savemark(data)
+
+        rd_plus(name, sub, today)
+
+        curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '')", [str(num), name, sub, data, today, ip])
+        conn.commit()
+        
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#reload')
+    else:
+        curs.execute("select title from rd where title = ? and sub = ? and stop = 'O'", [name, sub])
+        close_data = curs.fetchall()
+        
+        curs.execute("select title from rd where title = ? and sub = ? and stop = 'S'", [name, sub])
+        stop_data = curs.fetchall()
+        
+        curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub])
+        topic_exist = curs.fetchall()
+        
+        display = ''
+        all_data = ''
+        data = ''
+        number = 1
+        
+        if admin == 1 and topic_exist:
+            if close_data:
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('open') + ')</a> '
+            else:
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/close">(' + load_lang('close') + ')</a> '
+            
+            if stop_data:
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('restart') + ')</a> '
+            else:
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/stop">(' + load_lang('stop') + ')</a> '
+
+            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
+            if curs.fetchall():
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('destruction') + ')</a>'
+            else:
+                all_data += '<a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/tool/agree">(' + load_lang('agreement') + ')</a>'
+            
+            all_data += '<hr class=\"main_hr\">'
+        
+        if (close_data or stop_data) and admin != 1:
+            display = 'display: none;'
+        
+        curs.execute("select data, id, date, ip, block, top from topic where title = ? and sub = ? order by id + 0 asc", [name, sub])
+        topic = curs.fetchall()
+        
+        curs.execute("select data, id, date, ip from topic where title = ? and sub = ? and top = 'O' order by id + 0 asc", [name, sub])
+        for topic_data in curs.fetchall():                   
+            who_plus = ''
+            
+            curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['notice (' + name + ' - ' + sub + '#' + topic_data[1] + ')'])
+            topic_data_top = curs.fetchall()
+            if topic_data_top:
+                who_plus += ' <span style="margin-right: 5px;">@' + topic_data_top[0][0] + ' </span>'
+                                
+            all_data += '''
+                        <table id="toron">
+                            <tbody>
+                                <tr>
+                                    <td id="toron_color_red">
+                                        <a href="#''' + topic_data[1] + '''">
+                                            #''' + topic_data[1] + '''
+                                        </a> ''' + ip_pas(topic_data[3]) + who_plus + ''' <span style="float: right;">''' + topic_data[2] + '''</span>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>''' + render_set(data = topic_data[0]) + '''</td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <br>
+                        '''    
+
+        for topic_data in topic:
+            user_write = topic_data[0]
+
+            if number == 1:
+                start = topic_data[3]
+
+            if topic_data[4] == 'O':
+                blind_data = 'id="toron_color_grey"'
+                
+                if admin != 1:
+                    curs.execute("select who from re_admin where what = ? order by time desc limit 1", ['blind (' + name + ' - ' + sub + '#' + str(number) + ')'])
+                    who_blind = curs.fetchall()
+                    if who_blind:
+                        user_write = '[[user:' + who_blind[0][0] + ']] ' + load_lang('hide')
+                    else:
+                        user_write = load_lang('hide')
+            else:
+                blind_data = ''
+
+            user_write = render_set(data = user_write)
+            ip = ip_pas(topic_data[3])
+            
+            curs.execute('select acl from user where id = ?', [topic_data[3]])
+            user_acl = curs.fetchall()
+            if user_acl and user_acl[0][0] != 'user':
+                ip += ' <a href="javascript:void(0);" title="' + load_lang('admin') + '">★</a>'
+
+            if admin == 1 or blind_data == '':
+                ip += ' <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/admin/' + str(number) + '">(' + load_lang('discussion_tool') + ')</a>'
+
+            curs.execute("select end from ban where block = ?", [topic_data[3]])
+            if curs.fetchall():
+                ip += ' <a href="javascript:void(0);" title="' + load_lang('blocked') + '">†</a>'
+                    
+            if topic_data[5] == '1':
+                color = '_blue'
+            elif topic_data[3] == start:
+                color = '_green'
+            else:
+                color = ''
+                
+            if user_write == '':
+                user_write = '<br>'
+                         
+            all_data += '''
+                        <table id="toron">
+                            <tbody>
+                                <tr>
+                                    <td id="toron_color''' + color + '''">
+                                        <a href="javascript:void(0);" id="''' + str(number) + '">#' + str(number) + '</a> ' + ip + '''</span>
+                                    </td>
+                                </tr>
+                                <tr ''' + blind_data + '''>
+                                    <td>''' + user_write + '''</td>
+                                </tr>
+                            </tbody>
+                        </table>
+                        <br>
+                        '''
+            number += 1
+
+        if ban != 1 or admin == 1:
+            data += '''
+                    <div id="plus"></div>
+                    <script type="text/javascript" src="/views/main_css/topic_reload.js"></script>
+                    <script>topic_load("''' + name + '''", "''' + sub + '''");</script>
+                    <a id="reload" href="javascript:void(0);" onclick="location.href.endsWith(\'#reload\')? location.reload(true):location.href=\'#reload\'">(''' + load_lang('reload') + ''')</a>
+                    <form style="''' + display + '''" method="post">
+                    <br>
+                    <textarea style="height: 100px;" name="content"></textarea>
+                    <hr class=\"main_hr\">
+                    ''' + captcha_get()
+            
+            if display == '':
+                data += ip_warring()
+
+            data += '''
+                        <button type="submit">''' + load_lang('send') + '''</button>
+                    </form>
+                    '''
+
+        return easy_minify(flask.render_template(skin_check(), 
+            imp = [name, wiki_set(), custom(), other2([' (' + load_lang('discussion') + ')', 0])],
+            data = '<h2 id="topic_top_title">' + sub + '</h2>' + all_data + data,
+            menu = [['topic/' + url_pas(name), load_lang('list')]]
+        ))

+ 77 - 0
route/topic_admin.py

@@ -0,0 +1,77 @@
+from .tool.func import *
+
+def topic_admin_2(conn, name, sub, num):
+    curs = conn.cursor()
+
+    curs.execute("select block, ip, date from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+    data = curs.fetchall()
+    if not data:
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
+
+    ban = ''
+
+    if admin_check(3) == 1:
+        ban +=  '''
+                </ul>
+                <br>
+                <h2>''' + load_lang('admin_tool') + '''</h2>
+                <ul>
+                '''
+        is_ban = '<li><a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '/b/' + str(num) + '">'
+
+        if data[0][0] == 'O':
+            is_ban += load_lang('hide_release')
+        else:
+            is_ban += load_lang('hide')
+        
+        is_ban +=   '''
+                        </a>
+                    </li>
+                    <li>
+                        <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/notice/' + str(num) + '''">
+                    '''
+
+        curs.execute("select id from topic where title = ? and sub = ? and id = ? and top = 'O'", [name, sub, str(num)])
+        if curs.fetchall():
+            is_ban += load_lang('notice_release')
+        else:
+            is_ban += load_lang('notice') + ''
+        
+        is_ban += '</a></li></ul>'
+        ban += '<li><a href="/ban/' + url_pas(data[0][1]) + '">'
+
+        curs.execute("select end from ban where block = ?", [data[0][1]])
+        if curs.fetchall():
+            ban += load_lang('ban_release')
+        else:
+            ban += load_lang('ban')
+        
+        ban += '</a></li>' + is_ban
+
+    ban +=  '''
+            </ul>
+            <br>
+            <h2>''' + load_lang('other_tool') + '''</h2>
+            <ul>
+                <li>
+                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/raw/' + str(num) + '''">raw</a>
+                </li>
+            '''
+    ban = '<li>' + load_lang('time') + ' : ' + data[0][2] + '</li>' + ban
+    
+    if ip_or_user(data[0][1]) == 1:
+        ban = '<li>' + load_lang('writer') + ' : ' + data[0][1] + ' <a href="/record/' + url_pas(data[0][1]) + '">(' + load_lang('record') + ')</a></li>' + ban
+    else:
+        ban =   '''
+                <li>
+                    ''' + load_lang('writer') + ' : <a href="/w/user:' + data[0][1] + '">' + data[0][1] + '</a> <a href="/record/' + url_pas(data[0][1]) + '">(' + load_lang('record') + ''')</a>
+                </li>
+                ''' + ban
+
+    ban = '<h2>' + load_lang('state') + '</h2><ul>' + ban
+
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [load_lang('discussion_tool'), wiki_set(), custom(), other2([' (' + str(num) + ')', 0])],
+        data = ban,
+        menu = [['topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num), load_lang('return')]]
+    ))

+ 55 - 0
route/topic_stop.py

@@ -0,0 +1,55 @@
+from .tool.func import *
+
+def topic_stop_2(conn, name, sub, tool):
+    curs = conn.cursor()
+
+    if tool == 'close':
+        set_list = [
+            'O', 
+            'S', 
+            load_lang('close', 1), 
+            load_lang('open', 1)
+        ]
+    elif tool == 'stop':
+        set_list = [
+            '', 
+            'O', 
+            load_lang('stop', 1), 
+            load_lang('restart', 1)
+        ]
+    elif tool == 'agree':
+        pass
+    else:
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))
+
+    if admin_check(3, 'topic ' + tool + ' (' + name + ' - ' + sub + ')') != 1:
+        return re_error('/error/3')
+
+    ip = ip_check()
+    time = get_time()
+    
+    curs.execute("select id from topic where title = ? and sub = ? order by id + 0 desc limit 1", [name, sub])
+    topic_check = curs.fetchall()
+    if topic_check:
+        if tool == 'agree':
+            curs.execute("select title from rd where title = ? and sub = ? and agree = 'O'", [name, sub])
+            if curs.fetchall():
+                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " X', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
+                curs.execute("update rd set agree = '' where title = ? and sub = ?", [name, sub])
+            else:
+                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, '" + load_lang('agreement', 1) + " O', ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, time, ip])
+                curs.execute("update rd set agree = 'O' where title = ? and sub = ?", [name, sub])
+        else:
+            curs.execute("select title from rd where title = ? and sub = ? and stop = ?", [name, sub, set_list[0]])
+            if curs.fetchall():
+                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[3], time, ip])
+                curs.execute("update rd set stop = '' where title = ? and sub = ?", [name, sub])
+            else:
+                curs.execute("insert into topic (id, title, sub, data, date, ip, block, top) values (?, ?, ?, ?, ?, ?, '', '1')", [str(int(topic_check[0][0]) + 1), name, sub, set_list[2], time, ip])
+                curs.execute("update rd set stop = ? where title = ? and sub = ?", [set_list[0], name, sub])
+        
+        rd_plus(name, sub, time)
+        
+        conn.commit()
+        
+    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub))    

+ 23 - 0
route/topic_top.py

@@ -0,0 +1,23 @@
+from .tool.func import *
+
+def topic_top_2(conn, name, sub, num):
+    curs = conn.cursor()
+    
+    if admin_check(3, 'notice (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
+        return re_error('/error/3')
+
+    curs.execute("select title from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+    if curs.fetchall():
+        curs.execute("select top from topic where id = ? and title = ? and sub = ?", [str(num), name, sub])
+        top_data = curs.fetchall()
+        if top_data:
+            if top_data[0][0] == 'O':
+                curs.execute("update topic set top = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+            else:
+                curs.execute("update topic set top = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+        
+        rd_plus(name, sub, get_time())
+
+        conn.commit()
+
+    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))        

+ 32 - 0
route/user_tool.py

@@ -0,0 +1,32 @@
+from .tool.func import *
+
+def user_tool_2(conn, name):
+    curs = conn.cursor()
+    
+    data =  '''
+            <h2>''' + load_lang('tool') + '''</h2>
+            <ul>
+                <li><a href="/record/''' + url_pas(name) + '''">''' + load_lang('record') + '''</a></li>
+            </ul>
+            '''
+            
+    if admin_check(1) == 1:
+        curs.execute("select block from ban where block = ?", [name])
+        if curs.fetchall():
+            ban_name = load_lang('ban_release')
+        else:
+            ban_name = load_lang('ban')
+    
+        data += '''
+                <h2>''' + load_lang('admin') + '''</h2>
+                <ul>
+                    <li><a href="/ban/''' + url_pas(name) + '''">''' + ban_name + '''</a></li>
+                    <li><a href="/check/''' + url_pas(name) + '''">''' + load_lang('check') + '''</a></li>
+                </ul>
+                '''
+
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = [name, wiki_set(), custom(), other2([' (' + load_lang('tool') + ')', 0])],
+        data = data,
+        menu = 0
+    ))