Kaynağa Gözat

Merge pull request #1651 from openNAMU/dev

Dev
잉여개발기 (SPDV) 3 yıl önce
ebeveyn
işleme
52815c9b9d

+ 1 - 0
.gitignore

@@ -11,6 +11,7 @@ route/tool/set_mark/custom.py
 images
 
 .vscode
+.vs
 goorm.manifest
 .DS_Store
 

+ 7 - 8
app.py

@@ -192,7 +192,7 @@ with get_db_connect() as conn:
         elif server_set_env[i] != None:
             server_set_val = server_set_env[i]
 
-            curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, server_set_env[i]])
+            curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, server_set_env[i]])
         else:
             if 'list' in server_set_var[i]:
                 print(server_set_var[i]['display'] + ' (' + server_set_var[i]['default'] + ') [' + ', '.join(server_set_var[i]['list']) + ']' + ' : ', end = '')
@@ -206,7 +206,7 @@ with get_db_connect() as conn:
                 if not server_set_val in server_set_var[i]['list']:
                     server_set_val = server_set_var[i]['default']
 
-            curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, server_set_val])
+            curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, server_set_val])
 
         print(server_set_var[i]['display'] + ' : ' + server_set_val)
 
@@ -495,7 +495,10 @@ app.route('/change/head', methods=['GET', 'POST'], defaults = { 'skin_name' : ''
 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/skin_set/main')(user_setting_skin_set)
+# 하위 호환용 S
+app.route('/skin_set')(user_setting_skin_set)
+# 하위 호환용 E
+app.route('/change/skin_set/main', methods = ['POST', 'GET'])(user_setting_skin_set_main)
 
 app.route('/user')(user_info)
 app.route('/user/<name>')(user_info)
@@ -514,11 +517,6 @@ app.route('/watch_list/<everything:name>', defaults = { 'tool' : 'watch_list' })
 app.route('/star_doc', defaults = { 'tool' : 'star_doc' })(user_watch_list)
 app.route('/star_doc/<everything:name>', defaults = { 'tool' : 'star_doc' })(user_watch_list_name)
 
-# 하위 호환용 S
-# /change/skin_set
-app.route('/skin_set')(user_setting_skin_set)
-# 하위 호환용 E
-
 # 개편 보류중 S
 @app.route('/change/email', methods = ['POST', 'GET'])
 def user_setting_email():
@@ -642,6 +640,7 @@ app.route('/goto/<everything:name>', methods=['POST'])(main_search_goto)
 app.route('/setting')(main_func_setting)
 app.route('/setting/main', defaults = { 'db_set' : data_db_set['type'] }, methods = ['POST', 'GET'])(main_func_setting_main)
 app.route('/setting/main/logo', methods = ['POST', 'GET'])(main_func_setting_main_logo)
+app.route('/setting/top_menu', methods = ['POST', 'GET'])(main_func_setting_top_menu)
 app.route('/setting/phrase', methods = ['POST', 'GET'])(main_func_setting_phrase)
 app.route('/setting/head', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/head/<skin_name>', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)

+ 1 - 6
emergency_tool.py

@@ -198,12 +198,7 @@ elif what_i_do == '12':
         count_data = 0
 
     curs.execute(db_change('delete from other where name = "count_all_title"'))
-    curs.execute(
-        db_change(
-            'insert into other (name, data) values ("count_all_title", ?)'
-        ),
-        [str(count_data)]
-    )
+    curs.execute(db_change('insert into other (name, data, coverage) values ("count_all_title", ?, "")'), [str(count_data)])
 elif what_i_do == '14':
     curs.execute(db_change('delete from other where name = "head"'))
 elif what_i_do == '15':

+ 6 - 1
lang/en-US.json

@@ -174,7 +174,8 @@
         "edit_button_paragraph" : "Paragraph",
         "password_change" : "Change password",
         "email_change" : "Change email",
-        "acl_change" : "Change documents ACL",
+        "acl_change" : "Change document ACL",
+		"acl_thread_change" : "Change thread ACL",
         "user_tool" : "Users tools",
         "skin_info" : "Skin information",
         "closed_discussion" : "Closed discussions",
@@ -227,6 +228,7 @@
         "multiple_ban" : "Multiple ban",
         "dont_move" : "Don't move",
         "file_delete" : "File delete",
+        "added_menu" : "Added menu",
         "_comment_" : "Edit",
             "load" : "Load another document",
             "turn_off_monaco" : "Turn off monaco editor",
@@ -264,6 +266,8 @@
             "adsense_enable" : "Adsense enable",
             "skin_setting" : "Skin settings",
             "main_acl_setting" : "Default ACL settings",
+            "top_menu_setting" : "Added menu setting",
+            "enter_top_menu_setting" : "Enter name in the upper line and URL in the lower line.",
             "_comment_2.2.1_" : "List",
                 "main_setting" : "Main settings",
                 "text_setting" : "Text settings",
@@ -519,6 +523,7 @@
             "history_delete_warning" : "If you erase history, it's hard to restore it, so please be careful.",
             "user_css_warning" : "If you have a problem using this, connect here.",
             "main_css_warning" : "If you have a problem using this, use the emergency tool.",
+            "not_support_skin_warning" : "It does not work on skins that do not support this feature.",
         "_comment_" : "Challenge",
             "challenge_title_register" : "Hello, World!",
             "challenge_info_register" : "Sign up",

+ 7 - 2
lang/ko-KR.json

@@ -487,6 +487,11 @@
     "topic_agree": "토론 합의 완료",
     "user_css_warning": "만약 사용하다가 문제가 생기면 여기로 접속하세요.",
     "main_css_warning": "만약 사용하다가 문제가 생기면 이머전시 툴을 사용하세요.",
-    "reset" : "초기화",
-    "namumark_fully_compatible_mode" : "나무마크 디자인 호환 모드"
+    "reset": "초기화",
+    "namumark_fully_compatible_mode": "나무마크 디자인 호환 모드",
+    "added_menu": "추가 메뉴",
+    "top_menu_setting": "추가 메뉴 설정",
+    "enter_top_menu_setting": "윗 줄에는 이름을 쓰고 아랫 줄에는 URL을 입력하세요.",
+    "not_support_skin_warning": "이 기능을 미지원하는 스킨에서는 작동하지 않습니다.",
+    "acl_thread_change": "스레드 ACL 변경"
 }

+ 9 - 3
route/edit.py

@@ -228,8 +228,14 @@ def edit(name = 'Test', section = 0, do_type = ''):
             sql_d = curs.fetchall()
             p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
             
-            monaco_on = flask.request.cookies.get('main_css_monaco', '0')
-            if monaco_on == '1':
+            if ip_or_user(ip) == 0:
+                curs.execute(db_change('select data from user_set where name = "main_css_monaco" and id = ?'), [ip])
+                db_data = curs.fetchall()
+                monaco_on = db_data[0][0] if db_data else 'normal'
+            else:
+                monaco_on = flask.session['main_css_monaco'] if 'main_css_monaco' in flask.session else 'normal'
+            
+            if monaco_on == 'use':
                 editor_display = 'style="display: none;"'
                 monaco_display = ''
                 add_get_file = '''
@@ -333,7 +339,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
                         }
 
                         do_stop_exit();
-                        do_paste_image();
+                        do_paste_image('opennamu_edit_textarea', 'opennamu_monaco_editor');
 
                         ''' + add_script + '''
                     </script>

+ 23 - 1
route/main_func_easter_egg.py

@@ -2,8 +2,30 @@ from .tool.func import *
 
 def main_func_easter_egg():
     with get_db_connect() as conn:
+        curs = conn.cursor()
+        
+        random_n = random.randrange(0, 8)
+        select_list = [
+            'https://www.youtube.com/embed/PWD0ZbR7AOY', # TH06   - Shanghai Teahouse ~ Chinese Tea
+            'https://www.youtube.com/embed/HoU29ljOmTE', # TH10.5 - Flawless Clothing of Celestials
+            'https://www.youtube.com/embed/PR2vUm-Ald8', # TH06   - U.N. Owen Was Her
+            'https://www.youtube.com/embed/opZoEmsu_Lo', # TH09   - Flowering Night
+            'https://www.youtube.com/embed/txZFFTusSvw', # TH08   - Reach for the Moon ~ Immortal Smoke
+            'https://www.youtube.com/embed/Ixq9xL2tvRU', # TH07   - Phantom Ensemble
+            'https://www.youtube.com/embed/-3IAx_r4Au0', # TH17   - Entrusting This World to Idols ~ Idolatrize World
+            'https://www.youtube.com/embed/wObZkycA6sc', # TH11   - Last Remote
+            # Remix by NyxTheShield
+        ]
+
+        ip = ip_check()
+        if ip_or_user(ip) == 0:
+            curs.execute(db_change('select name from user_set where id = ? and name = ?'), [ip, 'get_🥚'])
+            if not curs.fetchall():
+                curs.execute(db_change('insert into user_set (name, id, data) values ("get_🥚", ?, "Y")'), [ip])
+                conn.commit()
+
         return easy_minify(flask.render_template(skin_check(),
             imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = '<iframe width="640" height="360" src="https://www.youtube.com/embed/iQPbgD_CTd4" frameborder="0" allowfullscreen></iframe>',
+            data = '<iframe width="640" height="360" src="' + select_list[random_n] + '" frameborder="0" allowfullscreen></iframe>',
             menu = [['manager', load_lang('return')]]
         ))

+ 2 - 1
route/main_func_setting.py

@@ -10,7 +10,8 @@ def main_func_setting():
             ['head', load_lang('main_head')],
             ['body/top', load_lang('main_body')],
             ['body/bottom', load_lang('main_bottom_body')],
-            ['sitemap', load_lang('sitemap_management') + ' (' + load_lang('beta') + ')']
+            ['sitemap', load_lang('sitemap_management')],
+            ['top_menu', load_lang('top_menu_setting') + ' (' + load_lang('beta') + ')']
         ]
 
         li_data = ''.join(['<li><a href="/setting/' + str(li[0]) + '">' + li[1] + '</a></li>' for li in li_list])

+ 1 - 1
route/main_func_setting_acl.py

@@ -40,7 +40,7 @@ def main_func_setting_acl():
                 if sql_d:
                     d_list[i] = sql_d[0][0]
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i_list[i], 'normal'])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i_list[i], 'normal'])
 
                     d_list[i] = 'normal'
 

+ 1 - 1
route/main_func_setting_external.py

@@ -42,7 +42,7 @@ def main_func_setting_external():
                 if sql_d:
                     d_list += [sql_d[0][0]]
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, ''])
 
                     d_list += ['']
 

+ 1 - 5
route/main_func_setting_head.py

@@ -26,11 +26,7 @@ def main_func_setting_head(num, skin_name = '', set_preview = 0):
 
             curs.execute(db_change("select name from other where name = ? and coverage = ?"), [info_d, coverage])
             if curs.fetchall():
-                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [
-                    flask.request.form.get('content', ''),
-                    info_d,
-                    coverage
-                ])
+                curs.execute(db_change("update other set data = ? where name = ? and coverage = ?"), [flask.request.form.get('content', ''), info_d, coverage])
             else:
                 curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, ?)"), [info_d, flask.request.form.get('content', ''), coverage])
 

+ 4 - 1
route/main_func_setting_main.py

@@ -56,7 +56,10 @@ def main_func_setting_main(db_set):
                 curs.execute(db_change('select data from other where name = ?'), [setting_list[i][0]])
                 db_data = curs.fetchall()
                 if not db_data:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [setting_list[i][0], setting_list[i][1]])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [
+                        setting_list[i][0],
+                        setting_list[i][1]
+                    ])
 
                 d_list[i] = db_data[0][0] if db_data else setting_list[i][1]
             else:

+ 1 - 1
route/main_func_setting_phrase.py

@@ -51,7 +51,7 @@ def main_func_setting_phrase():
                 if sql_d:
                     d_list += [sql_d[0][0]]
                 else:
-                    curs.execute(db_change('insert into other (name, data) values (?, ?)'), [i, ''])
+                    curs.execute(db_change('insert into other (name, data, coverage) values (?, ?, "")'), [i, ''])
 
                     d_list += ['']
 

+ 2 - 2
route/main_func_setting_robot.py

@@ -25,12 +25,12 @@ def main_func_setting_robot():
             if db_data:
                 curs.execute(db_change("update other set data = ? where name = 'robot'"), [flask.request.form.get('content', '')])
             else:
-                curs.execute(db_change("insert into other (name, data) values ('robot', ?)"), [flask.request.form.get('content', '')])
+                curs.execute(db_change("insert into other (name, data, coverage) values ('robot', ?, '')"), [flask.request.form.get('content', '')])
 
             if db_data_2:
                 curs.execute(db_change("update other set data = ? where name = 'robot_default'"), [flask.request.form.get('default', '')])
             else:
-                curs.execute(db_change("insert into other (name, data) values ('robot_default', ?)"), [flask.request.form.get('default', '')])
+                curs.execute(db_change("insert into other (name, data, coverage) values ('robot_default', ?, '')"), [flask.request.form.get('default', '')])
 
             conn.commit()
 

+ 51 - 0
route/main_func_setting_top_menu.py

@@ -0,0 +1,51 @@
+from .tool.func import *
+
+def main_func_setting_top_menu():
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        if admin_check() != 1:
+            return re_error('/ban')
+        
+        if flask.request.method == 'POST':
+            curs.execute(db_change("select name from other where name = 'top_menu'"))
+            if curs.fetchall():
+                curs.execute(db_change("update other set data = ? where name = 'top_menu'"), [flask.request.form.get('content', '')])
+            else:
+                curs.execute(db_change("insert into other (name, data, coverage) values ('top_menu', ?, '')"), [flask.request.form.get('content', '')])
+
+            conn.commit()
+
+            admin_check(None, 'edit_set (top_menu)')
+
+            return redirect('/setting/top_menu')
+        else:
+            curs.execute(db_change("select data from other where name = 'top_menu'"))
+            db_data = curs.fetchall()
+            db_data = db_data[0][0] if db_data else ''
+            
+            return easy_minify(flask.render_template(skin_check(),
+                imp = [load_lang('top_menu_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
+                data = '''
+                    <span>
+                        EX)
+                        <br>
+                        ONTS
+                        <br>
+                        https://2du.pythonanywhere.com/
+                        <br>
+                        FrontPage
+                        <br>
+                        /w/FrontPage
+                    </span>
+                    <hr class="main_hr">
+                    ''' + load_lang('not_support_skin_warning') + '''
+                    <hr class="main_hr">
+                    <form method="post">
+                        <textarea class="opennamu_textarea_500" placeholder="''' + load_lang('enter_top_menu_setting') + '''" name="content" id="content">''' + html.escape(db_data) + '''</textarea>
+                        <hr class="main_hr">
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
+                menu = [['setting', load_lang('return')]]
+            ))

