diff --git a/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py b/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py new file mode 100644 index 0000000..04d2217 --- /dev/null +++ b/core/data/alembic/versions/81e44dd6047a_mai2_buddies_support.py @@ -0,0 +1,68 @@ +"""mai2_buddies_support + +Revision ID: 81e44dd6047a +Revises: d8950c7ce2fc +Create Date: 2024-03-12 19:10:37.063907 + +""" + +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = "81e44dd6047a" +down_revision = "6a7e8277763b" +branch_labels = None +depends_on = None + + +def upgrade(): + op.create_table( + "mai2_playlog_2p", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user", sa.Integer(), nullable=False), + sa.Column("userId1", sa.Integer(), nullable=True), + sa.Column("userId2", sa.Integer(), nullable=True), + sa.Column("userName1", sa.String(length=25), nullable=True), + sa.Column("userName2", sa.String(length=25), nullable=True), + sa.Column("regionId", sa.Integer(), nullable=True), + sa.Column("placeId", sa.Integer(), nullable=True), + sa.Column("user2pPlaylogDetailList", sa.JSON(), nullable=True), + sa.ForeignKeyConstraint( + ["user"], ["aime_user.id"], onupdate="cascade", ondelete="cascade" + ), + sa.PrimaryKeyConstraint("id"), + mysql_charset="utf8mb4", + ) + + op.add_column( + "mai2_playlog", + sa.Column( + "extBool1", sa.Boolean(), nullable=True, server_default=sa.text("NULL") + ), + ) + + op.add_column( + "mai2_profile_detail", + sa.Column( + "renameCredit", sa.Integer(), nullable=True, server_default=sa.text("NULL") + ), + ) + op.add_column( + "mai2_profile_detail", + sa.Column( + "currentPlayCount", + sa.Integer(), + nullable=True, + server_default=sa.text("NULL"), + ), + ) + + +def downgrade(): + op.drop_table("mai2_playlog_2p") + + op.drop_column("mai2_playlog", "extBool1") + op.drop_column("mai2_profile_detail", "renameCredit") + op.drop_column("mai2_profile_detail", "currentPlayCount") diff --git a/core/data/schema/arcade.py b/core/data/schema/arcade.py index 03d0915..680f827 100644 --- a/core/data/schema/arcade.py +++ b/core/data/schema/arcade.py @@ -94,7 +94,7 @@ class ArcadeData(BaseData): return None return result.fetchone() - async def put_machine( + async def create_machine( self, arcade_id: int, serial: str = "", @@ -102,12 +102,12 @@ class ArcadeData(BaseData): game: str = None, is_cab: bool = False, ) -> Optional[int]: - if arcade_id: + if not arcade_id: self.logger.error(f"{__name__ }: Need arcade id!") return None sql = machine.insert().values( - arcade=arcade_id, keychip=serial, board=board, game=game, is_cab=is_cab + arcade=arcade_id, serial=serial, board=board, game=game, is_cab=is_cab ) result = await self.execute(sql) @@ -148,15 +148,15 @@ class ArcadeData(BaseData): return None return result.fetchall() - async def put_arcade( + async def create_arcade( self, - name: str, + name: str = None, nickname: str = None, country: str = "JPN", country_id: int = 1, state: str = "", city: str = "", - regional_id: int = 1, + region_id: int = 1, ) -> Optional[int]: if nickname is None: nickname = name @@ -168,7 +168,7 @@ class ArcadeData(BaseData): country_id=country_id, state=state, city=city, - regional_id=regional_id, + region_id=region_id, ) result = await self.execute(sql) @@ -206,8 +206,8 @@ class ArcadeData(BaseData): return None return result.lastrowid - async def format_serial( - self, platform_code: str, platform_rev: int, serial_num: int, append: int = 4152 + def format_serial( # TODO: Actual serial stuff + self, platform_code: str, platform_rev: int, serial_num: int, append: int = 8888 ) -> str: return f"{platform_code}{platform_rev:02d}A{serial_num:04d}{append:04d}" # 0x41 = A, 0x52 = R diff --git a/core/frontend.py b/core/frontend.py index 8e480b0..9a00ca5 100644 --- a/core/frontend.py +++ b/core/frontend.py @@ -10,6 +10,9 @@ import bcrypt import re import jwt import yaml +import secrets +import string +import random from base64 import b64decode from enum import Enum from datetime import datetime, timezone @@ -131,6 +134,10 @@ class FrontendServlet(): Route("/", self.system.render_GET, methods=['GET']), Route("/lookup.user", self.system.lookup_user, methods=['GET']), Route("/lookup.shop", self.system.lookup_shop, methods=['GET']), + Route("/add.user", self.system.add_user, methods=['POST']), + Route("/add.card", self.system.add_card, methods=['POST']), + Route("/add.shop", self.system.add_shop, methods=['POST']), + Route("/add.cab", self.system.add_cab, methods=['POST']), ]), Mount("/shop", routes=[ Route("/", self.arcade.render_GET, methods=['GET']), @@ -551,10 +558,16 @@ class FE_System(FE_Base): if not usr_sesh or not self.test_perm_minimum(usr_sesh.permissions, PermissionOffset.USERMOD): return RedirectResponse("/gate/", 303) + if request.query_params.get("e", None): + err = int(request.query_params.get("e")) + else: + err = 0 + return Response(template.render( title=f"{self.core_config.server.name} | System", sesh=vars(usr_sesh), usrlist=[], + error = err ), media_type="text/html; charset=utf-8") async def lookup_user(self, request: Request): @@ -661,6 +674,113 @@ class FE_System(FE_Base): shoplist=shoplist, ), media_type="text/html; charset=utf-8") + async def add_user(self, request: Request): + template = self.environment.get_template("core/templates/sys/index.jinja") + + usr_sesh = self.validate_session(request) + if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.ACMOD): + return RedirectResponse("/gate/", 303) + + frm = await request.form() + username = frm.get("userName", None) + email = frm.get("userEmail", None) + perm = frm.get("usrPerm", "1") + passwd = "".join( + secrets.choice(string.ascii_letters + string.digits) for i in range(20) + ) + hash = bcrypt.hashpw(passwd.encode(), bcrypt.gensalt()) + + if not email: + return RedirectResponse("/sys/?e=4", 303) + + uid = await self.data.user.create_user(username=username if username else None, email=email, password=hash.decode(), permission=int(perm)) + return Response(template.render( + title=f"{self.core_config.server.name} | System", + sesh=vars(usr_sesh), + usradd={"id": uid, "username": username, "password": passwd}, + ), media_type="text/html; charset=utf-8") + + async def add_card(self, request: Request): + template = self.environment.get_template("core/templates/sys/index.jinja") + + usr_sesh = self.validate_session(request) + if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.ACMOD): + return RedirectResponse("/gate/", 303) + + frm = await request.form() + userid = frm.get("cardUsr", None) + access_code = frm.get("cardAc", None) + idm = frm.get("cardIdm", None) + + if userid is None or access_code is None or not userid.isdigit() or not len(access_code) == 20 or not access_code.isdigit: + return RedirectResponse("/sys/?e=4", 303) + + cardid = await self.data.card.create_card(int(userid), access_code) + if not cardid: + return RedirectResponse("/sys/?e=99", 303) + + if idm is not None: + # TODO: save IDM + pass + + return Response(template.render( + title=f"{self.core_config.server.name} | System", + sesh=vars(usr_sesh), + cardadd={"id": cardid, "user": userid, "access_code": access_code}, + ), media_type="text/html; charset=utf-8") + + async def add_shop(self, request: Request): + template = self.environment.get_template("core/templates/sys/index.jinja") + + usr_sesh = self.validate_session(request) + if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.ACMOD): + return RedirectResponse("/gate/", 303) + + frm = await request.form() + name = frm.get("shopName", None) + country = frm.get("shopCountry", "JPN") + ip = frm.get("shopIp", None) + + acid = await self.data.arcade.create_arcade(name if name else None, name if name else None, country) + if not acid: + return RedirectResponse("/sys/?e=99", 303) + + if ip: + # TODO: set IP + pass + + return Response(template.render( + title=f"{self.core_config.server.name} | System", + sesh=vars(usr_sesh), + shopadd={"id": acid}, + ), media_type="text/html; charset=utf-8") + + async def add_cab(self, request: Request): + template = self.environment.get_template("core/templates/sys/index.jinja") + + usr_sesh = self.validate_session(request) + if not usr_sesh or not self.test_perm(usr_sesh.permissions, PermissionOffset.ACMOD): + return RedirectResponse("/gate/", 303) + + frm = await request.form() + shopid = frm.get("cabShop", None) + serial = frm.get("cabSerial", None) + game_code = frm.get("cabGame", None) + + if not shopid or not shopid.isdigit(): + return RedirectResponse("/sys/?e=4", 303) + + if not serial: + serial = self.data.arcade.format_serial("A69E", 1, random.randint(1, 9999)) + + cab_id = await self.data.arcade.create_machine(int(shopid), serial, None, game_code if game_code else None) + + return Response(template.render( + title=f"{self.core_config.server.name} | System", + sesh=vars(usr_sesh), + cabadd={"id": cab_id, "serial": serial}, + ), media_type="text/html; charset=utf-8") + class FE_Arcade(FE_Base): async def render_GET(self, request: Request): template = self.environment.get_template("core/templates/arcade/index.jinja") diff --git a/core/templates/arcade/index.jinja b/core/templates/arcade/index.jinja index 1de4301..393443a 100644 --- a/core/templates/arcade/index.jinja +++ b/core/templates/arcade/index.jinja @@ -10,7 +10,7 @@ Cab added successfully {% endif %}
Added user {{ usradd.username if usradd.username is not none else "with no name"}} with id {{usradd.id}} and password {{ usradd.password }}+ {% endif %} +
Added {{ cardadd.access_code }} with id {{cardadd.id}} to user {{ cardadd.user }}+ {% endif %} +
Added Shop {{ shopadd.id }}+ {% endif %} +
Added Machine {{ cabadd.id }} with serial {{ cabadd.serial }}+ {% endif %} +