mirror of
https://github.com/573dev/gfdm-server.git
synced 2026-08-27 04:44:24 -05:00
Start using xml templating
This commit is contained in:
@@ -2,10 +2,26 @@ from lxml.builder import E
|
||||
|
||||
from v8_server import db
|
||||
from v8_server.eamuse.services.services import ServiceRequest
|
||||
from v8_server.eamuse.utils.xml import get_xml_attrib
|
||||
from v8_server.eamuse.xml.utils import (
|
||||
drop_attributes,
|
||||
get_xml_attrib,
|
||||
load_xml_template,
|
||||
)
|
||||
from v8_server.model.user import Card, Profile, RefID, User, UserAccount
|
||||
|
||||
|
||||
class CardStatus(object):
|
||||
"""
|
||||
Possible Card Status Values
|
||||
"""
|
||||
|
||||
SUCCESS = 0
|
||||
NO_PROFILE = 109
|
||||
NOT_ALLOWED = 110
|
||||
NOT_REGISTERED = 112
|
||||
INVALID_PIN = 116
|
||||
|
||||
|
||||
class CardMng(object):
|
||||
"""
|
||||
Handle the CardMng (Card Manage) request.
|
||||
@@ -13,13 +29,6 @@ class CardMng(object):
|
||||
This is for supporting eAmuse card interaction.
|
||||
"""
|
||||
|
||||
# List of statuses we return to the game for various card related reasons
|
||||
SUCCESS = 0
|
||||
NO_PROFILE = 109
|
||||
NOT_ALLOWED = 110
|
||||
NOT_REGISTERED = 112
|
||||
INVALID_PIN = 116
|
||||
|
||||
# Methods
|
||||
INQUIRE = "inquire"
|
||||
GETREFID = "getrefid"
|
||||
@@ -31,75 +40,59 @@ class CardMng(object):
|
||||
@classmethod
|
||||
def inquire(cls, req: ServiceRequest):
|
||||
"""
|
||||
Example Request:
|
||||
<call model="K32:J:B:A:2011033000" srcid="00010203040506070809">
|
||||
<cardmng
|
||||
cardid="E0040100DE52896C"
|
||||
cardtype="1"
|
||||
method="inquire"
|
||||
update="1"
|
||||
/>
|
||||
</call>
|
||||
Handle a Card Manage Inquire Request
|
||||
|
||||
Example Response:
|
||||
<response>
|
||||
<cardmng
|
||||
refid="ADE0FE0B14AEAEFC"
|
||||
dataid="ADE0FE0B14AEAEFC"
|
||||
newflag="1"
|
||||
binded="0"
|
||||
expired="0"
|
||||
ecflag="0"
|
||||
useridflag="1"
|
||||
extidflag="1"
|
||||
/>
|
||||
</response>
|
||||
Either the given card id is a brand new user, or a returning user.
|
||||
|
||||
Modifyable XML Text Replacements:
|
||||
refid: The RefID.refid value for an existing user
|
||||
newflag: Set to true for a new user, else 0
|
||||
binded: Set to true if the user has a profile/account, else 0
|
||||
status: See CardMng status consts at the top of this class
|
||||
"""
|
||||
|
||||
# Grab the card id
|
||||
cardid = get_xml_attrib(req.xml[0], "cardid")
|
||||
|
||||
# Default result for a new unregistered user
|
||||
args = {
|
||||
"refid": "",
|
||||
"newflag": 1,
|
||||
"binded": 0,
|
||||
"status": CardStatus.NOT_REGISTERED,
|
||||
}
|
||||
|
||||
# Check if a user with this card id already exists
|
||||
user = User.from_cardid(cardid)
|
||||
|
||||
if user is None:
|
||||
# The user doesn't exist, force system to create a new account
|
||||
response = E.response(
|
||||
E.cardmng(
|
||||
{
|
||||
"newflag": "1",
|
||||
"binded": "0",
|
||||
"status": str(CardMng.NOT_REGISTERED),
|
||||
}
|
||||
)
|
||||
)
|
||||
else:
|
||||
# We have a returning user
|
||||
if user is not None:
|
||||
refid = RefID.from_userid(user.userid)
|
||||
bound = UserAccount.from_userid(user.userid) is not None
|
||||
|
||||
if refid is None:
|
||||
# TODO: better exception?
|
||||
raise Exception("RefID Should not be None here!")
|
||||
|
||||
response = E.response(
|
||||
E.cardmng(
|
||||
{
|
||||
"refid": refid.refid,
|
||||
"dataid": refid.refid,
|
||||
"newflag": "0",
|
||||
"binded": "1" if bound else "0",
|
||||
"expired": "0",
|
||||
"exflag": "0",
|
||||
"useridflag": "1",
|
||||
"extidflag": "1",
|
||||
"status": str(CardMng.SUCCESS),
|
||||
}
|
||||
)
|
||||
args["refid"] = refid.refid
|
||||
args["newflag"] = 0
|
||||
args["binded"] = bound
|
||||
args["status"] = CardStatus.SUCCESS
|
||||
|
||||
result = load_xml_template("cardmng", "inquire", args)
|
||||
|
||||
# If we have a brand new user, we can remove unnecessary xml attributes from the
|
||||
# cardmng node
|
||||
if user is None:
|
||||
drop_attributes(
|
||||
result.find("cardmng"),
|
||||
["refid", "dataid", "expired", "exflag", "useridflag", "extidflag"],
|
||||
)
|
||||
|
||||
return response
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def getrefid(cls, req: ServiceRequest):
|
||||
""""""
|
||||
# Grab the card id and pin
|
||||
cardid = get_xml_attrib(req.xml[0], "cardid")
|
||||
pin = get_xml_attrib(req.xml[0], "passwd")
|
||||
@@ -117,7 +110,7 @@ class CardMng(object):
|
||||
# Generate the refid and return it
|
||||
refid = RefID.create_with_userid(user.userid)
|
||||
|
||||
return E.response(E.cardmng({"dataid": refid.refid, "refid": refid.refid}))
|
||||
return load_xml_template("cardmng", "getrefid", {"refid": refid.refid})
|
||||
|
||||
@classmethod
|
||||
def authpass(cls, req: ServiceRequest):
|
||||
@@ -134,13 +127,9 @@ class CardMng(object):
|
||||
|
||||
# Check if the pin is valid for the user
|
||||
user = refid.user
|
||||
valid = user.pin == pin
|
||||
status = CardStatus.SUCCESS if user.pin == pin else CardStatus.INVALID_PIN
|
||||
|
||||
return E.response(
|
||||
E.cardmng(
|
||||
{"status": str(CardMng.SUCCESS if valid else CardMng.INVALID_PIN)}
|
||||
)
|
||||
)
|
||||
return load_xml_template("cardmng", "authpass", {"status": status})
|
||||
|
||||
@classmethod
|
||||
def bindmodel(cls, req: ServiceRequest):
|
||||
@@ -157,18 +146,20 @@ class CardMng(object):
|
||||
db.session.add(profile)
|
||||
db.session.commit()
|
||||
|
||||
return E.response(E.cardmng({"dataid": refid.refid}))
|
||||
return load_xml_template("cardmng", "bindmodel", {"refid": refid.refid})
|
||||
|
||||
@classmethod
|
||||
def getkeepspan(cls):
|
||||
"""
|
||||
Unclear what this method does, return an arbitrary span
|
||||
"""
|
||||
return E.response(E.cardmng({"keepspan": "30"}))
|
||||
|
||||
keepspan = 30
|
||||
return load_xml_template("cardmng", "getkeepspan", {"keepspan": keepspan})
|
||||
|
||||
@classmethod
|
||||
def getdatalist(cls):
|
||||
"""
|
||||
Unclear what this method does, return a dummy response
|
||||
"""
|
||||
return E.response(E.cardmng())
|
||||
return load_xml_template("cardmng", "cardmng")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from lxml.builder import E
|
||||
|
||||
from v8_server.eamuse.utils.xml import XMLBinTypes as T, e_type
|
||||
from v8_server.eamuse.xml.utils import XMLBinTypes as T, e_type
|
||||
|
||||
|
||||
class Facility(object):
|
||||
|
||||
@@ -7,7 +7,7 @@ from lxml.builder import E
|
||||
from v8_server import db
|
||||
from v8_server.eamuse.services.services import ServiceRequest
|
||||
from v8_server.eamuse.utils.crc import calculate_crc8
|
||||
from v8_server.eamuse.utils.xml import XMLBinTypes as T, e_type, fill, get_xml_attrib
|
||||
from v8_server.eamuse.xml.utils import XMLBinTypes as T, e_type, fill, get_xml_attrib
|
||||
from v8_server.model.song import HitChart
|
||||
from v8_server.model.user import User, UserAccount
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from lxml.builder import E
|
||||
|
||||
from v8_server.eamuse.services.services import ServiceRequest
|
||||
from v8_server.eamuse.utils.xml import get_xml_attrib
|
||||
from v8_server.eamuse.xml.utils import get_xml_attrib
|
||||
|
||||
|
||||
class Package(object):
|
||||
|
||||
@@ -18,7 +18,7 @@ from v8_server import LOG_PATH, app
|
||||
from v8_server.eamuse.utils.arc4 import EAmuseARC4
|
||||
from v8_server.eamuse.utils.eamuse import Model
|
||||
from v8_server.eamuse.utils.lz77 import Lz77
|
||||
from v8_server.eamuse.utils.xml import get_xml_attrib, get_xml_tag
|
||||
from v8_server.eamuse.xml.utils import get_xml_attrib, get_xml_tag
|
||||
|
||||
|
||||
# We want a general logger, and a special logger to log requests separately
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
from datetime import datetime
|
||||
from typing import Dict, Optional
|
||||
|
||||
from lxml import etree
|
||||
|
||||
|
||||
def fill(count: int, value: str = "0") -> str:
|
||||
return " ".join(value for _ in range(0, count))
|
||||
|
||||
|
||||
class XMLBinTypes(object):
|
||||
s8 = "s8"
|
||||
u8 = "u8"
|
||||
s16 = "s16"
|
||||
u16 = "u16"
|
||||
s32 = "s32"
|
||||
u32 = "u32"
|
||||
s64 = "s64"
|
||||
u64 = "u64"
|
||||
ip4 = "ip4"
|
||||
time = "time"
|
||||
str = "str"
|
||||
|
||||
|
||||
def e_type(_type, count: Optional[int] = None) -> Dict[str, str]:
|
||||
result = {"__type": _type}
|
||||
if count is not None:
|
||||
result["__count"] = str(count)
|
||||
return result
|
||||
|
||||
|
||||
def get_xml_tag(xml: etree) -> str:
|
||||
return str(xml.tag)
|
||||
|
||||
|
||||
def get_xml_attrib(xml: etree, name: str) -> str:
|
||||
return str(xml.attrib[name]) if name in xml.attrib else "None"
|
||||
|
||||
|
||||
def format_date(timestamp: Optional[int]) -> str:
|
||||
if timestamp is None:
|
||||
return "None"
|
||||
|
||||
dt = datetime.fromtimestamp(timestamp)
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
0
v8_server/eamuse/xml/__init__.py
Normal file
0
v8_server/eamuse/xml/__init__.py
Normal file
3
v8_server/eamuse/xml/templates/cardmng/authpass.xml
Normal file
3
v8_server/eamuse/xml/templates/cardmng/authpass.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<response>
|
||||
<cardmng status="{status}"/>
|
||||
</response>
|
||||
3
v8_server/eamuse/xml/templates/cardmng/bindmodel.xml
Normal file
3
v8_server/eamuse/xml/templates/cardmng/bindmodel.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<response>
|
||||
<cardmng dataid="{refid}"/>
|
||||
</response>
|
||||
3
v8_server/eamuse/xml/templates/cardmng/getdatalist.xml
Normal file
3
v8_server/eamuse/xml/templates/cardmng/getdatalist.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<response>
|
||||
<cardmng/>
|
||||
</response>
|
||||
3
v8_server/eamuse/xml/templates/cardmng/getkeepspan.xml
Normal file
3
v8_server/eamuse/xml/templates/cardmng/getkeepspan.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<response>
|
||||
<cardmng keepspan="{keepspan}"/>
|
||||
</response>
|
||||
3
v8_server/eamuse/xml/templates/cardmng/getrefid.xml
Normal file
3
v8_server/eamuse/xml/templates/cardmng/getrefid.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<response>
|
||||
<cardmng dataid="{refid}" refid="{refid}"/>
|
||||
</response>
|
||||
13
v8_server/eamuse/xml/templates/cardmng/inquire.xml
Normal file
13
v8_server/eamuse/xml/templates/cardmng/inquire.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<response>
|
||||
<cardmng
|
||||
refid="{refid}"
|
||||
dataid="{refid}"
|
||||
newflag="{newflag}"
|
||||
binded="{binded}"
|
||||
expired="0"
|
||||
exflag="0"
|
||||
useridflag ="1"
|
||||
extidflag="1"
|
||||
status="{status}"
|
||||
/>
|
||||
</response>
|
||||
83
v8_server/eamuse/xml/utils.py
Normal file
83
v8_server/eamuse/xml/utils.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from lxml import etree
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def load_xml_template(
|
||||
service: str, method: str, args: Optional[Dict[str, Any]], / # noqa: W504
|
||||
) -> etree:
|
||||
"""
|
||||
Given a service and a method, load the appropriate XML template and return it
|
||||
|
||||
Args:
|
||||
service (str): eAmuse Service Name
|
||||
method (str): eAmuse Method Name
|
||||
args (Dict[str, Any]): Used for formatting the xml string
|
||||
|
||||
Returns:
|
||||
etree: Resulting XML etree
|
||||
"""
|
||||
template_path = Path(__file__).parent / "templates"
|
||||
filepath = template_path / service / f"{method}.xml"
|
||||
|
||||
try:
|
||||
xml_str = filepath.open().read()
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
if args is not None:
|
||||
xml_str = xml_str.format(**args)
|
||||
|
||||
return etree.fromstring(xml_str.encode("UTF-8"))
|
||||
|
||||
|
||||
def drop_attributes(element: etree, attributes: List[str]) -> None:
|
||||
for attribute in attributes:
|
||||
element.attrib.pop(attribute)
|
||||
|
||||
|
||||
def fill(count: int, value: str = "0") -> str:
|
||||
return " ".join(value for _ in range(0, count))
|
||||
|
||||
|
||||
class XMLBinTypes(object):
|
||||
s8 = "s8"
|
||||
u8 = "u8"
|
||||
s16 = "s16"
|
||||
u16 = "u16"
|
||||
s32 = "s32"
|
||||
u32 = "u32"
|
||||
s64 = "s64"
|
||||
u64 = "u64"
|
||||
ip4 = "ip4"
|
||||
time = "time"
|
||||
str = "str"
|
||||
|
||||
|
||||
def e_type(_type, count: Optional[int] = None) -> Dict[str, str]:
|
||||
result = {"__type": _type}
|
||||
if count is not None:
|
||||
result["__count"] = str(count)
|
||||
return result
|
||||
|
||||
|
||||
def get_xml_tag(xml: etree) -> str:
|
||||
return str(xml.tag)
|
||||
|
||||
|
||||
def get_xml_attrib(xml: etree, name: str) -> str:
|
||||
return str(xml.attrib[name]) if name in xml.attrib else "None"
|
||||
|
||||
|
||||
def format_date(timestamp: Optional[int]) -> str:
|
||||
if timestamp is None:
|
||||
return "None"
|
||||
|
||||
dt = datetime.fromtimestamp(timestamp)
|
||||
return dt.strftime("%Y-%m-%d %H:%M:%S")
|
||||
Reference in New Issue
Block a user