+ 0 - 2
route/recent_block.py

@@ -115,8 +115,6 @@ def recent_block_2(name, tool):
 
             if data[2] == '':
                 admin = ''
-            elif re.search(r'^tool:', data[2]):
-                admin = data[2]
             else:
                 admin = all_ip[data[2]]
 

+ 68 - 53
route/tool/func.py

@@ -305,6 +305,7 @@ class class_check_json:
 
 def get_db_table_list():
     # Init-Create_DB
+    # --이거 개편한다더니 도대체 언제?--
     create_data = {}
 
     # 폐지 예정 (data_set으로 통합)
@@ -342,6 +343,9 @@ def get_db_table_list():
     create_data['ua_d'] = ['name', 'ip', 'ua', 'today', 'sub']
 
     create_data['user_set'] = ['name', 'id', 'data']
+
+    create_data['bbs_set'] = ['set_name', 'set_code', 'set_id', 'set_data']
+    create_data['bbs_data'] = ['set_name', 'set_code', 'set_id', 'set_data']
     
     return create_data
 
@@ -618,7 +622,13 @@ def update(ver_num, set_data):
                 'Allow: /w/' + \
             ''
             if db_data[0][0] == robot_default:
-                curs.execute(db_change("insert into other (name, data) values ('robot_default', 'on')"))
+                curs.execute(db_change("insert into other (name, data, coverage) values ('robot_default', 'on', '')"))
+
+    if ver_num < 3500355:
+        # other coverage 오류 해결
+        curs.execute(db_change(
+            "update other set coverage = '' where coverage is null"
+        ))
 
     conn.commit()
     
