summaryrefslogtreecommitdiff
path: root/official-site
diff options
context:
space:
mode:
Diffstat (limited to 'official-site')
m---------official-site0
-rwxr-xr-xofficial-site/add-event.sh47
-rwxr-xr-xofficial-site/deploy.sh41
-rwxr-xr-xofficial-site/enrich-event.py305
-rw-r--r--official-site/events/2026-06-27-cre4m-sod4.json17
-rwxr-xr-xofficial-site/list-events.sh25
6 files changed, 0 insertions, 435 deletions
diff --git a/official-site b/official-site
new file mode 160000
+Subproject bb6b424e91001ba6f9309162af90613a0229929
diff --git a/official-site/add-event.sh b/official-site/add-event.sh
deleted file mode 100755
index 109c2c8..0000000
--- a/official-site/add-event.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/usr/bin/env bash
-# Usage: bash add-event.sh <json-file>
-# The JSON file should match the Event schema (see CLAUDE.md).
-# id, createdAt, updatedAt, _version, _deleted, _lastChangedAt are auto-managed.
-set -euo pipefail
-
-REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
-[ -f "$REPO_ROOT/.env" ] && set -a && source "$REPO_ROOT/.env" && set +a
-
-ENDPOINT="${APP_SYNC_ENDPOINT:?APP_SYNC_ENDPOINT not set}"
-API_KEY="${APP_SYNC_API_KEY:?APP_SYNC_API_KEY not set}"
-
-JSON_FILE="${1:-}"
-if [ -z "$JSON_FILE" ]; then
- echo "Usage: $0 <event-json-file>"
- exit 1
-fi
-
-INPUT=$(python3 -c "
-import json, sys
-with open('$JSON_FILE') as f:
- data = json.load(f)
-# Remove read-only / auto-managed fields
-for k in ['id', 'createdAt', 'updatedAt', '_version', '_deleted', '_lastChangedAt', '_note']:
- data.pop(k, None)
-# Remove null fields (optional)
-data = {k: v for k, v in data.items() if v is not None}
-print(json.dumps(data))
-")
-
-QUERY='mutation CreateEvent($input: CreateEventInput!) { createEvent(input: $input) { id type date title venueName published } }'
-PAYLOAD=$(python3 -c "
-import json, sys
-q = '$QUERY'
-inp = $INPUT
-print(json.dumps({'query': q, 'variables': {'input': inp}}))
-")
-
-echo "Creating event from $JSON_FILE ..."
-RESULT=$(curl -s -X POST "$ENDPOINT" \
- -H "Content-Type: application/json" \
- -H "x-api-key: $API_KEY" \
- -d "$PAYLOAD")
-
-echo "$RESULT" | python3 -m json.tool
-echo ""
-echo "Done. Run 'bash deploy.sh' to rebuild the site."
diff --git a/official-site/deploy.sh b/official-site/deploy.sh
deleted file mode 100755
index 32574e0..0000000
--- a/official-site/deploy.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
-[ -f "$REPO_ROOT/.env" ] && set -a && source "$REPO_ROOT/.env" && set +a
-
-AWS_CLI="${AWS_CLI:-/tmp/awscli/aws/dist/aws}"
-APP_ID="d33773t2lyrxkx"
-BRANCH="main"
-REGION="${AWS_DEFAULT_REGION:-ap-northeast-1}"
-
-echo "Starting Amplify build: app=$APP_ID branch=$BRANCH"
-JOB=$("$AWS_CLI" amplify start-job \
- --app-id "$APP_ID" \
- --branch-name "$BRANCH" \
- --job-type RELEASE \
- --region "$REGION" \
- --output json)
-
-JOB_ID=$(echo "$JOB" | python3 -c "import json,sys; print(json.load(sys.stdin)['jobSummary']['jobId'])")
-echo "Job started: $JOB_ID"
-echo "Console: https://ap-northeast-1.console.aws.amazon.com/amplify/apps/$APP_ID/branches/$BRANCH/deployments/$JOB_ID"
-
-echo "Waiting for build to complete..."
-while true; do
- STATUS=$("$AWS_CLI" amplify get-job \
- --app-id "$APP_ID" \
- --branch-name "$BRANCH" \
- --job-id "$JOB_ID" \
- --region "$REGION" \
- --output json | python3 -c "import json,sys; print(json.load(sys.stdin)['job']['summary']['status'])")
- echo " Status: $STATUS"
- if [[ "$STATUS" == "SUCCEED" ]]; then
- echo "Build succeeded! https://www.mosquit.one"
- break
- elif [[ "$STATUS" == "FAILED" || "$STATUS" == "CANCELLED" ]]; then
- echo "Build $STATUS"
- exit 1
- fi
- sleep 15
-done
diff --git a/official-site/enrich-event.py b/official-site/enrich-event.py
deleted file mode 100755
index 846a61e..0000000
--- a/official-site/enrich-event.py
+++ /dev/null
@@ -1,305 +0,0 @@
-#!/usr/bin/env python3
-"""
-Enrich an AppSync Event with details from golive DB and venue website.
-
-Usage:
- python3 enrich-event.py <appsync-event-id>
- python3 enrich-event.py --all-unenriched # process events missing ticketURL/detailURL
-
-Sources (tried in order):
- 1. golive SQLite DB (/app/tokyo-livehouse-events/data/events.db)
- 2. Venue website (direct fetch)
-
-What gets filled in:
- ticketURL ← golive ticket_url
- detailURL ← golive source_url
- ticketFee ← golive price (if current value looks incomplete)
- description ← "OPEN HH:MM / START HH:MM\\n出演: <artists>"
- mainImageURL← first non-logo <img> from the venue event page, uploaded to S3
-"""
-
-import json
-import os
-import re
-import sqlite3
-import sys
-import tempfile
-import urllib.request
-from pathlib import Path
-
-# ── config ──────────────────────────────────────────────────────────────────
-REPO_ROOT = Path(__file__).parent.parent
-ENV_FILE = REPO_ROOT / ".env"
-
-# Load .env early so os.environ is populated before constants are evaluated
-if ENV_FILE.exists():
- for _line in ENV_FILE.read_text().splitlines():
- _line = _line.strip()
- if _line and not _line.startswith("#") and "=" in _line:
- _k, _, _v = _line.partition("=")
- os.environ.setdefault(_k.strip(), _v.strip())
-
-APPSYNC_ENDPOINT = os.environ["APP_SYNC_ENDPOINT"]
-APPSYNC_KEY = os.environ["APP_SYNC_API_KEY"]
-S3_BUCKET = os.environ["S3_BUCKET"]
-S3_REGION = "ap-northeast-1"
-S3_PREFIX = "public/site/live"
-AWS_CLI = os.environ.get("AWS_CLI", "/tmp/awscli/aws/dist/aws")
-
-GOLIVE_DB_PATHS = [
- "/app/tokyo-livehouse-events/data/events.db",
-]
-
-# AppSync venueName patterns → golive venue_id
-VENUE_MAP: list[tuple[list[str], str]] = [
- (["navey floor", "navey floor AKASAKA"], "navey-floor"),
- (["Meets 大塚", "MEETS大塚"], "meets-otsuka"),
- (["国分寺MORGANA", "国分寺 MORGANA"], "morgana-kokubunji"),
- (["BuzzFront Yokohama", "BuzzFront"], "buzzfront-yokohama"),
- (["下北沢ERA", "shimokitazawa ERA"], "shimokitazawa-era"),
- (["新代田FEVER", "FEVER"], "fever-shindaita"),
- (["吉祥寺WARP", "WARP 吉祥寺"], "warp-kichijoji"),
- (["LIQUID ROOM", "liquidroom"], "liquid-room"),
- (["WWW", "WWW X"], "www-shibuya"),
-]
-
-# ── helpers ──────────────────────────────────────────────────────────────────
-
-def load_env():
- if ENV_FILE.exists():
- for line in ENV_FILE.read_text().splitlines():
- line = line.strip()
- if line and not line.startswith("#") and "=" in line:
- k, _, v = line.partition("=")
- os.environ.setdefault(k.strip(), v.strip())
-
-def appsync(query: str, variables: dict) -> dict:
- payload = json.dumps({"query": query, "variables": variables}).encode()
- req = urllib.request.Request(
- APPSYNC_ENDPOINT,
- data=payload,
- headers={"Content-Type": "application/json", "x-api-key": APPSYNC_KEY},
- )
- with urllib.request.urlopen(req) as r:
- return json.loads(r.read())
-
-def fetch_event(event_id: str) -> dict:
- res = appsync(
- "query GetEvent($id: ID!) { getEvent(id: $id) { "
- "id type date title venueName published description ticketFee "
- "ticketURL detailURL mainImageURL shortTitle key venueURL _version } }",
- {"id": event_id},
- )
- return res["data"]["getEvent"]
-
-def list_unenriched_events() -> list[dict]:
- res = appsync(
- "{ listEvents(limit: 200) { items { "
- "id date title venueName published ticketURL detailURL mainImageURL _version } } }",
- {},
- )
- items = res["data"]["listEvents"]["items"]
- return [
- e for e in items
- if not e.get("ticketURL") or not e.get("detailURL") or not e.get("mainImageURL")
- ]
-
-def golive_db() -> sqlite3.Connection | None:
- for p in GOLIVE_DB_PATHS:
- if os.path.exists(p):
- db = sqlite3.connect(p)
- db.row_factory = sqlite3.Row
- return db
- return None
-
-def venue_id_for(venue_name: str) -> str | None:
- vn = venue_name.lower()
- for patterns, vid in VENUE_MAP:
- if any(p.lower() in vn or vn in p.lower() for p in patterns):
- return vid
- return None
-
-def search_golive(db: sqlite3.Connection, date: str, venue_id: str, title: str) -> dict | None:
- # Exact date + venue_id match, pick the row whose title is closest
- rows = db.execute(
- "SELECT * FROM events WHERE date=? AND venue_id=?", (date, venue_id)
- ).fetchall()
- if not rows:
- return None
- if len(rows) == 1:
- return dict(rows[0])
- # Multiple events same day/venue — pick closest title match
- title_l = title.lower()
- def score(r):
- words = [w for w in re.split(r'\W+', title_l) if w]
- return sum(1 for w in words if w in r["title"].lower())
- best = max(rows, key=score)
- return dict(best)
-
-def fetch_url(url: str) -> str:
- req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
- with urllib.request.urlopen(req, timeout=15) as r:
- return r.read().decode("utf-8", errors="replace")
-
-def extract_flyer_image(html: str, base_url: str) -> str | None:
- """Return first <img src> that looks like a real flyer (not logo/icon)."""
- skip_patterns = [
- r"/logo", r"/icon", r"placeholder", r"noimage", r"instagram-feed",
- r"/themes/", r"nf_logo",
- ]
- for src in re.findall(r'<img[^>]+src=["\']([^"\']+)["\']', html):
- if any(re.search(p, src, re.I) for p in skip_patterns):
- continue
- if src.startswith("//"):
- src = "https:" + src
- elif src.startswith("/"):
- m = re.match(r"(https?://[^/]+)", base_url)
- src = m.group(1) + src if m else src
- return src
- return None
-
-def upload_to_s3(local_path: str, s3_key: str) -> str:
- import subprocess
- env = {**os.environ, "AWS_DEFAULT_REGION": S3_REGION}
- subprocess.run(
- [AWS_CLI, "s3", "cp", local_path, f"s3://{S3_BUCKET}/{s3_key}",
- "--content-type", "image/jpeg", "--acl", "public-read"],
- check=True, env=env,
- )
- return f"https://{S3_BUCKET}.s3.{S3_REGION}.amazonaws.com/{s3_key}"
-
-def download_image(url: str) -> str:
- """Download to a temp file. Returns local path."""
- suffix = ".jpg" if url.lower().endswith(".jpg") else ".png"
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
- req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
- with urllib.request.urlopen(req, timeout=20) as r:
- tmp.write(r.read())
- tmp.close()
- return tmp.name
-
-def build_description(golive_row: dict) -> str:
- parts = []
- open_t = golive_row.get("open_time")
- start_t = golive_row.get("start_time")
- if open_t and start_t:
- parts.append(f"OPEN {open_t} / START {start_t}")
- elif start_t:
- parts.append(f"START {start_t}")
- artists = golive_row.get("artist") or ""
- if artists:
- parts.append(f"出演: {artists}")
- return "\n".join(parts)
-
-def enrich(event_id: str, dry_run: bool = False):
- load_env()
- print(f"\n── enriching {event_id}")
-
- ev = fetch_event(event_id)
- if not ev:
- print(" ERROR: event not found")
- return
-
- print(f" {ev['date']} {ev['title']} @ {ev['venueName']}")
-
- updates: dict = {}
-
- # ── 1. golive DB lookup ───────────────────────────────────────────────
- db = golive_db()
- golive_row = None
- if db:
- vid = venue_id_for(ev["venueName"] or "")
- if vid:
- golive_row = search_golive(db, ev["date"], vid, ev["title"])
- if golive_row:
- print(f" golive match: [{golive_row['venue_id']}] {golive_row['title']}")
- else:
- print(f" golive: no match for venue_id={vid} date={ev['date']}")
- else:
- print(f" golive: venue not mapped ({ev['venueName']})")
- else:
- print(" golive DB not found (non-server environment)")
-
- if golive_row:
- if not ev.get("ticketURL") and golive_row.get("ticket_url"):
- updates["ticketURL"] = golive_row["ticket_url"]
- if not ev.get("detailURL") and golive_row.get("source_url"):
- updates["detailURL"] = golive_row["source_url"]
- if golive_row.get("price"):
- updates["ticketFee"] = golive_row["price"]
- desc = build_description(golive_row)
- if desc:
- updates["description"] = desc
-
- # ── 2. flyer image from venue event page ─────────────────────────────
- detail_url = updates.get("detailURL") or ev.get("detailURL")
- if detail_url and not ev.get("mainImageURL"):
- print(f" fetching event page: {detail_url}")
- try:
- html = fetch_url(detail_url)
- img_url = extract_flyer_image(html, detail_url)
- if img_url:
- print(f" flyer image: {img_url}")
- # derive S3 key from date + sanitized title
- slug = re.sub(r'[^\w-]', '-', ev["date"] + "-" + (ev["key"] or ev["title"][:20]))
- slug = re.sub(r'-+', '-', slug).strip("-").lower()
- ext = ".jpg" if "jpg" in img_url.lower() else ".png"
- s3_key = f"{S3_PREFIX}/{slug}-flyer{ext}"
- local = download_image(img_url)
- if not dry_run:
- s3_url = upload_to_s3(local, s3_key)
- updates["mainImageURL"] = s3_url
- print(f" uploaded: {s3_url}")
- else:
- print(f" [dry-run] would upload to s3://{S3_BUCKET}/{s3_key}")
- os.unlink(local)
- else:
- print(" no flyer image found on event page")
- except Exception as e:
- print(f" WARNING: could not fetch event page: {e}")
-
- if not updates:
- print(" nothing to update")
- return
-
- print(f" updates: {list(updates.keys())}")
-
- if dry_run:
- print(f" [dry-run] would update: {json.dumps(updates, ensure_ascii=False, indent=2)}")
- return
-
- updates["id"] = event_id
- updates["_version"] = ev["_version"]
-
- res = appsync(
- "mutation UpdateEvent($input: UpdateEventInput!) { updateEvent(input: $input) { "
- "id date title ticketURL detailURL mainImageURL description ticketFee _version } }",
- {"input": updates},
- )
- if "errors" in res:
- print(f" ERROR: {res['errors']}")
- else:
- print(f" ✓ updated (version {res['data']['updateEvent']['_version']})")
-
-# ── main ─────────────────────────────────────────────────────────────────────
-
-if __name__ == "__main__":
- args = sys.argv[1:]
- dry_run = "--dry-run" in args
- args = [a for a in args if not a.startswith("--")]
-
- if not args:
- print("Usage:")
- print(" python3 enrich-event.py <event-id> [--dry-run]")
- print(" python3 enrich-event.py --all-unenriched [--dry-run]")
- sys.exit(1)
-
- load_env()
-
- if "--all-unenriched" in sys.argv:
- events = list_unenriched_events()
- print(f"Found {len(events)} unenriched events")
- for e in sorted(events, key=lambda x: x["date"] or ""):
- enrich(e["id"], dry_run=dry_run)
- else:
- enrich(args[0], dry_run=dry_run)
diff --git a/official-site/events/2026-06-27-cre4m-sod4.json b/official-site/events/2026-06-27-cre4m-sod4.json
deleted file mode 100644
index ca9ebef..0000000
--- a/official-site/events/2026-06-27-cre4m-sod4.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "id": "4c99e242-c13d-404b-92a9-4c2cd59ad68a",
- "type": "LIVE",
- "date": "2026-06-27",
- "title": "cre4m sod4",
- "shortTitle": "cre4m sod4",
- "venueName": "navey floor AKASAKA",
- "published": true,
- "description": "雨傘とペトリコール / mosquitone / 人造ネオン / LOOM",
- "ticketFee": "一般 ¥3,000(+1D ¥700) ※学生証提示で¥1,000ディスカウント / 配信 ¥2,000",
- "key": "260627",
- "ticketURL": "https://tiget.net/events/494018",
- "detailURL": "https://navey-floor.com/event/2026-6-27n/",
- "mainImageURL": "https://S3_BUCKET_REDACTED.s3.ap-northeast-1.amazonaws.com/public/site/live/260627-cre4m-sod4-flyer.jpg",
- "venueURL": null,
- "_note": "OPEN 18:00 / START 18:30 (当初発表から変更あり)"
-}
diff --git a/official-site/list-events.sh b/official-site/list-events.sh
deleted file mode 100755
index d56aabf..0000000
--- a/official-site/list-events.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-set -euo pipefail
-
-REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
-[ -f "$REPO_ROOT/.env" ] && set -a && source "$REPO_ROOT/.env" && set +a
-
-AWS_CLI="${AWS_CLI:-/tmp/awscli/aws/dist/aws}"
-ENDPOINT="${APP_SYNC_ENDPOINT:?APP_SYNC_ENDPOINT not set}"
-API_KEY="${APP_SYNC_API_KEY:?APP_SYNC_API_KEY not set}"
-
-QUERY='{ listEvents(limit: 200) { items { id type date title venueName published shortTitle ticketFee key } } }'
-
-curl -s -X POST "$ENDPOINT" \
- -H "Content-Type: application/json" \
- -H "x-api-key: $API_KEY" \
- -d "{\"query\": $(echo "$QUERY" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')}" \
-| python3 -c "
-import json, sys
-d = json.load(sys.stdin)
-items = d['data']['listEvents']['items']
-items.sort(key=lambda x: x['date'] or '')
-for e in items:
- pub = '✓' if e['published'] else ' '
- print(f\"[{pub}] {e['date']} {e['title'][:50]:<50} {e['venueName'] or ''}\")
-"