ui.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. package tool
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "html"
  6. "os"
  7. "path/filepath"
  8. "strconv"
  9. "strings"
  10. "github.com/flosch/pongo2/v6"
  11. )
  12. func Get_skin_route(skin_name string, route string) string {
  13. return filepath.Join("..", "views", skin_name, route)
  14. }
  15. func Get_template_set(skin_name string) map[string]string {
  16. set_file_path := Get_skin_route(skin_name, "set.json")
  17. if _, err := os.Stat(set_file_path); err == nil {
  18. data, err := os.ReadFile(set_file_path)
  19. if err != nil {
  20. panic(err)
  21. }
  22. set_json := map[string]string{}
  23. json.Unmarshal([]byte(data), &set_json)
  24. return set_json
  25. }
  26. return map[string]string{}
  27. }
  28. func Get_use_skin_name(db *sql.DB, ip string) string {
  29. skin_list := Get_skin_list("ringo", true)
  30. skin := skin_list[0]
  31. user_skin_name := ""
  32. if !IP_or_user(ip) {
  33. QueryRow_DB(
  34. db,
  35. "select data from user_set where name = 'skin' and id = ?",
  36. []any{ &user_skin_name },
  37. ip,
  38. )
  39. }
  40. if user_skin_name == "default" {
  41. user_skin_name = ""
  42. }
  43. if user_skin_name == "" {
  44. QueryRow_DB(
  45. db,
  46. "select data from other where name = 'skin'",
  47. []any{ &user_skin_name },
  48. )
  49. }
  50. if user_skin_name != "" && Arr_in_str(skin_list, user_skin_name) {
  51. skin = user_skin_name
  52. }
  53. return skin
  54. }
  55. func Get_template(db *sql.DB, config Config, name string, data string, other []any, menu [][]any, option map[string]string) string {
  56. skin_name := Get_use_skin_name(db, config.IP)
  57. template_set := Get_template_set(skin_name)
  58. for k, v := range template_set {
  59. data = strings.ReplaceAll(data, k, v)
  60. }
  61. menu_func := func(menu [][]any) any {
  62. if len(menu) == 0 {
  63. return 0
  64. } else {
  65. return menu
  66. }
  67. }
  68. menu_func_result := menu_func(menu)
  69. if len(other) < 1 {
  70. other = append(other, 0)
  71. }
  72. if len(other) < 2 {
  73. other = append(other, 0)
  74. }
  75. for k := range other {
  76. switch v := other[k].(type) {
  77. case nil:
  78. other[k] = 0
  79. case float64:
  80. other[k] = int(v)
  81. case int64:
  82. other[k] = int(v)
  83. case int:
  84. other[k] = v
  85. case string:
  86. if v == "" {
  87. other[k] = 0
  88. } else {
  89. other[k] = v
  90. }
  91. default:
  92. other[k] = 0
  93. }
  94. }
  95. imp_1 := Get_wiki_set(db, config.IP, config.Cookies)
  96. imp_2 := Get_wiki_custom(db, config.IP, config.Session, config.Cookies)
  97. imp_3 := Get_wiki_css(other, config.Cookies)
  98. if len(imp_3) < 8 {
  99. imp_3 = append(imp_3, 0)
  100. }
  101. added_menu := []string{}
  102. switch imp_1[7].(type) {
  103. case []string:
  104. added_menu = imp_1[7].([]string)
  105. default:
  106. added_menu = []string{"", "", ""}
  107. }
  108. if len(added_menu) < 3 {
  109. for i := len(added_menu); i < 3; i++ {
  110. added_menu = append(added_menu, "")
  111. }
  112. }
  113. imp_1[7] = added_menu
  114. path := ""
  115. if option["path"] != "" {
  116. path = option["path"]
  117. }
  118. doc_length := ""
  119. if _, ok := option["length_doc"]; ok {
  120. doc_length = option["length_doc"]
  121. }
  122. context := pongo2.Context{
  123. "imp" : []any{
  124. name,
  125. imp_1,
  126. imp_2,
  127. imp_3,
  128. },
  129. "data" : `<div class="opennamu_main">` + data + `</div>`,
  130. "menu" : menu_func_result,
  131. "title" : name,
  132. "wiki_name" : imp_1[0],
  133. "license" : imp_1[1],
  134. "wiki_logo" : imp_1[4],
  135. "global_head" : imp_1[5],
  136. "add_menu" : imp_1[6],
  137. "template_var_1" : added_menu[0],
  138. "template_var_2" : added_menu[1],
  139. "template_var_3" : added_menu[2],
  140. "user_login" : imp_2[2],
  141. "user_head" : imp_2[3],
  142. "user_email" : imp_2[4],
  143. "user_name" : imp_2[5],
  144. "user_is_admin" : imp_2[6],
  145. "user_is_ban" : imp_2[7],
  146. "user_alarm_count" : imp_2[8],
  147. "user_auth" : imp_2[9],
  148. "user_ip" : imp_2[10],
  149. "user_discuss" : imp_2[11],
  150. "user_path" : path,
  151. "user_level" : imp_2[13],
  152. "sub_title" : imp_3[0],
  153. "last_edit" : imp_3[1],
  154. "main_head" : imp_3[3],
  155. "star_doc" : imp_3[4],
  156. "main_head_dark" : imp_3[5],
  157. "description_doc" : imp_3[6],
  158. "view_count" : imp_3[7],
  159. "length_doc" : doc_length,
  160. }
  161. tpl, err := pongo2.FromFile(Get_skin_route(skin_name, "index.html"))
  162. if err != nil {
  163. panic(err)
  164. }
  165. out, err := tpl.Execute(context)
  166. if err != nil {
  167. panic(err)
  168. }
  169. return out
  170. }
  171. func Get_redirect(target string) string {
  172. attrURL := html.EscapeString(target)
  173. jsURL := strconv.Quote(target)
  174. return fmt.Sprintf(`<!doctype html>
  175. <html lang="ko">
  176. <head>
  177. <meta charset="utf-8">
  178. <title>Redirecting…</title>
  179. <script>
  180. location.replace(%s);
  181. </script>
  182. <noscript>
  183. <meta http-equiv="refresh" content="0; url=%s">
  184. </noscript>
  185. </head>
  186. <body>
  187. <p>Redirecting… <a href="%s">continue</a></p>
  188. </body>
  189. </html>`, jsURL, attrURL, attrURL)
  190. }
  191. func Cache_v() string {
  192. return ".cache_v288"
  193. }
  194. func Get_wiki_css(data []any, cookies string) []any {
  195. for len(data) < 4 {
  196. data = append(data, "")
  197. }
  198. data_css := ""
  199. data_css_dark := ""
  200. data_css_ver := Cache_v()
  201. // Cache Control
  202. data_css += `<meta http-equiv="Cache-Control" content="max-age=31536000">`
  203. // External JS
  204. data_css += `<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.38/dist/katex.min.js" integrity="sha384-H6s1ZrH2CKpFpqR680poRdStIRJGXty7fSkxAcIfxwl9iu6A4BOPtTk7vQ58Ovio" crossorigin="anonymous"></script>`
  205. data_css += `<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js" integrity="sha512-rdhY3cbXURo13l/WU9VlaRyaIYeJ/KBakckXIvJNAQde8DgpOmE+eZf7ha4vdqVjTtwQt69bD2wH2LXob/LB7Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>`
  206. data_css += `<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/x86asm.min.js" integrity="sha512-HeAchnWb+wLjUb2njWKqEXNTDlcd1QcyOVxb+Mc9X0bWY0U5yNHiY5hTRUt/0twG8NEZn60P3jttqBvla/i2gA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>`
  207. data_css += `<script defer src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.48.0/min/vs/loader.min.js" integrity="sha512-ZG31AN9z/CQD1YDDAK4RUAvogwbJHv6bHrumrnMLzdCrVu4HeAqrUX7Jsal/cbUwXGfaMUNmQU04tQ8XXl5Znw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>`
  208. data_css += `<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>`
  209. data_css += `<script defer src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>`
  210. // Func JS
  211. data_css += `<script defer src="/views/main_css/js/func/func.js` + data_css_ver + `"></script>`
  212. data_css += `<script defer src="/views/main_css/js/func/insert_version.js` + data_css_ver + `"></script>`
  213. data_css += `<script defer src="/views/main_css/js/func/insert_user_info.js` + data_css_ver + `"></script>`
  214. data_css += `<script defer src="/views/main_css/js/func/insert_version_skin.js` + data_css_ver + `"></script>`
  215. data_css += `<script defer src="/views/main_css/js/func/insert_http_warning_text.js` + data_css_ver + `"></script>`
  216. data_css += `<script defer src="/views/main_css/js/func/ie_end_of_life.js` + data_css_ver + `"></script>`
  217. data_css += `<script defer src="/views/main_css/js/func/shortcut.js` + data_css_ver + `"></script>`
  218. data_css += `<script defer src="/views/main_css/js/func/editor.js` + data_css_ver + `"></script>`
  219. data_css += `<script defer src="/views/main_css/js/func/render.js` + data_css_ver + `"></script>`
  220. // Main CSS
  221. data_css += `<link rel="stylesheet" href="/views/main_css/css/main.css` + data_css_ver + `">`
  222. // External CSS
  223. data_css += `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.38/dist/katex.min.css" integrity="sha384-/L6i+LN3dyoaK2jYG5ZLh5u13cjdsPDcFOSNJeFBFa/KgVXR5kOfTdiN3ft1uMAq" crossorigin="anonymous">`
  224. data_css += `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous" referrerpolicy="no-referrer" />`
  225. data_css += `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.41.0/min/vs/editor/editor.main.min.css" integrity="sha512-MFDhxgOYIqLdcYTXw7en/n5BshKoduTitYmX8TkQ+iJOGjrWusRi8+KmfZOrgaDrCjZSotH2d1U1e/Z1KT6nWw==" crossorigin="anonymous" referrerpolicy="no-referrer" />`
  226. cookie_map := Get_cookie_header(cookies)
  227. if cookie_map["main_css_darkmode"] == "1" {
  228. // Main CSS
  229. data_css_dark += `<link rel="stylesheet" href="/views/main_css/css/sub/dark.css` + data_css_ver + `">`
  230. // External CSS
  231. data_css_dark += `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/dark.min.css" integrity="sha512-bfLTSZK4qMP/TWeS1XJAR/VDX0Uhe84nN5YmpKk5x8lMkV0D+LwbuxaJMYTPIV13FzEv4CUOhHoc+xZBDgG9QA==" crossorigin="anonymous" referrerpolicy="no-referrer" />`
  232. }
  233. end := 2
  234. if end > len(data) {
  235. end = len(data)
  236. }
  237. new_data := append([]any{}, data[:end]...)
  238. new_data = append(new_data, "", data_css)
  239. if len(data) >= 3 {
  240. new_data = append(new_data, data[2])
  241. }
  242. new_data = append(new_data, data_css_dark)
  243. if len(data) >= 3 {
  244. new_data = append(new_data, data[3:]...)
  245. }
  246. return new_data
  247. }
  248. func Get_list_ui(left string, right string, bottom string, class_name string) string {
  249. data_html := ""
  250. data_html += `<span class="` + class_name + `">`
  251. data_html += `<div class="opennamu_recent_change">`
  252. data_html += left
  253. data_html += `<div style="float: right;">`
  254. data_html += right
  255. data_html += `</div>`
  256. data_html += `<div style="clear: both;"></div>`
  257. if bottom != "" {
  258. data_html += "<hr>"
  259. data_html += bottom
  260. }
  261. data_html += "</div>"
  262. data_html += `<hr class="main_hr">`
  263. data_html += "</span>"
  264. return data_html
  265. }
  266. // Get_error_page : auth, slow edit limit, edit filter (content), edit filter (send), send require, checkbox check require, overflow max length
  267. func Get_error_page(db *sql.DB, config Config, error_name string) string {
  268. data := ""
  269. switch error_name {
  270. case "auth":
  271. data = Get_language(db, "authority_error", true)
  272. case "slow edit limit":
  273. data = Get_language(db, "fast_edit_error", true)
  274. case "edit filter (content)":
  275. data = Get_language(db, "edit_filter_error", true) + " (content)"
  276. case "edit filter (send)":
  277. data = Get_language(db, "edit_filter_error", true) + " (send)"
  278. case "send require":
  279. data = Get_language(db, "error_edit_send_request", true)
  280. case "checkbox check require":
  281. data = Get_language(db, "copyright_disagreed", true)
  282. case "overflow max length":
  283. data = Get_language(db, "document_content_max_length_error", true)
  284. default:
  285. data = Get_language(db, "inter_error", true)
  286. }
  287. return Get_template(
  288. db,
  289. config,
  290. Get_language(db, "error", true),
  291. `<h2>` + Get_language(db, "error", true) + `</h2>` +
  292. `<ul>` +
  293. `<li>` + data + `</li>` +
  294. `</ul>`,
  295. []any{},
  296. [][]any{},
  297. map[string]string{},
  298. )
  299. }
  300. func Get_page_control(db *sql.DB, page int, count int, max_count int, url string) string {
  301. data_html := "<hr class=\"main_hr\">"
  302. if page > 1 {
  303. prev_page := page - 1
  304. before_url := strings.ReplaceAll(url, "{}", strconv.Itoa(prev_page))
  305. data_html += `<a href="` + before_url + `">(` + Get_language(db, "previous", true) + `)</a> `
  306. }
  307. if count == max_count {
  308. prev_page := page + 1
  309. after_url := strings.ReplaceAll(url, "{}", strconv.Itoa(prev_page))
  310. data_html += `<a href="` + after_url + `">(` + Get_language(db, "next", true) + `)</a> `
  311. }
  312. return data_html
  313. }
  314. func Get_editor_ui(db *sql.DB, config Config, data string, do_type string, add_on string, doc_name string) string {
  315. monaco_editor_top := ""
  316. help_text := ""
  317. document_top := ""
  318. switch do_type {
  319. case "edit":
  320. QueryRow_DB(
  321. db,
  322. `select data from other where name = "edit_help"`,
  323. []any{ &help_text },
  324. )
  325. QueryRow_DB(
  326. db,
  327. `select set_data from data_set where doc_name = ? and set_name = 'document_top'`,
  328. []any{ &document_top },
  329. doc_name,
  330. )
  331. case "bbs":
  332. QueryRow_DB(
  333. db,
  334. `select data from other where name = "bbs_help"`,
  335. []any{ &help_text },
  336. )
  337. case "bbs_comment":
  338. QueryRow_DB(
  339. db,
  340. `select data from other where name = "bbs_comment_help"`,
  341. []any{ &help_text },
  342. )
  343. default:
  344. QueryRow_DB(
  345. db,
  346. `select data from other where name = "topic_text"`,
  347. []any{ &help_text },
  348. )
  349. }
  350. if help_text == "" {
  351. help_text = Get_language(db, "default_edit_help", true)
  352. } else {
  353. help_text = HTML_escape(help_text)
  354. }
  355. editor_type := "edit"
  356. if do_type == "bbs_comment" || do_type == "thread" {
  357. editor_type = "thread"
  358. }
  359. monaco_editor_top += `
  360. <a href="javascript:opennamu_do_editor_temp_save();">(` + Get_language(db, "load_temp_save", true) + `)</a> <a href="javascript:opennamu_do_editor_temp_save_load();">(` + Get_language(db, "load_temp_save_load", true) + `)</a>
  361. <hr class="main_hr">
  362. `
  363. dark_mode := false
  364. cookie_map := Get_cookie_header(config.Cookies)
  365. if cookie_map["main_css_darkmode"] == "1" {
  366. dark_mode = true
  367. }
  368. monaco_theme := ""
  369. if dark_mode {
  370. monaco_theme = "vs-dark"
  371. }
  372. monaco_on := false
  373. if Get_main_skin_set(db, config, "main_css_monaco") == "use" {
  374. monaco_on = true
  375. }
  376. editor_display := []string{}
  377. for for_a := 0; for_a < 3; for_a++ {
  378. editor_display = append(editor_display, `style="display: none;"`)
  379. }
  380. select_A := ""
  381. select_B := ""
  382. if monaco_on {
  383. editor_display[1] = ""
  384. select_B = "selected"
  385. } else {
  386. editor_display[0] = ""
  387. select_A = "selected"
  388. }
  389. monaco_editor_top += `
  390. <span class="__ON_SELECT_DIV__">
  391. <select class="__ON_SELECT__" onclick="do_sync_monaco_and_textarea();" id="opennamu_select_editor" onchange="opennamu_edit_turn_off_monaco();">
  392. <option value="default" ` + select_A + `>` + Get_language(db, "default", true) + `</option>
  393. <option value="monaco" ` + select_B + `>` + Get_language(db, "monaco_editor", true) + `</option>
  394. </select>
  395. </span>
  396. `
  397. if editor_type == "edit" {
  398. monaco_editor_top += Get_markup_select_ui(db, config, doc_name, "", `id="opennamu_editor_markup" onclick="opennamu_do_sync_monaco_markup();"`, "")
  399. } else {
  400. monaco_editor_top += Get_markup_select_ui(db, config, doc_name, "", `id="opennamu_editor_markup" onclick="opennamu_do_sync_monaco_markup();"`, "disabled")
  401. }
  402. textarea_size := "opennamu_textarea_500"
  403. if editor_type != "edit" {
  404. textarea_size = "opennamu_textarea_100"
  405. }
  406. out_field := Get_captcha_ui(db, config) + Get_IP_warning_ui(db, config) + add_on
  407. return `
  408. <textarea class="__ON_TEXTAREA__" style="display: none;" id="opennamu_edit_origin" name="doc_data_org">` + HTML_escape(data) + `</textarea>
  409. <div>
  410. ` + monaco_editor_top + `
  411. <hr class="main_hr">
  412. ` + Get_editor_button_ui(db) + `
  413. <div id="opennamu_editor_user_button"></div>
  414. </div>
  415. ` + document_top + `
  416. <div id="opennamu_monaco_editor" class="` + textarea_size + `" ` + editor_display[1] + `></div>
  417. <textarea id="opennamu_edit_textarea" class="` + textarea_size + ` __ON_TEXTAREA__" ` + editor_display[0] + ` name="content" placeholder="` + help_text + `">` + HTML_escape(data) + `</textarea>
  418. <hr class="main_hr">
  419. ` + out_field + `
  420. <script>
  421. window.addEventListener('DOMContentLoaded', function() {
  422. do_stop_exit();
  423. do_paste_image();
  424. do_monaco_init("` + monaco_theme + `");
  425. opennnamu_do_user_editor();
  426. });
  427. </script>
  428. <button class="__ON_BUTTON__" id="opennamu_save_button" type="submit" onclick="do_stop_exit_release();">` + Get_language(db, "send", true) + `</button>
  429. <button class="__ON_BUTTON__" id="opennamu_preview_button" type="button" onclick="opennamu_do_editor_preview();">` + Get_language(db, "preview", true) + `</button>
  430. <hr class="main_hr">
  431. <div id="opennamu_preview_area"></div>
  432. `
  433. }
  434. func Get_markup_select_ui(db *sql.DB, config Config, doc_name string, markup string, add_on string, disable string) string {
  435. default_markup := ""
  436. QueryRow_DB(
  437. db,
  438. `select data from other where name = "markup"`,
  439. []any{ &default_markup },
  440. )
  441. markup_load := markup
  442. if markup == "" {
  443. QueryRow_DB(
  444. db,
  445. `select set_data from data_set where doc_name = ? and set_name = 'document_markup'`,
  446. []any{ &markup_load },
  447. doc_name,
  448. )
  449. }
  450. markup_list := []string{ "normal" }
  451. markup_list = append(markup_list, Get_init_set_list("markup")["markup"]["list"].([]string)...)
  452. markup_html := ""
  453. for _, v := range markup_list {
  454. selected := ""
  455. if markup_load == v {
  456. selected = "selected"
  457. }
  458. value := v
  459. if v == "normal" {
  460. value = default_markup
  461. }
  462. markup_html += `<option value="` + value + `" ` + selected + `>` + v + `</option>`
  463. }
  464. markup_html = `
  465. <span class="__ON_SELECT_DIV__">
  466. <select class="__ON_SELECT__" name="document_markup" ` + disable + ` ` + add_on + `>` + markup_html + `</select>
  467. </span>
  468. `
  469. return markup_html
  470. }
  471. func Get_captcha_ui(db *sql.DB, config Config) string {
  472. data := ""
  473. if !Check_acl(db, "", "", "recaptcha", config.IP) {
  474. pub_key := ""
  475. QueryRow_DB(
  476. db,
  477. `select data from other where name = "recaptcha"`,
  478. []any{ &pub_key },
  479. )
  480. sec_key := ""
  481. QueryRow_DB(
  482. db,
  483. `select data from other where name = "sec_re"`,
  484. []any{ &sec_key },
  485. )
  486. if pub_key != "" && sec_key != "" {
  487. rec_ver := ""
  488. QueryRow_DB(
  489. db,
  490. `select data from other where name = "recaptcha_ver"`,
  491. []any{ &rec_ver },
  492. )
  493. switch rec_ver {
  494. case "":
  495. data += `
  496. <script defer src="https://www.google.com/recaptcha/api.js"></script>
  497. <div class="g-recaptcha" data-sitekey="` + pub_key + `"></div>
  498. <hr class="main_hr">
  499. `
  500. case "v3":
  501. data += `
  502. <script defer src="https://www.google.com/recaptcha/api.js?render=` + pub_key + `"></script>
  503. <input class="__ON_INPUT__" type="hidden" id="g-recaptcha" name="g-recaptcha">
  504. <script type="text/javascript">
  505. document.addEventListener('DOMContentLoaded', function () {
  506. grecaptcha.ready(function() {
  507. grecaptcha.execute('` + pub_key + `', {action: 'homepage'}).then(function(token) {
  508. document.getElementById('g-recaptcha').value = token;
  509. });
  510. });
  511. });
  512. </script>
  513. `
  514. case "cf":
  515. data += `
  516. <script defer src="https://challenges.cloudflare.com/turnstile/v0/api.js?compat=recaptcha"></script>
  517. <div class="g-recaptcha" data-sitekey="` + pub_key + `"></div>
  518. <hr class="main_hr">
  519. `
  520. default:
  521. data += `
  522. <script defer src="https://js.hcaptcha.com/1/api.js"></script>
  523. <div class="h-captcha" data-sitekey="` + pub_key + `"></div>
  524. <hr class="main_hr">
  525. `
  526. }
  527. }
  528. }
  529. return data
  530. }
  531. func Get_IP_warning_ui(db *sql.DB, config Config) string {
  532. text_data := ""
  533. if IP_or_user(config.IP) {
  534. text_db := ""
  535. QueryRow_DB(
  536. db,
  537. `select data from other where name = "no_login_warning"`,
  538. []any{ &text_db },
  539. )
  540. if text_db == "" {
  541. text_db = Get_language(db, "no_login_warning", true)
  542. }
  543. text_data = `<span>` + text_db + `</span><hr class="main_hr">`
  544. }
  545. return text_data
  546. }
  547. func Get_editor_button_ui(db *sql.DB) string {
  548. data_html := ""
  549. rows := Query_DB(
  550. db,
  551. `select html, plus from html_filter where kind = 'edit_top'`,
  552. )
  553. defer rows.Close()
  554. for rows.Next() {
  555. var html string
  556. var plus string
  557. err := rows.Scan(&html, &plus)
  558. if err != nil {
  559. panic(err)
  560. }
  561. data_html += `<a href="javascript:do_insert_data('` + JS_escape(plus) + `');">` + HTML_escape(html) + `</a>`
  562. }
  563. if data_html != "" {
  564. data_html += " "
  565. }
  566. data_html += `<a href="/filter/edit_top">(` + Get_language(db, "add", true) + `)</a><hr class="main_hr">`
  567. return data_html
  568. }
  569. func Get_thread_ui(user_name string, date string, data string, code string, color string, blind string, add_style string, topic_num string) string {
  570. color_b := ""
  571. class_b := ""
  572. if blind == "O" {
  573. if data == "" {
  574. color_b = "opennamu_comment_blind"
  575. } else {
  576. color_b = "opennamu_comment_blind_admin"
  577. }
  578. class_b = "opennamu_comment_blind_js opennamu_list_hidden"
  579. } else {
  580. color_b = "opennamu_comment_blind_not"
  581. }
  582. admin_check_box := ""
  583. if topic_num != "" {
  584. admin_check_box = `<input type="checkbox" class="opennamu_blind_button" id="opennamu_blind_` + topic_num + `_` + code + `">`
  585. }
  586. return `
  587. <span class="` + class_b + `">
  588. <table class="opennamu_comment" style="` + add_style + `">
  589. <tr>
  590. <td class="opennamu_comment_color_` + color + `">
  591. ` + admin_check_box + `
  592. <a href="#thread_shortcut" id="` + code + `">#` + code + `</a>
  593. ` + user_name + `
  594. <span style="float: right;">` + date + `</span>
  595. </td>
  596. </tr>
  597. <tr>
  598. <td class="` + color_b + ` opennamu_comment_data_main" id="thread_` + code + `">
  599. <div class="opennamu_comment_scroll" id="opennamu_thread_render_` + code + `">` + HTML_escape(data) + `</div>
  600. </td>
  601. <script>
  602. window.addEventListener('DOMContentLoaded', function() {
  603. opennamu_do_render_with_dom("opennamu_thread_render_` + code + `", "opennamu_thread_render_` + code + `", "", "thread");
  604. })
  605. </script>
  606. </tr>
  607. </table>
  608. <hr class="main_hr">
  609. </span>
  610. `
  611. }
  612. func Get_edit_check_box_ui(db *sql.DB) string {
  613. cccb_text := ""
  614. QueryRow_DB(
  615. db,
  616. `select data from other where name = "copyright_checkbox_text"`,
  617. []any{ &cccb_text },
  618. )
  619. result := ""
  620. if cccb_text != "" {
  621. result = `
  622. <label class="__ON_CHECKLABEL__"><input class="__ON_CHECKBOX__" type="checkbox" name="copyright_agreement" value="yes" checked> ` + cccb_text + `</label>
  623. <hr class="main_hr">
  624. `
  625. }
  626. return result
  627. }
  628. func Get_edit_bottom_text_ui(db *sql.DB, do_type string) string {
  629. b_text := ""
  630. QueryRow_DB(
  631. db,
  632. `select data from other where name = "edit_bottom_text"`,
  633. []any{ &b_text },
  634. )
  635. db_data := ""
  636. switch do_type {
  637. case "edit":
  638. QueryRow_DB(
  639. db,
  640. `select data from other where name = "edit_only_bottom_text"`,
  641. []any{ &db_data },
  642. )
  643. case "move":
  644. QueryRow_DB(
  645. db,
  646. `select data from other where name = "move_bottom_text"`,
  647. []any{ &db_data },
  648. )
  649. case "delete":
  650. QueryRow_DB(
  651. db,
  652. `select data from other where name = "delete_bottom_text"`,
  653. []any{ &db_data },
  654. )
  655. default:
  656. QueryRow_DB(
  657. db,
  658. `select data from other where name = "revert_bottom_text"`,
  659. []any{ &db_data },
  660. )
  661. }
  662. result := ""
  663. if db_data != "" {
  664. result = db_data + `<hr class="main_hr">`
  665. } else if b_text != "" {
  666. result = b_text + `<hr class="main_hr">`
  667. }
  668. return result
  669. }