@@ -632,7 +642,7 @@ def set_init_always(ver_num):
     curs = conn.cursor()
 
     curs.execute(db_change('delete from other where name = "ver"'))
-    curs.execute(db_change('insert into other (name, data) values ("ver", ?)'), [ver_num])
+    curs.execute(db_change('insert into other (name, data, coverage) values ("ver", ?, "")'), [ver_num])
     
     curs.execute(db_change('delete from alist where name = "owner"'))
     curs.execute(db_change('insert into alist (name, acl) values ("owner", "owner")'))
@@ -642,15 +652,15 @@ def set_init_always(ver_num):
 
     curs.execute(db_change('select data from other where name = "key"'))
     if not curs.fetchall():
-        curs.execute(db_change('insert into other (name, data) values ("key", ?)'), [load_random_key()])
+        curs.execute(db_change('insert into other (name, data, coverage) values ("key", ?, "")'), [load_random_key()])
         
     curs.execute(db_change('select data from other where name = "salt_key"'))
     if not curs.fetchall():
-        curs.execute(db_change('insert into other (name, data) values ("salt_key", ?)'), [load_random_key(4)])
+        curs.execute(db_change('insert into other (name, data, coverage) values ("salt_key", ?, "")'), [load_random_key(4)])
 
     curs.execute(db_change('select data from other where name = "count_all_title"'))
     if not curs.fetchall():
