forked from Hay1tsme/artemis
add ota update channels
This commit is contained in:
@ -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(
|
||||
@ -446,15 +446,13 @@ class AllnetServlet:
|
||||
return PlainTextResponse(content=self.enc_lite(litekey, iv, resp))
|
||||
return PlainTextResponse(resp)
|
||||
|
||||
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"
|
||||
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('.', '')}-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:
|
||||
|
42
core/data/alembic/versions/7070a6fa8cdc_update_channels.py
Normal file
42
core/data/alembic/versions/7070a6fa8cdc_update_channels.py
Normal file
@ -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 ###
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -3,13 +3,9 @@
|
||||
<script type="text/javascript">
|
||||
function swap_ota() {
|
||||
let is_cab = document.getElementById("is_cab").checked;
|
||||
let cbx_ota = document.getElementById("is_ota");
|
||||
let txt_ota = document.getElementById("ota_channel");
|
||||
|
||||
cbx_ota.disabled = !is_cab;
|
||||
|
||||
if (cbx_ota.disabled) {
|
||||
cbx_ota.checked = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<h1>Machine: {{machine.serial}}</h1>
|
||||
@ -64,8 +60,8 @@ Info
|
||||
<label for="is_cab" class="form-label">Real Cabinet</label>
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
<input type="checkbox" class="form-control-check" id="is_ota" name="is_ota" {{ 'checked' if machine.ota_enable else ''}}>
|
||||
<label for="is_ota" class="form-label">Allow OTA updates</label>
|
||||
<input type="text" class="form-control-check" id="ota_channel" name="ota_channel" value={{ machine.ota_channel }} {{ 'disabled' if not machine.is_cab else '' }}>
|
||||
<label for="ota_channel" class="form-label">OTA Update Channel</label>
|
||||
</div>
|
||||
<div class="col mb-3">
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user