Просмотр исходного кода

Merge pull request #1869 from openNAMU/dev

BBS 댓글 도구 및 닉네임 기능
잉여개발기 (SPDV) 2 лет назад
Родитель
Сommit
8a90086d78

+ 9 - 1
app.py

@@ -456,6 +456,8 @@ app.route('/change/head/<skin_name>', methods=['GET', 'POST'])(user_setting_head
 app.route('/change/head_reset', methods=['GET', 'POST'])(user_setting_head_reset)
 app.route('/change/skin_set')(user_setting_skin_set)
 app.route('/change/top_menu', methods=['GET', 'POST'])(user_setting_top_menu)
+app.route('/change/user_name', methods=['GET', 'POST'])(user_setting_user_name)
+app.route('/change/user_name/<user_name>', methods=['GET', 'POST'])(user_setting_user_name)
 # 하위 호환용 S
 app.route('/skin_set')(user_setting_skin_set)
 # 하위 호환용 E
@@ -524,10 +526,15 @@ app.route('/bbs/set/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_set)
 app.route('/bbs/edit/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_edit)
 app.route('/bbs/edit/preview/<int:bbs_num>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'preview' })(bbs_w_edit)
 app.route('/bbs/w/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_post)
+app.route('/bbs/raw/<int:bbs_num>/<int:post_num>')(view_raw_2)
+app.route('/bbs/tool/<int:bbs_num>/<int:post_num>')(bbs_w_tool)
 app.route('/bbs/edit/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'])(bbs_w_edit)
 app.route('/bbs/edit/preview/<int:bbs_num>/<int:post_num>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'preview' })(bbs_w_edit)
 app.route('/bbs/w/preview/<int:bbs_num>/<int:post_num>', methods = ['POST'], defaults = { 'do_type' : 'preview' })(bbs_w_post)
-# app.route('/bbs/edit/<int:bbs_num>/<int:post_num>')
+app.route('/bbs/tool/<int:bbs_num>/<int:post_num>/<comment_num>')(bbs_w_comment_tool)
+app.route('/bbs/raw/<int:bbs_num>/<int:post_num>/<comment_num>')(view_raw_2)
+app.route('/bbs/edit/<int:bbs_num>/<int:post_num>/<comment_num>', methods = ['POST', 'GET'])(bbs_w_edit)
+app.route('/bbs/edit/preview/<int:bbs_num>/<int:post_num>/<comment_num>', methods = ['POST', 'GET'])(bbs_w_edit)
 
 # Func-api
 app.route('/api/w/<everything:name>/doc_tool/<tool>/doc_rev/<int(signed = True):rev>')(api_w)
@@ -537,6 +544,7 @@ app.route('/api/raw/<everything:name>')(api_raw)
 
 app.route('/api/bbs/w/<sub_code>')(api_bbs_w_post)
 app.route('/api/bbs/w/comment/<sub_code>')(api_bbs_w_comment)
+app.route('/api/bbs/w/comment_one/<sub_code>')(api_bbs_w_comment)
 
 app.route('/api/version', defaults = { 'version_list' : version_list })(api_version)
 app.route('/api/skin_info')(api_skin_info)

+ 1 - 1
lang/en-US.json

@@ -552,7 +552,7 @@
             "error_skin_set" : "The skin you are using does not support individual settings.",
             "error_skin_set_old" : "Some older skins may only work by using the old version link.",
             "same_id_exist_error" : "There are users using the same username.",
-            "long_id_error" : "Username must be shorter than 20 characters.",
+            "long_id_error" : "Username must be shorter than 32 characters.",
             "id_char_error" : "Only Korean letters and alphabets are allowed for Username.",
             "file_exist_error" : "The file does not exist.",
             "password_error" : "Password does not match.",

+ 1 - 1
lang/ko-KR.json

@@ -208,7 +208,7 @@
     "name": "이름",
     "period": "기간",
     "writer": "작성자",
-    "long_id_error": "ID는 20자보다 짧아야 합니다.",
+    "long_id_error": "ID는 32자보다 짧아야 합니다.",
     "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
     "revert": "복원",
     "discussion_authority": "토론 관리 권한",

+ 4 - 0
route/__init__.py

@@ -14,6 +14,7 @@ from route.api_version import api_version
 from route.api_w import api_w
 from route.api_bbs_w_post import api_bbs_w_post
 from route.api_bbs_w_comment import api_bbs_w_comment
+from route.api_bbs_w_comment_one import api_bbs_w_comment_one
 
 from route.bbs_w_edit import bbs_w_edit
 from route.bbs_main import bbs_main
@@ -21,6 +22,8 @@ from route.bbs_make import bbs_make
 from route.bbs_w import bbs_w
 from route.bbs_w_post import bbs_w_post
 from route.bbs_w_set import bbs_w_set
+from route.bbs_w_comment_tool import bbs_w_comment_tool
+from route.bbs_w_tool import bbs_w_tool
 
 from route.edit import edit
 from route.edit_backlink_reset import edit_backlink_reset
@@ -146,6 +149,7 @@ from route.user_setting_pw import user_setting_pw
 from route.user_setting_skin_set import user_setting_skin_set
 from route.user_setting_skin_set_main import user_setting_skin_set_main
 from route.user_setting_top_menu import user_setting_top_menu
+from route.user_setting_user_name import user_setting_user_name
 
 from route.user_watch_list import user_watch_list
 from route.user_watch_list_name import user_watch_list_name

+ 30 - 0
route/api_bbs_w_comment_one.py

@@ -0,0 +1,30 @@
+from .tool.func import *
+
+def api_bbs_w_comment_one(sub_code = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        sub_code = sub_code.split('-')
+        sub_code_last = ''
+        if len(sub_code) > 2:
+            sub_code_last = sub_code[len(sub_code) - 1]
+            del sub_code[len(sub_code) - 1]
+            
+        sub_code = '-'.join(sub_code)
+
+        curs.execute(db_change('select set_name, set_data, set_code, set_id from bbs_data where (set_name = "comment" or set_name = "comment_date" or set_name = "comment_user_id") and set_id = ? and set_code = ?'), [sub_code, sub_code_last])
+        db_data = curs.fetchall()
+        if not db_data:
+            return flask.jsonify({})
+        else:
+            temp_id = ''
+            temp_dict = {}
+
+            for for_a in db_data:
+                if temp_id != for_a[2]:
+                    temp_id = for_a[2]
+                    temp_dict['code'] = for_a[2]
+
+                temp_dict[for_a[0]] = for_a[1]
+
+            return flask.jsonify(temp_dict)

+ 25 - 0
route/bbs_w_comment_tool.py

@@ -0,0 +1,25 @@
+from .tool.func import *
+
+def bbs_w_comment_tool(bbs_num = '', post_num = '', comment_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        data = ''
+        
+        bbs_num_str = str(bbs_num)
+        post_num_str = str(post_num)
+        
+        data += '''
+            <h2>''' + load_lang('tool') + '''</h2>
+            <ul class="opennamu_ul">
+                <li><a href="/bbs/raw/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/' + url_pas(comment_num) + '">' + load_lang('raw') + '''</a></li>
+                <li><a href="/bbs/edit/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/' + url_pas(comment_num) + '">' + load_lang('edit') + '''</a></li>
+                <li><a href="/bbs/w/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '/blind">' + load_lang('hide') + '''</a></li>
+            </ul>
+        '''
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('bbs_comment_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = data,
+            menu = [['bbs/w/' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '#' + url_pas(comment_num), load_lang('return')]]
+        ))

+ 63 - 31
route/bbs_w_edit.py

@@ -1,9 +1,10 @@
 from .tool.func import *
 
 from .api_bbs_w_post import api_bbs_w_post
+from .api_bbs_w_comment_one import api_bbs_w_comment_one
 from .edit import edit_editor
 
-def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
+def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -16,14 +17,20 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
         if not curs.fetchall():
             return redirect('/bbs/main')
         
-        if post_num != '':
-            curs.execute(db_change('select set_data from bbs_data where set_name = "user_id" and set_id = ? and set_code = ?'), [bbs_num, post_num])
-            db_data = curs.fetchall()
-            if not db_data:
-                return redirect('/bbs/main')
+        if comment_num != '':
+            temp_dict = json.loads(api_bbs_w_comment_one(bbs_num_str + '-' + post_num_str + '-' + comment_num).data)
+            if 'comment_user_id' in temp_dict:
+                if not temp_dict['comment_user_id'] == ip and admin_check() != 1:
+                    return re_error('/ban')
             else:
-                if not db_data[0][0] == ip and admin_check() != 1:
+                return redirect('/bbs/main')
+        elif post_num != '':
+            temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+            if 'user_id' in temp_dict:
+                if not temp_dict['user_id'] == ip and admin_check() != 1:
                     return re_error('/ban')
+            else:
+                return redirect('/bbs/main')
             
         if acl_check(bbs_num_str, 'bbs_edit') == 1:
             return redirect('/bbs/set/' + bbs_num_str)
@@ -52,7 +59,17 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
             
             date = get_time()
 
-            if post_num == '':
+            if comment_num != '':
+                sub_code = (bbs_num_str + '-' + post_num_str + '-' + comment_num).split('-')
+                sub_code_last = ''
+                if len(sub_code) > 2:
+                    sub_code_last = sub_code[len(sub_code) - 1]
+                    del sub_code[len(sub_code) - 1]
+                    
+                sub_code = '-'.join(sub_code)
+
+                curs.execute(db_change("update bbs_data set set_data = ? where set_name = 'comment' and set_code = ? and set_id = ?"), [data, sub_code_last, sub_code])
+            elif post_num == '':
                 curs.execute(db_change("insert into bbs_data (set_name, set_code, set_id, set_data) values ('title', ?, ?, ?)"), [id_data, bbs_num_str, title])
                 curs.execute(db_change("insert into bbs_data (set_name, set_code, set_id, set_data) values ('data', ?, ?, ?)"), [id_data, bbs_num_str, data])
                 curs.execute(db_change("insert into bbs_data (set_name, set_code, set_id, set_data) values ('date', ?, ?, ?)"), [id_data, bbs_num_str, date])
@@ -62,8 +79,13 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
                 curs.execute(db_change("update bbs_data set set_data = ? where set_name = 'data' and set_code = ? and set_id = ?"), [data, id_data, bbs_num_str])
                 curs.execute(db_change("update bbs_data set set_data = ? where set_name = 'date' and set_code = ? and set_id = ?"), [date, id_data, bbs_num_str])
 
-            return redirect('/bbs/w/' + bbs_num_str + '/' + id_data)
+            if comment_num != '':
+                return redirect('/bbs/w/' + bbs_num_str + '/' + id_data + '#' + url_pas(comment_num))
+            else:
+                return redirect('/bbs/w/' + bbs_num_str + '/' + id_data)
         else:
+            option_display = ''
+
             d_list = ['' for _ in range(0, len(i_list))]
             if do_type == 'preview':
                 title = flask.request.form.get('title', '')
@@ -77,15 +99,18 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
                 for for_a in range(0, len(i_list)):
                     d_list[for_a] = flask.request.form.get(i_list[for_a], 'normal')
             else:
-                if post_num == '':
+                if comment_num != '':
+                    temp_dict = json.loads(api_bbs_w_comment_one(bbs_num_str + '-' + post_num_str + '-' + comment_num).data)
+
+                    title = ''
+                    data = temp_dict['comment']
+                    data_preview = ''
+                    option_display = 'display: none;'
+                elif post_num == '':
                     title = ''
                     data = ''
                     data_preview = ''
                 else:
-                    curs.execute(db_change('select set_name, set_data, set_code from bbs_data where set_id = ? and set_code = ?'), [bbs_num, post_num])
-                    db_data = curs.fetchall()
-                    db_data = list(db_data) if db_data else []
-
                     temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
 
                     title = temp_dict['title']
@@ -103,7 +128,10 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
 
                     acl_div[for_a] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
             
-            if post_num == '':
+            if comment_num != '':
+                form_action = 'formaction="/bbs/edit/' + bbs_num_str + '/' + post_num_str + '/' + url_pas(comment_num) + '"'
+                form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '/' + post_num_str + '/' + url_pas(comment_num) + '"'
+            elif post_num == '':
                 form_action = 'formaction="/bbs/edit/' + bbs_num_str + '"'
                 form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '"'
             else:
@@ -115,7 +143,9 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
             if editor_top_text != '':
                 editor_top_text += '<hr class="main_hr">'
 
-            if post_num == '':
+            if comment_num != '':
+                bbs_title = load_lang('bbs_comment_edit')
+            elif post_num == '':
                 bbs_title = load_lang('post_add')
             else:
                 bbs_title = load_lang('post_edit')
@@ -124,8 +154,8 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
                 imp = [bbs_title, wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data =  editor_top_text + '''
                     <form method="post">                        
-                        <input placeholder="''' + load_lang('title') + '''" name="title" value="''' + html.escape(title) + '''">
-                        <hr class="main_hr">
+                        <input style="''' + option_display + '''" placeholder="''' + load_lang('title') + '''" name="title" value="''' + html.escape(title) + '''">
+                        <hr style="''' + option_display + '''" class="main_hr">
 
                         ''' + edit_editor(curs, ip, data, 'bbs') + '''
                         <hr class="main_hr">
@@ -138,19 +168,21 @@ def bbs_w_edit(bbs_num = '', post_num = '', do_type = ''):
                         <hr class="main_hr">
                         <div id="opennamu_preview_area">''' + data_preview + '''</div>
 
-                        ''' + render_simple_set('''
-                            <hr class="main_hr">
-                            <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
-                            <h2>''' + load_lang('acl') + '''</h2>
-                            <h3>''' + load_lang('post_view_acl') + '''</h3>
-                            <select name="post_view_acl">''' + acl_div[0] + '''</select>
-
-                            <h4>''' + load_lang('post_comment_acl') + '''</h4>
-                            <select name="post_comment_acl">''' + acl_div[1] + '''</select>
-
-                            <h2>''' + load_lang('markup') + '''</h2>
-                            ''' + load_lang('not_working') + '''
-                        ''') + '''
+                        <div style="''' + option_display + '''">
+                            ''' + render_simple_set('''
+                                <hr class="main_hr">
+                                <a href="/acl/TEST#exp">(''' + load_lang('reference') + ''')</a>
+                                <h2>''' + load_lang('acl') + '''</h2>
+                                <h3>''' + load_lang('post_view_acl') + '''</h3>
+                                <select name="post_view_acl">''' + acl_div[0] + '''</select>
+
+                                <h4>''' + load_lang('post_comment_acl') + '''</h4>
+                                <select name="post_comment_acl">''' + acl_div[1] + '''</select>
+
+                                <h2>''' + load_lang('markup') + '''</h2>
+                                ''' + load_lang('not_working') + '''
+                            ''') + '''
+                        </div>
                     </form>
                 ''',
                 menu = [['bbs/w/' + bbs_num_str, load_lang('return')]]

+ 4 - 6
route/bbs_w_post.py

@@ -28,7 +28,7 @@ def bbs_w_post_comment(user_id, sub_code, comment_num, bbs_num_str, post_num_str
 
         date = ''
         date += '<a href="javascript:opennamu_change_comment(\'' + sub_code_check + '\');">(' + load_lang('comment') + ')</a> '
-        date += '<a href="/bbs/w/' + bbs_num_str + '/' + post_num_str + '/comment/' + sub_code_check + '/tool">(' + load_lang('tool') + ')</a> '
+        date += '<a href="/bbs/tool/' + bbs_num_str + '/' + post_num_str + '/' + sub_code_check + '">(' + load_lang('tool') + ')</a> '
         date += temp_dict['comment_date']
 
         comment_data += '<span style="padding-left: 20px;"></span>' * margin_count
@@ -135,7 +135,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     )
 
                 date = ''
-                date += '<a href="/bbs/w/' + bbs_num_str + '/' + post_num_str + '/tool">(' + load_lang('tool') + ')</a> '
                 date += temp_dict['date']
 
                 data = ''
@@ -165,7 +164,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                         color = 'default'
                         
                     date = ''
-                    date += '<a href="/bbs/w/' + bbs_num_str + '/' + post_num_str + '/comment/' + str(count) + '/tool">(' + load_lang('tool') + ')</a> '
+                    date += '<a href="/bbs/tool/' + bbs_num_str + '/' + post_num_str + '/' + str(count) + '">(' + load_lang('tool') + ')</a> '
                     date += temp_dict['comment_date']
 
                     data += api_topic_thread_make(
@@ -204,7 +203,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 return easy_minify(flask.render_template(skin_check(),
                     imp = [bbs_name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('bbs') + ')', 0])],
                     data = data,
-                    menu = [['bbs/w/' + bbs_num_str, load_lang('return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, load_lang('edit')]]
+                    menu = [['bbs/w/' + bbs_num_str, load_lang('return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, load_lang('edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, load_lang('tool')]]
                 ))
         else:
             # db_data_2[0][0] == 'comment'
@@ -293,7 +292,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
 
                 date = ''
                 date += '<a href="javascript:opennamu_change_comment(\'0\');">(' + load_lang('comment') + ')</a> '
-                date += '<a href="/bbs/w/' + bbs_num_str + '/' + post_num_str + '/tool">(' + load_lang('tool') + ')</a> '
                 date += temp_dict['date']
 
                 data = ''
@@ -364,5 +362,5 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 return easy_minify(flask.render_template(skin_check(),
                     imp = [bbs_name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('bbs') + ')', 0])],
                     data = data,
-                    menu = [['bbs/w/' + bbs_num_str, load_lang('return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, load_lang('edit')]]
+                    menu = [['bbs/w/' + bbs_num_str, load_lang('return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, load_lang('edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, load_lang('tool')]]
                 ))

+ 24 - 0
route/bbs_w_tool.py

@@ -0,0 +1,24 @@
+from .tool.func import *
+
+def bbs_w_tool(bbs_num = '', post_num = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        data = ''
+        
+        bbs_num_str = str(bbs_num)
+        post_num_str = str(post_num)
+        
+        data += '''
+            <h2>''' + load_lang('tool') + '''</h2>
+            <ul class="opennamu_ul">
+                <li><a href="/bbs/raw/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('raw') + '''</a></li>
+                <li><a href="/bbs/blind/''' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str) + '">' + load_lang('hide') + '''</a></li>
+            </ul>
+        '''
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = [load_lang('bbs_post_tool'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = data,
+            menu = [['bbs/w/' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str), load_lang('return')]]
+        ))

+ 4 - 0
route/give_user_fix.py

@@ -53,6 +53,10 @@ def give_user_fix(user_name = ''):
                 imp = [load_lang('user_fix'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
                 data = '''
                     <form method="post">
+                        <div id="opennamu_get_user_info">''' + html.escape(user_name) + '''</div>
+                        <hr class="main_hr">
+                        <a href="/change/user_name/''' + url_pas(user_name) + '''">(''' + load_lang('change_user_name') + ''')</a>
+                        <hr class="main_hr">
                         <select name="select">
                             <option value="password_change">''' + load_lang('password_change') + '''</option>
                             <option value="2fa_password_change">''' + load_lang('2fa_password_change') + '''</option>

+ 1 - 14
route/login_register.py

@@ -44,22 +44,9 @@ def login_register_2():
                 if password_min_length > len(user_pw):
                     return re_error('/error/40')
 
-            # ID 글자 확인
-            if re.search(r'(?:[^A-Za-zㄱ-힣0-9])', user_id):
+            if do_user_name_check(user_id) == 1:
                 return re_error('/error/8')
 
-            # ID 필터
-            curs.execute(db_change('select html from html_filter where kind = "name"'))
-            set_d = curs.fetchall()
-            for i in set_d:
-                check_r = re.compile(i[0], re.I)
-                if check_r.search(user_id):
-                    return re_error('/error/8')
-
-            # ID 길이 제한 (32글자)
-            if len(user_id) > 32:
-                return re_error('/error/7')
-
             # 중복 확인
             curs.execute(db_change("select id from user_set where id = ?"), [user_id])
             if curs.fetchall():

+ 2 - 1
route/main_setting_external.py

@@ -59,7 +59,8 @@ def main_setting_external():
             re_ver_list = {
                 '' : 'reCAPTCHA v2',
                 'v3' : 'reCAPTCHA v3',
-                'h' : 'hCAPTCHA'
+                'h' : 'hCAPTCHA',
+                'cf' : 'Turnstile'
             }
             re_ver = ''
             for i in re_ver_list:

+ 61 - 17
route/tool/func.py

@@ -1580,7 +1580,14 @@ def captcha_get():
                             '});' + \
                         '</script>' + \
                     ''
+                elif rec_ver[0][0] == 'cf':
+                    data += '' + \
+                        '<script src="https://challenges.cloudflare.com/turnstile/v0/api.js?compat=recaptcha" async defer></script>' + \
+                        '<div class="g-recaptcha" data-sitekey="' + recaptcha[0][0] + '"></div>' + \
+                        '<hr class="main_hr">' + \
+                    ''
                 else:
+                    # rec_ver[0][0] == 'h'
                     data += '''
                         <script src="https://js.hcaptcha.com/1/api.js" async defer></script>
                         <div class="h-captcha" data-sitekey="''' + recaptcha[0][0] + '''"></div>
@@ -1601,27 +1608,61 @@ def captcha_post(re_data, num = 1):
             rec_ver = curs.fetchall()
             if captcha_get() != '':
                 if not rec_ver or rec_ver[0][0] in ('', 'v3'):
-                    data = requests.get(
-                        'https://www.google.com/recaptcha/api/siteverify' + \
-                        '?secret=' + sec_re[0][0] + '&response=' + re_data
+                    data = requests.post(
+                        'https://www.google.com/recaptcha/api/siteverify',
+                        data = {
+                            "secret" : sec_re[0][0],
+                            "response" : re_data
+                        }
+                    )
+                elif rec_ver[0][0] == 'cf':
+                    data = requests.post(
+                        'https://challenges.cloudflare.com/turnstile/v0/siteverify',
+                        data = {
+                            "secret" : sec_re[0][0],
+                            "response" : re_data
+                        }
                     )
-                    if data.status_code == 200:
-                        json_data = json.loads(data.text)
-                        if json_data['success'] != True:
-                            return 1
                 else:
-                    data = requests.get(
-                        'https://hcaptcha.com/siteverify' + \
-                        '?secret=' + sec_re[0][0] + '&response=' + re_data
+                    # rec_ver[0][0] == 'h'
+                    data = requests.post(
+                        'https://hcaptcha.com/siteverify',
+                        data = {
+                            "secret" : sec_re[0][0],
+                            "response" : re_data
+                        }
                     )
-                    if data.status_code == 200:
-                        json_data = json.loads(data.text)
-                        if json_data['success'] != True:
-                            return 1
+                    
+                if data.status_code == 200:
+                    json_data = json.loads(data.text)
+                    if json_data['success'] != True:
+                        return 1
 
         return 0
 
 # Func-user
+def do_user_name_check(user_name):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        # ID 글자 확인
+        if re.search(r'(?:[^A-Za-zㄱ-힣0-9])', user_name):
+            return 1
+
+        # ID 필터
+        curs.execute(db_change('select html from html_filter where kind = "name"'))
+        set_d = curs.fetchall()
+        for i in set_d:
+            check_r = re.compile(i[0], re.I)
+            if check_r.search(user_name):
+                return 1
+
+        # ID 길이 제한 (32글자)
+        if len(user_name) > 32:
+            return 1
+        
+        return 0
+
 def get_admin_auth_list(num = None):
     # without_DB
 
@@ -2125,11 +2166,13 @@ def ip_pas(raw_ip, type_data = 0):
 
                     change_ip = 1
                 else:
-                    ip = raw_ip
+                    curs.execute(db_change('select data from user_set where name = "user_name" and id = ?'), [raw_ip])
+                    db_data = curs.fetchall()
+                    ip = db_data[0][0] if db_data else raw_ip
                 
             if type_data == 0 and change_ip == 0:
                 if is_this_ip == 0:
-                    ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + raw_ip + '</a>'
+                    ip = '<a href="/w/' + url_pas('user:' + raw_ip) + '">' + ip + '</a>'
                     
                     if admin_check('all', None, raw_ip) == 1:
                         ip = '<b>' + ip + '</b>'
@@ -2593,9 +2636,10 @@ def re_error(data):
             elif num == 6:
                 data = load_lang('same_id_exist_error')
             elif num == 7:
+                # 폐지
                 data = load_lang('long_id_error')
             elif num == 8:
-                data = load_lang('id_char_error') + ' <a href="/name_filter">(' + load_lang('id_filter_list') + ')</a>'
+                data = load_lang('long_id_error') + '<br>' + load_lang('id_char_error') + ' <a href="/name_filter">(' + load_lang('id_filter_list') + ')</a>'
             elif num == 9:
                 data = load_lang('file_exist_error')
             elif num == 10:

+ 8 - 0
route/user_setting.py

@@ -95,6 +95,10 @@ def user_setting():
                 fa_data_pw = curs.fetchall()
                 fa_data_pw = load_lang('2fa_password_change') if fa_data_pw else load_lang('2fa_password')
 
+                curs.execute(db_change('select data from user_set where name = "user_name" and id = ?'), [ip])
+                db_data = curs.fetchall()
+                user_name = db_data[0][0] if db_data else ip
+
                 curs.execute(db_change('select data from user_set where name = "sub_user_name" and id = ?'), [ip])
                 db_data = curs.fetchall()
                 sub_user_name = db_data[0][0] if db_data else ''
@@ -130,6 +134,10 @@ def user_setting():
                             <select name="2fa" id="twofa_check_input">''' + fa_data_select + '''</select>
                             <hr class="main_hr">
                             <input type="password" name="2fa_pw" placeholder="''' + fa_data_pw + '''">
+                            <h2>''' + load_lang('main_user_name') + '''</h2>
+                            <a href="/change/user_name">(''' + load_lang('change_user_name') + ''')</a>
+                            <hr class="main_hr">
+                            ''' + load_lang('user_name') + ''' : ''' + html.escape(user_name) + '''
                             <h2>''' + load_lang('sub_user_name') + '''</h2>
                             <input name="sub_user_name" value="''' + html.escape(sub_user_name) + '''" placeholder="''' + load_lang('sub_user_name') + '''">
                             <hr class="main_hr">

+ 1 - 1
route/user_setting_head.py

@@ -73,5 +73,5 @@ def user_setting_head(skin_name = ''):
                         <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
-                menu = [['user', load_lang('return')]]
+                menu = [['change', load_lang('return')]]
             ))

+ 54 - 0
route/user_setting_user_name.py

@@ -0,0 +1,54 @@
+from .tool.func import *
+
+def user_setting_user_name(user_name = ''):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        ip = ip_check()
+        if user_name != '':
+            if admin_check() != 1:
+                return re_error('/error/3')
+            else:
+                ip = user_name
+    
+        if ip_or_user(ip) == 0:
+            if flask.request.method == 'POST':
+                auto_data = ['user_name', flask.request.form.get('new_user_name', '')]
+                if do_user_name_check(auto_data[1]) == 1:
+                    return re_error('/error/8')
+
+                curs.execute(db_change('select data from user_set where name = ? and data = ?'), [auto_data[0], auto_data[1]])
+                if curs.fetchall():
+                    return re_error('/error/6')
+                else:
+                    curs.execute(db_change('select data from user_set where name = ? and id = ?'), [auto_data[0], ip])
+                    if curs.fetchall():
+                        curs.execute(db_change("update user_set set data = ? where name = ? and id = ?"), [auto_data[1], auto_data[0], ip])
+                    else:
+                        curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), [auto_data[0], ip, auto_data[1]])
+
+                    if user_name != '':
+                        return redirect('/change/user_name/' + url_pas(user_name))
+                    else:
+                        return redirect('/change/user_name')
+            else:
+                user_name = ip
+
+                curs.execute(db_change("select data from user_set where id = ? and name = 'user_name'"), [ip])
+                db_data = curs.fetchall()
+                if db_data and db_data[0][0] != '':
+                    user_name = db_data[0][0]
+
+                return easy_minify(flask.render_template(skin_check(),
+                    imp = [load_lang('change_user_name'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                    data = '''
+                        <form method="post">
+                            <input name="new_user_name" placeholder="''' + load_lang('user_name') + '''" value="''' + html.escape(user_name) + '''">
+                            <hr class="main_hr">
+                            <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
+                        </form>
+                    ''',
+                    menu = [['change', load_lang('return')]]
+                ))
+        else:
+            return redirect('/login')

+ 40 - 6
route/view_raw.py

@@ -1,10 +1,21 @@
 from .tool.func import *
 
-def view_raw_2(name = None, topic_num = None, num = None, doc_acl = 0):
+from .api_bbs_w_post import api_bbs_w_post
+from .api_bbs_w_comment_one import api_bbs_w_comment_one
+
+def view_raw_2(name = None, topic_num = None, num = None, doc_acl = 0, bbs_num = '', post_num = '', comment_num = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
+        
+        bbs_num_str = str(bbs_num)
+        post_num_str = str(post_num)
 
-        if topic_num:
+        if bbs_num != '' and post_num != '':
+            if acl_check(bbs_num_str, 'bbs_view') == 1:
+                    return re_error('/ban')
+                    
+            name = ''
+        elif topic_num:
             topic_num = str(topic_num)
             
             if acl_check('', 'topic_view', topic_num) == 1:
@@ -18,9 +29,15 @@ def view_raw_2(name = None, topic_num = None, num = None, doc_acl = 0):
 
         v_name = name
         p_data = ''
-        sub = ' (' + load_lang('raw') + ')'
+        sub = '(' + load_lang('raw') + ')'
 
-        if not topic_num and num:
+        if bbs_num != '' and post_num != '':
+            sub += ' (' + load_lang('bbs') + ')'
+            menu = [['bbs/tool/' + url_pas(bbs_num_str) + '/' + url_pas(post_num_str), load_lang('return')]]
+            
+            if comment_num != '':
+                sub += ' (' + comment_num + ')'
+        elif not topic_num and num:
             curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, num])
             if curs.fetchall() and admin_check(6) != 1:
                 return re_error('/error/3')
@@ -29,7 +46,7 @@ def view_raw_2(name = None, topic_num = None, num = None, doc_acl = 0):
 
             sub += ' (r' + num + ')'
 
-            menu = [['history/' + url_pas(name), load_lang('history')]]
+            menu = [['history_tool/' + url_pas(num) + '/' + url_pas(name), load_lang('return')]]
         elif topic_num:
             if admin_check(6) != 1:
                 curs.execute(db_change("select data from topic where id = ? and code = ? and block = ''"), [num, topic_num])
@@ -48,7 +65,24 @@ def view_raw_2(name = None, topic_num = None, num = None, doc_acl = 0):
 
             menu = [['w/' + url_pas(name), load_lang('return')]]
 
-        data = curs.fetchall()
+        if bbs_num != '' and post_num != '':
+            if comment_num != '':
+                data = json.loads(api_bbs_w_comment_one(bbs_num_str + '-' + post_num_str + '-' + comment_num).data)
+                sub_data = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+            else:
+                data = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+                
+            if 'comment' in data:
+                v_name = sub_data["title"]
+                data = [[data["comment"]]]
+            elif 'data' in data:
+                v_name = data["title"]
+                data = [[data["data"]]]
+            else:
+                data = None
+        else:
+            data = curs.fetchall()
+            
         if data:
             p_data += '<textarea readonly class="opennamu_textarea_500">' + html.escape(data[0][0]) + '</textarea>'
             

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.6-RC3-dev216",
+        "r_ver" : "v3.4.6-RC3-dev219",
         "c_ver" : "3500361",
         "s_ver" : "3500111"
     }

+ 1 - 1
views/ringo/index.html

@@ -13,7 +13,7 @@
         <script src="/views/ringo/js/main.js?ver=2"></script>
         <script src="/views/ringo/js/sidebar.js?ver=1"></script>
         <script src="/views/ringo/js/skin_set.js?ver=1"></script>
-        <link rel="stylesheet" href="/views/ringo/css/main.css?ver=3">
+        <link rel="stylesheet" href="/views/ringo/css/main.css?ver=4">
         {% if request.cookies.get('main_css_darkmode', '') == '1' %}
             <link rel="stylesheet" href="/views/main_css/css/sub/dark.css?ver=1">
             <link rel="stylesheet" href="/views/ringo/css/dark.css?ver=1">

+ 3 - 1
views/ringo/js/main.js

@@ -21,7 +21,9 @@ function ringo_opening(data) {
 
         for(for_a in element) {
             if(for_a !== '0') { 
-                document.getElementById(element[for_a]).style.display = 'none';
+                if(document.getElementById(element[for_a]) !== null) {
+                    document.getElementById(element[for_a]).style.display = 'none';
+                }
             }
         }