-        curs.execute(db_change('insert into other (name, data) values ("count_all_title", "0")'))
+        curs.execute(db_change('insert into other (name, data, coverage) values ("count_all_title", "0", "")'))
         
     curs.execute(db_change('select data from other where name = "wiki_access_password_need"'))
     db_data = curs.fetchall()
@@ -690,9 +700,7 @@ def set_init():
             ['smtp_port', '587'], 
             ['smtp_security', 'starttls']
         ]:
-            curs.execute(db_change(
-                "insert into other (name, data) values (?, ?)"
-            ), [i[0], i[1]])
+            curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, '')"), [i[0], i[1]])
         
     conn.commit()
 
@@ -719,7 +727,11 @@ def get_default_robots_txt():
 
     return data
 
-def get_user_title_list():
+def get_user_title_list(ip = ''):
+    curs = conn.cursor()
+
+    ip = ip_check() if ip == '' else ip
+
     # default
     user_title = {
         '' : load_lang('default'),
@@ -727,8 +739,12 @@ def get_user_title_list():
     }
     
     # admin
-    if admin_check('all') == 1:
+    if admin_check('all', None, ip) == 1:
         user_title['✅'] = '✅ admin'
+
+    curs.execute(db_change('select name from user_set where id = ? and name = ?'), [ip, 'get_🥚'])
+    if curs.fetchall():
+        user_title['🥚'] = '🥚 easter_egg'
     
     return user_title
 
@@ -1041,7 +1057,7 @@ def wiki_css(data):
     data += ['' for _ in range(0, 3 - len(data))]
     
     data_css = ''
-    data_css_ver = '171'
+    data_css_ver = '172'
     
     # Func JS + Defer
     data_css += '<script src="/views/main_css/js/func/func.js?ver=' + data_css_ver + '"></script>'
@@ -1054,14 +1070,11 @@ def wiki_css(data):
     data_css += '<script defer src="/views/main_css/js/func/ie_end_of_life.js?ver=' + data_css_ver + '"></script>'
     data_css += '<script defer src="/views/main_css/js/func/shortcut.js?ver=' + data_css_ver + '"></script>'
     
-    data_css += '<script defer src="/views/main_css/js/func/render_simple.js?ver=' + data_css_ver + '"></script>'
-    
     # Route JS + Defer
     data_css += '<script defer src="/views/main_css/js/route/thread.js?ver=' + data_css_ver + '"></script>'
     
     # 레거시 일반 JS
     data_css += '<script src="/views/main_css/js/load_editor.js?ver=' + data_css_ver + '"></script>'
-    data_css += '<script src="/views/main_css/js/load_skin_set.js?ver=' + data_css_ver + '"></script>'
     
     # Main CSS
     data_css += '<link rel="stylesheet" href="/views/main_css/css/main.css?ver=' + data_css_ver + '">'
@@ -1079,11 +1092,19 @@ def wiki_css(data):
 
 def cut_100(data):
     # without_DB
-    
-    data = data.replace('<pre class="render_content_load" id="render_content_load">', '')
-    data = data.replace('</pre>', ' ' * 100)
-    
-    return data[0 : 100]
+    data = data.replace('<br>', ' ')
+    data = data.replace('\r', '') 
+    data = data.replace('\n', ' ')
+    data = re.sub(r'<[^<>]+>', ' ', data)
+    data = data.replace('\n', ' ')
+    data = re.sub(r' {2,}', ' ', data)
+    data = re.sub(r'(^ +| +$)', '', data)
+
+    data_len = len(data)
+    if data_len > 100:
+        return data[0:100]
+    else:
+        return data[0:data_len]
 
 def wiki_set(num = 1):
     curs = conn.cursor()
@@ -1122,6 +1143,20 @@ def wiki_set(num = 1):
 
     data_list += [head_data]
 
+    curs.execute(db_change("select data from other where name = 'top_menu'"))
+    db_data = curs.fetchall()
+    db_data = db_data[0][0] if db_data else ''
+    db_data = db_data.replace('\r', '')
+    if db_data != '':
+        db_data = db_data.split('\n')
+    
+        if len(db_data) % 2 != 0:
+            db_data += ['']
+
+        db_data = [[db_data[for_a], db_data[for_a + 1]] for for_a in range(0, len(db_data), 2)]
+
+    data_list += [db_data]
+
     return data_list
 
 def wiki_custom():
@@ -1302,7 +1337,7 @@ def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', d
             curs.execute(db_change("select data from other where name = 'namumark_compatible'"))
             db_data = curs.fetchall()
             if db_data and db_data[0][0] != '':
