' + await get_lang('error') + '
' + \ '- ' + \
'
- ' + data + ' ' + \ '
# Init
import os
import sys
import platform
import smtplib
import shutil
import json
import datetime
import ipaddress
import subprocess
import email.mime.text
import email.utils
import email.header
# Init-Version
with open('version.json', encoding = 'utf8') as file_data:
version_list = json.loads(file_data.read())
print('Version : ' + version_list['r_ver'])
print('DB set version : ' + version_list['c_ver'])
print('Skin set version : ' + version_list['s_ver'])
# Init-PIP_Install
data_up_date = 1
if os.path.exists(os.path.join('data', 'version.json')):
with open(os.path.join('data', 'version.json'), encoding = 'utf8') as file_data:
data_load_ver = file_data.read()
if data_load_ver == version_list['r_ver']:
data_up_date = 0
if os.getenv('NAMU_DOCKER') == 'O': # skip update check when run at docker
data_up_date = 0
if data_up_date == 1:
with open(os.path.join('data', 'version.json'), 'w', encoding = 'utf8') as f:
f.write(version_list['r_ver'])
if platform.system() in ('Linux', 'Darwin', 'Windows'):
python_ver = ''
python_ver = str(sys.version_info.major) + '.' + str(sys.version_info.minor)
run_list = [
sys.executable,
'python' + python_ver,
'python3',
'python',
'py -' + python_ver
]
user_opt = [] if getattr(sys, "base_prefix", sys.prefix) != sys.prefix else ["--user"]
for exe_name in run_list:
try:
subprocess.check_call([exe_name, "-m", "pip", "install", "--upgrade", *user_opt, "-r", "requirements-optional.txt"])
except:
pass
try:
subprocess.check_call([exe_name, "-m", "pip", "install", "--upgrade", *user_opt, "-r", "requirements.txt"])
subprocess.Popen([exe_name] + sys.argv)
os._exit(0)
except:
pass
else:
print('Error : automatic installation is not supported.')
print('Help : try "python3 -m pip install -r requirements.txt"')
else:
print('Error : automatic installation is not supported.')
print('Help : try "python3 -m pip install -r requirements.txt"')
else:
print('PIP check pass')
# Init-Load
from .func_tool import *
from .func_render import class_do_render
from diff_match_patch import diff_match_patch
import werkzeug.routing
import werkzeug.debug
import flask
import asyncio
import nest_asyncio
import aiohttp
import requests
import psutil
from PIL import Image
try:
import mysqlclient as pymysql
except:
import pymysql
if sys.version_info < (3, 6):
import sha3
# Func
# Func-main
async def render_template(name, data, sub, menu, other = [], option = {}):
other_set = {}
other_set["name"] = name
other_set["data"] = data
other_set["sub"] = [sub] + other
other_set["menu"] = menu
other_set["option"] = {
"path" : flask.request.path
}
for for_a in option:
other_set["option"][for_a] = option[for_a]
return await python_to_golang("post", other_set = other_set, path = "template")
global_lang_data = {}
global_some_set = {}
def do_db_set(db_set):
for for_a in db_set:
global_func_some_set_do('db_' + for_a, db_set[for_a])
global_some_set_do('db_' + for_a, db_set[for_a])
class flask_data_or_variable:
def __init__(self, flask_data, var_dict):
if var_dict == {}:
self.data = flask_data
self.selected_flask = True
else:
self.data = var_dict
self.selected_flask = False
def get(self, dict_name, replace_data):
if self.selected_flask == True:
return self.data.get(dict_name, replace_data)
else:
if dict_name in self.data:
return self.data[dict_name]
else:
return replace_data
def global_some_set_do(set_name, data = None):
global global_some_set
if data != None:
global_some_set[set_name] = data
if set_name in global_some_set:
return global_some_set[set_name]
else:
return None
async def python_to_golang(func_name, other_set = {}, path = ''):
headers = {}
if flask.has_request_context():
if "Cookie" in flask.request.headers:
headers["Cookie"] = flask.request.headers["Cookie"]
headers["X-Forwarded-For"] = ip_check()
port_data = global_some_set_do("setup_golang_port")
# print(func_name, other_set)
if func_name == "same":
async with aiohttp.ClientSession() as session:
if flask.request.method == 'POST':
form_data = flask.request.form.to_dict(flat = False)
async with session.post('http://127.0.0.1:' + port_data + flask.request.path, data = form_data, headers = headers) as res:
data = await res.text()
return data
else:
async with session.get('http://127.0.0.1:' + port_data + flask.request.path, headers = headers) as res:
data = await res.text()
return data
elif path != "":
if func_name == "get":
async with aiohttp.ClientSession() as session:
async with session.get('http://127.0.0.1:' + port_data + "/api/" + path, headers = headers) as res:
data = await res.text()
return data
elif func_name == "post":
async with aiohttp.ClientSession() as session:
async with session.post('http://127.0.0.1:' + port_data + "/api/" + path, data = json_dumps(other_set), headers = headers) as res:
data = await res.text()
return data
elif func_name == "get_json":
async with aiohttp.ClientSession() as session:
async with session.get('http://127.0.0.1:' + port_data + "/api/" + path, headers = headers) as res:
data = await res.json()
return data
else:
async with aiohttp.ClientSession() as session:
async with session.post('http://127.0.0.1:' + port_data + "/api/" + path, data = json_dumps(other_set), headers = headers) as res:
data = await res.json()
return data
else:
async with aiohttp.ClientSession() as session:
async with session.post('http://127.0.0.1:' + port_data + '/compatible_api/' + func_name, data = json_dumps(other_set), headers = headers) as res:
data = await res.json()
if "response" in data and data["response"] == "error":
raise Exception(f"API returned error: {data}")
else:
return data
async def opennamu_make_list(left = '', right = '', bottom = '', class_name = ''):
data_html = f''
data_html += '
'
data_html += bottom
data_html += '
'
data_html += ''
return data_html
# Func-init
def get_init_set_list(need = 'all'):
init_set_list = {
'host' : {
'display' : 'Host',
'require' : 'conv',
'default' : '0.0.0.0'
}, 'port' : {
'display' : 'Port',
'require' : 'conv',
'default' : '3000'
}, 'golang_port' : {
'display' : 'Golang port',
'require' : 'conv',
'default' : '3001'
}, 'language' : {
'display' : 'Language',
'require' : 'select',
'default' : 'ko-KR',
'list' : ['ko-KR', 'en-US']
}, 'markup' : {
'display' : 'Markup',
'require' : 'select',
'default' : 'namumark',
'list' : ['namumark', 'namumark_beta', 'macromark', 'markdown', 'custom', 'raw']
}, 'encode' : {
'display' : 'Encryption method',
'require' : 'select',
'default' : 'sha3',
'list' : ['sha3', 'sha3-salt', 'sha3-512', 'sha3-512-salt']
}
}
if need == 'all':
return init_set_list
else:
return init_set_list[need]
class get_db_connect:
def __init__(self, db_type = '', init_mode = False):
self.db_set = {}
self.init_mode = init_mode
for for_a in ("db_type", "db_name"):
self.db_set[for_a] = global_some_set_do(for_a)
if db_type != '':
self.db_set['db_type'] = db_type
if self.db_set['db_type'] == 'mysql':
for for_a in ("db_mysql_host", "db_mysql_user", "db_mysql_pw", "db_mysql_port"):
self.db_set[for_a] = global_some_set_do(for_a)
def __enter__(self):
if self.db_set['db_type'] == 'sqlite':
self.conn = sqlite3.connect(
self.db_set['db_name'] + '.db',
check_same_thread = False,
isolation_level = None
)
else:
# try connect
# print('Wait for DB connection...')
self.conn = None
try_cnt = 1
max_try = 30
while self.conn == None and try_cnt <= max_try:
try:
if self.init_mode:
try:
self.conn = pymysql.connect(
host = self.db_set['db_mysql_host'],
user = self.db_set['db_mysql_user'],
password = self.db_set['db_mysql_pw'],
charset = 'utf8mb4',
port = int(self.db_set['db_mysql_port']),
autocommit = True,
db = self.db_set['db_name']
)
except pymysql.err.OperationalError:
self.conn = pymysql.connect(
host = self.db_set['db_mysql_host'],
user = self.db_set['db_mysql_user'],
password = self.db_set['db_mysql_pw'],
charset = 'utf8mb4',
port = int(self.db_set['db_mysql_port']),
autocommit = True
)
else:
self.conn = pymysql.connect(
host = self.db_set['db_mysql_host'],
user = self.db_set['db_mysql_user'],
password = self.db_set['db_mysql_pw'],
charset = 'utf8mb4',
port = int(self.db_set['db_mysql_port']),
autocommit = True,
db = self.db_set['db_name']
)
except pymysql.err.OperationalError as err:
if try_cnt + 1 > max_try:
raise err
finally:
if self.conn == None:
try_cnt += 1
time.sleep(1)
if self.conn == None:
raise Exception("Unable to connect database")
# print('DB connected')
return self.conn
def __exit__(self, exc_type, exc_value, traceback):
self.conn.commit()
self.conn.close()
# class get_whoosh_connect:
class class_check_json:
def do_check_set_json(self):
if os.getenv('NAMU_DB') or os.getenv('NAMU_DB_TYPE'):
set_data = {}
set_data['db'] = os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data'
set_data['db_type'] = os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
else:
if os.path.exists(os.path.join('data', 'set.json')):
db_set_list = ['db', 'db_type']
with open(os.path.join('data', 'set.json'), encoding = 'utf8') as file_data:
set_data = json_loads(file_data.read())
for i in db_set_list:
if not i in set_data:
os.remove(os.path.join('data', 'set.json'))
break
if not os.path.exists(os.path.join('data', 'set.json')):
set_data = {}
normal_db_type = ['sqlite', 'mysql']
print('DB type (' + normal_db_type[0] + ') [' + ', '.join(normal_db_type) + '] : ', end = '')
try:
data_get = str(input())
except EOFError:
print("\nInput is not available. You can set the environment variable NAMU_DB_TYPE instead.")
print("No input detected. Using default value.")
data_get = ''
if data_get == '' or not data_get in normal_db_type:
set_data['db_type'] = 'sqlite'
else:
set_data['db_type'] = data_get
all_src = []
if set_data['db_type'] == 'sqlite':
for i_data in os.listdir("."):
f_src = re.search(r"(.+)\.db$", i_data)
if f_src:
all_src += [f_src.group(1)]
print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
data_get = str(input())
if data_get == '':
set_data['db'] = 'data'
else:
set_data['db'] = data_get
with open(os.path.join('data', 'set.json'), 'w', encoding = 'utf8') as f:
f.write(json_dumps(set_data))
print('DB name : ' + set_data['db'])
print('DB type : ' + set_data['db_type'])
data_db_set = {}
data_db_set['name'] = set_data['db']
data_db_set['type'] = set_data['db_type']
return data_db_set
def do_check_mysql_json(self, data_db_set):
def do_check_mysql_env():
env_keys = ['NAMU_DB_HOST', 'NAMU_DB_PORT', 'NAMU_DB_USER', 'NAMU_DB_PASSWORD']
vaild = False
for key in env_keys:
if os.getenv(key):
vaild = True
break
return vaild
if do_check_mysql_env():
# ['user', 'password', 'host', 'port']
set_data_mysql = {}
set_data_mysql['host'] = os.getenv('NAMU_DB_HOST') if os.getenv('NAMU_DB_HOST') else '127.0.0.1'
set_data_mysql['port'] = os.getenv('NAMU_DB_PORT') if os.getenv('NAMU_DB_PORT') else 3306
if not os.getenv('NAMU_DB_USER'):
raise Exception('Error : NAMU_DB_USER env not set')
else:
set_data_mysql['user'] = os.getenv('NAMU_DB_USER')
if not os.getenv('NAMU_DB_PASSWORD'):
raise Exception('Error : NAMU_DB_PASSWORD env not set')
else:
set_data_mysql['password'] = os.getenv('NAMU_DB_PASSWORD')
elif os.path.exists(os.path.join('data', 'mysql.json')):
db_set_list = ['user', 'password', 'host', 'port']
with open(os.path.join('data', 'mysql.json'), encoding = 'utf8') as file_data:
set_data = json_loads(file_data.read())
for i in db_set_list:
if not i in set_data:
os.remove(os.path.join('data', 'mysql.json'))
break
set_data_mysql = set_data
elif not os.path.exists(os.path.join('data', 'mysql.json')):
set_data_mysql = {}
print('DB user ID : ', end = '')
set_data_mysql['user'] = str(input())
print('DB password : ', end = '')
set_data_mysql['password'] = str(input())
print('DB host (127.0.0.1) : ', end = '')
set_data_mysql['host'] = str(input())
if set_data_mysql['host'] == '':
set_data_mysql['host'] = '127.0.0.1'
print('DB port (3306) : ', end = '')
set_data_mysql['port'] = str(input())
if set_data_mysql['port'] == '':
set_data_mysql['port'] = '3306'
with open(os.path.join('data', 'mysql.json'), 'w', encoding = 'utf8') as f:
f.write(json_dumps(set_data_mysql))
data_db_set['mysql_user'] = set_data_mysql['user']
data_db_set['mysql_pw'] = set_data_mysql['password']
if 'host' in set_data_mysql:
data_db_set['mysql_host'] = set_data_mysql['host']
else:
data_db_set['mysql_host'] = '127.0.0.1'
if 'port' in set_data_mysql:
data_db_set['mysql_port'] = set_data_mysql['port']
else:
data_db_set['mysql_port'] = '3306'
return data_db_set
def __init__(self):
self.data_db_set = {}
def __new__(cls):
instance = super().__new__(cls)
cls.data_db_set = instance.do_check_set_json()
if cls.data_db_set['type'] == 'mysql':
cls.data_db_set = instance.do_check_mysql_json(cls.data_db_set)
return cls.data_db_set
def get_db_table_list():
# DB table
# Init-Create_DB
# --이거 개편한다더니 도대체 언제?--
create_data = {}
# 폐지 예정 (data_set으로 통합)
create_data['data_set'] = ['doc_name', 'doc_rev', 'set_name', 'set_data']
create_data['data'] = ['title', 'data', 'type']
create_data['history'] = ['id', 'title', 'data', 'date', 'ip', 'send', 'leng', 'hide', 'type']
create_data['rc'] = ['id', 'title', 'date', 'type']
create_data['acl'] = ['title', 'data', 'type']
# 개편 예정 (data_link로 변경)
create_data['back'] = ['title', 'link', 'type', 'data']
# 폐지 예정 (topic_set으로 통합) [가장 시급]
create_data['topic_set'] = ['thread_code', 'set_name', 'set_id', 'set_data']
create_data['rd'] = ['title', 'sub', 'code', 'date', 'band', 'stop', 'agree', 'acl']
create_data['topic'] = ['id', 'data', 'date', 'ip', 'block', 'top', 'code']
# 폐지 예정 (user_set으로 통합)
create_data['rb'] = ['block', 'end', 'today', 'blocker', 'why', 'band', 'login', 'ongoing']
# 개편 예정 (wiki_set과 wiki_filter과 wiki_vote으로 변경)
create_data['other'] = ['name', 'data', 'coverage']
create_data['html_filter'] = ['html', 'kind', 'plus', 'plus_t']
create_data['vote'] = ['name', 'id', 'subject', 'data', 'user', 'type', 'acl']
# 개편 예정 (auth와 auth_log로 변경)
create_data['alist'] = ['name', 'acl']
create_data['re_admin'] = ['who', 'what', 'time']
# 개편 예정 (user_notice와 user_agent로 변경)
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']
return create_data
async def update(conn, ver_num, set_data):
curs = conn.cursor()
# 업데이트 하위 호환 유지 함수
if ver_num < 3160027:
print('Add init set')
set_init(conn)
ver_num = 3160027
if ver_num < 3170002:
curs.execute(db_change("select html from html_filter where kind = 'extension'"))
if not curs.fetchall():
for i in ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg']:
curs.execute(db_change("insert into html_filter (html, kind) values (?, 'extension')"), [i])
ver_num = 3170002
if ver_num < 3170400:
curs.execute(db_change("select title, sub, code from topic where id = '1'"))
for i in curs.fetchall():
curs.execute(db_change("update topic set code = ? where title = ? and sub = ?"), [i[2], i[0], i[1]])
curs.execute(db_change("update rd set code = ? where title = ? and sub = ?"), [i[2], i[0], i[1]])
ver_num = 3170400
if ver_num < 3171800:
curs.execute(db_change("select data from other where name = 'recaptcha'"))
change_rec = curs.fetchall()
if change_rec and change_rec[0][0] != '':
new_rec = re.search(r'data-sitekey="([^"]+)"', change_rec[0][0])
if new_rec:
curs.execute(db_change("update other set data = ? where name = 'recaptcha'"), [new_rec.group(1)])
else:
curs.execute(db_change("update other set data = '' where name = 'recaptcha'"))
curs.execute(db_change("update other set data = '' where name = 'sec_re'"))
ver_num = 3171800
if ver_num < 3172800 and set_data['type'] == 'mysql':
get_data_mysql = json_loads(open('data/mysql.json', encoding = 'utf8').read())
with open('data/mysql.json', 'w') as f:
f.write('{ "user" : "' + get_data_mysql['user'] + '", "password" : "' + get_data_mysql['password'] + '", "host" : "127.0.0.1" }')
ver_num = 3172800
if ver_num < 3183603:
curs.execute(db_change("select block from ban where band = 'O'"))
for i in curs.fetchall():
curs.execute(db_change("update ban set block = ?, band = 'regex' where block = ? and band = 'O'"), ['^' + i[0].replace('.', '\\.'), i[0]])
curs.execute(db_change("select block from rb where band = 'O'"))
for i in curs.fetchall():
curs.execute(db_change("update rb set block = ?, band = 'regex' where block = ? and band = 'O'"), ['^' + i[0].replace('.', '\\.'), i[0]])
ver_num = 3183603
if ver_num < 3190201:
today_time = get_time()
curs.execute(db_change("select block, end, why, band, login from ban"))
for i in curs.fetchall():
curs.execute(db_change("insert into rb (block, end, today, why, band, login, ongoing) values (?, ?, ?, ?, ?, ?, ?)"), [i[0], i[1], today_time, i[2], i[3], i[4], '1'])
ver_num = 3190201
if ver_num < 3191301:
curs.execute(db_change('select id, title, date from history where not title like "user:%" order by date desc limit 50'))
data_list = curs.fetchall()
for get_data in data_list:
curs.execute(db_change("insert into rc (id, title, date, type) values (?, ?, ?, 'normal')"), [get_data[0], get_data[1], get_data[2]])
ver_num = 3191301
if ver_num < 3202400:
curs.execute(db_change("select data from other where name = 'update'"))
get_data = curs.fetchall()
if get_data and get_data[0][0] == 'master':
curs.execute(db_change("update other set data = 'beta' where name = 'update'"), [])
ver_num = 3202400
if ver_num < 3202600:
curs.execute(db_change("select name, regex, sub from filter"))
for i in curs.fetchall():
curs.execute(db_change("insert into html_filter (html, kind, plus, plus_t) values (?, 'regex_filter', ?, ?)"), [i[0], i[1], i[2]])
curs.execute(db_change("select title, link, icon from inter"))
for i in curs.fetchall():
curs.execute(db_change("insert into html_filter (html, kind, plus, plus_t) values (?, 'inter_wiki', ?, ?)"), [i[0], i[1], i[2]])
ver_num = 3202600
if ver_num < 3203400:
curs.execute(db_change("select user, css from custom"))
for i in curs.fetchall():
curs.execute(db_change("insert into user_set (name, id, data) values ('custom_css', ?, ?)"), [re.sub(r' \(head\)$', '', i[0]), i[1]])
ver_num = 3203400
if ver_num < 3205500:
curs.execute(db_change("select title, decu, dis, view, why from acl"))
for i in curs.fetchall():
curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [i[0], i[1], 'decu'])
curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [i[0], i[2], 'dis'])
curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [i[0], i[3], 'view'])
curs.execute(db_change("insert into acl (title, data, type) values (?, ?, ?)"), [i[0], i[4], 'why'])
ver_num = 3205500
if ver_num < 3300101:
# 캐시 초기화
curs.execute(db_change('delete from cache_data'))
ver_num = 3300101
if ver_num < 3300301:
# regex_filter 오류 해결
curs.execute(db_change('delete from html_filter where kind = "regex_filter" and html is null'))
ver_num = 3300301
if ver_num < 3302302:
# user이랑 user_set 테이블의 통합
curs.execute(db_change('select id, pw, acl, date, encode from user'))
for i in curs.fetchall():
curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), ['pw', i[0], i[1]])
curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), ['acl', i[0], i[2]])
curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), ['date', i[0], i[3]])
curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), ['encode', i[0], i[4]])
ver_num = 3302302
if ver_num < 3400101:
# user_set이랑 user_application 테이블의 통합
curs.execute(db_change('select id, pw, date, encode, question, answer, ip, ua, email from user_application'))
for i in curs.fetchall():
sql_data = {}
sql_data['id'] = i[0]
sql_data['pw'] = i[1]
sql_data['date'] = i[2]
sql_data['encode'] = i[3]
sql_data['question'] = i[4]
sql_data['answer'] = i[5]
sql_data['ip'] = i[6]
sql_data['ua'] = i[7]
sql_data['email'] = i[8]
curs.execute(db_change("insert into user_set (name, id, data) values (?, ?, ?)"), ['application', i[0], json_dumps(sql_data)])
ver_num = 3400101
if ver_num < 3500105:
curs.execute(db_change('delete from acl where title like "file:%" and data = "admin" and type like "decu%"'))
ver_num = 3500105
if ver_num < 3500106:
curs.execute(db_change("select data from other where name = 'domain'"))
db_data = curs.fetchall()
if db_data and db_data[0][0] != '':
db_data = db_data[0][0]
db_data = re.match(r'[^/]+\/\/([^/]+)', db_data)
if db_data:
db_data = db_data.group(1)
curs.execute(db_change("update other set data = ? where name = 'domain'"), [db_data])
else:
curs.execute(db_change("update other set data = '' where name = 'domain'"))
ver_num = 3500106
if ver_num < 3500107:
db_table_list = get_db_table_list()
for for_a in db_table_list:
for for_b in db_table_list[for_a]:
curs.execute(db_change("update " + for_a + " set " + for_b + " = '' where " + for_b + " is null"))
ver_num = 3500107
if ver_num < 3500113:
db_table_list = get_db_table_list()
for for_a in db_table_list:
for for_b in db_table_list[for_a]:
curs.execute(db_change("update " + for_a + " set " + for_b + " = '' where " + for_b + " is null"))
ver_num = 3500113
if ver_num < 3500114:
curs.execute(db_change('delete from alarm'))
ver_num = 3500114
if ver_num < 3500354:
curs.execute(db_change("select data from other where name = 'robot'"))
db_data = curs.fetchall()
if db_data:
robot_default = '' + \
'User-agent: *\n' + \
'Disallow: /\n' + \
'Allow: /$\n' + \
'Allow: /image/\n' + \
'Allow: /views/\n' + \
'Allow: /w/' + \
''
if db_data[0][0] == robot_default:
curs.execute(db_change("insert into other (name, data, coverage) values ('robot_default', 'on', '')"))
ver_num = 3500354
if ver_num < 3500355:
# other coverage 오류 해결
curs.execute(db_change("update other set coverage = '' where coverage is null"))
ver_num = 3500355
if ver_num < 3500358:
curs.execute(db_change("drop index history_index"))
curs.execute(db_change("create index history_index on history (title, ip)"))
ver_num = 3500358
if ver_num < 3500360:
# 마지막 편집 따로 기록하도록
# create_data['data_set'] = ['doc_name', 'doc_rev', 'set_name', 'set_data']
print("Update 3500360...")
curs.execute(db_change('delete from data_set where set_name = "last_edit"'))
curs.execute(db_change("select title from data"))
db_data = curs.fetchall()
for for_a in db_data:
curs.execute(db_change("select date from history where title = ? order by date desc limit 1"), [for_a[0]])
db_data_2 = curs.fetchall()
if db_data_2:
curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'last_edit', ?)"), [for_a[0], db_data_2[0][0]])
curs.execute(db_change('delete from acl where title like "file:%" and data = "admin" and type like "decu%"'))
print("Update 3500360 complete")
ver_num = 3500360
if ver_num < 3500361:
# curs.execute(db_change('select id from user_set where name = "email" and data = ?'), [user_email])
curs.execute(db_change('select id from user_set where name = "email"'))
for db_data in curs.fetchall():
if ip_or_user(db_data[0]) == 1:
curs.execute(db_change('delete from user_set where id = ? and name = "email"'), [db_data[0]])
ver_num = 3500361
# create_data['history'] = ['id', 'title', 'data', 'date', 'ip', 'send', 'leng', 'hide', 'type']
# create_data['rc'] = ['id', 'title', 'date', 'type']
if ver_num == 3500362:
curs.execute(db_change("drop index history_index"))
curs.execute(db_change("create index history_index on history (title, ip)"))
if ver_num < 3500365:
curs.execute(db_change("update back set data = '' where data is null"))
ver_num = 3500365
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]])
ver_num = 3500371
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', '', ''])
ver_num = 3500372
if ver_num < 3500373:
select_data = {}
curs.execute(db_change("select name, id, data from user_set where name = 'application'"))
for db_data in curs.fetchall():
select_data[db_data[1]] = db_data
curs.execute(db_change("delete from user_set where name = 'application'"))
for db_data in select_data:
curs.execute(db_change("insert into user_set (id, name, data) values (?, ?, ?)"), [select_data[db_data][1], select_data[db_data][0], select_data[db_data][2]])
ver_num = 3500373
if ver_num < 3500374:
# ban 오류 해결
curs.execute(db_change("update rb set ongoing = '' where ongoing is null"))
curs.execute(db_change("update rb set login = '' where login is null"))
ver_num = 3500374
if ver_num < 3500375:
curs.execute(db_change("select title, type, user from scan"))
for for_a in curs.fetchall():
type_data = 'watchlist' if for_a[1] == '' else 'star_doc'
curs.execute(db_change("insert into user_set (id, name, data) values (?, ?, ?)"), [for_a[2], type_data, for_a[0]])
ver_num = 3500375
if ver_num < 3500376:
curs.execute(db_change("select doc_name, doc_rev from data_set where set_name = 'edit_request_data'"))
for for_a in curs.fetchall():
curs.execute(db_change("select id from history where title = ? order by id + 0 desc limit 1"), [for_a[0]])
get_data = curs.fetchall()
if get_data and (int(get_data[0][0]) + 1) == int(for_a[1]):
curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, ?, 'edit_request_doing', '1')"), [for_a[0], for_a[1]])
ver_num = 3500376
if ver_num < 3500377 and set_data['type'] == 'sqlite':
conn.execute('pragma journal_mode = delete')
ver_num = 3500377
if ver_num < 3500378:
curs.execute(db_change("select title from data where title like 'category:%' or title like 'user:%' or title like 'file:%'"))
for for_a in curs.fetchall():
mode = ''
if re.search('^user:', for_a[0]):
mode = 'user'
elif re.search('^file:', for_a[0]):
mode = 'file'
elif re.search('^category:', for_a[0]):
mode = 'category'
curs.execute(db_change('delete from data_set where doc_name = ? and set_name = "doc_type"'), [for_a[0]])
curs.execute(db_change("insert into data_set (doc_name, doc_rev, set_name, set_data) values (?, '', 'doc_type', ?)"), [for_a[0], mode])
ver_num = 3500378
if ver_num < 3500379:
curs.execute(db_change("select distinct doc_name from data_set where doc_rev = 'not_exist' or doc_rev = ''"))
for for_a in curs.fetchall():
data_set_exist = ''
curs.execute(db_change("select title from data where title = ?"), [for_a[0]])
if not curs.fetchall():
data_set_exist = 'not_exist'
curs.execute(db_change("update data_set set doc_rev = ? where doc_name = ? and (doc_rev = '' or doc_rev = 'not_exist')"), [data_set_exist, for_a[0]])
ver_num = 3500379
if ver_num < 20240513:
curs.execute(db_change("update user_set set data = '☑️' where name = 'user_title' and data = '✅'"))
ver_num = 20240513
if ver_num < 20240732:
curs.execute(db_change("select distinct name from alist where acl = 'owner'"))
for for_a in curs.fetchall():
curs.execute(db_change("select distinct id from user_set where name = 'acl' and data = ?"), [for_a[0]])
for for_b in curs.fetchall():
lang_name = 'en-US'
if lang_name == 'ko-KR':
print('메인 ACL이 권한으로 개편되면서 기존 설정 값이 날라갔으니 권한으로 재설정 해주세요.')
else:
print('As the main ACL has been reorganized into the auth, the existing setting values have been lost, so please reset it to the auth.')
ver_num = 20240732
print('Update completed')
def set_init_always(conn, ver_num, run_mode):
curs = conn.cursor()
# 버전 기입
curs.execute(db_change('delete from other where name = "ver"'))
curs.execute(db_change('insert into other (name, data, coverage) values ("ver", ?, "")'), [ver_num])
# 기본 권한 그룹 설정
curs.execute(db_change('delete from alist where name = "owner"'))
curs.execute(db_change('insert into alist (name, acl) values ("owner", "owner")'))
curs.execute(db_change("select name from alist where name = 'user' limit 1"))
if not curs.fetchall():
curs.execute(db_change('insert into alist (name, acl) values ("user", "user")'))
curs.execute(db_change("select name from alist where name = 'ip' limit 1"))
if not curs.fetchall():
curs.execute(db_change('insert into alist (name, acl) values ("ip", "ip")'))
curs.execute(db_change("select name from alist where name = 'ban' limit 1"))
if not curs.fetchall():
curs.execute(db_change('insert into alist (name, acl) values ("ban", "view")'))
# 문서 댓글용 게시판 생성
bbs_num = '0'
bbs_name = 'document_comment'
bbs_type = 'comment'
curs.execute(db_change("insert into bbs_set (set_name, set_code, set_id, set_data) values ('bbs_name', '', ?, ?)"), [bbs_num, bbs_name])
curs.execute(db_change("insert into bbs_set (set_name, set_code, set_id, set_data) values ('bbs_type', '', ?, ?)"), [bbs_num, bbs_type])
# 이미지 폴더 없으면 생성
if not os.path.exists(load_image_url(conn)):
os.makedirs(load_image_url(conn))
# 비밀키 없으면 생성
curs.execute(db_change('select data from other where name = "key"'))
if not curs.fetchall():
curs.execute(db_change('insert into other (name, data, coverage) values ("key", ?, "")'), [load_random_key()])
# 솔트키 없으면 생성
curs.execute(db_change('select data from other where name = "salt_key"'))
if not curs.fetchall():
curs.execute(db_change('insert into other (name, data, coverage) values ("salt_key", ?, "")'), [load_random_key(4)])
# 문서 전체 갯수 없으면 생성
curs.execute(db_change('select data from other where name = "count_all_title"'))
if not curs.fetchall():
curs.execute(db_change('insert into other (name, data, coverage) values ("count_all_title", "0", "")'))
# 위키 접근 비밀번호 있으면 temp DB로 넘겨줌
curs.execute(db_change('select data from other where name = "wiki_access_password_need"'))
db_data = curs.fetchall()
if db_data and db_data[0][0] != '':
curs.execute(db_change('select data from other where name = "wiki_access_password"'))
db_data = curs.fetchall()
if db_data:
global_some_set_do("wiki_access_password", db_data[0][0])
curs.execute(db_change('select data from other where name = "load_ip_select"'))
db_data = curs.fetchall()
if db_data and db_data[0][0] != '':
global_func_some_set_do("load_ip_select", db_data[0][0])
# OS마다 실행 파일 설정
exe_type = linux_exe_chmod()
if platform.system() == 'Linux' or platform.system() == 'Darwin':
os.system('chmod +x ./bin/' + exe_type)
def linux_exe_chmod():
exe_type = ''
if platform.system() == 'Linux':
if platform.machine() in ["AMD64", "x86_64"]:
exe_type = 'main.amd64.bin'
else:
exe_type = 'main.arm64.bin'
elif platform.system() == 'Darwin':
exe_type = 'main.mac.arm64.bin'
else:
if platform.machine() in ["AMD64", "x86_64"]:
exe_type = 'main.amd64.exe'
else:
exe_type = 'main.arm64.exe'
return exe_type
def set_init(conn):
curs = conn.cursor()
# 초기값 설정 함수
curs.execute(db_change("select html from html_filter where kind = 'email'"))
if not curs.fetchall():
for i in ['naver.com', 'gmail.com', 'daum.net', 'kakao.com']:
curs.execute(db_change("insert into html_filter (html, kind, plus, plus_t) values (?, 'email', '', '')"), [i])
curs.execute(db_change("select html from html_filter where kind = 'extension'"))
if not curs.fetchall():
for i in ['jpg', 'jpeg', 'png', 'gif', 'webp']:
curs.execute(db_change("insert into html_filter (html, kind, plus, plus_t) values (?, 'extension', '', '')"), [i])
curs.execute(db_change('select data from other where name = "smtp_server" or name = "smtp_port" or name = "smtp_security"'))
if not curs.fetchall():
for i in [['smtp_server', 'smtp.gmail.com'], ['smtp_port', '587'], ['smtp_security', 'starttls']]:
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():
return ['owner', 'user', 'ip', 'ban']
def get_default_robots_txt(conn):
data = '' + \
'User-agent: *\n' + \
'Disallow: /\n' + \
'Allow: /$\n' + \
'Allow: /w/\n' + \
'Allow: /bbs/w/\n' + \
'Allow: /sitemap.xml$\n' + \
'Allow: /sitemap_*.xml$' + \
''
if os.path.exists('sitemap.xml'):
data += '' + \
'\n' + \
'Sitemap: ' + load_domain(conn, 'full') + '/sitemap.xml' + \
''
return data
def load_random_key(long = 128):
return ''.join(random.choice("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") for _ in range(long))
async def http_warning():
return '''