Selaa lähdekoodia

Merge pull request #1927 from openNAMU/dev

베타로 보내서 검증 받아봐야겠다
잉여개발기 (SPDV) 2 vuotta sitten
vanhempi
sitoutus
62aa612d33
50 muutettua tiedostoa jossa 721 lisäystä ja 378 poistoa
  1. 16 37
      app.py
  2. 2 1
      emergency_tool.py
  3. 4 0
      lang/en-US.json
  4. 7 3
      lang/ko-KR.json
  5. 4 0
      route/api_preview.py
  6. 20 15
      route/api_topic.py
  7. 18 56
      route/bbs_w_edit.py
  8. 5 51
      route/bbs_w_post.py
  9. 24 38
      route/edit.py
  10. 9 9
      route/edit_revert.py
  11. 1 1
      route/login_login.py
  12. 16 1
      route/main_func_easter_egg.py
  13. 6 4
      route/main_setting_head.py
  14. 12 0
      route/main_setting_skin_set.py
  15. 9 36
      route/recent_history_add.py
  16. 62 16
      route/tool/func.py
  17. 176 54
      route/tool/func_render_namumark.py
  18. 9 26
      route/topic.py
  19. 16 2
      route/user_alarm.py
  20. 6 2
      route/user_alarm_delete.py
  21. 1 1
      route/user_info.py
  22. 27 0
      route/user_setting_skin_set_main.py
  23. 14 8
      route/view_random.py
  24. BIN
      route_go/bin/main_easter_egg.amd64.bin
  25. BIN
      route_go/bin/main_easter_egg.amd64.exe
  26. BIN
      route_go/bin/main_easter_egg.arm64.bin
  27. BIN
      route_go/bin/main_easter_egg.arm64.exe
  28. BIN
      route_go/bin/main_func_easter_egg.amd64.bin
  29. BIN
      route_go/bin/main_func_easter_egg.amd64.exe
  30. BIN
      route_go/bin/main_func_easter_egg.arm64.bin
  31. BIN
      route_go/bin/main_func_easter_egg.arm64.exe
  32. BIN
      route_go/bin/view_random.amd64.bin
  33. BIN
      route_go/bin/view_random.amd64.exe
  34. BIN
      route_go/bin/view_random.arm64.bin
  35. BIN
      route_go/bin/view_random.arm64.exe
  36. 30 0
      route_go/go.mod
  37. 68 0
      route_go/go.sum
  38. 4 4
      route_go/linux_amd64.sh
  39. 1 1
      route_go/main_func_easter_egg.go
  40. 39 0
      route_go/tool/db_connect.go
  41. 31 0
      route_go/view_random.go
  42. 2 2
      version.json
  43. 4 5
      views/main_css/css/main.css
  44. 5 1
      views/main_css/css/sub/dark.css
  45. 0 3
      views/main_css/js/func/check_new_thread.ts
  46. 20 0
      views/main_css/js/route/editor_sub.js
  47. 20 0
      views/main_css/js/route/editor_sub.ts
  48. 1 1
      views/main_css/js/route/render.js
  49. 14 0
      views/main_css/js/route/topic.js
  50. 18 0
      views/main_css/js/route/topic.ts

+ 16 - 37
app.py

@@ -75,7 +75,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change('create table ' + create_table + '(test longtext default (""))'))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -83,7 +84,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change('create table ' + create_table + '(test longtext default "")'))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -91,7 +93,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change('create table ' + create_table + '(test longtext)'))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -99,7 +102,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ('')"))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -107,7 +111,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext default ''"))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -115,7 +120,8 @@ with get_db_connect() as conn:
                         curs.execute(db_change("alter table " + create_table + " add column " + create + " longtext"))
 
                         db_pass = 1
-                    except:
+                    except Exception as e:
+                        # print(e)
                         pass
 
                 if db_pass == 0:
@@ -257,6 +263,8 @@ if os.path.exists('custom.py'):
     from custom import custom_run
     custom_run('error', app)
 
+db_set_str = json.dumps(data_db_set)
+
 # Func
 # Func-inter_wiki
 app.route('/inter_wiki', defaults = { 'tool' : 'inter_wiki' })(filter_inter_wiki)
