main.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. #codec=utf-8
  2. import pages
  3. import sqlite3
  4. from bottle import route, run, static_file, abort, post, response, request, redirect, error
  5. from random import choice
  6. from json import load, dump
  7. from sys import argv
  8. from os import path, mkdir, listdir, remove, rmdir
  9. from zipfile import ZipFile, BadZipFile
  10. from hashlib import sha3_256 as sha3
  11. ADMIN_KEY = ''
  12. MAIN_TYPE = 0
  13. db = ''
  14. sql_search = ('chars', 'genres', 'series', 'comands')
  15. def hash(text):
  16. return sha3(str(text).encode('utf-8')).hexdigest()
  17. def get_path(file):
  18. return path.join(path.dirname(path.abspath(__file__)), argv[1], file)
  19. def _optimize(text):
  20. return text.replace('\n', '').replace('\t', '')
  21. def prepare_main(text, header=''):
  22. return _optimize(pages.main_page.format(header+text))
  23. def prepare_err(text, ico):
  24. return _optimize(pages.main_page.format(pages.error.format(text, ico)))
  25. def db_work(func):
  26. def wrap(*a, **ka):
  27. cursor = db.cursor()
  28. ret = func(*a, cursor=cursor, **ka)
  29. cursor.close()
  30. return ret
  31. return wrap
  32. def login(func):
  33. def wrap(*a, **ka):
  34. session = get_session(request)
  35. if session:
  36. return func(*a, session=session, **ka)
  37. redirect('/')
  38. return wrap
  39. def red(cursor, redir):
  40. cursor.close()
  41. redirect(redir)
  42. def ab(cursor, ab):
  43. cursor.close()
  44. abort(ab)
  45. @db_work
  46. def get_session(request, cursor):
  47. """
  48. return session data or None
  49. """
  50. if request.get_cookie('auth') and request.get_cookie('id_auth'):
  51. cursor.execute('select * from session where id=?;', (request.get_cookie('id_auth'), ))
  52. res = cursor.fetchone()
  53. if res is not None:
  54. ip = request['REMOTE_ADDR']
  55. agent = request.headers.get('User-Agent')
  56. if ip == res[2] and agent == res[3] and request.get_cookie('auth') == res[4]:
  57. return res
  58. return None
  59. @db_work
  60. def is_admin(session, cursor):
  61. if session is None:
  62. return False
  63. cursor.execute('select * from admin where id_user=?;', (session[1], ))
  64. return cursor.fetchone() is not None
  65. @db_work
  66. def is_access(manga_id, session, cursor):
  67. return is_admin(session) or cursor.execute('select * from hentai_user where id_hentai=? and id_user=?;', (manga_id, session[1])).fetchone() is not None
  68. def get_header(c_request):
  69. """
  70. Check admin mode status and generate header
  71. :param c_request: gotted request
  72. """
  73. session = get_session(c_request)
  74. if session:
  75. if is_admin(session):###
  76. header = pages.header.format(pages.add_manga_button + pages.admin_button + pages.exit_button)
  77. header += pages.admin_yes.format(choice(listdir('static/admin')))
  78. else:
  79. header = pages.header.format(pages.add_manga_button + pages.exit_button)
  80. else:
  81. header = pages.header.format('')#Дописати кнопку увійти
  82. return header
  83. def get_flag(id):
  84. cursor = db.cursor()
  85. flag = ''
  86. if cursor.execute('select * from lang where id_hentai=?;', (id, )).fetchone() is not None:
  87. flag = pages.flag_ua
  88. cursor.close()
  89. return flag
  90. def get_wall(dir):
  91. try:
  92. return '/hentai/{}/{}'.format(dir, sorted(listdir(path.join(get_path('hentai'), dir)))[0])
  93. except (IndexError, FileNotFoundError):
  94. return '/static/ico/U_logo.svg'
  95. @route('/sitemap.xml')
  96. def sitemap():
  97. return static_file("sitemap.xml", argv[1])
  98. @route('/robots.txt')
  99. def sitemap():
  100. return static_file("robots.txt", argv[1])
  101. @route('/static/css/<file:re:.*css>')
  102. def load_static(file):
  103. with open(path.join(path.dirname(path.abspath(__file__)), 'static', 'css', file), encoding='utf-8') as fd:
  104. return _optimize(fd.read())
  105. abort(404)
  106. @route('/static/<file:path>')
  107. def load_static(file):
  108. return static_file(file, 'static')
  109. @route('/hentai/<file:path>')
  110. def load_hentai(file):
  111. return static_file(file, get_path('hentai'), 'image/jpg')
  112. @db_work
  113. def get_manga(sql, param='', cursor=''):
  114. """
  115. :param sql: sql query to get id, name, dir
  116. :param param: tuple param to sql
  117. """
  118. if cursor == '':
  119. abort(500)
  120. ind = cursor.execute(sql, param).fetchall()
  121. content = '<div class="wrap container">'
  122. if len(ind) > 0:
  123. for row in ind:
  124. content += '''<div class="block">
  125. {}<a href=/manga/{}>
  126. <img class="block__img" src="{}">
  127. <div class="font block__title">{}</div></a>
  128. </div>'''.format(get_flag(row[0]), row[0], get_wall(row[2]), row[1])
  129. else:
  130. content += '<img src="/static/ico/MNF.png"><br><div class="font">Схоже, що мальописи відсутні</div>'
  131. content += '</div>'
  132. return content
  133. @route('/')
  134. def index():
  135. if MAIN_TYPE == 0:
  136. return prepare_main(get_manga('select * from last_series;'), get_header(request))
  137. else:
  138. return prepare_main(get_manga('select * from last_hentai;'), get_header(request))
  139. @route('/all')
  140. def all():
  141. return prepare_main(get_manga('select * from last_hentai;'), get_header(request))
  142. @route('/search/series/<id:int>')
  143. @db_work
  144. def search_engine(id, cursor):
  145. cursor.execute('select id_hentai from hentai_series where id_series=? order by id_hentai;', (id,))
  146. red(cursor, '/manga/{}'.format(cursor.fetchone()[0]))
  147. @route('/search/<type>/<id:int>')
  148. def search_engine(type, id):
  149. if type in sql_search:
  150. return prepare_main(
  151. get_manga(
  152. 'select id,name,dir from hentai,hentai_' + type + ' where id_hentai=id and id_' + type + '=?;',
  153. (id, )),
  154. get_header(request))
  155. else:
  156. abort(404)
  157. @route('/list/<type>')
  158. @db_work
  159. def genres_list(type, cursor):
  160. if type in sql_search:
  161. genres = cursor.execute('SELECT * from ' + type + ';').fetchall()
  162. genres.sort(key = lambda el: el[1])
  163. content = '<div class="search wrap container">'
  164. current_symbol = genres[0][1][0]
  165. content += pages.genre_group.format(current_symbol, current_symbol.upper())
  166. symbols = [current_symbol]
  167. for g_id, name in genres:
  168. if name[0] != current_symbol:
  169. current_symbol = name[0]
  170. content += '</div>' + pages.genre_group.format(current_symbol, current_symbol.upper())
  171. symbols += current_symbol
  172. content += pages.genre_button.format(type, g_id, name)
  173. content += '</div></div><div class="bottom-bar">'
  174. for i in symbols:
  175. content += pages.bottom_bar_symbol.format(i, i.upper())
  176. content += '</div>'
  177. return prepare_main(content, get_header(request))
  178. else:
  179. ab(cursor, 404)
  180. @route('/lang/<id:int>')
  181. def lang(id):
  182. return prepare_main(
  183. get_manga('select id, name, dir from hentai, lang where id_hentai = id;'),
  184. get_header(request))
  185. @route('/manga/<id:int>')
  186. @db_work
  187. def manga(id, cursor):
  188. cursor.execute('select name, dir from hentai where id=?;', (id,))
  189. res = cursor.fetchone()
  190. if res is not None:
  191. disc_content = ''
  192. info = ('Персонажі', 'Жанри', 'Серія мальописів', 'Переклали')
  193. for i in range(len(info)):
  194. genres = cursor.execute(
  195. 'select id_{0} from hentai_{0} where id_hentai=?;'.format(sql_search[i]), (id,)
  196. ).fetchall()
  197. if len(genres) > 0:
  198. disc_content += '<div class="font manga__font">{}</div>'.format(info[i])
  199. for genre in genres:
  200. cursor.execute('select id,name from {} where id=?;'.format(sql_search[i]), (genre[0],))
  201. genre_info = cursor.fetchone()
  202. disc_content += pages.genre_button.format(sql_search[i], genre_info[0], genre_info[1])
  203. controler = '<div class="manga__bottom-button"><a class="font big-font button manga__button" href="/show/{0}/0">Читати немов книгу</a>'\
  204. '<a class="font big-font button manga__button" href="/show/{0}">Читати немов сувій</a></div>'.format(id)
  205. cursor.execute('select id_series from hentai_series where id_hentai=?;', (id,))
  206. id_series = cursor.fetchone()
  207. if id_series:
  208. cursor.execute('select id_hentai, name, dir from hentai_series,hentai where id_series=? and id_hentai=id;', id_series)
  209. controler += '<ul class="font manga-list list">'
  210. mangas = cursor.fetchall()
  211. for i in mangas:
  212. controler += '<li><a class="list__link" href="/manga/{}">{}</a></li>'.format(i[0], i[1])
  213. controler += '</ul>'
  214. content = pages.manga.format(res[0], get_flag(id), id,
  215. get_wall(res[1]),
  216. disc_content, controler)
  217. #ADMIN MENU
  218. session = get_session(request)
  219. if session:
  220. if is_access(id, session):
  221. content += '<div>'
  222. for type, type_name in zip(sql_search, ('персонажа', 'жанр', 'серію', 'команду')):
  223. content += '<div class="list-block">' \
  224. '<form class="list" method="post" action="/a_add/' + type + '">' \
  225. '<input type="hidden" name="id" value={}>' \
  226. '<div class="font">Додати {}</div>' \
  227. '<select multiple class="font list__select" name="'.format(id, type_name) + type + '">'
  228. genres = cursor.execute('select id_' + type + ' from hentai_' + type + ' where id_hentai={};'.format(id)).fetchall()
  229. genres_full = cursor.execute('select id, name from ' + type + ' order by name;').fetchall()
  230. genres_exclude = [i for i in genres_full if (i[0],) not in genres]
  231. genres_x = [i for i in genres_full if (i[0],) in genres]
  232. for genre_i in genres_exclude:
  233. content += '<option value="{}">{}</option>'.format(genre_i[0], genre_i[1])
  234. content += '</select><br><button class="font button"' \
  235. 'type="submit">Додати</button></form>' \
  236. '<form class="list" method="post" action="/a_del/' + type + '">' \
  237. '<input type="hidden" name=id value={}>' \
  238. '<div class="font">Видалити {}</div>' \
  239. '<select multiple class="font list__select" name="'.format(id, type_name) + type + '">'
  240. for genre_i in genres_x:
  241. content += '<option value="{}">{}</option>'.format(genre_i[0], genre_i[1])
  242. content += '</select><br><button class="font button"'\
  243. ' type="submit">Видалити</button></form></div>'
  244. content += pages.u_manga_edit.format(id)
  245. content += '</div>'
  246. content += '</div>'
  247. return prepare_main(content, get_header(request))
  248. @route('/show/<id:int>')
  249. @db_work
  250. def show(id, cursor):
  251. dir = cursor.execute('select dir from hentai where id=?;', (id, )).fetchone()[0]
  252. content = ''
  253. for img in sorted(listdir(path.join(get_path('hentai'), dir))):
  254. content += '<img class="show__img" src="/hentai/' + dir + '/' + img + '"><br>'
  255. return prepare_main(pages.show.format(id, content))
  256. @route('/show/<id:int>/<page:int>')
  257. @db_work
  258. def show(id, page, cursor):
  259. dir = cursor.execute('select dir from hentai where id=?;', (id, )).fetchone()[0]
  260. l_manga = len(listdir(path.join(get_path('hentai'), dir)))
  261. if l_manga <= page or 0 > page:
  262. ab(cursor, 404)
  263. elif l_manga <= page+1:
  264. content = pages.show_book.format('/manga/'+str(id), dir, sorted(listdir(path.join(get_path('hentai'), dir)))[page])
  265. else:
  266. content = pages.show_book.format('/show/'+str(id)+'/'+str(page+1), dir, sorted(listdir(path.join(get_path('hentai'), dir)))[page])
  267. args = [id, '', '/show/'+str(id)+'/0', '/show/'+str(id)+'/'+str(page-1), page + 1, l_manga, '',
  268. '/show/'+str(id)+'/'+str(l_manga - 1), '/show/'+str(id)+'/'+str(page+1)]
  269. if page == 0:
  270. args[1], args[6] = 'hidden', 'visible'
  271. elif page == l_manga - 1:
  272. args[1], args[6] = 'visible', 'hidden'
  273. else:
  274. args[1], args[6] = 'visible', 'visible'
  275. content += pages.page_scroll.format(*args)
  276. return prepare_main(content)
  277. @route('/a')
  278. @db_work
  279. @login
  280. def admin(cursor, session):
  281. if is_admin(session):###
  282. el_list = ''
  283. for el, eln in zip(sql_search, ('персонажа', 'жанр', 'серію', 'команду')):
  284. op_list = ''
  285. for op in cursor.execute('select * from ' + el + ' order by name;').fetchall():
  286. op_list += '<option class="font" value="{}">{}</option>'.format(op[0], op[1])
  287. el_list += pages.admin_mode_el.format(el, eln, op_list)
  288. return prepare_main(pages.admin_mode.format(el_list), get_header(request))
  289. else:
  290. ab(cursor, 401)
  291. def admin_test(func):
  292. def wrap(*a, **ka):
  293. if is_admin(get_session(request)):
  294. try:
  295. return func(*a, **ka)
  296. except KeyError:
  297. abort(404)
  298. else:
  299. abort(401)
  300. return wrap
  301. @route('/a_manga')
  302. def add_manga():
  303. if get_session(request):
  304. return prepare_main(pages.add_manga, get_header(request))
  305. else:
  306. return prepare_main(pages.admin_mode.format('Для заливання манґи, будь ласка, зареєструйтесь'), get_header(request))
  307. @post('/a_manga')
  308. @db_work
  309. @login
  310. def p_add_manga(cursor, session):
  311. name = request.forms.get('dir')
  312. dir = name.replace('.', '').replace('/', '').replace('\\', '')
  313. if path.exists(get_path(path.join('hentai/', dir))):
  314. suffix=0
  315. while path.exists(get_path(path.join('hentai/', dir + '-' + str(suffix)))):
  316. suffix += 1
  317. dir += '-' + str(suffix)
  318. zip = request.files.get('zip')
  319. file, ext = path.splitext(zip.filename)
  320. if ext.lower() != '.zip':
  321. return 'То людина чи компутор? Я тобі кажу zip мені кидай'
  322. real_dir = get_path(path.join('hentai/', dir))
  323. mkdir(real_dir)
  324. zip.save(real_dir)
  325. try:
  326. with ZipFile(path.join(real_dir, zip.filename)) as file:
  327. file.extractall(real_dir)
  328. except BadZipFile:
  329. remove(path.join(real_dir, zip.filename))
  330. rmdir(real_dir)
  331. return 'Поганий файл, йолопе'
  332. remove(path.join(real_dir, zip.filename))
  333. cursor.execute('insert into hentai values (null, ?, ?);', (name, dir))
  334. hentai_id = cursor.execute('select id from hentai where dir=?;', (dir, )).fetchone()[0]
  335. cursor.execute('insert into hentai_user values (?, ?);', (hentai_id, session[1]))
  336. db.commit()
  337. red(cursor, '/all')
  338. @post('/c_file/<id:int>')
  339. @login
  340. @db_work
  341. def c_file(id, cursor, session):
  342. if is_access(id, session):
  343. zip = request.files.zip
  344. file, ext = path.splitext(zip.filename)
  345. if ext.lower() != '.zip':
  346. return 'То людина чи компутор? Я тобі кажу zip мені кидай'
  347. dir = cursor.execute('select dir from hentai where id=?;', (id,)).fetchone()[0]
  348. dir = path.join(get_path('hentai'), dir)
  349. for i in listdir(dir):
  350. remove(path.join(dir, i))
  351. zip.save(dir)
  352. try:
  353. with ZipFile(path.join(dir, zip.filename)) as file:
  354. file.extractall(dir)
  355. except BadZipFile:
  356. remove(path.join(dir, zip.filename))
  357. rmdir(dir)
  358. return 'Поганий файл, йолопе'
  359. remove(path.join(dir, zip.filename))
  360. red(cursor, '/manga/' + str(id))
  361. else:
  362. ab(cursor, 401)
  363. @post('/c_name/<id:int>')
  364. @login
  365. @db_work
  366. def c_name(id, cursor, session):
  367. if is_access(id, session):
  368. name = request.forms.name
  369. cursor.execute('update hentai set name=? where id=?;', (name, id))
  370. db.commit()
  371. red(cursor, '/manga/' + str(id))
  372. @post('/show/<id:int>/<page:int>')
  373. @db_work
  374. def show_post(id, page, cursor):
  375. dir = cursor.execute('select dir from hentai where id=?;', (id, )).fetchone()[0]
  376. cursor.close()
  377. hentai = len(listdir(path.join(get_path('hentai'), dir)))
  378. try:
  379. new_page = int(request.forms.page) - 1
  380. if new_page < 0 or new_page >= hentai:
  381. redirect(request.url)
  382. else: redirect('/show/{}/{}'.format(dict(request.url_args)['id'], new_page))
  383. except ValueError: redirect(request.url)
  384. @post('/a_add/<type>')
  385. @db_work
  386. @login
  387. def admin_add(type, cursor, session):
  388. if is_access(request.POST['id'], session):
  389. if type in sql_search:
  390. for genre in request.forms.getall(type):
  391. cursor.execute('insert into hentai_' + type + ' values(?, ?);',
  392. (request.POST['id'], genre))
  393. db.commit()
  394. red(cursor, '/manga/{}'.format(request.POST['id']))
  395. else:
  396. ab(cursor, 401)
  397. @post('/a_del/<type>')
  398. @db_work
  399. @login
  400. def admin_del(cursor, type, session):
  401. if is_access(request.POST['id'], session):
  402. if type in sql_search:
  403. for genre in request.forms.getall(type):
  404. cursor.execute('delete from hentai_' + type + ' where id_hentai=? '
  405. 'and id_' + type + '=?;', (request.POST['id'], genre))
  406. db.commit()
  407. red(cursor, '/manga/{}'.format(request.POST['id']))
  408. else:
  409. cursor.close()
  410. ab(cursor, 401)
  411. @post('/a_a/<type>')
  412. @db_work
  413. @admin_test
  414. def admin_add_tag(type, cursor):
  415. if type in sql_search:
  416. cursor.execute('insert into ' + type + ' values(null, ?);',
  417. (request.forms.name, ))
  418. db.commit()
  419. red(cursor, '/a')
  420. @post('/a_d/<type>')
  421. @db_work
  422. @admin_test
  423. def admin_add_tag(type, cursor):
  424. if type in sql_search:
  425. for i in request.forms.getall('el'):
  426. cursor.execute('delete from ' + type + ' where id=?;', (i, ))
  427. db.commit()
  428. red(cursor, '/a')
  429. @route('/about')
  430. def about():
  431. return prepare_main(pages.about, get_header(request))
  432. @route('/friend')
  433. def friend():
  434. return prepare_main(pages.friend, get_header(request))
  435. @route('/login')
  436. def g_login():
  437. session = get_session(request)
  438. if session:
  439. redirect('/')
  440. else:
  441. err = ('Немає такого користувача', 'Неправильний пароль')
  442. try:
  443. err_num = int(request.query.err)
  444. if err_num >= 0 and err_num < len(err):
  445. return prepare_main(pages.login.format(pages.error_head.format(err[err_num])), get_header(request))
  446. except ValueError:
  447. pass
  448. return prepare_main(pages.login.format(''), get_header(request))
  449. @post('/login')
  450. @db_work
  451. def p_index(cursor):
  452. cursor.execute('select pass from user where id=?;', (request.forms.get('login'),))
  453. res = cursor.fetchone()
  454. if res is None:
  455. red(cursor, '/login?err=0')
  456. else:
  457. if hash(request.forms.get('pass')) == res[0]:
  458. ip = request['REMOTE_ADDR']
  459. agent = request.headers.get('User-Agent')
  460. _hash = hash(hash(hash(request.forms.get('pass'))+ip)+agent)
  461. cursor.execute('insert into session values(null, ?, ?, ?, ?);', (request.forms.get('login'), ip, agent, _hash))
  462. db.commit()
  463. cursor.execute('select id from session where id_user=? and ip=? and agent=?;', (request.forms.get('login'), ip, agent))
  464. response.set_cookie('auth', _hash, max_age=432000)
  465. response.set_cookie('id_auth', str(cursor.fetchone()[0]), max_age=432000)
  466. else:
  467. red(cursor, '/login?err=1')
  468. red(cursor, '/login')
  469. @route('/exit')
  470. @db_work
  471. @login
  472. def exit(cursor, session):
  473. response.set_cookie('auth', '')
  474. response.set_cookie('id_auth', '')
  475. cursor.execute('delete from session where id=?;', (session[0],))
  476. db.commit()
  477. red(cursor, '/')
  478. @error(404)
  479. def err404(err):
  480. return prepare_err('Як ти сюди потрапив?', '404.png')
  481. @error(500)
  482. def err500(err):
  483. return prepare_err('Або ти лізеж куди не треба, або у нас '
  484. 'полетіла БД. І якщо це так — то пізно срати. '
  485. 'Може полагодим скоро, може ні', '500.png')
  486. @error(401)
  487. def err401(err):
  488. return prepare_err('У тебе немає доступу до цього.'
  489. ' Йди-но звідси доки не втрапив у халепу', '401.png')
  490. if __name__ == '__main__':
  491. if len(argv) <= 0:
  492. print('Specify work dir')
  493. exit(1)
  494. db = sqlite3.connect(get_path('db'))
  495. db.execute('pragma foreign_keys = 1')
  496. SETTING = None
  497. try:
  498. with open(get_path('conf.json'), 'r') as fd:
  499. SETTING = load(fd)
  500. except FileNotFoundError:
  501. print('Config not found! Creating template...')
  502. SETTING = {'ADMIN_KEY': '', 'ADMIN_MODE': False, 'RELOAD': False, 'QUITE': True, 'IP': '127.0.0.1', 'SRV': 'wsgiref', 'PORT': 80, 'SSL': '', 'MAIN_TYPE': 0}
  503. with open(get_path('conf.json'), 'w') as fd:
  504. dump(SETTING, fd)
  505. print('Template was created')
  506. print('RL:{} QT:{} AM:{}'.format(SETTING['RELOAD'], SETTING['QUITE'], SETTING['ADMIN_MODE']))
  507. MAIN_TYPE = SETTING['MAIN_TYPE']
  508. print('Admin key is: {}'.format(SETTING['ADMIN_KEY']))
  509. ADMIN_KEY = SETTING['ADMIN_KEY']
  510. try:
  511. if SETTING['SRV'] == 'gevent':
  512. from gevent import monkey; monkey.patch_all()
  513. run(server=SETTING['SRV'], host=SETTING['IP'],
  514. port=SETTING['PORT'], quiet=SETTING['QUITE'],
  515. reloader=SETTING['RELOAD'],
  516. keyfile=SETTING['SSL']+'privkey.pem',
  517. certfile=SETTING['SSL']+'fullchain.pem')
  518. else:
  519. run(server=SETTING['SRV'], host=SETTING['IP'], port=SETTING['PORT'], quiet=SETTING['QUITE'], reloader=SETTING['RELOAD'])
  520. except BrokenPipeError:
  521. print('Someone disconect!')