diff --git a/core/allnet.py b/core/allnet.py index 43a2478..011cc74 100644 --- a/core/allnet.py +++ b/core/allnet.py @@ -435,7 +435,7 @@ class AllnetServlet: else: machine = await self.data.arcade.get_machine(req.serial) - if not machine or not machine['ota_enable'] or not machine['is_cab']: + if not machine or not machine['ota_channel'] or not machine['is_cab']: resp = urllib.parse.unquote(urllib.parse.urlencode(vars(resp))) + "\n" if is_dfi: return PlainTextResponse( @@ -445,16 +445,14 @@ class AllnetServlet: iv = bytes([random.randint(2, 255) for _ in range(16)]) return PlainTextResponse(content=self.enc_lite(litekey, iv, resp)) return PlainTextResponse(resp) + + update = await self.data.arcade.get_ota_update(req.game_id, req.ver, machine['ota_channel']) + if update: + if update['app_ini'] and path.exists(f"{self.config.allnet.update_cfg_folder}/{update['app_ini']}"): + resp.uri = f"http://{self.config.server.hostname}:{self.config.server.port}/dl/ini/{update['app_ini']}" - if path.exists( - f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver.replace('.', '')}-app.ini" - ): - resp.uri = f"http://{self.config.server.hostname}:{self.config.server.port}/dl/ini/{req.game_id}-{req.ver.replace('.', '')}-app.ini" - - if path.exists( - f"{self.config.allnet.update_cfg_folder}/{req.game_id}-{req.ver.replace('.', '')}-opt.ini" - ): - resp.uri += f"|http://{self.config.server.hostname}:{self.config.server.port}/dl/ini/{req.game_id}-{req.ver.replace('.', '')}-opt.ini" + if update['opt_ini'] and path.exists(f"{self.config.allnet.update_cfg_folder}/{update['opt_ini']}"): + resp.uri += f"|http://{self.config.server.hostname}:{self.config.server.port}/dl/ini/{update['opt_ini']}" if resp.uri: self.logger.info(f"Sending download uri {resp.uri}") @@ -496,7 +494,7 @@ class AllnetServlet: f"{self.config.allnet.update_cfg_folder}/{req_file}", "r", encoding="utf-8" ).read()) - self.logger.info(f"DL INI File {req_file} not found") + self.logger.warning(f"DL INI File {req_file} not found") return PlainTextResponse() async def handle_dlorder_report(self, request: Request) -> bytes: diff --git a/core/data/alembic/versions/7070a6fa8cdc_update_channels.py b/core/data/alembic/versions/7070a6fa8cdc_update_channels.py new file mode 100644 index 0000000..63690f5 --- /dev/null +++ b/core/data/alembic/versions/7070a6fa8cdc_update_channels.py @@ -0,0 +1,42 @@ +"""update_channels + +Revision ID: 7070a6fa8cdc +Revises: f6007bbf057d +Create Date: 2025-09-27 16:09:55.853051 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import mysql + +# revision identifiers, used by Alembic. +revision = '7070a6fa8cdc' +down_revision = 'f6007bbf057d' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('machine_update', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('game', sa.CHAR(length=4), nullable=False), + sa.Column('version', sa.VARCHAR(length=15), nullable=False), + sa.Column('channel', sa.VARCHAR(length=260), nullable=False), + sa.Column('app_ini', sa.VARCHAR(length=260), nullable=True), + sa.Column('opt_ini', sa.VARCHAR(length=260), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('game', 'version', 'channel', name='machine_update_uk'), + mysql_charset='utf8mb4' + ) + op.add_column('machine', sa.Column('ota_channel', sa.VARCHAR(length=260), nullable=True)) + op.drop_column('machine', 'ota_enable') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('machine', sa.Column('ota_enable', mysql.TINYINT(display_width=1), autoincrement=False, nullable=True)) + op.drop_column('machine', 'ota_channel') + op.drop_table('machine_update') + # ### end Alembic commands ### diff --git a/core/data/schema/arcade.py b/core/data/schema/arcade.py index 4787a5b..d587f71 100644 --- a/core/data/schema/arcade.py +++ b/core/data/schema/arcade.py @@ -7,7 +7,7 @@ from sqlalchemy.dialects.mysql import insert from sqlalchemy.engine import Row from sqlalchemy.sql import func, select from sqlalchemy.sql.schema import ForeignKey, PrimaryKeyConstraint -from sqlalchemy.types import JSON, Boolean, Integer, String, BIGINT, INTEGER, CHAR, FLOAT +from sqlalchemy.types import JSON, Boolean, Integer, String, BIGINT, INTEGER, CHAR, FLOAT, VARCHAR from core.data.schema.base import BaseData, metadata @@ -41,13 +41,26 @@ machine: Table = Table( Column("game", String(4)), Column("country", String(3)), # overwrites if not null Column("timezone", String(255)), - Column("ota_enable", Boolean), Column("memo", String(255)), Column("is_cab", Boolean), + Column("ota_channel", VARCHAR(260)), Column("data", JSON), mysql_charset="utf8mb4", ) +update: Table = Table( + "machine_update", + metadata, + Column("id", Integer, primary_key=True, nullable=False), + Column("game", CHAR(4), nullable=False), + Column("version", VARCHAR(15), nullable=False), + Column("channel", VARCHAR(260), nullable=False), + Column("app_ini", VARCHAR(260)), + Column("opt_ini", VARCHAR(260)), + UniqueConstraint("game", "version", "channel", name="machine_update_uk"), + mysql_charset="utf8mb4", +) + arcade_owner: Table = Table( "arcade_owner", metadata, @@ -250,12 +263,12 @@ class ArcadeData(BaseData): return False return True - async def set_machine_can_ota(self, machine_id: int, can_ota: bool = False) -> bool: - sql = machine.update(machine.c.id == machine_id).values(ota_enable = can_ota) + async def set_machine_ota_channel(self, machine_id: int, channel_name: Optional[str] = None) -> bool: + sql = machine.update(machine.c.id == machine_id).values(ota_channel = channel_name) result = await self.execute(sql) if result is None: - self.logger.error(f"Failed to update machine {machine_id} ota_enable to {can_ota}") + self.logger.error(f"Failed to update machine {machine_id} ota channel to {channel_name}") return False return True @@ -530,6 +543,29 @@ class ArcadeData(BaseData): if result is not None: return result.fetchone() + async def create_ota_update(self, game_id: str, ver: str, channel: str, app: Optional[str], opt: Optional[str] = None) -> Optional[int]: + result = await self.execute(insert(update).values( + game = game_id, + version = ver, + channel = channel, + app_ini = app, + opt_ini = opt + )) + + if result is None: + self.logger.error(f"Failed to create {game_id} v{ver} update on channel {channel}") + return result.lastrowid + + async def get_ota_update(self, game_id: str, ver: str, channel: str) -> Optional[Row]: + result = await self.execute(update.select(and_( + and_(update.c.game == game_id, update.c.version == ver), + update.c.channel == channel + ))) + + if result is None: + return None + return result.fetchone() + def format_serial( self, platform_code: str, platform_rev: int, serial_letter: str, serial_num: int, append: int, dash: bool = False ) -> str: diff --git a/core/frontend.py b/core/frontend.py index 47399d2..75528d9 100644 --- a/core/frontend.py +++ b/core/frontend.py @@ -1146,7 +1146,7 @@ class FE_Machine(FE_Base): new_country = frm.get('country', None) new_tz = frm.get('tz', None) new_is_cab = frm.get('is_cab', False) == 'on' - new_is_ota = frm.get('is_ota', False) == 'on' + new_ota_channel = frm.get('ota_channel', None) new_memo = frm.get('memo', None) try: @@ -1158,7 +1158,7 @@ class FE_Machine(FE_Base): did_country = await self.data.arcade.set_machine_country(cab['id'], new_country if new_country else None) did_timezone = await self.data.arcade.set_machine_timezone(cab['id'], new_tz if new_tz else None) did_real_cab = await self.data.arcade.set_machine_real_cabinet(cab['id'], new_is_cab) - did_ota = await self.data.arcade.set_machine_can_ota(cab['id'], new_is_ota) + did_ota = await self.data.arcade.set_machine_ota_channel(cab['id'], new_ota_channel if new_is_cab else None) did_memo = await self.data.arcade.set_machine_memo(cab['id'], new_memo if new_memo else None) if not did_game or not did_country or not did_timezone or not did_real_cab or not did_ota or not did_memo: diff --git a/core/templates/machine/index.jinja b/core/templates/machine/index.jinja index e9b7adb..3914c48 100644 --- a/core/templates/machine/index.jinja +++ b/core/templates/machine/index.jinja @@ -3,13 +3,9 @@

Machine: {{machine.serial}}

@@ -64,8 +60,8 @@ Info
- - + +