2022-02-03 03:18:21 +00:00
from flask import render_template , Blueprint , redirect , url_for , request , abort , flash , make_response
2022-01-16 18:22:00 +00:00
from flask_user import login_required , current_user
import json
from datatables import ColumnDT , DataTables
import datetime , time
from app . models import CharacterInfo , CharacterXML , Account , db
from app . schemas import CharacterInfoSchema
2022-02-20 04:36:33 +00:00
from app . forms import RescueForm
2022-02-12 05:05:00 +00:00
from app import gm_level , log_audit
2022-02-20 04:36:33 +00:00
from app . luclient import translate_from_locale
2022-01-16 18:22:00 +00:00
import xmltodict
2022-02-20 04:36:33 +00:00
import xml . etree . ElementTree as ET
2022-01-16 18:22:00 +00:00
character_blueprint = Blueprint ( ' characters ' , __name__ )
character_schema = CharacterInfoSchema ( )
@character_blueprint.route ( ' / ' , methods = [ ' GET ' ] )
@login_required
@gm_level ( 3 )
def index ( ) :
return render_template ( ' character/index.html.j2 ' )
@character_blueprint.route ( ' /approve_name/<id>/<action> ' , methods = [ ' GET ' ] )
@login_required
@gm_level ( 3 )
def approve_name ( id , action ) :
character = CharacterInfo . query . filter ( CharacterInfo . id == id ) . first ( )
if action == " approve " :
2022-02-12 05:05:00 +00:00
log_audit ( f " Approved ( { character . id } ) { character . pending_name } from { character . name } " )
flash (
f " Approved ( { character . id } ) { character . pending_name } from { character . name } " ,
" success "
)
2022-01-16 18:22:00 +00:00
if character . pending_name :
character . name = character . pending_name
character . pending_name = " "
character . needs_rename = False
2022-02-12 05:05:00 +00:00
2022-01-16 18:22:00 +00:00
elif action == " rename " :
character . needs_rename = True
2022-02-12 05:05:00 +00:00
log_audit ( f " Marked character ( { character . id } ) { character . name } (Pending Name: { character . pending_name if character . pending_name else ' None ' } ) as needing Rename " )
2022-01-16 18:22:00 +00:00
flash (
f " Marked character { character . name } (Pending Name: { character . pending_name if character . pending_name else ' None ' } ) as needing Rename " ,
" danger "
)
character . save ( )
return redirect ( request . referrer if request . referrer else url_for ( " main.index " ) )
@character_blueprint.route ( ' /view/<id> ' , methods = [ ' GET ' ] )
@login_required
def view ( id ) :
character_data = CharacterInfo . query . filter ( CharacterInfo . id == id ) . first ( )
if character_data == { } :
abort ( 404 )
return
if current_user . gm_level < 3 :
if character_data . account_id and character_data . account_id != current_user . id :
abort ( 403 )
return
character_json = xmltodict . parse (
CharacterXML . query . filter (
CharacterXML . id == id
) . first ( ) . xml_data ,
attr_prefix = " attr_ "
)
# print json for reference
# with open("errorchar.json", "a") as file:
# file.write(
# json.dumps(character_json, indent=4)
# )
# stupid fix for jinja parsing
character_json [ " obj " ] [ " inv " ] [ " holdings " ] = character_json [ " obj " ] [ " inv " ] . pop ( " items " )
# sort by items slot index
for inv in character_json [ " obj " ] [ " inv " ] [ " holdings " ] [ " in " ] :
if " i " in inv . keys ( ) and type ( inv [ " i " ] ) == list :
inv [ " i " ] = sorted ( inv [ " i " ] , key = lambda i : int ( i [ ' attr_s ' ] ) )
return render_template (
' character/view.html.j2 ' ,
character_data = character_data ,
character_json = character_json
)
2022-02-03 03:18:21 +00:00
@character_blueprint.route ( ' /view_xml/<id> ' , methods = [ ' GET ' ] )
@login_required
def view_xml ( id ) :
character_data = CharacterInfo . query . filter ( CharacterInfo . id == id ) . first ( )
if character_data == { } :
abort ( 404 )
return
2022-02-20 04:36:33 +00:00
if current_user . gm_level < 3 :
if character_data . account_id and character_data . account_id != current_user . id :
abort ( 403 )
return
2022-02-03 03:18:21 +00:00
character_xml = CharacterXML . query . filter (
CharacterXML . id == id
) . first ( ) . xml_data
response = make_response ( character_xml )
response . headers . set ( ' Content-Type ' , ' text/xml ' )
return response
@character_blueprint.route ( ' /get_xml/<id> ' , methods = [ ' GET ' ] )
@login_required
def get_xml ( id ) :
character_data = CharacterInfo . query . filter ( CharacterInfo . id == id ) . first ( )
if character_data == { } :
abort ( 404 )
return
2022-02-20 04:36:33 +00:00
if current_user . gm_level < 3 :
if character_data . account_id and character_data . account_id != current_user . id :
abort ( 403 )
return
2022-02-03 03:18:21 +00:00
character_xml = CharacterXML . query . filter (
CharacterXML . id == id
) . first ( ) . xml_data
response = make_response ( character_xml )
response . headers . set ( ' Content-Type ' , ' attachment/xml ' )
response . headers . set (
' Content-Disposition ' ,
' attachment ' ,
filename = f " { character_data . name } .xml "
)
return response
2022-01-16 18:22:00 +00:00
@character_blueprint.route ( ' /restrict/<bit>/<id> ' , methods = [ ' GET ' ] )
@login_required
@gm_level ( 3 )
def restrict ( id , bit ) :
# restrict to bit 4-6
if 6 < int ( bit ) < 3 :
abort ( 403 )
return
character_data = CharacterInfo . query . filter ( CharacterInfo . id == id ) . first ( )
if character_data == { } :
abort ( 404 )
return
2022-02-12 05:05:00 +00:00
log_audit ( f " Updated ( { character_data . id } ) { character_data . name } ' s permission map to \
{ character_data . permission_map ^ ( 1 << int ( bit ) ) } from { character_data . permission_map } " )
2022-01-16 18:22:00 +00:00
character_data . permission_map ^ = ( 1 << int ( bit ) )
character_data . save ( )
return redirect ( request . referrer if request . referrer else url_for ( " main.index " ) )
2022-02-20 04:36:33 +00:00
@character_blueprint.route ( ' /rescue/<id> ' , methods = [ ' GET ' , ' POST ' ] )
@login_required
@gm_level ( 3 )
def rescue ( id ) :
form = RescueForm ( )
character_data = CharacterXML . query . filter (
CharacterXML . id == id
) . first ( )
character_xml = ET . XML ( character_data . xml_data )
for zone in character_xml . findall ( ' .//r ' ) :
if int ( zone . attrib [ " w " ] ) % 100 == 0 :
form . save_world . choices . append (
(
zone . attrib [ " w " ] ,
translate_from_locale ( f " ZoneTable_ { zone . attrib [ ' w ' ] } _DisplayDescription " )
)
)
if form . validate_on_submit ( ) :
new_zone = character_xml . find ( f ' .//r[@w= " { form . save_world . data } " ] ' )
char = character_xml . find ( " .//char " )
char . attrib [ " lzx " ] = new_zone . attrib [ " x " ]
char . attrib [ " lzy " ] = new_zone . attrib [ " y " ]
char . attrib [ " lzz " ] = new_zone . attrib [ " z " ]
2022-02-20 14:18:18 +00:00
char . attrib [ " lwid " ] = form . save_world . data
2022-02-20 04:36:33 +00:00
character_data . xml_data = ET . tostring ( character_xml )
character_data . save ( )
return redirect ( url_for ( ' characters.view ' , id = id ) )
return render_template ( " character/rescue.html.j2 " , form = form )
2022-01-16 18:22:00 +00:00
@character_blueprint.route ( ' /get/<status> ' , methods = [ ' GET ' ] )
@login_required
@gm_level ( 3 )
def get ( status ) :
columns = [
ColumnDT ( CharacterInfo . id ) , # 0
ColumnDT ( Account . username ) , # 1
ColumnDT ( CharacterInfo . name ) , # 2
ColumnDT ( CharacterInfo . pending_name ) , # 3
ColumnDT ( CharacterInfo . needs_rename ) , # 4
ColumnDT ( CharacterInfo . last_login ) , # 5
ColumnDT ( CharacterInfo . permission_map ) , # 6
]
query = None
if status == " all " :
query = db . session . query ( ) . select_from ( CharacterInfo ) . join ( Account )
elif status == " approved " :
query = db . session . query ( ) . select_from ( CharacterInfo ) . join ( Account ) . filter ( ( CharacterInfo . pending_name == " " ) & ( CharacterInfo . needs_rename == False ) )
elif status == " unapproved " :
query = db . session . query ( ) . select_from ( CharacterInfo ) . join ( Account ) . filter ( ( CharacterInfo . pending_name != " " ) | ( CharacterInfo . needs_rename == True ) )
else :
raise Exception ( " Not a valid filter " )
params = request . args . to_dict ( )
rowTable = DataTables ( params , query , columns )
data = rowTable . output_result ( )
for character in data [ " data " ] :
id = character [ " 0 " ]
character [ " 0 " ] = f """
< div class = " d-none " > { id } < / div >
< a role = " button " class = " btn btn-primary btn btn-block "
href = ' { url_for( ' characters . view ' , id=id)} ' >
View
< / a >
"""
if not character [ " 4 " ] :
character [ " 0 " ] + = f """
< a role = " button " class = " btn btn-danger btn btn-block "
href = ' { url_for( ' characters . approve_name ' , id=id, action= " rename " )} ' >
Needs Rename
< / a >
"""
if character [ " 3 " ] or character [ " 4 " ] :
character [ " 0 " ] + = f """
< a role = " button " class = " btn btn-success btn btn-block "
href = ' { url_for( ' characters . approve_name ' , id=id, action= " approve " )} ' >
Approve Name
< / a >
"""
character [ " 1 " ] = f """
< a role = " button " class = " btn btn-primary btn btn-block "
href = ' { url_for( ' accounts . view ' , id=Account.query.filter(Account.username==character[ " 1 " ]).first().id)} ' >
View { character [ " 1 " ] }
< / a >
"""
if character [ " 4 " ] :
character [ " 4 " ] = ''' <h1 class= " far fa-check-square text-danger " ></h1> '''
else :
character [ " 4 " ] = ''' <h1 class= " far fa-times-circle text-success " ></h1> '''
character [ " 5 " ] = time . ctime ( character [ " 5 " ] )
perm_map = character [ " 6 " ]
character [ " 6 " ] = " "
if perm_map & ( 1 << 4 ) :
character [ " 6 " ] + = " Restricted Trade</br> "
if perm_map & ( 1 << 5 ) :
character [ " 6 " ] + = " Restricted Mail</br> "
if perm_map & ( 1 << 6 ) :
character [ " 6 " ] + = " Restricted Chat</br> "
return data