Jelajahi Sumber

Merge pull request #2154 from openNAMU/dev

신규 API 추가
잉여개발기 2 tahun lalu
induk
melakukan
1230b10342

+ 12 - 7
app.py

@@ -548,9 +548,11 @@ app.route('/revert/<int:num>/<everything:name>', methods = ['POST', 'GET'])(edit
 app.route('/move/<everything:name>', methods = ['POST', 'GET'])(edit_move)
 
 # Func-topic
+app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
+app.route('/topic_page/<int:page>/<everything:name>', methods = ['POST', 'GET'])(topic_list)
+
 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('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
 app.route('/thread/<int:topic_num>/setting', methods = ['POST', 'GET'])(topic_tool_setting)
@@ -644,7 +646,8 @@ app.route('/vote/add', methods = ['POST', 'GET'])(vote_add)
 app.route('/bbs/main')(bbs_main)
 app.route('/bbs/make', methods = ['POST', 'GET'])(bbs_make)
 # app.route('/bbs/main/set')
-app.route('/bbs/w/<int:bbs_num>')(bbs_w)
+app.route('/bbs/in/<int:bbs_num>')(bbs_in)
+app.route('/bbs/in/<int:bbs_num>/<int:page>')(bbs_in)
 # app.route('/bbs/blind/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_hide)
 app.route('/bbs/delete/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_delete)
 app.route('/bbs/set/<int:bbs_num>', methods = ['POST', 'GET'])(bbs_w_set)
@@ -678,11 +681,6 @@ app.route('/api/xref_this/<int:num>/<everything:name>', defaults = { 'xref_type'
 
 app.route('/api/random', defaults = { 'db_set' : db_set_str })(api_w_random)
 
-app.route('/api/bbs', defaults = { 'db_set' : db_set_str })(api_bbs_list)
-app.route('/api/bbs/main', defaults = { 'db_set' : db_set_str })(api_bbs)
-app.route('/api/bbs/w/<int:bbs_num>', defaults = { 'db_set' : db_set_str })(api_bbs)
-app.route('/api/bbs/w/<int:bbs_num>/<int:page>', defaults = { 'db_set' : db_set_str })(api_bbs)
-
 app.route('/api/bbs/w/<sub_code>')(api_bbs_w_post)
 app.route('/api/bbs/w/comment/<sub_code>')(api_bbs_w_comment)
 app.route('/api/bbs/w/comment_one/<sub_code>')(api_bbs_w_comment)
@@ -731,6 +729,13 @@ app.route('/api/v2/recent_discuss/<set_type>/<int:num>', defaults = { 'db_set' :
 app.route('/api/v2/list/document/old/<int:num>', defaults = { 'db_set' : db_set_str, 'set_type' : 'old' })(api_list_old_page)
 app.route('/api/v2/list/document/new/<int:num>', defaults = { 'db_set' : db_set_str, 'set_type' : 'new' })(api_list_old_page)
 
+app.route('/api/v2/topic/<int:num>/<set_type>/<everything:name>', defaults = { 'db_set' : db_set_str })(api_topic_list)
+
+app.route('/api/v2/bbs', defaults = { 'db_set' : db_set_str })(api_bbs_list)
+app.route('/api/v2/bbs/main', defaults = { 'db_set' : db_set_str })(api_bbs)
+app.route('/api/v2/bbs/in/<int:bbs_num>/<int:page>', defaults = { 'db_set' : db_set_str })(api_bbs)
+app.route('/api/v2/bbs/w/comment/<int:bbs_num>/<int:post_num>/<tool>', defaults = { 'db_set' : db_set_str })(api_bbs_w_comment_n)
+
 # Func-main
 # 여기도 전반적인 조정 시행 예정
 app.route('/other')(main_tool_other)

+ 6 - 1
route/__init__.py

@@ -117,7 +117,6 @@ from route.topic_comment_blind import topic_comment_blind
 from route.topic_comment_delete import topic_comment_delete
 from route.topic_comment_notice import topic_comment_notice
 from route.topic_comment_tool import topic_comment_tool
-from route.topic_list import topic_list
 from route.topic_tool import topic_tool
 from route.topic_tool_acl import topic_tool_acl
 from route.topic_tool_change import topic_tool_change
@@ -167,8 +166,12 @@ from route.n_list_recent_change import list_recent_change
 from route.n_list_recent_discuss import list_recent_discuss
 from route.n_list_old_page import list_old_page
 
+from route.n_bbs_in import bbs_in
+
 from route.n_w_watch_list import w_watch_list
 
+from route.n_topic_list import topic_list
+
 from route.n_bbs_main import bbs_main
 
 from route.go_api_func_llm import api_func_llm
@@ -186,8 +189,10 @@ from route.go_api_list_old_page import api_list_old_page
 
 from route.go_api_bbs import api_bbs
 from route.go_api_bbs_list import api_bbs_list
+from route.go_api_bbs_w_comment import api_bbs_w_comment_n
 
 from route.go_api_topic import api_topic
+from route.go_api_topic_list import api_topic_list
 
 from route.go_api_w_raw import api_w_raw
 from route.go_api_w_random import api_w_random

+ 2 - 2
route/bbs_delete.py

@@ -14,14 +14,14 @@ def bbs_delete(bbs_num = ''):
         bbs_num_str = str(bbs_num)
 
         if admin_check(conn) != 1:
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         
         if flask.request.method == 'POST':
             curs.execute(db_change('delete from bbs_data where set_id = ?'), [bbs_num_str])
             curs.execute(db_change('delete from bbs_set where set_id = ?'), [bbs_num_str])
             curs.execute(db_change('delete from bbs_data where set_id like ?'), [bbs_num_str + '-%'])
             
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         else:
             return easy_minify(conn, flask.render_template(skin_check(conn),
                 imp = [get_lang(conn, 'bbs_delete'), wiki_set(conn), wiki_custom(conn), wiki_css(['(' + bbs_name + ')', 0])],

+ 1 - 1
route/bbs_w.py

@@ -61,7 +61,7 @@ def bbs_w(bbs_num = '', tool = 'bbs', page = 1, name = ''):
                     last_date = ('(' + db_data_2[0][0] + ')') if db_data_2 else ''
 
                     data += '<li>'
-                    data += '<a href="/bbs/w/' + for_a[1] + '">' + html.escape(for_a[0]) + '</a> (' + bbs_type + ') ' + last_date
+                    data += '<a href="/bbs/in/' + for_a[1] + '">' + html.escape(for_a[0]) + '</a> (' + bbs_type + ') ' + last_date
                     data += '</li>'
 
                 data += '</ul>'

+ 2 - 2
route/bbs_w_delete.py

@@ -17,7 +17,7 @@ def bbs_w_delete(bbs_num = '', post_num = '', comment_num = ''):
         post_num_str = str(post_num)
 
         if admin_check(conn) != 1:
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         
         temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
         if not 'user_id' in temp_dict:
@@ -29,7 +29,7 @@ def bbs_w_delete(bbs_num = '', post_num = '', comment_num = ''):
                 curs.execute(db_change('delete from bbs_set where set_code = ? and set_id = ?'), [post_num_str, bbs_num_str])
                 curs.execute(db_change('delete from bbs_data where set_id = ? or set_id like ?'), [bbs_num_str + '-' + post_num_str, bbs_num_str + '-' + post_num_str + '-%'])
                 
-                return redirect(conn, '/bbs/w/' + bbs_num_str)
+                return redirect(conn, '/bbs/in/' + bbs_num_str)
             else:
                 comment_num_split = comment_num.split('-')
                 

+ 2 - 2
route/bbs_w_edit.py

@@ -56,7 +56,7 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = ''):
             data = flask.request.form.get('content', '')
             if data == '':
                 # re_error로 대체 예정
-                return redirect(conn, '/bbs/w/' + bbs_num_str)
+                return redirect(conn, '/bbs/in/' + bbs_num_str)
             
             date = get_time()
 
@@ -148,5 +148,5 @@ def bbs_w_edit(bbs_num = '', post_num = '', comment_num = ''):
                         -->
                     </form>
                 ''',
-                menu = [['bbs/w/' + bbs_num_str, get_lang(conn, 'return')]]
+                menu = [['bbs/in/' + bbs_num_str, get_lang(conn, 'return')]]
             ))

+ 1 - 1
route/bbs_w_hide.py

@@ -15,7 +15,7 @@ def bbs_w_hide(bbs_num = '', post_num = ''):
         post_num_str = str(post_num)
 
         if admin_check(conn) != 1:
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         
         if flask.request.method == 'POST':
             pass

+ 2 - 2
route/bbs_w_pinned.py

@@ -17,7 +17,7 @@ def bbs_w_pinned(bbs_num = '', post_num = ''):
         post_num_str = str(post_num)
 
         if admin_check(conn) != 1:
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         
         temp_dict = json.loads(api_bbs_w_post(bbs_num_str + '-' + post_num_str).data)
         if not 'user_id' in temp_dict:
@@ -30,7 +30,7 @@ def bbs_w_pinned(bbs_num = '', post_num = ''):
             else:
                 curs.execute(db_change('delete from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
             
-            return redirect(conn, '/bbs/w/' + bbs_num_str)
+            return redirect(conn, '/bbs/in/' + bbs_num_str)
         else:
             curs.execute(db_change('select set_data from bbs_data where set_code = ? and set_id = ? and set_name = "pinned"'), [post_num_str, bbs_num_str])
             pinned = get_lang(conn, 'pinned') if not curs.fetchall() else get_lang(conn, 'pinned_release')

+ 2 - 2
route/bbs_w_post.py

@@ -165,7 +165,7 @@ def bbs_w_post(bbs_num = '', post_num = ''):
                 return easy_minify(conn, flask.render_template(skin_check(conn),
                     imp = [bbs_name, wiki_set(conn), wiki_custom(conn), wiki_css(['(' + get_lang(conn, 'bbs') + ')', 0])],
                     data = data,
-                    menu = [['bbs/w/' + bbs_num_str, get_lang(conn, 'return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'tool')]]
+                    menu = [['bbs/in/' + bbs_num_str, get_lang(conn, 'return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'tool')]]
                 ))
         else:
             # db_data_2[0][0] == 'comment'
@@ -300,5 +300,5 @@ def bbs_w_post(bbs_num = '', post_num = ''):
                 return easy_minify(conn, flask.render_template(skin_check(conn),
                     imp = [bbs_name, wiki_set(conn), wiki_custom(conn), wiki_css(['(' + get_lang(conn, 'bbs') + ')', 0])],
                     data = data,
-                    menu = [['bbs/w/' + bbs_num_str, get_lang(conn, 'return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'tool')]]
+                    menu = [['bbs/in/' + bbs_num_str, get_lang(conn, 'return')], ['bbs/edit/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'edit')], ['bbs/tool/' + bbs_num_str + '/' + post_num_str, get_lang(conn, 'tool')]]
                 ))

+ 1 - 1
route/bbs_w_set.py

@@ -87,5 +87,5 @@ def bbs_w_set(bbs_num = ''):
                         <button id="opennamu_save_button" type="submit">''' + get_lang(conn, 'save') + '''</button>
                     </form>
                 '''),
-                menu = [['bbs/w/' + bbs_num_str, get_lang(conn, 'return')]] + other_menu
+                menu = [['bbs/in/' + bbs_num_str, get_lang(conn, 'return')]] + other_menu
             ))

+ 23 - 0
route/go_api_bbs_w_comment.py

@@ -0,0 +1,23 @@
+from .tool.func import *
+
+def api_bbs_w_comment_n(db_set, bbs_num = "", post_num = "", tool = "length"):
+    other_set = {}
+    other_set["bbs_num"] = str(bbs_num)
+    other_set["post_num"] = str(post_num)
+    other_set["tool"] = tool
+    other_set = json.dumps(other_set)
+
+    if platform.system() == 'Linux':
+        if platform.machine() in ["AMD64", "x86_64"]:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.amd64.bin"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+        else:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.arm64.bin"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+    else:
+        if platform.machine() in ["AMD64", "x86_64"]:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.amd64.exe"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+        else:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.arm64.exe"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+
+    data = data.decode('utf8')
+
+    return flask.Response(response = data, status = 200, mimetype = 'application/json')

+ 23 - 0
route/go_api_topic_list.py

@@ -0,0 +1,23 @@
+from .tool.func import *
+
+def api_topic_list(db_set, name = 'Test', set_type = 'normal', num = 1):
+    other_set = {}
+    other_set["name"] = str(name)
+    other_set["set_type"] = set_type
+    other_set["num"] = str(num)
+    other_set = json.dumps(other_set)
+
+    if platform.system() == 'Linux':
+        if platform.machine() in ["AMD64", "x86_64"]:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.amd64.bin"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+        else:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.arm64.bin"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+    else:
+        if platform.machine() in ["AMD64", "x86_64"]:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.amd64.exe"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+        else:
+            data = subprocess.Popen([os.path.join(".", "route_go", "bin", "main.arm64.exe"), sys._getframe().f_code.co_name, db_set, other_set], stdout = subprocess.PIPE).communicate()[0]
+
+    data = data.decode('utf8')
+
+    return flask.Response(response = data, status = 200, mimetype = 'application/json')

+ 24 - 0
route/n_bbs_in.py

@@ -0,0 +1,24 @@
+from .tool.func import *
+
+def bbs_in(bbs_num = 1, page = 1):
+    with get_db_connect() as conn:
+        curs = conn.cursor()
+
+        bbs_num_str = str(bbs_num)
+
+        curs.execute(db_change('select set_data from bbs_set where set_id = ? and set_name = "bbs_name"'), [bbs_num])
+        db_data = curs.fetchall()
+        if not db_data:
+            return redirect(conn, '/bbs/main')
+    
+        bbs_name = db_data[0][0]
+
+        return easy_minify(conn, flask.render_template(skin_check(conn),
+            imp = [bbs_name, wiki_set(conn), wiki_custom(conn), wiki_css(['(' + get_lang(conn, 'bbs') + ') (' + str(page) + ')', 0])],
+            data = '' + \
+                '<div id="opennamu_bbs_in"></div>' + \
+                '<script src="/views/main_css/js/route/bbs_in.js' + cache_v() + '"></script>' + \
+                '<script>opennamu_bbs_in();</script>' + \
+            '',
+            menu = [['bbs/main', get_lang(conn, 'return')], ['bbs/edit/' + bbs_num_str, get_lang(conn, 'add')], ['bbs/set/' + bbs_num_str, get_lang(conn, 'bbs_set')]]
+        ))

+ 13 - 0
route/n_topic_list.py

@@ -0,0 +1,13 @@
+from .tool.func import *
+
+def topic_list(page = 1, name = 'Test'):
+    with get_db_connect() as conn:
+        return easy_minify(conn, flask.render_template(skin_check(conn),
+            imp = [name, wiki_set(conn), wiki_custom(conn), wiki_css(['(' + get_lang(conn, 'discussion_list') + ')', 0])],
+            data = '' + \
+                '<div id="opennamu_topic_list"></div>' + \
+                '<script src="/views/main_css/js/route/topic_list.js' + cache_v() + '"></script>' + \
+                '<script>opennamu_topic_list();</script>' + \
+            '',
+            menu = [['w/' + url_pas(name), get_lang(conn, 'document')]]
+        ))

+ 1 - 1
route/tool/func.py

@@ -1069,7 +1069,7 @@ def skin_check(conn, set_n = 0):
         return skin
     
 def cache_v():
-    return '.cache_v237'
+    return '.cache_v242'
 
 def wiki_css(data):
     global global_wiki_set

TEMPAT SAMPAH
route_go/bin/main.amd64.bin


TEMPAT SAMPAH
route_go/bin/main.amd64.exe


TEMPAT SAMPAH
route_go/bin/main.arm64.bin


TEMPAT SAMPAH
route_go/bin/main.arm64.exe


+ 1 - 1
route_go/go.mod

@@ -5,6 +5,7 @@ go 1.21
 toolchain go1.22.0
 
 require (
+	github.com/dlclark/regexp2 v1.11.0
 	github.com/go-sql-driver/mysql v1.8.0
 	github.com/google/generative-ai-go v0.10.0
 	github.com/yuin/goldmark v1.7.0
@@ -19,7 +20,6 @@ require (
 	cloud.google.com/go/compute/metadata v0.2.3 // indirect
 	cloud.google.com/go/longrunning v0.5.2 // indirect
 	filippo.io/edwards25519 v1.1.0 // indirect
-	github.com/dlclark/regexp2 v1.11.0 // indirect
 	github.com/dustin/go-humanize v1.0.1 // indirect
 	github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
 	github.com/golang/protobuf v1.5.3 // indirect

+ 5 - 1
route_go/main.go

@@ -24,7 +24,7 @@ func main() {
 	} else if call_arg[0] == "api_search" {
 		route_data = route.Api_search(call_arg[1:])
 	} else if call_arg[0] == "api_topic" {
-		route_data = route.Api_thread(call_arg[1:])
+		route_data = route.Api_topic(call_arg[1:])
 	} else if call_arg[0] == "api_func_ip" {
 		route_data = route.Api_func_ip(call_arg[1:])
 	} else if call_arg[0] == "api_list_recent_change" {
@@ -53,6 +53,10 @@ func main() {
 		route_data = route.Api_bbs_list(call_arg[1:])
 	} else if call_arg[0] == "api_list_old_page" {
 		route_data = route.Api_list_old_page(call_arg[1:])
+	} else if call_arg[0] == "api_topic_list" {
+		route_data = route.Api_topic_list(call_arg[1:])
+	} else if call_arg[0] == "api_bbs_w_comment_n" {
+		route_data = route.Api_bbs_w_comment(call_arg[1:])
 	} else {
 		log.Fatal("404")
 	}

+ 76 - 49
route_go/route/api_bbs.go

@@ -18,14 +18,16 @@ func Api_bbs(call_arg []string) string {
 	db := tool.DB_connect(db_set)
 	defer db.Close()
 
-	var rows *sql.Rows
+	var rows []*sql.Rows
 	if other_set["bbs_num"] == "" {
 		var err error
 
-		rows, err = db.Query(tool.DB_change(db_set, "select set_code, set_id from bbs_data where set_name = 'date' order by set_data desc limit 50"))
+		row, err := db.Query(tool.DB_change(db_set, "select set_code, set_id, '0' from bbs_data where set_name = 'date' order by set_data desc limit 50"))
 		if err != nil {
 			log.Fatal(err)
 		}
+
+		rows = append(rows, row)
 	} else {
 		page, _ := strconv.Atoi(other_set["page"])
 		num := 0
@@ -33,87 +35,112 @@ func Api_bbs(call_arg []string) string {
 			num = page*50 - 50
 		}
 
-		stmt, err := db.Prepare(tool.DB_change(db_set, "select set_code, set_id from bbs_data where set_name = 'title' and set_id like ? order by set_code + 0 desc limit ?, 50"))
+		stmt, err := db.Prepare(tool.DB_change(db_set, "select set_code, set_id, '1' from bbs_data where set_name = 'pinned' and set_id like ? order by set_data desc"))
 		if err != nil {
 			log.Fatal(err)
 		}
 		defer stmt.Close()
 
-		rows, err = stmt.Query(other_set["bbs_num"], num)
-		if err != nil {
-			log.Fatal(err)
-		}
-	}
-	defer rows.Close()
-
-	var data_list []map[string]string
-	ip_parser_temp := map[string][]string{}
-
-	for rows.Next() {
-		temp_data := make(map[string]string)
-
-		var set_code string
-		var set_id string
-
-		err := rows.Scan(&set_code, &set_id)
+		row, err := stmt.Query(other_set["bbs_num"])
 		if err != nil {
 			log.Fatal(err)
 		}
 
-		temp_data["set_code"] = set_code
-		temp_data["set_id"] = set_id
+		rows = append(rows, row)
 
-		stmt, err := db.Prepare(tool.DB_change(db_set, "select set_name, set_data, set_code, set_id from bbs_data where set_code = ? and set_id = ?"))
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select set_code, set_id, '0' from bbs_data where set_name = 'title' and set_id like ? order by set_code + 0 desc limit ?, 50"))
 		if err != nil {
 			log.Fatal(err)
 		}
 		defer stmt.Close()
 
-		rows, err := stmt.Query(set_code, set_id)
+		row, err = stmt.Query(other_set["bbs_num"], num)
 		if err != nil {
 			log.Fatal(err)
 		}
-		defer rows.Close()
 
-		for rows.Next() {
-			var set_name string
-			var set_data string
+		rows = append(rows, row)
+	}
+
+	var data_list []map[string]string
+	ip_parser_temp := map[string][]string{}
+
+	for for_a := 0; for_a < len(rows); for_a++ {
+		defer rows[for_a].Close()
+
+		for rows[for_a].Next() {
+			temp_data := make(map[string]string)
+
+			var set_code string
+			var set_id string
+			var pinned string
 
-			err := rows.Scan(&set_name, &set_data, &set_code, &set_id)
+			err := rows[for_a].Scan(&set_code, &set_id, &pinned)
 			if err != nil {
 				log.Fatal(err)
 			}
 
-			if set_name == "user_id" {
-				var ip_pre string
-				var ip_render string
+			temp_data["set_code"] = set_code
+			temp_data["set_id"] = set_id
+			temp_data["pinned"] = pinned
 
-				if _, ok := ip_parser_temp[set_data]; ok {
-					ip_pre = ip_parser_temp[set_data][0]
-					ip_render = ip_parser_temp[set_data][1]
-				} else {
-					ip_pre = tool.IP_preprocess(db, db_set, set_data, other_set["ip"])[0]
-					ip_render = tool.IP_parser(db, db_set, set_data, other_set["ip"])
+			stmt, err := db.Prepare(tool.DB_change(db_set, "select set_name, set_data, set_code, set_id from bbs_data where set_code = ? and set_id = ?"))
+			if err != nil {
+				log.Fatal(err)
+			}
+			defer stmt.Close()
 
-					ip_parser_temp[set_data] = []string{ip_pre, ip_render}
+			rows, err := stmt.Query(set_code, set_id)
+			if err != nil {
+				log.Fatal(err)
+			}
+			defer rows.Close()
+
+			for rows.Next() {
+				var set_name string
+				var set_data string
+
+				err := rows.Scan(&set_name, &set_data, &set_code, &set_id)
+				if err != nil {
+					log.Fatal(err)
 				}
 
-				set_data = ip_pre
-				temp_data["user_id_render"] = ip_render
-			}
+				if set_name == "user_id" {
+					var ip_pre string
+					var ip_render string
 
-			if set_name != "data" {
-				temp_data[set_name] = set_data
+					if _, ok := ip_parser_temp[set_data]; ok {
+						ip_pre = ip_parser_temp[set_data][0]
+						ip_render = ip_parser_temp[set_data][1]
+					} else {
+						ip_pre = tool.IP_preprocess(db, db_set, set_data, other_set["ip"])[0]
+						ip_render = tool.IP_parser(db, db_set, set_data, other_set["ip"])
+
+						ip_parser_temp[set_data] = []string{ip_pre, ip_render}
+					}
+
+					set_data = ip_pre
+					temp_data["user_id_render"] = ip_render
+				}
+
+				if set_name != "data" && set_name != "pinned" {
+					temp_data[set_name] = set_data
+				}
 			}
-		}
 
-		data_list = append(data_list, temp_data)
+			data_list = append(data_list, temp_data)
+		}
 	}
 
+	return_data := make(map[string]interface{})
+	return_data["language"] = map[string]string{}
+
 	if len(data_list) == 0 {
-		return "{}"
+		return_data["data"] = map[string]string{}
 	} else {
-		json_data, _ := json.Marshal(data_list)
-		return string(json_data)
+		return_data["data"] = data_list
 	}
+
+	json_data, _ := json.Marshal(return_data)
+	return string(json_data)
 }

+ 11 - 3
route_go/route/api_bbs_list.go

@@ -79,10 +79,18 @@ func Api_bbs_list(call_arg []string) string {
 		data_list_sub[k] = []string{v, bbs_type, bbs_date}
 	}
 
+	return_data := make(map[string]interface{})
+	return_data["language"] = map[string]string{
+		"thread_base":  tool.Get_language(db, db_set, "thread_base", false),
+		"comment_base": tool.Get_language(db, db_set, "comment_base", false),
+	}
+
 	if len(data_list_sub) == 0 {
-		return "{}"
+		return_data["data"] = map[string]string{}
 	} else {
-		json_data, _ := json.Marshal(data_list_sub)
-		return string(json_data)
+		return_data["data"] = data_list_sub
 	}
+
+	json_data, _ := json.Marshal(return_data)
+	return string(json_data)
 }

+ 45 - 0
route_go/route/api_bbs_post.go

@@ -0,0 +1,45 @@
+package route
+
+import (
+	"encoding/json"
+	"log"
+	"opennamu/route/tool"
+)
+
+func Api_bbs_post(call_arg []string) string {
+	db_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[0]), &db_set)
+
+	other_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[1]), &other_set)
+
+	db := tool.DB_connect(db_set)
+	defer db.Close()
+
+	stmt, err := db.Prepare(tool.DB_change(db_set, "select set_name, set_data from bbs_data where set_id = ? and set_code = ?"))
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer stmt.Close()
+
+	rows, err := stmt.Query(other_set["bbs_num"], other_set["post_num"])
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	data_list := map[string]string{}
+
+	for rows.Next() {
+		var set_name string
+		var set_data string
+
+		data_list[set_name] = set_data
+	}
+
+	return_data := make(map[string]interface{})
+	return_data["language"] = map[string]string{}
+	return_data["data"] = data_list
+
+	json_data, _ := json.Marshal(return_data)
+	return string(json_data)
+}

+ 48 - 0
route_go/route/api_bbs_w_comment.go

@@ -0,0 +1,48 @@
+package route
+
+import (
+	"database/sql"
+	"encoding/json"
+	"log"
+	"opennamu/route/tool"
+)
+
+func Api_bbs_w_comment(call_arg []string) string {
+	db_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[0]), &db_set)
+
+	other_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[1]), &other_set)
+
+	db := tool.DB_connect(db_set)
+	defer db.Close()
+
+	if other_set["tool"] == "length" {
+		stmt, err := db.Prepare(tool.DB_change(db_set, "select count(*) from bbs_data where set_name = 'comment_date' and (set_id = ? or set_id like ?) order by set_code + 0 desc"))
+		if err != nil {
+			log.Fatal(err)
+		}
+		defer stmt.Close()
+
+		var comment_length string
+		bbs_and_post_num := other_set["bbs_num"] + "-" + other_set["post_num"]
+
+		err = stmt.QueryRow(bbs_and_post_num, bbs_and_post_num + "-%").Scan(&comment_length)
+		if err != nil {
+			if err == sql.ErrNoRows {
+				comment_length = "0"
+			} else {
+				log.Fatal(err)
+			}
+		}
+
+		data_list := map[string]string{
+			"data": comment_length,
+		}
+
+		json_data, _ := json.Marshal(data_list)
+		return string(json_data)
+	} else {
+		return ""
+	}
+}

+ 13 - 9
route_go/route/api_list_recent_discuss.go

@@ -42,11 +42,11 @@ func Api_list_recent_discuss(call_arg []string) string {
 
 	set_type := other_set["set_type"]
 	if set_type == "normal" {
-		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop from rd order by date desc limit ?, ?"))
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop, agree from rd order by date desc limit ?, ?"))
 	} else if set_type == "close" {
-		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop from rd where stop = 'O' order by date desc limit ?, ?"))
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop, agree from rd where stop = 'O' order by date desc limit ?, ?"))
 	} else {
-		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop from rd where stop != 'O' order by date desc limit ?, ?"))
+		stmt, err = db.Prepare(tool.DB_change(db_set, "select title, sub, date, code, stop, agree from rd where stop != 'O' order by date desc limit ?, ?"))
 	}
 
 	if err != nil {
@@ -69,8 +69,9 @@ func Api_list_recent_discuss(call_arg []string) string {
 		var date string
 		var code string
 		var stop string
+		var agree string
 
-		err := rows.Scan(&title, &sub, &date, &code, &stop)
+		err := rows.Scan(&title, &sub, &date, &code, &stop, &agree)
 		if err != nil {
 			log.Fatal(err)
 		}
@@ -115,6 +116,7 @@ func Api_list_recent_discuss(call_arg []string) string {
 			ip_pre,
 			ip_render,
 			id,
+			agree,
 		})
 	}
 
@@ -131,11 +133,13 @@ func Api_list_recent_discuss(call_arg []string) string {
 
 		return_data := make(map[string]interface{})
 		return_data["language"] = map[string]string{
-			"tool":             tool.Get_language(db, db_set, "tool", false),
-			"normal":           tool.Get_language(db, db_set, "normal", false),
-			"close_discussion": tool.Get_language(db, db_set, "close_discussion", false),
-			"open_discussion":  tool.Get_language(db, db_set, "open_discussion", false),
-			"closed":           tool.Get_language(db, db_set, "closed", false),
+			"tool":              tool.Get_language(db, db_set, "tool", false),
+			"normal":            tool.Get_language(db, db_set, "normal", false),
+			"close_discussion":  tool.Get_language(db, db_set, "close_discussion", false),
+			"open_discussion":   tool.Get_language(db, db_set, "open_discussion", false),
+			"closed":            tool.Get_language(db, db_set, "closed", false),
+			"agreed_discussion": tool.Get_language(db, db_set, "agreed_discussion", false),
+			"stop":              tool.Get_language(db, db_set, "stop", false),
 		}
 		return_data["auth"] = auth_info
 

+ 17 - 3
route_go/route/api_thread.go → route_go/route/api_topic.go

@@ -8,7 +8,7 @@ import (
 	"opennamu/route/tool"
 )
 
-func Api_thread(call_arg []string) string {
+func Api_topic(call_arg []string) string {
 	db_set := map[string]string{}
 	json.Unmarshal([]byte(call_arg[0]), &db_set)
 
@@ -83,6 +83,7 @@ func Api_thread(call_arg []string) string {
 
 		var id, data, date, ip, block, top string
 		var data_list [][]string
+		ip_parser_temp := map[string][]string{}
 
 		for rows.Next() {
 			err := rows.Scan(&id, &data, &date, &ip, &block, &top)
@@ -99,18 +100,31 @@ func Api_thread(call_arg []string) string {
 
 		admin_auth := tool.Get_user_auth(db, db_set, other_set["ip"])
 
+		var ip_pre string
+		var ip_render string
+
 		for for_a := 0; for_a < len(data_list); for_a++ {
 			data := ""
 			if data_list[for_a][4] != "O" || admin_auth != "" {
 				data = data_list[for_a][1]
 			}
 
+			if _, ok := ip_parser_temp[data_list[for_a][3]]; ok {
+				ip_pre = ip_parser_temp[data_list[for_a][3]][0]
+				ip_render = ip_parser_temp[data_list[for_a][3]][1]
+			} else {
+				ip_pre = tool.IP_preprocess(db, db_set, data_list[for_a][3], other_set["ip"])[0]
+				ip_render = tool.IP_parser(db, db_set, data_list[for_a][3], other_set["ip"])
+
+				ip_parser_temp[data_list[for_a][3]] = []string{ip_pre, ip_render}
+			}
+
 			data_slice = append(data_slice, map[string]string{
 				"id":        data_list[for_a][0],
 				"data":      data,
 				"date":      data_list[for_a][2],
-				"ip":        tool.IP_preprocess(db, db_set, data_list[for_a][3], other_set["ip"])[0],
-				"ip_render": tool.IP_parser(db, db_set, data_list[for_a][3], other_set["ip"]),
+				"ip":        ip_pre,
+				"ip_render": ip_render,
 				"blind":     data_list[for_a][4],
 			})
 		}

+ 115 - 2
route_go/route/api_topic_list.go

@@ -1,5 +1,118 @@
 package route
 
-func Api_topic_list() string {
-	return ""
+import (
+	"database/sql"
+	"encoding/json"
+	"log"
+	"opennamu/route/tool"
+	"strconv"
+)
+
+func Api_topic_list(call_arg []string) string {
+	db_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[0]), &db_set)
+
+	other_set := map[string]string{}
+	json.Unmarshal([]byte(call_arg[1]), &other_set)
+
+	db := tool.DB_connect(db_set)
+	defer db.Close()
+
+	page_int, err := strconv.Atoi(other_set["num"])
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	if page_int > 0 {
+		page_int = (page_int * 50) - 50
+	} else {
+		page_int = 0
+	}
+
+	stmt, err := db.Prepare(tool.DB_change(db_set, "select code, sub, stop, agree, date from rd where title = ? order by sub asc limit ?, 50"))
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer stmt.Close()
+
+	rows, err := stmt.Query(other_set["name"], page_int)
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer rows.Close()
+
+	var data_list [][]string
+	ip_parser_temp := map[string][]string{}
+
+	for rows.Next() {
+		var code string
+		var sub string
+		var stop string
+		var agree string
+		var date string
+
+		err := rows.Scan(&code, &sub, &stop, &agree, &date)
+		if err != nil {
+			log.Fatal(err)
+		}
+
+		stmt, err := db.Prepare(tool.DB_change(db_set, "select ip, id from topic where code = ? order by id + 0 desc limit 1"))
+		if err != nil {
+			log.Fatal(err)
+		}
+		defer stmt.Close()
+
+		var ip string
+		var id string
+
+		err = stmt.QueryRow(code).Scan(&ip, &id)
+		if err != nil {
+			if err == sql.ErrNoRows {
+				ip = ""
+			} else {
+				log.Fatal(err)
+			}
+		}
+
+		var ip_pre string
+		var ip_render string
+
+		if _, ok := ip_parser_temp[ip]; ok {
+			ip_pre = ip_parser_temp[ip][0]
+			ip_render = ip_parser_temp[ip][1]
+		} else {
+			ip_pre = tool.IP_preprocess(db, db_set, ip, other_set["ip"])[0]
+			ip_render = tool.IP_parser(db, db_set, ip, other_set["ip"])
+
+			ip_parser_temp[ip] = []string{ip_pre, ip_render}
+		}
+
+		data_list = append(data_list, []string{
+			code,
+			sub,
+			stop,
+			agree,
+			ip_pre,
+			ip_render,
+			date,
+			id,
+		})
+	}
+
+	return_data := make(map[string]interface{})
+	return_data["language"] = map[string]string{
+		"closed":            tool.Get_language(db, db_set, "closed", false),
+		"agreed_discussion": tool.Get_language(db, db_set, "agreed_discussion", false),
+		"make_new_topic":    tool.Get_language(db, db_set, "make_new_topic", false),
+		"stop":              tool.Get_language(db, db_set, "stop", false),
+	}
+
+	if len(data_list) == 0 {
+		return_data["data"] = map[string]string{}
+	} else {
+		return_data["data"] = data_list
+	}
+
+	json_data, _ := json.Marshal(return_data)
+	return string(json_data)
 }

+ 28 - 7
route_go/route/api_w_watch_list.go

@@ -24,8 +24,7 @@ func Api_w_watch_list(call_arg []string) string {
 	db := tool.DB_connect(db_set)
 	defer db.Close()
 
-	ip := other_set["ip"]
-	if tool.Get_user_auth(db, db_set, ip) == "" {
+	if tool.Get_user_auth(db, db_set, other_set["ip"]) == "" {
 		return "{}"
 	}
 
@@ -47,7 +46,8 @@ func Api_w_watch_list(call_arg []string) string {
 	}
 	defer rows.Close()
 
-	var data_list []string
+	var data_list [][]string
+	ip_parser_temp := map[string][]string{}
 
 	for rows.Next() {
 		var user_name string
@@ -57,13 +57,34 @@ func Api_w_watch_list(call_arg []string) string {
 			log.Fatal(err)
 		}
 
-		data_list = append(data_list, user_name)
+		var ip_pre string
+		var ip_render string
+
+		if _, ok := ip_parser_temp[user_name]; ok {
+			ip_pre = ip_parser_temp[user_name][0]
+			ip_render = ip_parser_temp[user_name][1]
+		} else {
+			ip_pre = tool.IP_preprocess(db, db_set, user_name, other_set["ip"])[0]
+			ip_render = tool.IP_parser(db, db_set, user_name, other_set["ip"])
+
+			ip_parser_temp[user_name] = []string{ip_pre, ip_render}
+		}
+
+		data_list = append(data_list, []string{ip_pre, ip_render})
+	}
+
+	return_data := make(map[string]interface{})
+	return_data["language"] = map[string]string{
+		"watchlist": tool.Get_language(db, db_set, "watchlist", false),
+		"star_doc":  tool.Get_language(db, db_set, "star_doc", false),
 	}
 
 	if len(data_list) == 0 {
-		return "{}"
+		return_data["data"] = map[string]string{}
 	} else {
-		json_data, _ := json.Marshal(data_list)
-		return string(json_data)
+		return_data["data"] = data_list
 	}
+
+	json_data, _ := json.Marshal(return_data)
+	return string(json_data)
 }

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.5.0-dev86",
+        "r_ver" : "v3.5.0-dev91",
         "c_ver" : "3500379",
         "s_ver" : "3500113"
     }

+ 60 - 0
views/main_css/js/route/bbs_in.js

@@ -0,0 +1,60 @@
+"use strict";
+
+function opennamu_bbs_in() {
+    const url = window.location.pathname;
+    const url_split = url.split('/');
+
+    let bbs_num = url_split[3];
+    let page;
+    if(url_split.length > 4) {
+        page = url_split[4];
+    } else {
+        page = '1';
+    }
+
+    fetch('/api/v2/bbs/in/' + bbs_num + '/' + page).then(function(res) {
+        return res.json();
+    }).then(function(data) {
+        data = data["data"];
+
+        let data_html = '';
+
+        for(let for_a = 0; for_a < data.length; for_a++) {
+            data_html += '<div class="opennamu_recent_change">';
+
+            data_html += '<a href="/bbs/w/' + data[for_a]['set_id'] + '/' + data[for_a]['set_code'] + '">' + opennamu_xss_filter(data[for_a]['title']) + '</a>';
+
+            data_html += '<div style="float: right;">';
+
+            data_html += '<span id="opennamu_bbs_comment_' + String(for_a) + '"></span>';
+
+            data_html += data[for_a]['user_id_render'] + ' | ';
+
+            if(data[for_a]['pinned'] === '1') {
+                data_html += '<span style="color: red;">' + data[for_a]['date'] + '</span>';
+            } else {
+                data_html += data[for_a]['date'];
+            }
+
+            data_html += '</div>'
+            data_html += '<div style="clear: both;"></div>';
+
+            data_html += '</div>';
+            data_html += '<hr class="main_hr">';
+        }
+
+        data_html += opennamu_page_control('/bbs/in/' + bbs_num + '/{}', Number(page), data.length);
+        
+        document.getElementById('opennamu_bbs_in').innerHTML = data_html;
+
+        for(let for_a = 0; for_a < data.length; for_a++) {
+            fetch('/api/v2/bbs/w/comment/' + data[for_a]['set_id'] + '/' + data[for_a]['set_code'] + '/length').then(function(res) {
+                return res.json();
+            }).then(function(comment_data) {
+                if(comment_data) {
+                    document.getElementById('opennamu_bbs_comment_' + String(for_a)).innerText = comment_data['data'] + ' | ';
+                }
+            });
+        }
+    });
+}

+ 64 - 58
views/main_css/js/route/bbs_main.js

@@ -1,76 +1,82 @@
 "use strict";
 
 function opennamu_bbs_main() {
-    let lang_data = new FormData();
-    // user_document -> 8
-    lang_data.append('data', 'thread_base comment_base');
-
-    fetch('/api/lang', {
-        method : 'post',
-        body : lang_data,
-    }).then(function(res) {
+    fetch('/api/v2/bbs').then(function(res) {
         return res.json();
-    }).then(function(lang) {
-        lang = lang["data"];
-    
-        fetch('/api/bbs').then(function(res) {
+    }).then(function(bbs_list) {
+        let lang = bbs_list["language"];
+        bbs_list = bbs_list["data"];
+
+        fetch('/api/v2/bbs/main').then(function(res) {
             return res.json();
-        }).then(function(bbs_list) {
-            fetch('/api/bbs/main').then(function(res) {
-                return res.json();
-            }).then(function(data) {
-                let data_html = '<ul class="opennamu_ul">';
-                let bbs_id_to_name = {};
-
-                for(let key in bbs_list) {
-                    bbs_id_to_name[bbs_list[key][0]] = key;
-
-                    data_html += '<li>';
-
-                    data_html += '<a href="/bbs/w/' + bbs_list[key][0] + '">';
-                    data_html += opennamu_xss_filter(key);
-                    data_html += '</a>';
-
-                    data_html += ' (';
-                    if(bbs_list[key][1] === 'comment') {
-                        data_html += lang[1];
-                    } else {
-                        data_html += lang[0];
-                    }
-                    data_html += ')';
+        }).then(function(data) {
+            data = data["data"];
 
-                    data_html += ' (' + bbs_list[key][2] + ')';
+            let data_html = '<ul class="opennamu_ul">';
+            let bbs_id_to_name = {};
+
+            for(let key in bbs_list) {
+                bbs_id_to_name[bbs_list[key][0]] = key;
+
+                data_html += '<li>';
 
-                    data_html += '</li>';
+                data_html += '<a href="/bbs/in/' + bbs_list[key][0] + '">';
+                data_html += opennamu_xss_filter(key);
+                data_html += '</a>';
+
+                data_html += ' (';
+                if(bbs_list[key][1] === 'comment') {
+                    data_html += lang['comment_base'];
+                } else {
+                    data_html += lang['thread_base'];
                 }
-        
-                data_html += '</ul>';
-                data_html += '<hr class="main_hr">';
+                data_html += ')';
+
+                if(bbs_list[key][2] !== '') {
+                    data_html += ' (' + bbs_list[key][2] + ')';
+                }
+                
+                data_html += '</li>';
+            }
 
-                for(let for_a = 0; for_a < data.length; for_a++) {
-                    data_html += '<div class="opennamu_recent_change">';
+            data_html += '</ul>';
+            data_html += '<hr class="main_hr">';
 
-                    data_html += '<a href="/bbs/w/' + data[for_a]['set_id'] + '/' + data[for_a]['set_code'] + '">' + opennamu_xss_filter(data[for_a]['title']) + '</a>';
+            for(let for_a = 0; for_a < data.length; for_a++) {
+                data_html += '<div class="opennamu_recent_change">';
 
-                    data_html += '<div style="float: right;">';
+                data_html += '<a href="/bbs/w/' + data[for_a]['set_id'] + '/' + data[for_a]['set_code'] + '">' + opennamu_xss_filter(data[for_a]['title']) + '</a>';
 
-                    data_html += '<a href="/bbs/w/' + data[for_a]['set_id'] + '">';
-                    data_html += bbs_id_to_name[data[for_a]['set_id']]
-                    data_html += '</a>';
-                    data_html += ' | ';
+                data_html += '<div style="float: right;">';
 
-                    data_html += data[for_a]['user_id_render'] + ' | ';
-                    data_html += data[for_a]['date'];
+                data_html += '<span id="opennamu_bbs_comment_' + String(for_a) + '"></span>';
 
-                    data_html += '</div>'
-                    data_html += '<div style="clear: both;"></div>';
+                data_html += '<a href="/bbs/in/' + data[for_a]['set_id'] + '">';
+                data_html += bbs_id_to_name[data[for_a]['set_id']]
+                data_html += '</a>';
+                data_html += ' | ';
 
-                    data_html += '</div>';
-                    data_html += '<hr class="main_hr">';
-                }
-                
-                document.getElementById('opennamu_bbs_main').innerHTML = data_html;
-            });
+                data_html += data[for_a]['user_id_render'] + ' | ';
+                data_html += data[for_a]['date'];
+
+                data_html += '</div>'
+                data_html += '<div style="clear: both;"></div>';
+
+                data_html += '</div>';
+                data_html += '<hr class="main_hr">';
+            }
+            
+            document.getElementById('opennamu_bbs_main').innerHTML = data_html;
+
+            for(let for_a = 0; for_a < data.length; for_a++) {
+                fetch('/api/v2/bbs/w/comment/' + data[for_a]['set_id'] + '/' + data[for_a]['set_code'] + '/length').then(function(res) {
+                    return res.json();
+                }).then(function(comment_data) {
+                    if(comment_data) {
+                        document.getElementById('opennamu_bbs_comment_' + String(for_a)).innerText = comment_data['data'] + ' | ';
+                    }
+                });
+            }
         });
     });
 }

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

@@ -2,7 +2,7 @@
 
 function opennamu_list_old_page() {
     const url = window.location.pathname;
-    const url_split = url.split('/')
+    const url_split = url.split('/');
     
     let set_type = '';
     let num = '';

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

@@ -12,7 +12,7 @@ function opennamu_list_recent_change() {
     }
 
     const url = window.location.pathname;
-    const url_split = url.split('/')
+    const url_split = url.split('/');
     
     let set_type = '';
     let num = '';

+ 7 - 1
views/main_css/js/route/list_recent_discuss.js

@@ -2,7 +2,7 @@
 
 function opennamu_list_recent_discuss() {
     const url = window.location.pathname;
-    const url_split = url.split('/')
+    const url_split = url.split('/');
     
     let set_type = '';
     let num = '';
@@ -42,6 +42,12 @@ function opennamu_list_recent_discuss() {
             let right = '';
             if(data[for_a][4] === 'O') {
                 right += lang['closed'] + ' | ';
+            } else if(data[for_a][4] === 'S') {
+                right += lang['stop'] + ' | ';
+            }
+
+            if(data[for_a][8] !== '') {
+                right += lang['agreed_discussion'] + ' | ';
             }
 
             right += '<a href="/thread/' + data[for_a][3] + '#' + data[for_a][7] + '">#' + data[for_a][7] + '</a> | ';

+ 59 - 0
views/main_css/js/route/topic_list.js

@@ -0,0 +1,59 @@
+function opennamu_topic_list() {
+    const url = window.location.pathname;
+    const url_split = url.split('/');
+
+    let num;
+    if(url_split[1] === 'topic') {
+        num = '1';
+    } else {
+        num = url_split[2];
+    }
+
+    
+    let doc_name;
+    if(url_split[1] === 'topic') {
+        doc_name = url_split.slice(2, undefined).join('/');
+    } else {
+        doc_name = url_split.slice(3, undefined).join('/');
+    }
+
+    fetch('/api/v2/topic/' + num + '/normal/' + doc_name).then(function(res) {
+        return res.json();
+    }).then(function(data) {
+        let lang = data['language'];
+        data = data['data'];
+
+        let data_html = '';
+
+        for(let for_a = 0; for_a < data.length; for_a++) {
+            let left = '<a href="/thread/' + data[for_a][0] + '">' + opennamu_xss_filter(data[for_a][1]) + '</a>';
+            
+            let right = '';
+            if(data[for_a][2] === 'O') {
+                right += lang['closed'] + ' | ';
+            } else if(data[for_a][2] === 'S') {
+                right += lang['stop'] + ' | ';
+            }
+
+            if(data[for_a][3] !== '') {
+                right += lang['agreed_discussion'] + ' | ';
+            }
+
+            right += '<a href="/thread/' + data[for_a][0] + '#' + data[for_a][7] + '">#' + data[for_a][7] + '</a> | ';
+            right += data[for_a][5] + ' | ';
+            right += data[for_a][6];
+
+            data_html += openamu_make_list(left, right);
+        }
+
+        if(data_html !== '') {
+            data_html += '<hr class="main_hr">';
+        }
+
+        data_html += '<a href="/thread/0/' + doc_name + '">(' + lang['make_new_topic'] + ')</a>';
+
+        data_html += opennamu_page_control('/topic_page/{}/normal/' + doc_name, Number(num), data.length);
+
+        document.getElementById('opennamu_topic_list').innerHTML = data_html;
+    });
+}