-                get_class_render[0] = '''
+                get_class_render[0] += '''
                     <style>
                         .opennamu_render_complete {
                             font-size: 14.4px !important;
@@ -1317,7 +1352,7 @@ def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', d
                             font-weight: bold;
                         }
                     </style>
-                ''' + get_class_render[0]
+                '''
 
             if data_type == 'api_view':
                 return [
@@ -1380,7 +1415,7 @@ def render_simple_set(data):
         if footnote_count != 1:
             footnote_data += '<br>'
     
-        footnote_data += '<a id="fn_' + footnote_count_str + '" href="#rfn_' + footnote_count_str + '">(' + footnote_count_str + ')</a> ' + footnote_search
+        footnote_data += '<a id="fn-' + footnote_count_str + '" href="#rfn-' + footnote_count_str + '">(' + footnote_count_str + ')</a> ' + footnote_search
         data = re.sub(footnote_regex, '<sup id="rfn-' + footnote_count_str + '"><a href="#fn-' + footnote_count_str + '">(' + footnote_count_str + ')</a></sup>', data, 1)
         
         footnote_count += 1
@@ -1527,20 +1562,6 @@ def captcha_post(re_data, num = 1):
         return 0
 
 # Func-user
-def ip_or_user(data = ''):
-    # without_DB
-
-    # 1 == ip
-    # 0 == reg
-    
-    if data == '':
-        data = ip_check()
-
-    if re.search(r'(\.|:)', data):
-        return 1
-    else:
-        return 0
-
 def admin_check(num = None, what = None, name = ''):
     curs = conn.cursor()
 
@@ -1913,12 +1934,9 @@ def ip_pas(raw_ip, type_data = 0):
     
     for raw_ip in get_ip:
         change_ip = 0
-        if re.search(r'^Add:', raw_ip):
-            is_this_ip = 1
-            ip = raw_ip
-        else:
-            is_this_ip = ip_or_user(raw_ip)
-            if is_this_ip != 0 and ip_view != '':
+        is_this_ip = ip_or_user(raw_ip)
+        if is_this_ip != 0 and ip_view != '':
+            try:
                 ip = ipaddress.ip_address(raw_ip)
                 if type(ip) == ipaddress.IPv6Address:
                     ip = ip.exploded
@@ -1928,8 +1946,10 @@ def ip_pas(raw_ip, type_data = 0):
                     ip = re.sub(r'\.([^.]*)\.([^.]*)$', '.*.*', ip)
                     
                 change_ip = 1
-            else:     
+            except:
                 ip = raw_ip
+        else:     
+            ip = raw_ip
             
         if type_data == 0 and change_ip == 0:
             if is_this_ip == 0:
@@ -2451,17 +2471,12 @@ def re_error(data):
             data = '???'
 
         if num == 5:
-            if not flask.request.path in ('/main_skin_set', '/change/skin_set/main'):
-                if flask.request.path != '/skin_set':
-                    data += '<br>' + load_lang('error_skin_set_old') + ' <a href="/skin_set">(' + load_lang('go') + ')</a>'
+            if flask.request.path != '/skin_set':
+                data += '<br>' + load_lang('error_skin_set_old') + ' <a href="/skin_set">(' + load_lang('go') + ')</a>'
 
-                title = load_lang('skin_set')
-                tool = [['change', load_lang('user_setting')], ['change/skin_set/main', load_lang('main_skin_set')]]
-                load_skin_set = ''
-            else:
-                title = load_lang('main_skin_set')
-                tool = [['change', load_lang('user_setting')], ['change/skin_set', load_lang('skin_set')]]
-                load_skin_set = '<script>main_css_skin_set();</script>'
+            title = load_lang('skin_set')
+            tool = [['change', load_lang('user_setting')], ['change/skin_set/main', load_lang('main_skin_set')]]
+            load_skin_set = ''
         
             return easy_minify(flask.render_template(skin_check(),
                 imp = [title, wiki_set(), wiki_custom(), wiki_css([0, 0])],

+ 46 - 13
route/tool/func_render_namumark.py

@@ -10,6 +10,7 @@ class class_do_render_namumark:
         self.doc_include = self.doc_set['doc_include'] if 'doc_include' in self.doc_set else ''
 
         self.lang_data = lang_data
+        self.ip = ip_check()
 
         self.data_temp_storage = {}
         self.data_temp_storage_count = 0
@@ -170,12 +171,18 @@ class class_do_render_namumark:
 
     def do_render_text(self):
         # <b> function
-        bold_user_set = flask.request.cookies.get('main_css_del_bold', '0')
+        if ip_or_user(self.ip) == 0:
+            self.curs.execute(db_change('select data from user_set where name = "main_css_bold" and id = ?'), [self.ip])
+            db_data = self.curs.fetchall()
+            bold_user_set = db_data[0][0] if db_data else 'normal'
+        else:
+            bold_user_set = flask.session['main_css_bold'] if 'main_css_bold' in flask.session else 'normal'
+
         def do_render_text_bold(match):
             data = match.group(1)
-            if bold_user_set == '0':
+            if bold_user_set == 'normal':
                 data_name = self.get_tool_data_storage('<b>', '</b>', match.group(0))
-            elif bold_user_set == '1':
+            elif bold_user_set == 'change':
                 data_name = self.get_tool_data_storage('', '', match.group(0))
             else:
                 return ''
@@ -229,13 +236,19 @@ class class_do_render_namumark:
         # <sub> 2
         self.render_data = re.sub(r",,((?:(?!,,).)+),,", do_render_text_sub, self.render_data)
 
-        # <sub> function
-        strike_user_set = flask.request.cookies.get('main_css_del_strike', '0')
+        # <s> function
+        if ip_or_user(self.ip) == 0:
+            self.curs.execute(db_change('select data from user_set where name = "main_css_strike" and id = ?'), [self.ip])
+            db_data = self.curs.fetchall()
+            strike_user_set = db_data[0][0] if db_data else 'normal'
+        else:
+            strike_user_set = flask.session['main_css_strike'] if 'main_css_strike' in flask.session else 'normal'
+
         def do_render_text_strike(match):
             data = match.group(1)
-            if bold_user_set == '0':
+            if strike_user_set == 'normal':
                 data_name = self.get_tool_data_storage('<s>', '</s>', match.group(0))
-            elif bold_user_set == '1':
+            elif strike_user_set == 'change':
                 data_name = self.get_tool_data_storage('', '', match.group(0))
             else:
                 return ''
@@ -1081,14 +1094,20 @@ class class_do_render_namumark:
                 db_data = self.curs.fetchall()
                 if db_data:
                     self.data_backlink += [[self.doc_name, include_name, 'include']]
+                    include_data = db_data[0][0].replace('\r', '')
 
                     # include link func
+                    if ip_or_user(self.ip) == 0:
+                        self.curs.execute(db_change('select data from user_set where name = "main_css_include_link" and id = ?'), [self.ip])
+                        db_data = self.curs.fetchall()
+                        include_set_data = db_data[0][0] if db_data else 'normal'
+                    else:
+                        include_set_data = flask.session['main_css_include_link'] if 'main_css_include_link' in flask.session else 'normal'
+
                     include_link = ''
-                    if flask.request.cookies.get('main_css_include_link', '') == '1':
+                    if include_set_data == 'use':
                         include_link = '<div><a href="/w/' + url_pas(include_name) + '">(' + include_name_org + ')</a></div>'
 
-                    include_data = db_data[0][0].replace('\r', '')
-
                     # parameter replace
                     include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, include_data)
                     include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)@', do_render_include_default_sub, include_data)
@@ -1730,7 +1749,14 @@ class class_do_render_namumark:
             if self.data_category != '':
                 data_name = self.get_tool_data_storage(self.data_category, '</div>', '')
 
-                if flask.request.cookies.get('main_css_category_set', '0') == '0':
+                if ip_or_user(self.ip) == 0:
+                    self.curs.execute(db_change('select data from user_set where name = "main_css_category_set" and id = ?'), [self.ip])
+                    db_data = self.curs.fetchall()
+                    category_set_data = db_data[0][0] if db_data else 'normal'
+                else:
+                    category_set_data = flask.session['main_css_category_set'] if 'main_css_category_set' in flask.session else 'normal'
+
+                if category_set_data == 'normal':
                     if re.search(r'<footnote_category>', self.render_data):
                         self.render_data = re.sub(r'<footnote_category>', '<hr><' + data_name + '></' + data_name + '>', self.render_data, 1)
                     else:
@@ -1778,8 +1804,15 @@ class class_do_render_namumark:
             self.data_toc = toc_data
             self.data_toc = re.sub(r'<toc_inside>((?:(?!<toc_inside>|<\/toc_inside>).)*)<\/toc_inside>', do_render_last_toc, self.data_toc)
 
+            if ip_or_user(self.ip) == 0:
+                self.curs.execute(db_change('select data from user_set where name = "main_css_toc_set" and id = ?'), [self.ip])
+                db_data = self.curs.fetchall()
+                toc_set_data = db_data[0][0] if db_data else 'normal'
+            else:
+                toc_set_data = flask.session['main_css_toc_set'] if 'main_css_toc_set' in flask.session else 'normal'
+
             self.render_data = re.sub(toc_search_regex, '', self.render_data)
-            if flask.request.cookies.get('main_css_toc_set', '0') != '1':
+            if toc_set_data != 'off':
                 if re.search(r'<toc_need_part>', self.render_data):
                     toc_data_on = 1
 
@@ -1790,7 +1823,7 @@ class class_do_render_namumark:
 
             if  self.doc_include != '' or \
                 re.search(r'<toc_no_auto>', self.render_data) or \
-                flask.request.cookies.get('main_css_toc_set', '0') != '0' or \
+                toc_set_data != 'normal' or \
                 toc_data_on == 1:
                 self.render_data = re.sub(r'<toc_no_auto>', '', self.render_data)
             else:

+ 14 - 0
route/tool/func_tool.py

@@ -43,6 +43,20 @@ def ip_check(d_type = 0):
 
     return ip
 
+def ip_or_user(data = ''):
+    # without_DB
+
+    # 1 == ip
+    # 0 == reg
+    
+    if data == '':
+        data = ip_check()
+
+    if re.search(r'(\.|:)', data):
+        return 1
+    else:
+        return 0
+
 def url_pas(data):
     return urllib.parse.quote(data).replace('/','%2F')
 

+ 1 - 1
route/topic_tool_acl.py

@@ -45,7 +45,7 @@ def topic_tool_acl(topic_num = 1):
 
                 do_add_thread(
                     topic_num,
-                    'acl change ' + acl_data,
+                    load_lang('acl_thread_change') + ' : ' + acl_data,
                     '1'
                 )
                 do_reload_recent_thread(

+ 1 - 1
route/topic_tool_change.py

@@ -33,7 +33,7 @@ def topic_tool_change(topic_num = 1):
 
                 do_add_thread(
                     topic_num,
-                    'change name to ' + sub_d + ' (' + title_d + ')',
+                    load_lang('topic_name_change') + ' : ' + sub_d + ' (' + title_d + ')',
                     '1'
                 )
                 do_reload_recent_thread(

+ 2 - 2
route/user_setting.py

@@ -5,9 +5,9 @@ def user_setting():
         curs = conn.cursor()
 
         support_language = ['default'] + get_init_set_list()['language']['list']
+        
         ip = ip_check()
-
-        if ban_check() == 1:
+        if ban_check(ip) == 1:
             return re_error('/ban')
 
         if ip_or_user(ip) == 0:

+ 153 - 7
route/user_setting_skin_set_main.py

@@ -4,22 +4,168 @@ def user_setting_skin_set_main():
     with get_db_connect() as conn:
         curs = conn.cursor()
 
-        if ban_check() == 1:
+        ip = ip_check()
+        if ban_check(ip) == 1:
             return re_error('/ban')
             
+        set_list = {
+            'main_css_strike' : [
+                ['normal', load_lang('default')],
+                ['change', load_lang('change_to_normal')],
+                ['delete', load_lang('delete')]
+            ], 'main_css_bold' : [
+                ['normal', load_lang('default')],
+                ['change', load_lang('change_to_normal')],
+                ['delete', load_lang('delete')]
+            ], 'main_css_include_link' : [
+                ['normal', load_lang('default')],
+                ['use', load_lang('use')]
+            ], 'main_css_image_paste' : [
+                ['normal', load_lang('default')],
+                ['use', load_lang('use')]
+            ], 'main_css_category_set' : [
+                ['bottom', load_lang('bottom')],
+                ['top', load_lang('top')]
+            ], 'main_css_footnote_set' : [
+                ['normal', load_lang('default')],
+                ['spread', load_lang('spread')]
+            ], 'main_css_image_set' : [
+                ['normal', load_lang('default')],
+                ['click', load_lang('change_to_link')],
+                ['new_click', load_lang('click_load')]
+            ], 'main_css_toc_set' : [
+                ['normal', load_lang('default')],
+                ['off', load_lang('all_off')],
+                ['half_off', load_lang('in_content')]
+            ], 'main_css_monaco' : [
+                ['normal', load_lang('default')],
+                ['use', load_lang('use')]
+            ], 'main_css_exter_link' : [
+                ['blank', load_lang('default')],
+                ['self', load_lang('self_tab')]
+            ], 'main_css_link_delimiter' : [
+                ['normal', load_lang('default')],
+                ['use', load_lang('use')]
+            ], 'main_css_darkmode' : [
+                ['0', load_lang('default')],
+                ['1', load_lang('use')]
+            ], 'main_css_font_size' : [
+                ['']
+            ]
+        }
+        use_cookie = ['main_css_image_paste', 'main_css_darkmode']
+
         if flask.request.method == 'POST':
+            html_data = flask.make_response(redirect('/change/skin_set/main'))
+
+            for for_b in set_list:
+                if for_b in use_cookie:
+                    html_data.set_cookie(for_b, flask.request.form.get(for_b, set_list[for_b][0][0]))
+                elif ip_or_user(ip) == 0:
+                    curs.execute(db_change('select data from user_set where name = ? and id = ?'), [for_b, ip])
+                    if curs.fetchall():
+                        curs.execute(db_change("update user_set set data = ? where name = ? and id = ?"), [
+                            flask.request.form.get(for_b, set_list[for_b][0][0]),
+                            for_b,
+                            ip
+                        ])
+                    else:
+                        curs.execute(db_change('insert into user_set (name, id, data) values (?, ?, ?)'), [
+                            for_b, 
+                            ip,
+                            flask.request.form.get(for_b, set_list[for_b][0][0])
+                        ])
+                else:
+                    flask.session[for_b] = flask.request.form.get(for_b, set_list[for_b][0][0])
 
             conn.commit()
 
-            return redirect('/change')
+            return html_data
         else:
+            set_data = {}
+            for for_b in set_list:
+                set_data[for_b] = ''
+                if for_b in use_cookie:
+                    get_data = flask.request.cookies.get(for_b, '')
+                elif ip_or_user(ip) == 0:
+                    curs.execute(db_change('select data from user_set where name = ? and id = ?'), [for_b, ip])
+                    db_data = curs.fetchall()
+                    get_data = db_data[0][0] if db_data else ''
+                else:
+                    get_data = flask.session[for_b] if for_b in flask.session else ''
+
+                if set_list[for_b][0] == ['']:
+                    set_data[for_b] = get_data
+                else:
+                    for for_a in set_list[for_b]:
+                        if get_data == for_a[0]:
+                            set_data[for_b] = '<option value="' + for_a[0] + '">' + for_a[1] + '</option>' + set_data[for_b]
+                        else:
+                            set_data[for_b] += '<option value="' + for_a[0] + '">' + for_a[1] + '</option>'
 
             return easy_minify(flask.render_template(skin_check(),
-                imp = [load_lang('user_setting'), wiki_set(), wiki_custom(), wiki_css([0, 0])],
-                data = '''
+                imp = [load_lang('main_skin_set'), wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('beta') + ')', 0])],
+                data = render_simple_set('''
                     <form method="post">
-
+                        <h2>render</h2>
+                        <h3>strike</h3>
+                        <select name="main_css_strike">
+                            ''' + set_data["main_css_strike"] + '''
+                        </select>
+                        <h3>bold</h3>
+                        <select name="main_css_bold">
+                            ''' + set_data["main_css_bold"] + '''
+                        </select>
+                        <h3>category</h3>
+                        <select name="main_css_category_set">
+                            ''' + set_data["main_css_category_set"] + '''
+                        </select>
+                        <h3>footnote</h3>
+                        <select name="main_css_footnote_set">
+                            ''' + set_data["main_css_footnote_set"] + '''
+                        </select>
+                        <h3>include link</h3>
+                        <select name="main_css_include_link">
+                            ''' + set_data["main_css_include_link"] + '''
+                        </select>
+                        <h3>image</h3>
+                        <select name="main_css_image_set">
+                            ''' + set_data["main_css_image_set"] + '''
+                        </select>
+                        <h3>toc</h3>
+                        <select name="main_css_toc_set">
+                            ''' + set_data["main_css_toc_set"] + '''
+                        </select>
+                        <h3>exter link</h3>
+                        <select name="main_css_exter_link">
+                            ''' + set_data["main_css_exter_link"] + '''
+                        </select>
+                        <h3>link delimiter</h3>
+                        <select name="main_css_link_delimiter">
+                            ''' + set_data["main_css_link_delimiter"] + '''
+                        </select>
+                        <h3>force darkmode</h3>
+                        <select name="main_css_darkmode">
+                            ''' + set_data["main_css_darkmode"] + '''
+                        </select>
+                        <h3>font size</h3>
+                        (EX : 11) (''' + load_lang('off') + ''' : ''' + load_lang('empty') + ''')
+                        <hr class="main_hr">
+                        <input id="main_css_font_size" value="''' + set_data["main_css_font_size"] + '''">
+                        <h2>editor</h2>
+                        <h3>image paste</h3>
+                        <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>
+                        <hr class="main_hr">
+                        <select name="main_css_image_paste">
+                            ''' + set_data["main_css_image_paste"] + '''
+                        </select>
+                        <h3>monaco</h3>
+                        <select name="main_css_monaco">
+                            ''' + set_data["main_css_monaco"] + '''
+                        </select>
+                        <hr class="main_hr">
+                        <button type="submit">''' + load_lang('save') + '''</button>
                     </form>
-                ''',
-                menu = [['user', load_lang('return')]]
+                '''),
+                menu = [['change', load_lang('user_setting')], ['change/skin_set', load_lang('skin_set')]]
             ))

+ 2 - 2
version.json

@@ -1,7 +1,7 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.6-RC1 (stable1) (beta9-109)",
-        "c_ver" : "3500354",
+        "r_ver" : "v3.4.6-RC2-dev116",
+        "c_ver" : "3500355",
         "s_ver" : "3500111"
     }
 }