@@ -381,7 +389,6 @@ app.route('/history_hidden/<int(signed = True):rev>/<everything:name>')(recent_h
 app.route('/history_send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_send)
 app.route('/history_reset/<everything:name>', methods = ['POST', 'GET'])(recent_history_reset)
 app.route('/history_add/<everything:name>', methods = ['POST', 'GET'])(recent_history_add)
-app.route('/history_add_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(recent_history_add)
 
 # Func-view
 app.route('/xref/<everything:name>')(view_xref)
@@ -402,14 +409,12 @@ app.route('/w_rev/<int(signed = True):doc_rev>/<everything:name>')(view_read)
 app.route('/w_from/<everything:name>', defaults = { 'do_type' : 'from' })(view_read)
 app.route('/w/<everything:name>')(view_read)
 
-app.route('/random')(view_random)
+app.route('/random', defaults = { 'db_set' : db_set_str })(view_random)
 
 # Func-edit
 app.route('/edit/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
 app.route('/edit_from/<everything:name>', defaults = { 'do_type' : 'load' })(edit)
 app.route('/edit_section/<int:section>/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit_section_preview/<int:section>/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
 
 app.route('/upload', methods = ['POST', 'GET'])(edit_upload)
 
@@ -431,7 +436,6 @@ app.route('/recent_discuss/open', defaults = { 'tool' : 'open' })(recent_discuss
 
 app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
 app.route('/thread/0/<everything:doc_name>', defaults = { 'topic_num' : '0' }, methods = ['POST', 'GET'])(topic)
-app.route('/thread_preview/<int:topic_num>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(topic)
 app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
@@ -473,6 +477,7 @@ app.route('/count/<name>')(user_count)
 
 app.route('/alarm')(user_alarm)
 app.route('/alarm/delete')(user_alarm_delete)
+app.route('/alarm/delete/<int:id>')(user_alarm_delete)
 
 app.route('/watch_list', defaults = { 'tool' : 'watch_list' })(user_watch_list)
 app.route('/watch_list/<everything:name>', defaults = { 'tool' : 'watch_list' })(user_watch_list_name)
@@ -524,17 +529,13 @@ app.route('/bbs/make', methods = ['POST', 'GET'])(bbs_make)
 app.route('/bbs/w/<int:bbs_num>')(bbs_w)
 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/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)
@@ -610,28 +611,6 @@ app.route('/setting/skin_set', methods = ['POST', 'GET'])(main_setting_skin_set)
 
 app.route('/easter_egg')(main_func_easter_egg)
 
-def main_easter_egg_go():
-    with get_db_connect() as conn:
-        print(platform.machine())
-        if platform.system() == 'Linux':
-            if platform.machine() in ["AMD64", "x86_64"]:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.amd64.bin")).read()
-            else:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.arm64.bin")).read()
-        else:
-            if platform.machine() in ["AMD64", "x86_64"]:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.amd64.exe")).read()
-            else:
-                data = os.popen(os.path.join(".", "route_go", "bin", "main_easter_egg.arm64.exe")).read()
-
-        return easy_minify(flask.render_template(skin_check(),
-            imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
-            data = data,
-            menu = 0
-        ))
-
-app.route('/easter_egg_go')(main_easter_egg_go)
-
 # views -> view
 app.route('/view/<path:name>')(main_view)
 app.route('/views/<path:name>')(main_view)

+ 2 - 1
emergency_tool.py

@@ -269,10 +269,11 @@ elif what_i_do == '24':
     create_data = get_db_table_list()
     for create_table in create_data:
         create = ['test'] + create_data[create_table]
-        create_r = ', '.join(['?' for _ in create])
+        create_r = ', '.join(['%s' for _ in create])
         create = ', '.join(create)
         
         print('select ' + create + ' from ' + create_table)
+        mysql_curs.execute(db_change('delete from ' + create_table))
         sqlite_curs.execute(db_change('select ' + create + ' from ' + create_table))
         db_data = sqlite_curs.fetchall()
         mysql_curs.executemany(db_change("insert into " + create_table + " (" + create + ") values (" + create_r + ")"), db_data)

+ 4 - 0
lang/en-US.json

@@ -297,6 +297,9 @@
                 "footnote_real_num_view" : "Footnote original number view",
                 "category_change_title" : "Don't rename documents in category",
                 "table_scroll" : "Use scroll in tables",
+                "list_view_change" : "Change how the number list is viewed",
+                "view_joke" : "Show contents of joke macro",
+                "math_scroll" : "Use scroll in math macros",
             "_comment_" : "Option",
                 "change_to_normal" : "Change to plain text.",
                 "change_to_link" : "Change to Link.",
@@ -464,6 +467,7 @@
                 "edit_record" : "Edit record",
                 "discussion_record" : "Discussion record",
         "_comment_2.4_" : "Topic",
+            "remove_blind_thread" : "Hide blind thread",
             "make_new_topic" : "Make new discussion",
             "topic_tool" : "Discussion management tools",
             "topic_state" : "Discussion status",

+ 7 - 3
lang/ko-KR.json

@@ -208,7 +208,7 @@
     "name": "이름",
     "period": "기간",
     "writer": "작성자",
-    "long_id_error": "ID는 32자보다 짧아야 합니다.",
+    "long_id_error": "ID는 128자보다 짧아야 합니다.",
     "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
     "revert": "복원",
     "discussion_authority": "토론 관리 권한",
@@ -231,7 +231,7 @@
     "file_name": "파일명",
     "close_discussion": "닫힌 토론",
     "language": "언어",
-    "id_char_error": "오직 한글과 알파벳, 숫자만 사용 가능합니다.",
+    "id_char_error": "XSS 문자(부등호, 따옴표)는 사용 불가능합니다.",
     "id_filter_add": "ID 필터 추가",
     "skin": "스킨",
     "user_head": "사용자 <HEAD>",
@@ -569,5 +569,9 @@
     "category_change_title": "분류 내 문서명 변경 금지",
     "table_scroll": "표에 스크롤 사용",
     "data": "데이터",
-    "volume": "용량"
+    "volume": "용량",
+    "list_view_change" : "숫자 리스트의 보기 방식 변경",
+    "view_joke" : "농담 매크로 내용 보이기",
+    "math_scroll" : "Math 매크로에서 스크롤 사용",
+    "remove_blind_thread" : "숨겨진 토론 보이지 않기"
 }

+ 4 - 0
route/api_preview.py

@@ -0,0 +1,4 @@
+from .tool.func import *
+
+def api_preview():
+    pass

+ 20 - 15
route/api_topic.py

@@ -6,24 +6,30 @@ def api_topic_thread_make(user_id, date, data, code, color = '', blind = '', add
             color_b = 'opennamu_comment_blind'
         else:
             color_b = 'opennamu_comment_blind_admin'
+
+        class_b = 'opennamu_comment_blind_js'
     else:
         color_b = 'opennamu_comment_blind_not'
+        class_b = ''
 
     return '''
-        <table class="opennamu_comment" style="''' + add_style + '''">
-            <tr>
-                <td class="opennamu_comment_color_''' + color + '''">
-                    <a href="#thread_shortcut" id="''' + code + '''">#''' + code + '''</a>
-                    ''' + user_id + '''
-                    <span style="float: right;">''' + date + '''</span>
-                </td>
-            </tr>
-            <tr>
-                <td class="''' + color_b + '''" id="opennamu_comment_data_main">
-                    ''' + data + '''
-                </td>
-            </tr>
-        </table>
+        <span class="''' + class_b + '''">
+            <table class="opennamu_comment" style="''' + add_style + '''">
+                <tr>
+                    <td class="opennamu_comment_color_''' + color + '''">
+                        <a href="#thread_shortcut" id="''' + code + '''">#''' + code + '''</a>
+                        ''' + user_id + '''
+                        <span style="float: right;">''' + date + '''</span>
+                    </td>
+                </tr>
+                <tr>
+                    <td class="''' + color_b + '''" id="opennamu_comment_data_main">
+                        ''' + data + '''
+                    </td>
+                </tr>
+            </table>
+            <hr class="main_hr">
+        </span>
     '''
 
 def api_topic_thread_pre_render(curs, data, num, ip, topic_num = '', name = '', sub = '', do_type = 'thread'):
@@ -192,7 +198,6 @@ def api_topic(topic_num = 1, tool = 'normal', num = '', render = ''):
                                 blind = for_a["blind"],
                                 add_style = ''
                             )
-                            data_r += '<hr class="main_hr">'
 
                     return flask.jsonify({ "data" : data_r })
             else:

+ 18 - 56
route/bbs_w_edit.py

@@ -2,9 +2,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 = '', comment_num = '', do_type = ''):
+def bbs_w_edit(bbs_num = '', post_num = '', comment_num = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -37,7 +38,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
         
         i_list = ['post_view_acl', 'post_comment_acl']
 
-        if flask.request.method == 'POST' and do_type != 'preview':
+        if flask.request.method == 'POST':
             if captcha_post(flask.request.form.get('g-recaptcha-response', flask.request.form.get('g-recaptcha', ''))) == 1:
                 return re_error('/error/13')
             else:
@@ -86,57 +87,26 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
         else:
             option_display = ''
 
-            d_list = ['' for _ in range(0, len(i_list))]
-            if do_type == 'preview':
-                title = flask.request.form.get('title', '')
-                data = flask.request.form.get('content', '')
-                data = data.replace('\r', '')
-                data_preview = render_set(
-                    doc_data = data,
-                    data_type = 'thread',
-                    data_in = 'bbs'
-                ) + '<hr>'
-                for for_a in range(0, len(i_list)):
-                    d_list[for_a] = flask.request.form.get(i_list[for_a], 'normal')
+            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']
+                option_display = 'display: none;'
+            elif post_num == '':
+                title = ''
+                data = ''
             else:
-                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:
-                    temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
-
-                    title = temp_dict['title']
-                    data = temp_dict['data']
-                    data_preview = ''
+                temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
+
+                title = temp_dict['title']
+                data = temp_dict['data']
 
             acl_div = ['' for _ in range(0, len(i_list))]
             acl_list = get_acl_list()
             for for_a in range(0, len(i_list)):
                 for data_list in acl_list:
-                    if data_list == d_list[for_a]:
-                        check = 'selected="selected"'
-                    else:
-                        check = ''
-
-                    acl_div[for_a] += '<option value="' + data_list + '" ' + check + '>' + (data_list if data_list != '' else 'normal') + '</option>'
-            
-            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:
-                form_action = 'formaction="/bbs/edit/' + bbs_num_str + '/' + post_num_str + '"'
-                form_action_preview = 'formaction="/bbs/edit/preview/' + bbs_num_str + '/' + post_num_str + '"'
+                    acl_div[for_a] += '<option value="' + data_list + '">' + (data_list if data_list != '' else 'normal') + '</option>'
     
             editor_top_text = '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
 
@@ -158,15 +128,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = '', do_type = ''):
                         <hr style="''' + option_display + '''" class="main_hr">
 
                         ''' + edit_editor(curs, ip, data, 'bbs') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-                        
-                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                    
-                        <hr class="main_hr">
-                        <div id="opennamu_preview_area">''' + data_preview + '''</div>
+
                         <!--
                         <div style="''' + option_display + '''">
                             ''' + render_simple_set('''

+ 5 - 51
route/bbs_w_post.py

@@ -49,7 +49,6 @@ def bbs_w_post_comment(user_id, sub_code, comment_num, bbs_num_str, post_num_str
             comment_default = 'selected'
 
         comment_select += '<option value="' + sub_code_check + '" ' + comment_default + '>' + sub_code_check + '</option>'
-        comment_data += '<hr class="main_hr">'
 
         temp_data = bbs_w_post_comment(user_id, sub_code + '-' + temp_dict['code'], comment_num, bbs_num_str, post_num_str)
 
@@ -59,7 +58,7 @@ def bbs_w_post_comment(user_id, sub_code, comment_num, bbs_num_str, post_num_str
 
     return (comment_data, comment_select, comment_count, comment_add_count)
 
-def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
+def bbs_w_post(bbs_num = '', post_num = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -84,7 +83,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
         if not db_data_2:
             return redirect('/bbs/main')
         elif db_data_2[0][0] == 'thread':
-            if flask.request.method == 'POST' and do_type != 'preview':
+            if flask.request.method == 'POST':
                 if bbs_comment_acl == 1:
                     return redirect('/bbs/set/' + bbs_num_str)
                 
@@ -123,16 +122,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     return re_error('/ban')
 
                 text = ''
-                data_preview = ''
-                if do_type == 'preview':
-                    text = flask.request.form.get('content', '')
-                    text = text.replace('\r', '')
-
-                    data_preview = render_set(
-                        doc_data = text,
-                        data_type = 'thread',
-                        data_in = 'bbs_comment_preview'
-                    )
 
                 date = ''
                 date += temp_dict['date']
@@ -150,7 +139,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     '0',
                     color = 'green'
                 )
-                data += '<hr class="main_hr">'
 
                 user_id = temp_dict['user_id']
                 count = 0
@@ -178,25 +166,10 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                         str(count),
                         color = color
                     )
-                    data += '<hr class="main_hr">'
-
-                bbs_comment_form = ''
-                if bbs_comment_acl == 0:
-                    bbs_comment_form += '''                        
-                        ''' + edit_editor(curs, ip, text, 'bbs_comment') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-
-                        <button id="opennamu_save_button" formaction="/bbs/w/''' + bbs_num_str + '''/''' + post_num_str + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/bbs/w/preview/''' + bbs_num_str + '''/''' + post_num_str + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                        <hr class="main_hr">
-                    '''
 
                 data += '''
                     <form method="post">
-                        ''' + bbs_comment_form + '''
-                        ''' + data_preview + '''
+                        ''' + (edit_editor(curs, ip, text, 'bbs_comment') if bbs_comment_acl == 0 else '') + '''
                     </form>
                 '''
 
@@ -207,7 +180,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 ))
         else:
             # db_data_2[0][0] == 'comment'
-            if flask.request.method == 'POST' and do_type != 'preview':
+            if flask.request.method == 'POST':
                 if bbs_comment_acl == 1:
                     return redirect('/bbs/set/' + bbs_num_str)
                 
@@ -278,17 +251,6 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                     
                 text = ''
                 comment_num = ''
-                data_preview = ''
-                if do_type == 'preview':
-                    text = flask.request.form.get('content', '')
-                    text = text.replace('\r', '')
-
-                    comment_num = flask.request.form.get('comment_select', '')
-
-                    data_preview = render_set(
-                        doc_data = text,
-                        data_in = 'bbs_comment_preview'
-                    )
 
                 date = ''
                 date += '<a href="javascript:opennamu_change_comment(\'0\');">(' + load_lang('comment') + ')</a> '
@@ -325,7 +287,7 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                 comment_add_count -= comment_count
 
                 if comment_data != '':
-                    data += '<hr class="main_hr"><hr>'
+                    data += '<hr>'
 
                 comment_select += '</select>'
                 if comment_data != '':
@@ -342,19 +304,11 @@ def bbs_w_post(bbs_num = '', post_num = '', do_type = ''):
                         <hr class="main_hr">
                         
                         ''' + edit_editor(curs, ip, text, 'bbs_comment') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-
-                        <button id="opennamu_save_button" formaction="/bbs/w/''' + bbs_num_str + '''/''' + post_num_str + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/bbs/w/preview/''' + bbs_num_str + '''/''' + post_num_str + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
-                        <hr class="main_hr">
                     '''
 
                 data += '''
                     <form method="post">
                         ''' + bbs_comment_form + '''
-                        ''' + data_preview + '''
                     </form>
                     <script src="/views/main_css/js/route/bbs_w_post.js"></script>
                 '''

+ 24 - 38
route/edit.py

@@ -23,7 +23,7 @@ def edit_timeout(func, args = (), timeout = 3):
         pool.join()
         return 0
         
-def edit_editor(curs, ip, data_main = '', do_type = 'edit'):
+def edit_editor(curs, ip, data_main = '', do_type = 'edit', addon = ''):
     monaco_editor_top = ''
     editor_display = ''
     add_get_file = ''
@@ -81,11 +81,21 @@ def edit_editor(curs, ip, data_main = '', do_type = 'edit'):
         <div id="opennamu_monaco_editor" class="''' + textarea_size + '''" ''' + monaco_display + '''></div>
         <textarea id="opennamu_edit_textarea" ''' + editor_display + ''' class="''' + textarea_size + '''" name="content" placeholder="''' + p_text + '''">''' + html.escape(data_main) + '''</textarea>
         <hr class="main_hr">
+        
+        ''' + captcha_get() + ip_warning() + addon + '''
+        <hr class="main_hr">
+
         <script>
             do_stop_exit();
             do_paste_image('opennamu_edit_textarea', 'opennamu_monaco_editor');
             ''' + add_script + '''
         </script>
+                        
+        <button id="opennamu_save_button" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
+        <button id="opennamu_preview_button" type="button" onclick="do_monaco_to_textarea(); opennamu_do_editor_preview();">''' + load_lang('preview') + '''</button>
+        <hr class="main_hr">
+
+        <div id="opennamu_preview_area"></div>
     '''
 
 def edit(name = 'Test', section = 0, do_type = ''):
@@ -107,7 +117,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
         post_ver = flask.request.form.get('ver', '')
         if flask.request.method == 'POST':
             edit_repeat = 'error' if post_ver != doc_ver else 'post'
-            edit_repeat = 'error' if do_type == 'preview' else 'post'
         else:
             edit_repeat = 'get'
         
@@ -215,7 +224,6 @@ def edit(name = 'Test', section = 0, do_type = ''):
             doc_section_edit_apply = 'X'
             data_section = ''
             data_section_where = ''
-            data_preview = ''
 
             if edit_repeat == 'get':
                 if do_type == 'load':
@@ -285,36 +293,22 @@ def edit(name = 'Test', section = 0, do_type = ''):
 
                 doc_ver = flask.request.form.get('ver', '')
 
-                if do_type != 'preview':
-                    warning_edit = load_lang('exp_edit_conflict') + ' '
-        
-                    if flask.request.form.get('ver', '0') == '0':
-                        warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
-                    else:
-                        warning_edit += '' + \
-                            '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
-                                '(r' + doc_ver + ')' + \
-                            '</a>' + \
-                        ''
-        
-                    warning_edit += '<hr class="main_hr">'
-                    editor_top_text = warning_edit + editor_top_text
+                warning_edit = load_lang('exp_edit_conflict') + ' '
+    
+                if flask.request.form.get('ver', '0') == '0':
+                    warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
                 else:
-                    data_preview = render_set(
-                        doc_name = name, 
-                        doc_data = data,
-                        data_type = 'from'
-                    )
+                    warning_edit += '' + \
+                        '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
+                            '(r' + doc_ver + ')' + \
+                        '</a>' + \
+                    ''
+    
+                warning_edit += '<hr class="main_hr">'
+                editor_top_text = warning_edit + editor_top_text
 
             if data_section == '':
                 data_section = data
-
-            if section == '':
-                form_action = 'formaction="/edit/' + url_pas(name) + '"'
-                form_action_preview = 'formaction="/edit_preview/' + url_pas(name) + '"'
-            else:
-                form_action = 'formaction="/edit_section/' + str(section) + '/' + url_pas(name) + '"'
-                form_action_preview = 'formaction="/edit_section_preview/' + str(section) + '/' + url_pas(name) + '"'
     
             editor_top_text += '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
     
@@ -332,19 +326,11 @@ def edit(name = 'Test', section = 0, do_type = ''):
 
                         <input style="display: none;" name="ver" value="''' + doc_ver + '''">
                         
-                        ''' + edit_editor(curs, ip, data_section) + '''
-
                         <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         
-                        ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
-                        
-                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
+                        ''' + edit_editor(curs, ip, data_section, addon = get_edit_text_bottom_check_box() + get_edit_text_bottom()) + '''
                     </form>
-                    
-                    <hr class="main_hr">
-                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 ''',
                 menu = [
                     ['w/' + url_pas(name), load_lang('return')],

+ 9 - 9
route/edit_revert.py

@@ -71,19 +71,19 @@ def edit_revert(name, num):
             return redirect('/w/' + url_pas(name))
         else:
             if data:
-                preview = '<pre>' + html.escape(data[0][0]) + '</pre>'
+                preview = '<hr class="main_hr"><pre>' + html.escape(data[0][0]) + '</pre>'
             else:
                 preview = ''
             
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(r' + str(num) + ') (' + load_lang('revert') + ')', 0])],
-                data =  '''
-                        <form method="post">
-                            <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                            <hr class="main_hr">
-                            ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
-                            <button type="submit">''' + load_lang('revert') + '''</button>
-                        </form>
-                        ''' + preview,
+                data = '''
+                    <form method="post">
+                        <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                        <hr class="main_hr">
+                        ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
+                        <button type="submit">''' + load_lang('revert') + '''</button>
+                    </form>
+                ''' + preview,
                 menu = [['history/' + url_pas(name), load_lang('history')], ['recent_changes', load_lang('recent_change')]]
             ))

+ 1 - 1
route/login_login.py

@@ -25,7 +25,7 @@ def login_login_2():
             user_data = {}
 
             curs.execute(db_change(
-                'select name, data from user_set where id = ? and name = "pw" or name = "encode"'
+                'select name, data from user_set where id = ? and (name = "pw" or name = "encode")'
             ), [user_id])
             sql_data = curs.fetchall()
             if not sql_data:

+ 16 - 1
route/main_func_easter_egg.py

@@ -11,4 +11,19 @@ def main_func_easter_egg():
                 curs.execute(db_change('insert into user_set (name, id, data) values ("get_🥚", ?, "Y")'), [ip])
                 conn.commit()
     
-        return redirect('/easter_egg_go')
+        if platform.system() == 'Linux':
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.bin")).read()
+            else:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.bin")).read()
+        else:
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.exe")).read()
+            else:
+                data = os.popen(os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.exe")).read()
+
+        return easy_minify(flask.render_template(skin_check(),
+            imp = ['Easter Egg', wiki_set(), wiki_custom(), wiki_css([0, 0])],
+            data = data,
+            menu = 0
+        ))

+ 6 - 4
route/main_setting_head.py

@@ -39,10 +39,15 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
             else:
                 return redirect('/setting/' + end_r + '/' + skin_name)
         else:
+            title = ''
+            start = ''
+            form_action = ''
+            data_preview = ''
+            plus = ''
+
             if num == 4:
                 curs.execute(db_change("select data from other where name = 'body'"))
                 title = '_body'
-                start = ''
                 form_action = 'formaction="/setting/body/top"'
                 data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 plus = '''
@@ -53,7 +58,6 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
             elif num == 7:
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 title = '_bottom_body'
-                start = ''
                 data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 form_action = 'formaction="/setting/body/bottom"'
                 plus = '''
@@ -75,8 +79,6 @@ def main_setting_head(num, skin_name = '', set_preview = 0):
                     </span>
                     <hr class="main_hr">
                 '''
-                form_action = ''
-                plus = ''
 
             if set_preview == 1:
                 data = data_preview

+ 12 - 0
route/main_setting_skin_set.py

@@ -109,6 +109,18 @@ def main_setting_skin_set():
                         <select name="main_css_table_scroll">
                             ''' + set_data["main_css_table_scroll"] + '''
                         </select>
+                        <h3>''' + load_lang("list_view_change") + '''</h3>
+                        <select name="main_css_list_view_change">
+                            ''' + set_data["main_css_list_view_change"] + '''
+                        </select>
+                        <h3>''' + load_lang("view_joke") + '''</h3>
+                        <select name="main_css_view_joke">
+                            ''' + set_data["main_css_view_joke"] + '''
+                        </select>
+                        <h3>''' + load_lang("math_scroll") + '''</h3>
+                        <select name="main_css_math_scroll">
+                            ''' + set_data["main_css_math_scroll"] + '''
+                        </select>
                         <h2>''' + load_lang("edit") + '''</h2>
                         <h3>''' + load_lang("image_paste") + '''</h3>
                         <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>

+ 9 - 36
route/recent_history_add.py

@@ -1,5 +1,7 @@
 from .tool.func import *
 
+from .edit import edit_editor
+
 def recent_history_add(name = 'Test', do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
@@ -8,7 +10,7 @@ def recent_history_add(name = 'Test', do_type = ''):
         if admin_check() != 1:
             return re_error('/ban')
 
-        if flask.request.method == 'POST' and do_type == '':
+        if flask.request.method == 'POST':
             admin_check(None, 'history_add (' + name + ')')
 
             today = get_time()
@@ -29,48 +31,19 @@ def recent_history_add(name = 'Test', do_type = ''):
             conn.commit()
 
             return redirect('/history/' + url_pas(name))
-        else:
-            curs.execute(db_change('select data from other where name = "edit_help"'))
-            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')
-
-            send = ''
-            get_ip = ''
-            data = ''
-            data_preview = ''
-            if do_type == 'preview':
-                data = flask.request.form.get('content', '')
-                data = data.replace('\r', '')
-
-                send = flask.request.form.get('send', '')
-                get_ip = flask.request.form.get('get_ip', '')
-
-                data_preview = render_set(
-                    doc_name = name, 
-                    doc_data = data
-                )
-            
+        else:            
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('history_add'), wiki_set(), wiki_custom(), wiki_css(['(' + name + ')', 0])],
                 data = '''
-                    <form method="post">                        
-                        <div>''' + edit_button('opennamu_edit_textarea') + '''</div>
-                        
-                        <textarea id="opennamu_edit_textarea" class="opennamu_textarea_500" name="content" placeholder="''' + p_text + '''">''' + html.escape(data) + '''</textarea>
+                    <form method="post">
+                        <input placeholder="''' + load_lang('why') + '''" name="send">
                         <hr class="main_hr">
                         
-                        <input placeholder="''' + load_lang('why') + '''" name="send" value="''' + html.escape(send) + '''">
+                        <input placeholder="''' + load_lang('name') + '''" name="get_ip">
                         <hr class="main_hr">
-                        
-                        <input placeholder="''' + load_lang('name') + '''" name="get_ip" value="''' + html.escape(get_ip) + '''">
-                        <hr class="main_hr">
-                        
-                        <button id="opennamu_save_button" formaction="/history_add/''' + url_pas(name) + '''" type="submit">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/history_add_preview/''' + url_pas(name) + '''" type="submit">''' + load_lang('preview') + '''</button>
+
+                        ''' + edit_editor(curs, ip) + '''
                     </form>
-                    
-                    <hr class="main_hr">
-                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 ''',
                 menu = [['history/' + url_pas(name), load_lang('return')]]
             ))

+ 62 - 16
route/tool/func.py

@@ -333,10 +333,10 @@ def get_db_table_list():
     create_data['re_admin'] = ['who', 'what', 'time']
 
     # 개편 예정 (user_notice와 user_agent로 변경)
-    create_data['alarm'] = ['name', 'data', 'date']
     create_data['ua_d'] = ['name', 'ip', 'ua', 'today', 'sub']
 
     create_data['user_set'] = ['name', 'id', 'data']
+    create_data['user_notice'] = ['id', 'name', 'data', 'date', 'readme']
 
     create_data['bbs_set'] = ['set_name', 'set_code', 'set_id', 'set_data']
     create_data['bbs_data'] = ['set_name', 'set_code', 'set_id', 'set_data']
@@ -655,6 +655,30 @@ def update(ver_num, set_data):
         if ver_num < 3500365:
             curs.execute(db_change("update back set data = '' where data is null"))
 
+        if ver_num < 3500371:
+            curs.execute(db_change("delete from user_notice"))
+            user_alarm_count = {}
+
+            curs.execute(db_change("select name, data, date from alarm"))
+            for db_data in curs.fetchall():
+                if db_data[0] in user_alarm_count:
+                    user_alarm_count[db_data[0]] += 1
+                else:
+                    user_alarm_count[db_data[0]] = 1
+
+                curs.execute(db_change(
+                    'insert into user_notice (id, name, data, date, readme) values (?, ?, ?, ?, "")'
+                ), [str(user_alarm_count[db_data[0]]), db_data[0], db_data[1], db_data[2]])
+
+        if ver_num < 3500372:
+            # ID 글자 확인 호환용
+            curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [
+                r'(?:[^A-Za-zㄱ-힣0-9])',
+                'name',
+                '',
+                ''
+            ])
+
         conn.commit()
 
         print('Update completed')
@@ -725,6 +749,13 @@ def set_init():
             ]:
                 curs.execute(db_change("insert into other (name, data, coverage) values (?, ?, '')"), [i[0], i[1]])
 
+        curs.execute(db_change('insert into html_filter (html, kind, plus, plus_t) values (?, ?, ?, ?)'), [
+            r'(?:[^A-Za-zㄱ-힣0-9])',
+            'name',
+            '',
+            ''
+        ])
+
 # Func-simple
 ## Func-simple-without_DB
 def get_default_admin_group():
@@ -1097,7 +1128,7 @@ def wiki_css(data):
     data += ['' for _ in range(0, 3 - len(data))]
     
     data_css = ''
-    data_css_ver = '180'
+    data_css_ver = '182'
     
     # Func JS + Defer
     data_css += '<script src="/views/main_css/js/func/func.js?ver=' + data_css_ver + '"></script>'
@@ -1115,7 +1146,9 @@ def wiki_css(data):
     
     # Route JS
     data_css += '<script src="/views/main_css/js/route/editor.js?ver=' + data_css_ver + '"></script>'
+    data_css += '<script src="/views/main_css/js/route/editor_sub.js?ver=' + data_css_ver + '"></script>'
     data_css += '<script src="/views/main_css/js/route/render.js?ver=' + data_css_ver + '"></script>'
+    data_css += '<script src="/views/main_css/js/route/topic.js?ver=' + data_css_ver + '"></script>'
     
     # Main CSS
     data_css += '<link rel="stylesheet" href="/views/main_css/css/main.css?ver=' + data_css_ver + '">'
@@ -1253,7 +1286,7 @@ def wiki_custom():
                 user_admin = '0'
                 user_acl_list = '0'
 
-            curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
+            curs.execute(db_change("select count(*) from user_notice where name = ? and readme = ''"), [ip])
             count = curs.fetchall()
             user_notice = str(count[0][0]) if count else '0'
         else:
@@ -1354,6 +1387,8 @@ def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', d
 
         acl_dict = {}
         acl_dict[doc_name] = doc_acl
+
+        ip = ip_check()
             
         if doc_acl == 1:
             return 'HTTP Request 401.3'
@@ -1402,7 +1437,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;
@@ -1417,11 +1452,19 @@ def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', d
                                 font-weight: bold;
                             }
                         </style>
-                    '''
+                    ''' + get_class_render[0]
 
-                table_set_data = get_main_skin_set(curs, flask.session, 'main_css_table_scroll', ip_check())
+                table_set_data = get_main_skin_set(curs, flask.session, 'main_css_table_scroll', ip)
                 if table_set_data == 'on':
-                    get_class_render[0] += '<style>.table_safe { overflow-x: scroll; white-space: nowrap; }</style>'
+                    get_class_render[0] = '<style>.table_safe { overflow-x: scroll; white-space: nowrap; }</style>' + get_class_render[0]
+
+                joke_set_data = get_main_skin_set(curs, flask.session, 'main_css_view_joke', ip)
+                if joke_set_data == 'off':
+                    get_class_render[0] = '<style>.opennamu_joke { display: none; }</style>' + get_class_render[0]
+
+                math_set_data = get_main_skin_set(curs, flask.session, 'main_css_math_scroll', ip)
+                if math_set_data == 'on':
+                    get_class_render[0] = '<style>.katex .base { overflow-x: scroll; }</style>' + get_class_render[0]
 
                 if data_type == 'api_view' or data_type == 'api_thread':
                     return [
@@ -1660,8 +1703,8 @@ 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):
+        # XSS 필터
+        if html.escape(user_name) != user_name:
             return 1
 
         # ID 필터
@@ -1672,8 +1715,8 @@ def do_user_name_check(user_name):
             if check_r.search(user_name):
                 return 1
 
-        # ID 길이 제한 (32글자)
-        if len(user_name) > 32:
+        # ID 길이 제한 (128글자)
+        if len(user_name) > 128:
             return 1
         
         return 0
@@ -2397,9 +2440,15 @@ def add_alarm(to_user, from_user, context):
         if to_user != from_user:
             context = from_user + ' | ' + context
 
+            count = '1'
+            curs.execute(db_change("select id from user_notice where name = ? order by id + 0 desc"), [to_user])
+            db_data = curs.fetchall()
+            if db_data:
+                count = str(int(db_data[0][0]) + 1)
+
             curs.execute(db_change(
-                'insert into alarm (name, data, date) values (?, ?, ?)'
-            ), [to_user, context, get_time()])
+                'insert into user_notice (id, name, data, date, readme) values (?, ?, ?, ?, "")'
+            ), [count, to_user, context, get_time()])
     
 def add_user(user_name, user_pw, user_email = '', user_encode = ''):
     with get_db_connect() as conn:
@@ -2652,9 +2701,6 @@ def re_error(data):
                 data = load_lang('error_skin_set')
             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('long_id_error') + '<br>' + load_lang('id_char_error') + ' <a href="/name_filter">(' + load_lang('id_filter_list') + ')</a>'
             elif num == 9:

+ 176 - 54
route/tool/func_render_namumark.py

@@ -3,7 +3,7 @@ from .func_tool import *
 class class_do_render_namumark:
     def __init__(self, curs, doc_name, doc_data, doc_set, lang_data, footnote = {}):
         self.curs = curs
-        
+
         self.doc_data = doc_data.replace('\r', '')
         self.doc_name = doc_name
         self.doc_set = doc_set
@@ -17,8 +17,8 @@ class class_do_render_namumark:
 
         try:
             if 'main_css_bold' in flask.session:
-                pass    
-                
+                pass
+
             self.flask_session = flask.session
         except:
             self.flask_session = ''
@@ -38,7 +38,7 @@ class class_do_render_namumark:
 
         self.data_math_count = 0
         self.data_redirect = 0
-        
+
         self.data_toc = ''
         self.data_footnote = {}
         self.data_footnote_all = {}
@@ -234,7 +234,7 @@ class class_do_render_namumark:
                 data_name = self.get_tool_data_storage('', '', match.group(0))
             else:
                 data_name = self.get_tool_data_storage('<b>', '</b>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
 
         # <b>
@@ -244,7 +244,7 @@ class class_do_render_namumark:
         def do_render_text_italic(match):
             data = match.group(1)
             data_name = self.get_tool_data_storage('<i>', '</i>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
 
         # <i>
@@ -254,17 +254,17 @@ class class_do_render_namumark:
         def do_render_text_under(match):
             data = match.group(1)
             data_name = self.get_tool_data_storage('<u>', '</u>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
 
         # <u>
         self.render_data = re.sub(r"__((?:(?!__).)+)__", do_render_text_under, self.render_data)
-        
+
         # <sup> function
         def do_render_text_sup(match):
             data = match.group(1)
             data_name = self.get_tool_data_storage('<sup>', '</sup>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
 
         # <sup>
@@ -276,9 +276,9 @@ class class_do_render_namumark:
         def do_render_text_sub(match):
             data = match.group(1)
             data_name = self.get_tool_data_storage('<sub>', '</sub>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
-        
+
         # <sub>
         self.render_data = re.sub(r",,,((?:(?!,,,).)+),,,", do_render_text_sub, self.render_data)
         # <sub> 2
@@ -295,14 +295,14 @@ class class_do_render_namumark:
                 data_name = self.get_tool_data_storage('', '', match.group(0))
             else:
                 data_name = self.get_tool_data_storage('<s>', '</s>', match.group(0))
-            
+
             return '<' + data_name + '>' + data + '</' + data_name + '>'
-        
+
         # <s>
         self.render_data = re.sub(r"--((?:(?!--).)+)--", do_render_text_strike, self.render_data)
         # <s> 2
         self.render_data = re.sub(r"~~((?:(?!~~).)+)~~", do_render_text_strike, self.render_data)
-    
+
     def do_render_heading(self):
         toc_list = []
 
@@ -412,7 +412,7 @@ class class_do_render_namumark:
         heading_id_data = re.findall(heading_id_regex, self.render_data)
         for for_a in range(len(heading_id_data)):
             self.render_data = re.sub(heading_id_regex, '<a href="#toc" id="s-' + heading_id_data[for_a] + '">' + heading_id_data[for_a] + '.</a>', self.render_data, 1)
-            
+
             toc_list[for_a][0] = heading_id_data[for_a]
 
         # not heading restore
@@ -524,7 +524,7 @@ class class_do_render_namumark:
 
                 data_name = self.get_tool_data_storage(
                     '<iframe style="width: ' + video_width + '; height: ' + video_height + ';" src="' + video_code + '" frameborder="0" allowfullscreen>',
-                    '</iframe>', 
+                    '</iframe>',
                     match_org.group(0)
                 )
 
@@ -569,6 +569,43 @@ class class_do_render_namumark:
                 data_name = self.get_tool_data_storage('<span id="' + main_text + '">', '</span>', match_org.group(0))
 
                 return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'timeif':
+                data = re.findall(macro_split_regex, match[1])
+
+                main_text = ''
+                before_text = ''
+                after_text = ''
+                for for_a in data:
+                    data_sub = re.search(macro_split_sub_regex, for_a)
+                    if data_sub:
+                        data_sub = data_sub.groups()
+                        data_sub = [data_sub[0].lower(), data_sub[1]]
+
+                        if data_sub[0] == 'before':
+                            before_text = data_sub[1]
+                        elif data_sub[0] == 'after':
+                            after_text = data_sub[1]
+                    else:
+                        main_text = for_a
+
+                if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', main_text):
+                    try:
+                        date = datetime.datetime.strptime(main_text, '%Y-%m-%d')
+                        data_text = ''
+                    except:
+                        data_text = 'invalid date'
+
+                    date_now = datetime.datetime.today()
+
+                    if data_text == '':
+                        if date > date_now:
+                            data_text = before_text
+                        else:
+                            data_text = after_text
+                else:
+                    data_text = 'invalid date'
+
+                return data_text
             elif name_data == 'age':
                 if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', match[1]):
                     try:
@@ -590,7 +627,7 @@ class class_do_render_namumark:
                 data_name = self.get_tool_data_storage(data_text, '', match_org.group(0))
 
                 return '<' + data_name + '></' + data_name + '>'
-            elif name_data == 'dday':
+            elif name_data in ('dday', 'dmonth', 'dyear'):
                 if re.search(r'^[0-9]{4}-[0-9]{2}-[0-9]{2}$', match[1]):
                     try:
                         date = datetime.datetime.strptime(match[1], '%Y-%m-%d')
@@ -599,9 +636,26 @@ class class_do_render_namumark:
                         data_text = 'invalid date'
 
                     date_now = datetime.datetime.today()
-                    
                     if data_text == '':
-                        date_end = (date_now - date).days
+                        if name_data == 'dday':
+                            date_end = (date_now - date).days
+                        elif name_data == 'dyear':
+                            date_end = (date_now - date)
+                            if date_end.days > 0:
+                                date_end = datetime.date.min + date_end
+                                date_end = date_end.year - 1
+                            else:
+                                date_end = datetime.date.min - date_end
+                                date_end = 0 - (date_end.year - 1)
+                        else:
+                            date_end = (date_now - date)
+                            if date_end.days > 0:
+                                date_end = datetime.date.min + date_end
+                                date_end = (date_end.year - 1) * 12 + (date_end.month - 1)
+                            else:
+                                date_end = datetime.date.min - date_end
+                                date_end = 0 - ((date_end.year - 1) * 12 + (date_end.month - 1))
+
                         if date_end > 0:
                             data_text = '+' + str(date_end)
                         else:
@@ -615,10 +669,30 @@ class class_do_render_namumark:
                 data_name = self.get_tool_data_storage(data_text, '', match_org.group(0))
 
                 return '<' + data_name + '></' + data_name + '>'
+            elif name_data == 'joke':
+                data_name = self.get_tool_data_storage('<span class="opennamu_joke">', '</span>', match_org.group(0))
+
+                return '<' + data_name + '>' + match[1] + '</' + data_name + '>'
             elif name_data == 'pagecount':
                 return '0'
             elif name_data == 'lastedit':
-                link_main = self.get_tool_link_fix(match[1], 'redirect')
+                link_main = match[1]
+                data_view = ''
+
+                data = re.findall(macro_split_regex, match[1])
+                for for_a in data:
+                    data_sub = re.search(macro_split_sub_regex, for_a)
+                    if data_sub:
+                        data_sub = data_sub.groups()
+                        data_sub = [data_sub[0].lower(), data_sub[1]]
+
+                        if data_sub[0] == 'view':
+                            if data_sub[1] == 'full':
+                                data_view = '1'
+                    else:
+                        link_main = for_a
+                        
+                link_main = self.get_tool_link_fix(link_main, 'redirect')
 
                 link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
                 link_main = html.unescape(link_main)
@@ -626,7 +700,11 @@ class class_do_render_namumark:
                 self.curs.execute(db_change("select set_data from data_set where doc_name = ? and set_name = 'last_edit'"), [link_main])
                 db_data = self.curs.fetchall()
                 if db_data:
-                    return db_data[0][0]
+                    date_data = db_data[0][0]
+                    if data_view != '1':
+                        date_data = date_data.split()[0]
+
+                    return date_data
                 else:
                     return '0'
             else:
@@ -678,8 +756,8 @@ class class_do_render_namumark:
             data = match.group(1)
 
             if self.data_math_count == 0:
-                self.render_data_cdn += '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">'
-                self.render_data_cdn += '<script src="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js" integrity="sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4" crossorigin="anonymous"></script>'
+                self.render_data_cdn += '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.css" integrity="sha384-GvrOXuhMATgEsSwCs4smul74iXGOixntILdUW9XmUC6+HX0sLNAK3q71HotJqlAn" crossorigin="anonymous">'
+                self.render_data_cdn += '<script src="https://cdn.jsdelivr.net/npm/katex@0.16.8/dist/katex.min.js" integrity="sha384-cpW21h6RZv/phavutF+AuVYrr+dA8xD9zs6FwLpaCct6O9ctzYFfFr4dgmgccOTx" crossorigin="anonymous"></script>'
 
             data = re.sub(r'\n', '', data)
             data = self.get_tool_data_revert(data)
@@ -1097,8 +1175,8 @@ class class_do_render_namumark:
 
                 return slash_add + match[2]
 
-        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, self.render_data)
-        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z]+)@', do_render_include_default_sub, self.render_data)
+        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z0-9]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, self.render_data)
+        self.render_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z0-9]+)@', do_render_include_default_sub, self.render_data)
 
     def do_render_include(self):
         def do_render_include_default_sub(match):
@@ -1184,8 +1262,8 @@ class class_do_render_namumark:
                             include_link = '<div><a href="/w/' + url_pas(include_name) + '">(' + include_name_org + ')</a></div>'
 
                         # 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)
+                        include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z0-9]+)=((?:\\@|[^@\n])+)@', do_render_include_default_sub, include_data)
+                        include_data = re.sub(r'(\\+)?@([ㄱ-힣a-zA-Z0-9]+)@', do_render_include_default_sub, include_data)
 
                         # remove end br
                         include_data = re.sub('^\n+', '', include_data)
@@ -1333,8 +1411,18 @@ class class_do_render_namumark:
             link_data_full = match.group(0)
             link_main = match.group(1)
 
-            # under page & fix url
-            link_main = self.get_tool_link_fix(link_main, 'redirect')
+            link_inter_name = ''
+
+            link_inter_regex = re.compile('^(?:inter|인터):([^:]+):', flags = re.I)
+            inter_check = re.search(link_inter_regex, link_main)
+            if not inter_check:
+                # under page & fix url
+                link_main = self.get_tool_link_fix(link_main, 'redirect')
+            else:
+                link_inter_name = re.search(link_inter_regex, link_main)
+                link_inter_name = link_inter_name.group(1)
+
+                link_main = re.sub(link_inter_regex, '', link_main)
 
             # sharp
             link_main = link_main.replace('&#x27;', '<link_single>')
@@ -1351,24 +1439,50 @@ class class_do_render_namumark:
             
             link_main = link_main.replace('<link_single>', '&#x27;')
 
-            # main link fix
-            link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
-            link_main = html.unescape(link_main)
-
-            self.data_backlink += [[self.doc_name, link_main, 'redirect', '']]
+            if not inter_check:
+                # main link fix
+                link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                link_main = html.unescape(link_main)
 
-            link_main = url_pas(link_main)
+                self.data_backlink += [[self.doc_name, link_main, 'redirect', '']]
 
-            self.data_redirect = 1
-            if link_main != '':
-                link_main = '/w_from/' + link_main
+                link_main = url_pas(link_main)
+                if link_main != '':
+                    link_main = '/w_from/' + link_main
 
-            if 'doc_from' in self.doc_set:
-                data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                self.data_redirect = 1
+                if 'doc_from' in self.doc_set:
+                    data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                else:
+                    data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="0; url=' + link_main + link_data_sharp + '">', '', link_data_full)
+                    
+                self.render_data = '<' + data_name + '></' + data_name + '>'
             else:
-                data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="0; url=' + link_main + link_data_sharp + '">', '', link_data_full)
+                self.curs.execute(db_change("select plus, plus_t from html_filter where kind = 'inter_wiki' and html = ?"), [link_inter_name])
+                db_data = self.curs.fetchall()
+                if db_data:
+                    link_main = url_pas(link_main)
+                    link_main = db_data[0][0] + link_main
+
+                    link_sub_storage = match.group(1)
+                    link_sub_storage = re.sub(link_inter_regex, '', link_sub_storage)
+
+                    link_inter_icon = link_inter_name + ':'
+                    if db_data[0][1] != '':
+                        link_inter_icon = db_data[0][1]
+
+                    link_sub_storage = link_inter_icon + link_sub_storage
+
+                    self.data_redirect = 1
+                    if 'doc_from' in self.doc_set:
+                        data_name = self.get_tool_data_storage('<a href="' + link_main + link_data_sharp + '">(GO)</a>', '', link_data_full)
+                    else:
+                        data_name = self.get_tool_data_storage('<meta http-equiv="refresh" content="5; url=' + link_main + link_data_sharp + '">', link_sub_storage + ' - After 5s', link_data_full)
                 
-            self.render_data = '<' + data_name + '></' + data_name + '>'
+                    self.render_data = '<' + data_name + '></' + data_name + '>'
+                else:
+                    self.data_redirect = 1
+                    self.render_data = ''
 
     def do_render_table(self):
         self.render_data = re.sub(r'\n +\|\|', '\n||', self.render_data)
@@ -1449,7 +1563,7 @@ class class_do_render_namumark:
                             table_parameter_all['td'] += 'text-align: left;'
                         elif table_parameter == ':':
                             table_parameter_all['td'] += 'text-align: center;'
-                        elif table_parameter == ':':
+                        elif table_parameter == ')':
                             table_parameter_all['td'] += 'text-align: right;'
                     else:
                         table_parameter_data = self.get_tool_css_safe(table_parameter)
@@ -1500,7 +1614,7 @@ class class_do_render_namumark:
                 else:
                     table_caption = ''
 
-                table_parameter = { "div" : "", "class" : "", "table" : "", "col" : {}, "rowspan" : {} }
+                table_parameter = { "div" : "", "class" : "", "table" : "", "tr" : "", "td" : "", "col" : {}, "rowspan" : {} }
                 table_data_end = ''
                 table_col_num = 0
                 table_tr_change = 0
@@ -1509,13 +1623,14 @@ class class_do_render_namumark:
                     table_data_in = re.sub(r'^\n+', '', table_data_in)
 
                     table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_data_in)
-
-                    if table_data_end == '':
-                        table_data_end += '<tr style="' + table_sub_parameter['tr'] + '">'
+                    table_parameter["tr"] += table_sub_parameter['tr']
 
                     if table_sub[0] != '' and table_tr_change == 1:
                         table_col_num = 0
-                        table_data_end += '</tr><tr style="' + table_sub_parameter['tr'] + '">'
+                        table_data_end += '<tr style="' + table_parameter["tr"] + '">' + table_parameter["td"] + '</tr>'
+                        
+                        table_parameter["tr"] = ""
+                        table_parameter["td"] = ""
 
                     if not table_col_num in table_parameter['rowspan']:
                         table_parameter['rowspan'][table_col_num] = 0
@@ -1542,11 +1657,12 @@ class class_do_render_namumark:
                     else:
                         table_tr_change = 0
                     
-                        table_data_end += '<td colspan="' + table_sub_parameter['colspan'] + '" rowspan="' + table_sub_parameter['rowspan'] + '" style="' + table_parameter['col'][table_col_num] + table_sub_parameter['td'] + '"><back_br>\n' + table_sub_parameter['data'] + '\n<front_br></td>'
+                        table_parameter["td"] += '<td colspan="' + table_sub_parameter['colspan'] + '" rowspan="' + table_sub_parameter['rowspan'] + '" style="' + table_parameter['col'][table_col_num] + table_sub_parameter['td'] + '"><back_br>\n' + table_sub_parameter['data'] + '\n<front_br></td>'
                     
                     table_col_num += 1
+                else:
+                    table_data_end += '<tr style="' + table_parameter["tr"] + '">' + table_parameter["td"] + '</tr>'
 
-                table_data_end += '</tr>'
                 table_data_end = '<table class="' + table_parameter['class'] + '" style="' + table_parameter['table'] + '">' + table_caption + table_data_end + '</table>'
                 table_data_end = '<div class="table_safe" style="' + table_parameter['div'] + '">' + table_data_end + '</div>'
 
@@ -1923,11 +2039,14 @@ class class_do_render_namumark:
                 i -= 1
 
             return end_text
+            
+        list_view_set = get_main_skin_set(self.curs, self.flask_session, 'main_css_list_view_change', self.ip)
         
         class do_render_list_int_to:
-            def __init__(self, do_type):
+            def __init__(self, do_type, list_view_set = ''):
                 self.list_num = []
                 self.do_type = do_type
+                self.list_view_set = list_view_set
 
             def __call__(self, match):
                 list_data = match.group(3)
@@ -1948,7 +2067,10 @@ class class_do_render_namumark:
                     self.list_num[list_len - 1] = int(list_start)
 
                 if self.do_type == 'int':
-                    change_text = str(self.list_num[list_len - 1])
+                    if self.list_view_set == 'on':
+                        change_text = str('-'.join([str(for_a) for for_a in self.list_num if for_a != 0]))
+                    else:
+                        change_text = str(self.list_num[list_len - 1])
                 elif self.do_type == 'roman_big':
                     change_text = int_to_roman(self.list_num[list_len - 1])
                 elif self.do_type == 'roman_small':
@@ -1973,7 +2095,7 @@ class class_do_render_namumark:
                 list_data = list_data.group(1)
                 list_sub_regex = r'\n( *)1\.(?:#([0-9]*))? ?([^\n]*)'
 
-                list_class = do_render_list_int_to('int')
+                list_class = do_render_list_int_to('int', list_view_set)
                 list_data = re.sub(list_sub_regex, list_class, list_data)
 
                 self.render_data = re.sub(list_regex, lambda x : ('\n<front_br><ul class="opennamu_ul">' + list_data + '</ul><back_br>\n'), self.render_data, 1)
@@ -2215,4 +2337,4 @@ class class_do_render_namumark:
                 'include' : list(reversed(self.data_include)), # include data
                 'footnote' : self.data_footnote_all # footnote
             } # other
-        ]
+        ]

+ 9 - 26
route/topic.py

@@ -100,18 +100,13 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
             return redirect('/thread/' + topic_num + '#' + num)
         else:
             thread_data = ''
-            thread_data_preview = ''
 
             if topic_num == '0':
                 name = load_lang('make_new_topic')
                 sub = load_lang('make_new_topic')
 
-                if do_type == 'preview':
-                    name_value = flask.request.form.get('topic', '')
-                    sub_value = flask.request.form.get('title', '')
-                else:
-                    name_value = doc_name
-                    sub_value = ''
+                name_value = doc_name
+                sub_value = ''
             else:
                 curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
                 name = curs.fetchall()
@@ -124,14 +119,6 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
                 else:
                     return redirect('/')
 
-            if do_type == 'preview':
-                thread_data = flask.request.form.get('content', 'Test')
-                thread_data = thread_data.replace('\r', '')
-
-                thread_data_preview = render_set(
-                    doc_data = thread_data
-                )
-
             acl_display = 'display: none;' if topic_acl == 1 else ''
             name_display = 'display: none;' if topic_num != '0' else ''
 
@@ -156,6 +143,13 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
             return easy_minify(flask.render_template(skin_check(),
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
                 data = '''
+                    <style id="opennamu_remove_blind">
+                        .opennamu_comment_blind_js {
+                            display: none;
+                        }
+                    </style>
+                    <input type="checkbox" onclick="opennamu_do_remove_blind_thread();" checked> ''' + load_lang('remove_blind_thread') + '''
+
                     ''' + shortcut + '''
                     <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
                     
@@ -175,18 +169,7 @@ def topic(topic_num = 0, do_type = '', doc_name = 'Test'):
                         </div>
                         
                         ''' + edit_editor(curs, ip, thread_data, 'thread') + '''
-                        <hr class="main_hr">
-                        
-                        ''' + captcha_get() + ip_warning() + '''
-                        
-                        <button id="opennamu_save_button" formaction="/thread/''' + topic_num + '''" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_preview_button" formaction="/thread_preview/''' + topic_num + '''#opennamu_edit_textarea" type="submit" onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
                     </form>
-                    <hr class="main_hr">
-                    
-                    <div id="opennamu_preview_area">''' + thread_data_preview + '''</div>
-                    
-                    <!-- JS : opennamu_do_thread_make -->
                 ''',
                 menu = [['topic/' + url_pas(name), load_lang('list')]]
             ))

+ 16 - 2
route/user_alarm.py

@@ -8,8 +8,10 @@ def user_alarm():
         sql_num = (num * 50 - 50) if num * 50 > 0 else 0
     
         data = '<ul class="opennamu_ul">'
+
+        ip = ip_check()
     
-        curs.execute(db_change("select data, date from alarm where name = ? order by date desc limit ?, 50"), [ip_check(), sql_num])
+        curs.execute(db_change("select data, date, readme, id from user_notice where name = ? order by date desc limit ?, 50"), [ip, sql_num])
         data_list = curs.fetchall()
         if data_list:
             data = '' + \
@@ -20,8 +22,20 @@ def user_alarm():
     
             for data_one in data_list:
                 data_split = data_one[0].split(' | ')
+                data_style = ''
+                if data_one[2] == '1':
+                    data_style = 'opacity: 0.75;'
                 
-                data += '<li>' + ip_pas(data_split[0]) + (' | ' + ' | '.join(data_split[1:]) if len(data_split) > 1 else '') + ' (' + data_one[1] + ')</li>'
+                data += '' + \
+                    '<li style="' + data_style + '">' + \
+                        ip_pas(data_split[0]) + (' | ' + ' | '.join(data_split[1:]) if len(data_split) > 1 else '') + \
+                        ' | ' + data_one[1] + \
+                        ' <a href="/alarm/delete/' + url_pas(data_one[3]) + '">(' + load_lang('delete') + ')</a>' + \
+                    '</li>' + \
+                ''
+
+        curs.execute(db_change("update user_notice set readme = '1' where name = ?"), [ip])
+        conn.commit()
     
         data += '' + \
             '</ul>' + \

+ 6 - 2
route/user_alarm_delete.py

@@ -1,10 +1,14 @@
 from .tool.func import *
 
-def user_alarm_delete():
+def user_alarm_delete(id = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
     
-        curs.execute(db_change("delete from alarm where name = ?"), [ip_check()])
+        if id != '':
+            curs.execute(db_change("delete from user_notice where name = ? and id = ?"), [ip_check(), str(id)])
+        else:
+            curs.execute(db_change("delete from user_notice where name = ?"), [ip_check()])
+        
         conn.commit()
 
         return redirect('/alarm')

+ 1 - 1
route/user_info.py

@@ -13,7 +13,7 @@ def user_info(name = ''):
         tool_menu = ''
         
         if name == '':
-            curs.execute(db_change("select count(*) from alarm where name = ?"), [ip])
+            curs.execute(db_change("select count(*) from user_notice where name = ? and readme = ''"), [ip])
             count = curs.fetchall()
             if count and count[0][0] != 0:
                 tool_menu += '<li><a class="opennamu_not_exist_link" href="/alarm">' + load_lang('alarm') + ' (' + str(count[0][0]) + ')</a></li>'

+ 27 - 0
route/user_setting_skin_set_main.py

@@ -72,6 +72,18 @@ def user_setting_skin_set_main_set_list():
             ['default', load_lang('default')],
             ['off', load_lang('off')],
             ['on', load_lang('use')]
+        ], 'main_css_list_view_change' : [
+            ['default', load_lang('default')],
+            ['off', load_lang('off')],
+            ['on', load_lang('use')]
+        ], 'main_css_view_joke' : [
+            ['default', load_lang('default')],
+            ['on', load_lang('use')],
+            ['off', load_lang('off')]
+        ], 'main_css_math_scroll' : [
+            ['default', load_lang('default')],
+            ['off', load_lang('off')],
+            ['on', load_lang('use')]
         ]
     }
 
@@ -217,6 +229,21 @@ def user_setting_skin_set_main():
                         <select name="main_css_table_scroll">
                             ''' + set_data["main_css_table_scroll"] + '''
                         </select>
+                        <h3>''' + load_lang("list_view_change") + '''</h3>
+                        ''' + set_data_main["main_css_list_view_change"] + '''
+                        <select name="main_css_list_view_change">
+                            ''' + set_data["main_css_list_view_change"] + '''
+                        </select>
+                        <h3>''' + load_lang("view_joke") + '''</h3>
+                        ''' + set_data_main["main_css_view_joke"] + '''
+                        <select name="main_css_view_joke">
+                            ''' + set_data["main_css_view_joke"] + '''
+                        </select>
+                        <h3>''' + load_lang("math_scroll") + '''</h3>
+                        ''' + set_data_main["main_css_math_scroll"] + '''
+                        <select name="main_css_math_scroll">
+                            ''' + set_data["main_css_math_scroll"] + '''
+                        </select>
                         <h2>''' + load_lang("edit") + '''</h2>
                         <h3>''' + load_lang("image_paste") + '''</h3>
                         <sup>''' + load_lang('only_korean') + '''</sup> <sup>''' + load_lang('unavailable_in_monaco') + '''</sup>

+ 14 - 8
route/view_random.py

@@ -1,13 +1,19 @@
 from .tool.func import *
 
-def view_random():
+def view_random(db_set):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
-        curs.execute(db_change("" + \
-            "select title from data " + \
-            "where title not like 'user:%' and title not like 'category:%' and title not like 'file:%' " + \
-            "order by random() limit 1" + \
-        ""))
-        data = curs.fetchall()
-        return redirect('/w/' + url_pas(data[0][0])) if data else redirect()
+        if platform.system() == 'Linux':
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = subprocess.Popen([os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.bin"), db_set], stdout=subprocess.PIPE).communicate()[0]
+            else:
+                data = subprocess.Popen([os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.bin"), db_set], stdout=subprocess.PIPE).communicate()[0]
+        else:
+            if platform.machine() in ["AMD64", "x86_64"]:
+                data = subprocess.Popen([os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".amd64.exe"), db_set], stdout=subprocess.PIPE).communicate()[0]
+            else:
+                data = subprocess.Popen([os.path.join(".", "route_go", "bin", sys._getframe().f_code.co_name + ".arm64.exe"), db_set], stdout=subprocess.PIPE).communicate()[0]
+
+        print(sys._getframe().f_code.co_name, data.decode('utf8'))
+        return redirect('/w/' + url_pas(data.decode('utf8')))

BIN
route_go/bin/main_easter_egg.amd64.bin


BIN
route_go/bin/main_easter_egg.amd64.exe


BIN
route_go/bin/main_easter_egg.arm64.bin


BIN
route_go/bin/main_easter_egg.arm64.exe


BIN
route_go/bin/main_func_easter_egg.amd64.bin


BIN
route_go/bin/main_func_easter_egg.amd64.exe


BIN
route_go/bin/main_func_easter_egg.arm64.bin


BIN
route_go/bin/main_func_easter_egg.arm64.exe


BIN
route_go/bin/view_random.amd64.bin


BIN
route_go/bin/view_random.amd64.exe


BIN
route_go/bin/view_random.arm64.bin


BIN
route_go/bin/view_random.arm64.exe


+ 30 - 0
route_go/go.mod

@@ -0,0 +1,30 @@
+module opennamu/golang
+
+go 1.20
+
+require (
+	github.com/go-sql-driver/mysql v1.7.1
+	modernc.org/sqlite v1.25.0
+)
+
+require (
+	github.com/dustin/go-humanize v1.0.1 // indirect
+	github.com/google/uuid v1.3.0 // indirect
+	github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
+	github.com/mattn/go-isatty v0.0.16 // indirect
+	github.com/mattn/go-sqlite3 v1.14.17 // indirect
+	github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
+	golang.org/x/mod v0.3.0 // indirect
+	golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
+	golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 // indirect
+	golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
+	lukechampine.com/uint128 v1.2.0 // indirect
+	modernc.org/cc/v3 v3.40.0 // indirect
+	modernc.org/ccgo/v3 v3.16.13 // indirect
+	modernc.org/libc v1.24.1 // indirect
+	modernc.org/mathutil v1.5.0 // indirect
+	modernc.org/memory v1.6.0 // indirect
+	modernc.org/opt v0.1.3 // indirect
+	modernc.org/strutil v1.1.3 // indirect
+	modernc.org/token v1.0.1 // indirect
+)

+ 68 - 0
route_go/go.sum

@@ -0,0 +1,68 @@
+github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
+github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
+github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
+github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM=
+github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
+github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
+github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78 h1:M8tBwCtWD/cZV9DZpFYRUgaymAYAr+aIUTWzDaM3uPs=
+golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
+lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
+modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
+modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
+modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
+modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
+modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
+modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
+modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
+modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
+modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
+modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
+modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o=
+modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
+modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
+modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
+modernc.org/sqlite v1.25.0 h1:AFweiwPNd/b3BoKnBOfFm+Y260guGMF+0UFk0savqeA=
+modernc.org/sqlite v1.25.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU=
+modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
+modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
+modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
+modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
+modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
+modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=

+ 4 - 4
route_go/linux_amd64.sh

@@ -3,20 +3,20 @@ read file_name
 
 export GOOS=linux
 export GOARCH=amd64
-go build $file_name.go
+CGO_ENABLED=0 go build $file_name.go
 mv $file_name ./bin/$file_name.amd64.bin
 
 export GOOS=linux
 export GOARCH=arm64
-go build $file_name.go
+CGO_ENABLED=0 go build $file_name.go
 mv $file_name ./bin/$file_name.arm64.bin
 
 export GOOS=windows
 export GOARCH=amd64
-go build $file_name.go
+CGO_ENABLED=0 go build $file_name.go
 mv $file_name.exe ./bin/$file_name.amd64.exe
 
 export GOOS=windows
 export GOARCH=arm64
-go build $file_name.go
+CGO_ENABLED=0 go build $file_name.go
 mv $file_name.exe ./bin/$file_name.arm64.exe

+ 1 - 1
route_go/main_easter_egg.go → route_go/main_func_easter_egg.go

@@ -33,5 +33,5 @@ func main() {
 	}
 	select_str := select_list[rand.Intn(len(select_list)-1)]
 
-	fmt.Println("<iframe width=\"640\" height=\"360\" src=\"https://www.youtube.com/embed/" + select_str + "\" frameborder=\"0\" allowfullscreen></iframe>")
+	fmt.Print("<iframe width=\"640\" height=\"360\" src=\"https://www.youtube.com/embed/" + select_str + "\" frameborder=\"0\" allowfullscreen></iframe>")
 }

+ 39 - 0
route_go/tool/db_connect.go

@@ -0,0 +1,39 @@
+package tool
+
+import (
+	"database/sql"
+	"fmt"
+	"strings"
+
+	_ "github.com/go-sql-driver/mysql"
+	_ "modernc.org/sqlite"
+)
+
+func DB_connect(db_set map[string]string) *sql.DB {
+	if db_set["type"] == "sqlite" {
+		db, err := sql.Open("sqlite3", db_set["name"]+".db")
+		if err != nil {
+			fmt.Println(err)
+			return nil
+		}
+
+		return db
+	} else {
+		db, err := sql.Open("mysql", db_set["mysql_user"]+":"+db_set["mysql_pw"]+"@tcp("+db_set["mysql_host"]+":"+db_set["mysql_port"]+")/"+db_set["name"])
+		if err != nil {
+			fmt.Println(err)
+			return nil
+		}
+
+		return db
+	}
+}
+
+func DB_change(db_set map[string]string, data string) string {
+	if db_set["type"] == "mysql" {
+		data = strings.Replace(data, "random()", "rand()", -1)
+		data = strings.Replace(data, "collate nocase", "collate utf8mb4_general_ci", -1)
+	}
+
+	return data
+}

+ 31 - 0
route_go/view_random.go

@@ -0,0 +1,31 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"os"
+
+	"opennamu/golang/tool"
+)
+
+func main() {
+	call_arg := os.Args[1:]
+	db_set := map[string]string{}
+
+	json.Unmarshal([]byte(call_arg[0]), &db_set)
+
+	db := tool.DB_connect(db_set)
+	if db == nil {
+		return
+	}
+	defer db.Close()
+
+	var title string
+	err := db.QueryRow(tool.DB_change(db_set, "select title from data where title not like 'user:%' and title not like 'category:%' and title not like 'file:%' order by random() limit 1")).Scan(&title)
+	if err != nil {
+		fmt.Println(err)
+		return
+	}
+
+	fmt.Print(title)
+}

+ 2 - 2
version.json

@@ -1,7 +1,7 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.6-RC4.3-dev233",
-        "c_ver" : "3500365",
+        "r_ver" : "v3.4.6-RC5-dev11",
+        "c_ver" : "3500372",
         "s_ver" : "3500111"
     }
 }

+ 4 - 5
views/main_css/css/main.css

@@ -26,6 +26,8 @@ input[type="checkbox"], input[type="radio"] {
 
 /* 테이블 */
 table {
+    overflow-x: scroll;
+
     border-collapse: collapse;
 }
 
@@ -332,12 +334,9 @@ s:hover, strike:hover, del:hover {
     white-space: pre-line;
 }
 
-.katex {
+.katex .base {
     max-width: 100%;
-
-    display: inline-block;
-
-    overflow-x: scroll;
+    overflow-x: hidden;
     overflow-y: hidden;
 }
 

+ 5 - 1
views/main_css/css/sub/dark.css

@@ -40,6 +40,10 @@ input::placeholder, textarea::placeholder, select::placeholder {
     background: #314c56;
 }
 
+.opennamu_comment_blind_admin {
+    background: #2f2f2f;
+}
+
 #main_table_top_tr {
     background: #2e5f4e;
 }
@@ -68,4 +72,4 @@ blockquote {
 
 #topic_color {
     background: #325a56;
-}
+}

+ 0 - 3
views/main_css/js/func/check_new_thread.ts

@@ -1,3 +0,0 @@
-function opennamu_check_new_thread(do_type : string = '') {
-    
-}

+ 20 - 0
views/main_css/js/route/editor_sub.js

@@ -0,0 +1,20 @@
+function opennamu_do_editor_preview() {
+    var input = document.querySelector('#opennamu_edit_textarea');
+    if (input !== null) {
+        fetch("/api/w/test/doc_tool/preview", {
+            method: 'POST',
+            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+            body: new URLSearchParams({
+                'data': input.value,
+            })
+        }).then(function (res) {
+            return res.json();
+        }).then(function (text) {
+            var preview = document.querySelector('#opennamu_preview_area');
+            if (preview !== null) {
+                preview.innerHTML = text.data;
+                eval(text.js_data);
+            }
+        });
+    }
+}

+ 20 - 0
views/main_css/js/route/editor_sub.ts

@@ -0,0 +1,20 @@
+function opennamu_do_editor_preview() {
+    const input = document.querySelector('#opennamu_edit_textarea') as HTMLInputElement | null;
+    if(input !== null) {
+        fetch("/api/w/test/doc_tool/preview", {
+            method : 'POST',
+            headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
+            body : new URLSearchParams({
+                'data': input.value,
+            })
+        }).then(function(res) {
+            return res.json();
+        }).then(function(text) {
+            const preview = document.querySelector('#opennamu_preview_area') as HTMLInputElement | null;
+            if(preview !== null) {
+                preview.innerHTML = text.data;
+                eval(text.js_data);
+            }
+        });
+    }
+}

+ 1 - 1
views/main_css/js/route/render.js

@@ -55,7 +55,7 @@ function opennamu_do_render_html(name = '') {
                         link_data = '';
                     }
 
-                    return '<' + t_data[key] + ' id="out_link" href="' + link_data + '">' + in_data_2 + '</' + t_data[key] + '>';
+                    return '<' + t_data[key] + ' class="opennamu_link_out" href="' + link_data + '">' + in_data_2 + '</' + t_data[key] + '>';
                 } else if(t_data[key] === 'iframe') {
                     let src_data = in_data.match(/ src=['"]([^'"]*)['"]/);
                     if(src_data) {

+ 14 - 0
views/main_css/js/route/topic.js

@@ -0,0 +1,14 @@
+function opennamu_check_new_thread(do_type) {
+    if (do_type === void 0) { do_type = ''; }
+}
+function opennamu_do_remove_blind_thread() {
+    var style = document.querySelector('#opennamu_remove_blind');
+    if (style !== null) {
+        if (style.innerHTML !== "") {
+            style.innerHTML = '';
+        }
+        else {
+            style.innerHTML = "\n                .opennamu_comment_blind_js {\n                    display: none;\n                }\n            ";
+        }
+    }
+}

+ 18 - 0
views/main_css/js/route/topic.ts

@@ -0,0 +1,18 @@
+function opennamu_check_new_thread(do_type : string = '') {
+    
+}
+
+function opennamu_do_remove_blind_thread() {
+    const style = document.querySelector('#opennamu_remove_blind') as HTMLInputElement | null;
+    if(style !== null) {
+        if(style.innerHTML !== "") {
+            style.innerHTML = '';
+        } else {
+            style.innerHTML = `
+                .opennamu_comment_blind_js {
+                    display: none;
+                }
+            `;
+        }
+    }
+}