Initial NTE history exporter
Initial NTE history exporter Add a Windows live-capture exporter for NTE pull history with support for Permanent Monopoly, Limited Monopoly, and Arc Miracle Box histories. Included: - live packet capture via Windows raw sockets - CSV and JSON export generation - normalized reward and banner mapping files - Monopoly v7 Points Gift / Chase Reward classification - Arc Miracle Box decoding with shared pity metadata - timestamp grouping and UID generation - Windows launcher scripts with admin prompting - docs for usage, export format, limitations, and packet notes - tests covering decoder behaviour and mapping consistency Generated exports, captures, briefs, and local data are ignored for privacy.
This commit is contained in:
commit
bb3fe3b19a
35 changed files with 2439 additions and 0 deletions
57
src/nte_history_exporter/decoder/run.py
Normal file
57
src/nte_history_exporter/decoder/run.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
from nte_history_exporter.constants import POOL_META
|
||||
from nte_history_exporter.decoder.protocol import decode_response_records
|
||||
|
||||
|
||||
def fmt_packet_time(ts: float | None) -> str:
|
||||
if ts is None:
|
||||
return ""
|
||||
return datetime.fromtimestamp(ts, timezone.utc).strftime("%H:%M:%S.%f")[:-3]
|
||||
|
||||
|
||||
def build_rows_from_pairs(pairs: list[tuple]) -> list[dict[str, Any]]:
|
||||
rows_out: list[dict[str, Any]] = []
|
||||
for pair in pairs:
|
||||
page, offset, req_i, req_ts, resp_i, resp_ts, response_content = pair[:7]
|
||||
kind = pair[7] if len(pair) > 7 else "permanent"
|
||||
pool = POOL_META.get(kind, POOL_META["permanent"])
|
||||
records = decode_response_records(response_content)
|
||||
if not records:
|
||||
rows_out.append(
|
||||
{
|
||||
"page": page,
|
||||
"offset": offset,
|
||||
"row": "",
|
||||
"pool_group_id": pool["id"],
|
||||
"pool_group_name": pool["name"],
|
||||
"request_msg": req_i,
|
||||
"request_time_utc": fmt_packet_time(req_ts),
|
||||
"response_msg": resp_i,
|
||||
"response_time_utc": fmt_packet_time(resp_ts),
|
||||
"response_len": len(response_content),
|
||||
"record_count": 0,
|
||||
"record_hex": response_content.hex(),
|
||||
}
|
||||
)
|
||||
continue
|
||||
for record in records:
|
||||
rows_out.append(
|
||||
{
|
||||
"page": page,
|
||||
"offset": offset,
|
||||
"pool_group_id": pool["id"],
|
||||
"pool_group_name": pool["name"],
|
||||
"request_msg": req_i,
|
||||
"request_time_utc": fmt_packet_time(req_ts),
|
||||
"response_msg": resp_i,
|
||||
"response_time_utc": fmt_packet_time(resp_ts),
|
||||
"response_len": len(response_content),
|
||||
"record_count": len(records),
|
||||
**record,
|
||||
}
|
||||
)
|
||||
return rows_out
|
||||
Loading…
Add table
Add a link
Reference in a new issue