2024-10-15 17:46:59 +00:00
import json
2024-10-09 22:44:40 +00:00
import os
2024-10-19 16:13:31 +00:00
import uuid
from flask import Flask , redirect , render_template , g , request , send_file , session , url_for
2024-10-09 22:44:40 +00:00
from pathlib import Path
2024-10-16 11:35:06 +00:00
2024-10-16 13:52:47 +00:00
from kanken_online . api import get_kanji_by_character
2024-10-16 11:35:06 +00:00
from kanken_online . database import get_database
2024-10-09 22:44:40 +00:00
from . auth import login_required
DATABASE_NAME = " kanken_online.sqlite "
2024-10-16 13:52:47 +00:00
JITEN_DB_NAME = " kanken.db "
2024-10-19 16:13:31 +00:00
PFP_DIRECTORY_NAME = " pfp "
2024-10-09 22:44:40 +00:00
def create_app ( test_config = None ) :
app = Flask ( __name__ , instance_relative_config = True )
app . config . from_mapping (
SECRET_KEY = " dev " ,
2024-10-16 13:52:47 +00:00
DATABASE = str ( Path ( app . instance_path ) / DATABASE_NAME ) ,
2024-10-19 16:13:31 +00:00
JITEN_DB = str ( Path ( app . instance_path ) / JITEN_DB_NAME ) ,
PFP_STORE = str ( Path ( app . instance_path ) / PFP_DIRECTORY_NAME )
2024-10-09 22:44:40 +00:00
)
if test_config is None :
app . config . from_pyfile ( " config.py " , silent = True )
else :
app . config . from_mapping ( test_config )
# Ensure instance path exists
os . makedirs ( app . instance_path , exist_ok = True )
@app.route ( " /hello " )
def hello ( ) :
return " Hello, World! "
@app.route ( " / " )
def index ( ) :
return render_template ( " index.html " )
2024-10-14 15:20:28 +00:00
@app.route ( " /about " )
def about_page ( ) :
return render_template ( " about.html " )
2024-10-14 16:31:07 +00:00
2024-10-19 16:13:31 +00:00
def update_settings ( form , files ) :
2024-10-16 11:35:06 +00:00
db = get_database ( )
2024-10-21 09:20:15 +00:00
# Set values in the database
settings = db . execute ( " SELECT * FROM user_settings WHERE user_id = ? " ,
( session [ " user_id " ] , )
) . fetchone ( )
if settings :
db . execute ( " UPDATE user_settings SET lang = ?, theme = ? WHERE user_id = ? " ,
( form [ " language " ] , form [ " theme " ] , session [ " user_id " ] ) )
else :
db . execute ( " INSERT INTO user_settings (user_id, lang, theme) VALUES (?, ?, ?) " ,
( session [ " user_id " ] , form [ " language " ] , form [ " theme " ] ) )
if " pfp " in files and files [ " pfp " ] . filename != " " :
stored_filename = str ( uuid . uuid4 ( ) )
pfp = files [ " pfp " ]
pfp . save ( os . path . join ( app . config [ " PFP_STORE " ] , stored_filename ) )
2024-10-16 11:35:06 +00:00
2024-10-21 09:20:35 +00:00
# Remove old PFP
2024-10-21 09:22:30 +00:00
if settings and settings [ " pfp_filename " ] :
os . remove ( os . path . join ( app . config [ " PFP_STORE " ] , settings [ " pfp_filename " ] ) )
2024-10-21 09:20:35 +00:00
2024-10-21 09:20:15 +00:00
db . execute ( " UPDATE user_settings SET pfp_filename = ? " , ( stored_filename , ) )
2024-10-19 16:13:31 +00:00
2024-10-21 09:20:15 +00:00
db . commit ( )
2024-10-19 16:13:31 +00:00
2024-10-21 09:20:15 +00:00
update_logged_out_settings ( form )
return redirect ( " /options " )
def update_logged_out_settings ( form ) :
2024-10-16 11:35:06 +00:00
# Set values directly in the session
2024-10-14 16:31:07 +00:00
session [ " language " ] = form [ " language " ]
session [ " theme " ] = form [ " theme " ]
2024-10-21 09:20:15 +00:00
return redirect ( " /public_options " )
2024-10-14 15:20:28 +00:00
2024-10-14 16:31:07 +00:00
@app.route ( " /options " , methods = [ " GET " , " POST " ] )
2024-10-09 22:44:40 +00:00
def options ( ) :
2024-10-14 16:31:07 +00:00
if request . method == " GET " :
2024-10-21 09:20:15 +00:00
if " user_id " in session :
return render_template ( " options.html " )
else :
return redirect ( " /public_options " )
2024-10-14 16:31:07 +00:00
else :
2024-10-19 16:13:31 +00:00
return update_settings ( request . form , request . files )
2024-10-14 10:07:47 +00:00
2024-10-21 09:20:15 +00:00
@app.route ( " /public_options " , methods = [ " GET " , " POST " ] )
def public_options ( ) :
if request . method == " GET " :
if " user_id " in session :
return redirect ( " /public_options " )
else :
return render_template ( " logged_out_options.html " )
else :
return update_logged_out_settings ( request . form )
2024-10-18 15:36:03 +00:00
@app.get ( " /user/<int:user_id> " )
def user_page ( user_id : int ) :
db = get_database ( )
2024-10-19 16:13:31 +00:00
( username , pfp_filename ) = db . execute ( " SELECT username, pfp_filename FROM user, user_settings WHERE user.id = ? AND user_settings.user_id = ? " , ( user_id , user_id ) ) . fetchone ( )
return render_template ( " user_page.html " , username = username , pfp_filename = os . path . join ( app . config [ " PFP_STORE " ] , pfp_filename ) )
2024-10-18 15:36:03 +00:00
@app.get ( " /me " )
@login_required
def my_page ( ) :
return user_page ( session [ " user_id " ] )
2024-10-23 20:59:09 +00:00
@app.get ( " /exam " )
def exam ( ) :
return render_template ( " exams/level1.html " )
2024-10-18 15:36:03 +00:00
2024-10-16 14:34:03 +00:00
def format_reading ( reading : str ) - > str :
""" Apply bold to the part of the reading which the kanji represents; for kun, this can be
e . g . 選 : えら - ぶ - - > < b > えら < / b > ぶ . For reading strings which don ' t have any " - " character in them,
one is added to the end and the entire reading is emboldened .
Example : 簡 : かん - - > < b > かん < / b >
"""
if " - " not in reading :
reading + = " - "
okurigana_position = reading . index ( " - " )
emboldened_part = reading [ : okurigana_position ]
return f " <b> { emboldened_part } </b> { reading [ okurigana_position + 1 : ] } "
2024-10-23 20:59:09 +00:00
2024-10-14 10:07:47 +00:00
@app.route ( " /kanji/<kanji> " )
def kanji_page ( kanji : str ) :
2024-10-16 13:52:47 +00:00
kanji_obj = get_kanji_by_character ( kanji )
2024-10-14 10:07:47 +00:00
class Kanji ( ) :
pass
2024-10-16 13:52:47 +00:00
out = Kanji ( )
out . character = kanji_obj . character
out . is_joyo = " 常用 " if kanji_obj . level not in [ " 1 " , " 準1 " ] else " 表外 "
out . level = kanji_obj . level
out . strokes = kanji_obj . stroke_count
out . radical = kanji_obj . radical
out . added_strokes = kanji_obj . radical_added_stroke_count
2024-10-16 14:34:03 +00:00
out . goon = [ format_reading ( obj . reading ) for obj in kanji_obj . goon ]
out . kanon = [ format_reading ( obj . reading ) for obj in kanji_obj . kanon ]
out . toon = [ format_reading ( obj . reading ) for obj in kanji_obj . toon ]
out . soon = [ format_reading ( obj . reading ) for obj in kanji_obj . soon ]
out . kanyoon = [ format_reading ( obj . reading ) for obj in kanji_obj . kanyoon ]
out . kun = [ format_reading ( obj . reading ) for obj in kanji_obj . kun ]
2024-10-16 13:52:47 +00:00
out . meanings = kanji_obj . meanings
out . glyph_origin = kanji_obj . glyph_origin
2024-10-14 10:07:47 +00:00
2024-10-16 13:52:47 +00:00
return render_template ( " kanji.html " , kanji = out )
2024-10-14 10:28:53 +00:00
@app.route ( " /kotoba/<kotoba> " )
def kotoba_page ( kotoba : str ) :
return render_template ( " kotoba.html " , kotoba = kotoba )
2024-10-09 22:44:40 +00:00
2024-10-15 17:46:59 +00:00
from . import database
database . initialize_app ( app )
from . import auth , api , forum , search , indices
app . register_blueprint ( auth . blueprint )
app . register_blueprint ( api . blueprint )
app . register_blueprint ( forum . blueprint )
app . register_blueprint ( search . blueprint )
app . register_blueprint ( indices . blueprint )
from . import lang
2024-10-16 10:37:52 +00:00
lang . add_translation_commands ( app )
2024-10-15 17:46:59 +00:00
2024-10-15 15:52:22 +00:00
@app.route ( " /translations " , methods = [ " GET " , " POST " ] )
def strings_translation ( ) :
if request . method == " GET " :
strings = { }
for language , language_data in lang . LANGUAGES . items ( ) :
strings [ language ] = {
string : translation for string , translation in language_data . items ( )
}
return render_template ( " translations.html " , strings = strings )
else :
2024-10-15 17:46:59 +00:00
strings = { }
for i , language in enumerate ( lang . LANGUAGES ) :
strings [ language ] = {
string : request . form . getlist ( string ) [ i ] for string in request . form
}
with open ( Path ( app . root_path , " static " , " lang " , f " { language } .json " ) , mode = " w " ) as f :
json . dump ( strings [ language ] , f , ensure_ascii = False , indent = 0 )
2024-10-15 18:17:21 +00:00
lang . update_languages ( )
2024-10-15 15:52:22 +00:00
return redirect ( " /translations " )
2024-10-19 16:13:31 +00:00
@app.get ( app . config [ " PFP_STORE " ] + " /<img> " )
def get_pfp ( img : str ) :
return send_file ( os . path . join ( app . config [ " PFP_STORE " ] , img ) )
2024-10-16 10:56:44 +00:00
@app.route ( " /data " )
def data_page ( ) :
return render_template ( " data.html " )
2024-10-14 16:31:07 +00:00
# def use_english(text_id: str):
# return lang.localize(text_id, lang.JAPANESE)
app . jinja_env . globals . update ( localize = lang . localize )
2024-10-14 10:49:16 +00:00
2024-10-09 22:44:40 +00:00
return app