+ 10 - 4
views/main_css/js/load_editor.js

@@ -34,14 +34,20 @@ function do_insert_data(name, data, monaco_name) {
 }
 
 // 아직 개편이 더 필요함
-function do_paste_image() {
+function do_paste_image(name, monaco_name) {
     window.addEventListener('DOMContentLoaded', function() {
         if(
             document.cookie.match(opennamu_cookie_split_regex('main_css_image_paste')) &&
-            document.cookie.match(opennamu_cookie_split_regex('main_css_image_paste'))[1] === '1'
+            document.cookie.match(opennamu_cookie_split_regex('main_css_image_paste'))[1] === 'use'
         ) {
-            const textarea = document.querySelector("textarea");
-            if (textarea) {
+            let textarea;
+            if(!document.getElementById(monaco_name)) {
+                textarea = document.getElementById(monaco_name);   
+            } else {
+                textarea = document.getElementById(name);   
+            }
+
+            if(textarea) {
                 textarea.addEventListener("paste", pasteListener);
             }
         }

+ 18 - 1
views/ringo/index.html

@@ -9,7 +9,7 @@
         {% endif %}
         {{imp[3][3]|safe}}
         <script src="https://code.iconify.design/1/1.0.3/iconify.min.js"></script>
-        <script src="/views/ringo/js/main.js?ver=1"></script>
+        <script src="/views/ringo/js/main.js?ver=2"></script>
         <link rel="stylesheet" href="/views/ringo/css/main.css?ver=2">
         <link rel="shortcut icon" href="/views/main_css/file/favicon.ico?ver=1">
         {{imp[1][5]|safe}}
@@ -135,6 +135,23 @@
                         {% endif %}
                     </div>
                 </div>
+                {% if imp[1][6] != '' %}
+                    <div class="top_cel" id="add_cel">
+                        <a href="javascript:ringo_opening('add_cel_in');">
+                            <span class="iconify" data-icon="ic:baseline-playlist-add" data-inline="true"></span>
+                            <span class="not_mobile">{{'added_menu'|load_lang}}</span>
+                            <span class="iconify" data-icon="ic:baseline-arrow-drop-down" data-inline="true"></span>
+                        </a>
+                        <div class="top_cel_in" id="add_cel_in" style="display: none;">
+                            {% for added_top_menu in imp[1][6] %}
+                                <a href="{{added_top_menu[1]}}">
+                                    <span class="iconify" data-icon="ic:baseline-plus" data-inline="true"></span>
+                                    {{added_top_menu[0]}}
+                                </a>
+                            {% endfor %}
+                        </div>
+                    </div>
+                {% endif %}
                 <form class="not_mobile" method="post" action="/search" role="search" id="search">
                     <input class="not_mobile search" name="search" placeholder="{{'search'|load_lang}}" autocomplete="off" type="search">
                     <button type="submit" id="goto" formaction="/goto" class="search_button">

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

@@ -3,7 +3,8 @@ let ringo_open = 0;
 let ringo_menu_list = [
     'recent_cel',
     'other_cel',
-    'user_cel'
+    'user_cel',
+    'add_cel'
 ];
 
 function ringo_opening(data) {
@@ -41,7 +42,7 @@ document.onclick = function(event) {
         cel_list.push(document.getElementById(ringo_menu_list[for_a]));
     }
 
-    if(ringo_save_data !== '' && ringo_open == 2 && !cel_list.includes(event.path[1])) {
+    if(ringo_save_data !== '' && ringo_open == 2) {
         document.getElementById(ringo_save_data).style.display = 'none';
 
         setTimeout(function() { ringo_open = 0; }, 100);