Capture Steam Machine launch watch baseline

This commit is contained in:
seanbetts committed 2026-06-22 18:13:56 +01:00
1 parent dab6f8b6d0
commit ed9f4500a2
23 files changed
+1926 -82

No files matched your search

+16 -1
View File
@@ -33,11 +33,14 @@ looks_like_importinfo_shipment_table() {
looks_like_importgenius_shipment_page() {
path=$1
for marker in "Bill of Lading" "GAME CONSOLE" "VALVE CORPORATION"; do
for marker in "Bill of Lading" "VALVE CORPORATION"; do
if ! grep -qi "$marker" "$path"; then
return 1
fi
done
if ! grep -Eqi "GAME CONSOLE|VIRTUAL REALITY|WIRELESS PC CONTROLLER|VR CONTROLLER|HEADSET" "$path"; then
return 1
fi
return 0
}
@@ -123,6 +126,18 @@ fetch_importgenius \
"importgenius-ingram-valve" \
"importgenius-ingram-valve" \
"https://www.importgenius.com/importers/ingram-micro-c-o-valve-corporation" || true
fetch_importgenius \
"importgenius-ceva-valve" \
"importgenius-ceva-valve" \
"https://www.importgenius.com/importers/ceva-c-o-valve-corporation" || true
fetch_importgenius \
"importgenius-ceva-nl-valve" \
"importgenius-ceva-nl-valve" \
"https://www.importgenius.com/importers/ceva-nl-c-o-valve-corporation" || true
fetch_importgenius \
"importgenius-valve-corp" \
"importgenius-valve-corp" \
"https://www.importgenius.com/importers/valve-corp" || true
python3 "$SCRIPT_DIR/parse_importinfo_shipments.py" \
--manifest "$MANIFEST" \
+105 -7
View File
@@ -33,8 +33,71 @@ load_local_env() {
fi
}
configure_playwright_runtime() {
NODE_BIN="${NODE_BIN:-}"
if [ -z "$NODE_BIN" ]; then
NODE_BIN="$(command -v node 2>/dev/null || true)"
fi
bundled_node="$HOME/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node"
if [ -z "$NODE_BIN" ] && [ -x "$bundled_node" ]; then
NODE_BIN="$bundled_node"
fi
export NODE_BIN
if [ -z "${NODE_PATH:-}" ]; then
for node_modules in \
"$REPO_DIR/node_modules" \
"$HOME/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules"
do
if [ -d "$node_modules" ]; then
NODE_PATH="$node_modules"
export NODE_PATH
break
fi
done
fi
}
cdp_endpoint_alive() {
endpoint="${PLAYWRIGHT_CDP_ENDPOINT:-}"
if [ -z "$endpoint" ]; then
return 1
fi
curl --max-time 2 -fsS "$endpoint/json/version" >/dev/null 2>&1
}
KOMODO_BOOTSTRAP_ATTEMPTED=0
bootstrap_dedicated_browser() {
if [ "${KOMODO_PLAYWRIGHT_FALLBACK:-0}" != "1" ] || [ "${KOMODO_AUTO_BOOTSTRAP:-1}" = "0" ]; then
return 0
fi
if [ "$KOMODO_BOOTSTRAP_ATTEMPTED" = "1" ]; then
return 0
fi
KOMODO_BOOTSTRAP_ATTEMPTED=1
bootstrap_cmd="${KOMODO_BOOTSTRAP_CMD:-$SCRIPT_DIR/bootstrap_komodo.sh}"
if [ ! -x "$bootstrap_cmd" ]; then
printf '%s\n' "Komodo bootstrap command not executable: $bootstrap_cmd" >> "$ERROR_FILE"
return 0
fi
if "$bootstrap_cmd" >/dev/null 2>>"$ERROR_FILE"; then
load_local_env
fi
}
maybe_set_cdp_endpoint() {
if [ -n "${PLAYWRIGHT_CDP_ENDPOINT:-}" ] || [ -z "${PLAYWRIGHT_PROFILE_DIR:-}" ]; then
if [ -n "${PLAYWRIGHT_CDP_ENDPOINT:-}" ]; then
if cdp_endpoint_alive; then
return 0
fi
unset PLAYWRIGHT_CDP_ENDPOINT
fi
if [ -z "${PLAYWRIGHT_PROFILE_DIR:-}" ]; then
bootstrap_dedicated_browser
return 0
fi
@@ -50,7 +113,13 @@ maybe_set_cdp_endpoint() {
if [ -n "$port" ]; then
PLAYWRIGHT_CDP_ENDPOINT="http://127.0.0.1:$port"
export PLAYWRIGHT_CDP_ENDPOINT
if cdp_endpoint_alive; then
return 0
fi
unset PLAYWRIGHT_CDP_ENDPOINT
fi
bootstrap_dedicated_browser
}
load_local_env
@@ -71,14 +140,21 @@ fetch_json() {
rm -f "$tmp"
if [ "$allow_fallback" = "1" ] && [ "${KOMODO_PLAYWRIGHT_FALLBACK:-0}" = "1" ] && command -v node >/dev/null 2>&1; then
if [ "$allow_fallback" = "1" ] && [ "${KOMODO_PLAYWRIGHT_FALLBACK:-0}" = "1" ]; then
configure_playwright_runtime
if [ -z "${NODE_BIN:-}" ]; then
printf '%s\n' "Playwright fallback unavailable: node executable not found" >> "$ERROR_FILE"
rm -f "$tmp"
printf '%s\n' "failed to fetch JSON from $url" >> "$ERROR_FILE"
return 1
fi
maybe_set_cdp_endpoint
PLAYWRIGHT_CORE_PATH="${PLAYWRIGHT_CORE_PATH:-}"
if command -v playwright-cli >/dev/null 2>&1; then
PLAYWRIGHT_CLI_BIN="$(command -v playwright-cli)"
PLAYWRIGHT_CORE_PATH="$(CDPATH= cd -- "$(dirname "$PLAYWRIGHT_CLI_BIN")/../lib/node_modules/@playwright/cli/node_modules/playwright-core" 2>/dev/null && pwd || true)"
fi
PLAYWRIGHT_CORE_PATH="$PLAYWRIGHT_CORE_PATH" node "$SCRIPT_DIR/fetch_with_playwright.js" "$url" "$tmp"
PLAYWRIGHT_CORE_PATH="$PLAYWRIGHT_CORE_PATH" "$NODE_BIN" "$SCRIPT_DIR/fetch_with_playwright.js" "$url" "$tmp"
if jq empty "$tmp" >/dev/null 2>&1; then
mv "$tmp" "$OUT_DIR/$name.json"
return 0
@@ -124,8 +200,14 @@ do
fi
done
for id in $(jq -r '.[].id' "$OUT_DIR/sections-controller-search.json" 2>/dev/null || true); do
fetch_json "media-parent-section-$id" "https://komodostation.com/wp-json/wp/v2/media?parent=$id&per_page=100" || true
for section_report in \
sections-controller-search \
sections-machine-search \
sections-frame-search
do
for id in $(jq -r '.[].id' "$OUT_DIR/$section_report.json" 2>/dev/null || true); do
fetch_json "media-parent-section-$id" "https://komodostation.com/wp-json/wp/v2/media?parent=$id&per_page=100" || true
done
done
{
@@ -153,8 +235,24 @@ jq -r '
| @tsv
' "$OUT_DIR/media-controller-search.json" > "$REPORT_DIR/komodo-controller-media-interesting.tsv"
: > "$REPORT_DIR/komodo-machine-media.tsv"
: > "$REPORT_DIR/komodo-frame-media.tsv"
write_section_media_report() {
sections_file="$1"
output_file="$2"
: > "$output_file"
for id in $(jq -r '.[].id' "$sections_file" 2>/dev/null || true); do
media_file="$OUT_DIR/media-parent-section-$id.json"
if [ -f "$media_file" ]; then
jq -r '
.[]?
| [.id,.date,.modified,.slug,.mime_type,.post,.source_url]
| @tsv
' "$media_file" >> "$output_file"
fi
done
}
write_section_media_report "$OUT_DIR/sections-machine-search.json" "$REPORT_DIR/komodo-machine-media.tsv"
write_section_media_report "$OUT_DIR/sections-frame-search.json" "$REPORT_DIR/komodo-frame-media.tsv"
jq -r '
.[]?
+74 -3
View File
@@ -26,8 +26,71 @@ load_local_env() {
fi
}
configure_playwright_runtime() {
NODE_BIN="${NODE_BIN:-}"
if [ -z "$NODE_BIN" ]; then
NODE_BIN="$(command -v node 2>/dev/null || true)"
fi
bundled_node="$HOME/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/bin/node"
if [ -z "$NODE_BIN" ] && [ -x "$bundled_node" ]; then
NODE_BIN="$bundled_node"
fi
export NODE_BIN
if [ -z "${NODE_PATH:-}" ]; then
for node_modules in \
"$REPO_DIR/node_modules" \
"$HOME/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules"
do
if [ -d "$node_modules" ]; then
NODE_PATH="$node_modules"
export NODE_PATH
break
fi
done
fi
}
cdp_endpoint_alive() {
endpoint="${STEAMDB_CDP_ENDPOINT:-}"
if [ -z "$endpoint" ]; then
return 1
fi
curl --max-time 2 -fsS "$endpoint/json/version" >/dev/null 2>&1
}
STEAMDB_BOOTSTRAP_ATTEMPTED=0
bootstrap_dedicated_browser() {
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" != "1" ] || [ "${STEAMDB_AUTO_BOOTSTRAP:-1}" = "0" ]; then
return 0
fi
if [ "$STEAMDB_BOOTSTRAP_ATTEMPTED" = "1" ]; then
return 0
fi
STEAMDB_BOOTSTRAP_ATTEMPTED=1
bootstrap_cmd="${STEAMDB_BOOTSTRAP_CMD:-$SCRIPT_DIR/bootstrap_steamdb.sh}"
if [ ! -x "$bootstrap_cmd" ]; then
printf '%s\n' "SteamDB bootstrap command not executable: $bootstrap_cmd" >> "$ERROR_FILE"
return 0
fi
if "$bootstrap_cmd" >/dev/null 2>>"$ERROR_FILE"; then
load_local_env
fi
}
maybe_set_cdp_endpoint() {
if [ -n "${STEAMDB_CDP_ENDPOINT:-}" ] || [ -z "${STEAMDB_PROFILE_DIR:-}" ]; then
if [ -n "${STEAMDB_CDP_ENDPOINT:-}" ]; then
if cdp_endpoint_alive; then
return 0
fi
unset STEAMDB_CDP_ENDPOINT
fi
if [ -z "${STEAMDB_PROFILE_DIR:-}" ]; then
bootstrap_dedicated_browser
return 0
fi
@@ -43,7 +106,13 @@ maybe_set_cdp_endpoint() {
if [ -n "$port" ]; then
STEAMDB_CDP_ENDPOINT="http://127.0.0.1:$port"
export STEAMDB_CDP_ENDPOINT
if cdp_endpoint_alive; then
return 0
fi
unset STEAMDB_CDP_ENDPOINT
fi
bootstrap_dedicated_browser
}
is_challenge_page() {
@@ -74,9 +143,11 @@ fetch_html() {
fi
fi
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" = "1" ] && command -v node >/dev/null 2>&1; then
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" = "1" ]; then
configure_playwright_runtime
maybe_set_cdp_endpoint
if node "$SCRIPT_DIR/fetch_steamdb_with_playwright.js" "$url" "$tmp" >/dev/null 2>&1 \
if [ -n "${NODE_BIN:-}" ] \
&& "$NODE_BIN" "$SCRIPT_DIR/fetch_steamdb_with_playwright.js" "$url" "$tmp" >/dev/null 2>&1 \
&& [ -s "$tmp" ] \
&& ! is_challenge_page "$tmp"; then
mv "$tmp" "$out"
+104
View File
@@ -9,6 +9,8 @@ fi
RUN_DIR="$1"
OUT_DIR="$RUN_DIR/api/steamvr-depots"
REPORT_DIR="$RUN_DIR/reports"
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname "$0")" && pwd)"
REPO_DIR="$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd)"
mkdir -p "$OUT_DIR" "$REPORT_DIR"
ERROR_FILE="$REPORT_DIR/steamvr-depots-errors.txt"
@@ -28,6 +30,101 @@ is_challenge_page() {
rg -qi "Checking your browser|Just a moment|Cloudflare|cf-chl|cf-browser-verification" "$path"
}
load_steamdb_env() {
env_file="${STEAMDB_ENV_FILE:-$REPO_DIR/.local/steamdb-env.sh}"
if [ -f "$env_file" ]; then
# shellcheck disable=SC1090
. "$env_file"
fi
}
steamdb_cdp_endpoint_alive() {
endpoint="${STEAMDB_CDP_ENDPOINT:-}"
if [ -z "$endpoint" ]; then
return 1
fi
curl --max-time 2 -fsS "$endpoint/json/version" >/dev/null 2>&1
}
STEAMDB_BOOTSTRAP_ATTEMPTED=0
bootstrap_steamdb_browser() {
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" != "1" ] || [ "${STEAMDB_AUTO_BOOTSTRAP:-1}" = "0" ]; then
return 0
fi
if [ "$STEAMDB_BOOTSTRAP_ATTEMPTED" = "1" ]; then
return 0
fi
STEAMDB_BOOTSTRAP_ATTEMPTED=1
bootstrap_cmd="${STEAMDB_BOOTSTRAP_CMD:-$SCRIPT_DIR/bootstrap_steamdb.sh}"
if [ ! -x "$bootstrap_cmd" ]; then
printf '%s\n' "SteamDB bootstrap command not executable: $bootstrap_cmd" >> "$ERROR_FILE"
return 0
fi
if "$bootstrap_cmd" >/dev/null 2>>"$ERROR_FILE"; then
load_steamdb_env
fi
}
ensure_steamdb_browser() {
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" != "1" ]; then
return 0
fi
if [ -n "${STEAMDB_CDP_ENDPOINT:-}" ]; then
if steamdb_cdp_endpoint_alive; then
return 0
fi
unset STEAMDB_CDP_ENDPOINT
fi
if [ -n "${STEAMDB_PROFILE_DIR:-}" ]; then
port="$(ps aux | awk -v profile="$STEAMDB_PROFILE_DIR" '
index($0, profile) && match($0, /--remote-debugging-port=([0-9]+)/) {
value = substr($0, RSTART, RLENGTH)
sub(/^--remote-debugging-port=/, "", value)
print value
exit
}
' 2>/dev/null || true)"
if [ -n "$port" ]; then
STEAMDB_CDP_ENDPOINT="http://127.0.0.1:$port"
export STEAMDB_CDP_ENDPOINT
if steamdb_cdp_endpoint_alive; then
return 0
fi
unset STEAMDB_CDP_ENDPOINT
fi
fi
bootstrap_steamdb_browser
}
fetch_html_with_steamdb_playwright() {
url="$1"
output="$2"
tmp="$output.tmp.playwright"
if [ "${STEAMDB_PLAYWRIGHT_FALLBACK:-0}" != "1" ] || ! command -v node >/dev/null 2>&1; then
return 1
fi
ensure_steamdb_browser
if node "$SCRIPT_DIR/fetch_steamdb_with_playwright.js" "$url" "$tmp" >/dev/null 2>&1 \
&& [ -s "$tmp" ] \
&& ! is_challenge_page "$tmp"; then
mv "$tmp" "$output"
return 0
fi
rm -f "$tmp"
return 1
}
fetch_html() {
name="$1"
url="$2"
@@ -40,6 +137,11 @@ fetch_html() {
return 0
fi
rm -f "$tmp"
if fetch_html_with_steamdb_playwright "$url" "$out"; then
return 0
fi
rm -f "$tmp" "$out"
printf '%s\n' "failed to fetch $url: blocked or challenge page" >> "$ERROR_FILE"
return 1
@@ -57,6 +159,8 @@ fetch_json() {
fi
}
load_steamdb_env
fetch_html "steamdb-depots.html" "https://steamdb.info/app/250820/depots/" || true
fetch_json "steamvr-news.json" "https://api.steampowered.com/ISteamNews/GetNewsForApp/v2/?appid=250820&count=40&maxlength=12000&format=json" || true
+2 -1
View File
@@ -6,13 +6,14 @@ function loadPlaywright() {
const candidates = [];
if (process.env.PLAYWRIGHT_CORE_PATH) candidates.push(process.env.PLAYWRIGHT_CORE_PATH);
candidates.push("playwright-core");
candidates.push("playwright");
for (const candidate of candidates) {
try {
return require(candidate);
} catch (err) {
}
}
throw new Error("Unable to load playwright-core. Set PLAYWRIGHT_CORE_PATH or install playwright-core.");
throw new Error("Unable to load Playwright. Set PLAYWRIGHT_CORE_PATH, set NODE_PATH to a node_modules directory, or install playwright/playwright-core.");
}
function launchOptions(headless) {
+2 -1
View File
@@ -6,6 +6,7 @@ function loadPlaywright() {
const candidates = [];
if (process.env.PLAYWRIGHT_CORE_PATH) candidates.push(process.env.PLAYWRIGHT_CORE_PATH);
candidates.push("playwright-core");
candidates.push("playwright");
for (const candidate of candidates) {
try {
return require(candidate);
@@ -13,7 +14,7 @@ function loadPlaywright() {
}
}
throw new Error(
"Unable to load playwright-core. Set PLAYWRIGHT_CORE_PATH or install playwright-core."
"Unable to load Playwright. Set PLAYWRIGHT_CORE_PATH, set NODE_PATH to a node_modules directory, or install playwright/playwright-core."
);
}
+2 -1
View File
@@ -6,6 +6,7 @@ function loadPlaywright() {
const candidates = [];
if (process.env.PLAYWRIGHT_CORE_PATH) candidates.push(process.env.PLAYWRIGHT_CORE_PATH);
candidates.push("playwright-core");
candidates.push("playwright");
for (const candidate of candidates) {
try {
return require(candidate);
@@ -13,7 +14,7 @@ function loadPlaywright() {
}
}
throw new Error(
"Unable to load playwright-core. Set PLAYWRIGHT_CORE_PATH or install playwright-core."
"Unable to load Playwright. Set PLAYWRIGHT_CORE_PATH, set NODE_PATH to a node_modules directory, or install playwright/playwright-core."
);
}
+78 -17
View File
@@ -56,6 +56,9 @@ OUTPUT_FIELDS = [
PARTY_TERMS = ("VALVE", "CEVA", "INGRAM MICRO", "TECH-FRONT", "CHENG UEI")
PRODUCT_TERMS = (
"GAME CONSOLE",
"VIRTUAL REALITY",
"VIRTUAL REALITY DEVICES",
"WIRELESS PC CONTROLLER",
"VR CONTROLLER",
"CONTROLLER",
"STEAM",
@@ -70,6 +73,9 @@ SOURCE_URLS = {
"tech-front-game-console": "https://www.importinfo.com/search?s=TECH-FRONT%20GAME%20CONSOLE%20VALVE",
"valve-corporation-game-console": "https://www.importinfo.com/search?s=VALVE%20CORPORATION%20GAME%20CONSOLE",
"importgenius-ingram-valve": "https://www.importgenius.com/importers/ingram-micro-c-o-valve-corporation",
"importgenius-ceva-valve": "https://www.importgenius.com/importers/ceva-c-o-valve-corporation",
"importgenius-ceva-nl-valve": "https://www.importgenius.com/importers/ceva-nl-c-o-valve-corporation",
"importgenius-valve-corp": "https://www.importgenius.com/importers/valve-corp",
}
@@ -135,11 +141,11 @@ class TextParser(HTMLParser):
self.parts = []
def handle_starttag(self, tag, attrs):
if tag in ("br", "p", "tr", "li", "h1", "h2", "h3", "section"):
if tag in ("br", "p", "tr", "li", "h1", "h2", "h3", "section", "div"):
self.parts.append("\n")
def handle_endtag(self, tag):
if tag in ("p", "tr", "li", "h1", "h2", "h3", "section"):
if tag in ("p", "tr", "li", "h1", "h2", "h3", "section", "div"):
self.parts.append("\n")
def handle_data(self, data):
@@ -148,6 +154,10 @@ class TextParser(HTMLParser):
def text(self):
return html.unescape(" ".join("".join(self.parts).split()))
def lines(self):
raw_text = html.unescape("".join(self.parts))
return [" ".join(line.split()) for line in raw_text.splitlines() if line.strip()]
def normalize_header(value):
return FIELD_MAP.get(value.strip().lower(), "")
@@ -177,34 +187,83 @@ def parse_rows(spec):
def parse_importgenius_rows(spec):
parser = TextParser()
parser.feed(spec.path.read_text(encoding="utf-8", errors="ignore"))
text = parser.text()
text_lines = parser.lines() or [parser.text()]
importer_pattern = (
r"(?:INGRAM\s+MICRO|CEVA(?:\s+NL)?)\s+C/O\s+VALVE\s+CORPORATION"
r"|VALVE\s+CORPORATION"
)
supplier_pattern = (
r"TECH-?FRONT\s+\(CHONGQING\)\s+COMPUTER\s+CO"
r"|CHENG\s+UEI\s+PRECISION\s+IND\.\s+CO\s+LTD"
)
pattern = re.compile(
r"(?:^|\s)(?P<rank>\d+)\s+"
r"(?P<bol>[A-Z0-9]+)\s+"
r"(?P<product>GAME\s+CONSOLE\s*\.?)\s+"
r"(?P<importer>(?:INGRAM\s+MICRO|CEVA)\s+C/O\s+VALVE\s+CORPORATION)\s+"
r"(?P<supplier>TECH-?FRONT\s+\(CHONGQING\)\s+COMPUTER\s+CO)\s+"
r"(?P<product>[A-Z0-9][A-Z0-9 ./&()'-]+?)\s+"
r"(?P<importer>" + importer_pattern + r")\s+"
r"(?P<supplier>" + supplier_pattern + r")\s+"
r"(?P<arrival>\d{4}-\d{2}-\d{2})\s+"
r"(?P<country>[A-Za-z ]+?)\s+"
r"(?P<weight>[\d,]+\s+Kgs)\s+"
r"(?P<quantity>\d+\s+PKG)",
re.IGNORECASE,
)
rows = []
for match in pattern.finditer(text):
importer_re = re.compile(importer_pattern, re.IGNORECASE)
supplier_re = re.compile(supplier_pattern, re.IGNORECASE)
rank_re = re.compile(r"\d+")
bol_re = re.compile(r"[A-Z0-9]+")
date_re = re.compile(r"\d{4}-\d{2}-\d{2}")
country_re = re.compile(r"[A-Za-z ]+")
weight_re = re.compile(r"[\d,]+\s+Kgs", re.IGNORECASE)
quantity_re = re.compile(r"\d+\s+PKG", re.IGNORECASE)
def build_record(match):
record = {field: "" for field in OUTPUT_FIELDS}
record["source"] = "importgenius"
record["query"] = spec.query
record["house_bol"] = match.group("bol").upper()
record["arrival_date"] = match.group("arrival")
record["foreign_port"] = match.group("country").strip()
record["quantity"] = " ".join(match.group("quantity").split())
record["weight"] = " ".join(match.group("weight").split())
record["shipper"] = normalize_company(match.group("supplier"))
record["consignee"] = normalize_company(match.group("importer"))
record["house_bol"] = match["bol"].upper()
record["arrival_date"] = match["arrival"]
record["foreign_port"] = match["country"].strip()
record["quantity"] = " ".join(match["quantity"].split())
record["weight"] = " ".join(match["weight"].split())
record["shipper"] = normalize_company(match["supplier"])
record["consignee"] = normalize_company(match["importer"])
record["notify_party"] = record["consignee"]
record["commodity"] = " ".join(match.group("product").upper().split())
record["commodity"] = " ".join(match["product"].upper().split()).strip(" .")
record["source_url"] = spec.source_url
return record
rows = []
for line in text_lines:
for match in pattern.finditer(line):
record = build_record(match.groupdict())
if is_relevant(record):
rows.append(record)
for index in range(0, max(0, len(text_lines) - 8)):
values = text_lines[index : index + 9]
if not (
rank_re.fullmatch(values[0])
and bol_re.fullmatch(values[1])
and importer_re.fullmatch(values[3])
and supplier_re.fullmatch(values[4])
and date_re.fullmatch(values[5])
and country_re.fullmatch(values[6])
and weight_re.fullmatch(values[7])
and quantity_re.fullmatch(values[8])
):
continue
record = build_record(
{
"bol": values[1],
"product": values[2],
"importer": values[3],
"supplier": values[4],
"arrival": values[5],
"country": values[6],
"weight": values[7],
"quantity": values[8],
}
)
if is_relevant(record):
rows.append(record)
return rows
@@ -350,7 +409,9 @@ def write_report(rows, output):
"## Limitations",
"",
"Customs data is corroborating evidence, not a standalone confirmation. "
"GAME CONSOLE descriptions are medium confidence without other identifiers.",
"Product descriptions such as GAME CONSOLE, VIRTUAL REALITY DEVICES, "
"and WIRELESS PC CONTROLLER do not prove the final Valve retail SKU without "
"other identifiers.",
"",
]
)