jbit better messages
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate iran_cities_seed.sql from goldAli cities API.
|
||||
|
||||
Usage:
|
||||
python generate_cities_sql.py
|
||||
python generate_cities_sql.py --source /path/to/cities.json
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
import urllib.request
|
||||
from pathlib import Path
|
||||
|
||||
SQL_DIR = Path(__file__).resolve().parent
|
||||
DEFAULT_SOURCE = "https://goldaliii.com/server/api/city/all"
|
||||
OUTPUT = SQL_DIR / "iran_cities_seed.sql"
|
||||
|
||||
ARABIC_TO_PERSIAN = str.maketrans(
|
||||
{"ي": "ی", "ك": "ک", "ة": "ه", "ۀ": "ه", "ؤ": "و", "إ": "ا", "أ": "ا"}
|
||||
)
|
||||
|
||||
TITLE_FIXES = {
|
||||
"چهارمحال وبختیاری": "چهارمحال و بختیاری",
|
||||
"سیستان وبلوچستان": "سیستان و بلوچستان",
|
||||
"کهگیلویه وبویراحمد": "کهگیلویه و بویراحمد",
|
||||
}
|
||||
|
||||
|
||||
def normalize_title(title: str) -> str:
|
||||
title = title.translate(ARABIC_TO_PERSIAN)
|
||||
return TITLE_FIXES.get(title, title)
|
||||
|
||||
|
||||
def sql_str(value: str | None) -> str:
|
||||
if value is None:
|
||||
return "NULL"
|
||||
return "'" + str(value).replace("\\", "\\\\").replace("'", "''") + "'"
|
||||
|
||||
|
||||
def sql_bool(value: bool | None) -> str:
|
||||
return "1" if value else "0"
|
||||
|
||||
|
||||
def load_rows(source: str) -> list[dict]:
|
||||
if source.startswith("http://") or source.startswith("https://"):
|
||||
with urllib.request.urlopen(source, timeout=60) as resp:
|
||||
data = json.load(resp)
|
||||
else:
|
||||
data = json.loads(Path(source).read_text(encoding="utf-8"))
|
||||
|
||||
return [
|
||||
row
|
||||
for row in data
|
||||
if row.get("id") != 1600 and row.get("title") != "تست"
|
||||
]
|
||||
|
||||
|
||||
def generate_sql(rows: list[dict]) -> str:
|
||||
provinces = sorted(
|
||||
[row for row in rows if row.get("parent_id") is None], key=lambda r: r["id"]
|
||||
)
|
||||
others = sorted(
|
||||
[row for row in rows if row.get("parent_id") is not None], key=lambda r: r["id"]
|
||||
)
|
||||
ordered = provinces + others
|
||||
|
||||
lines = [
|
||||
"-- =============================================================================",
|
||||
"-- استانها + شهرها + زیرمجموعهها (جدول cities)",
|
||||
"--",
|
||||
"-- ساختار مطابق City model:",
|
||||
"-- level=1 → استان (parent_id = NULL, has_children = 1)",
|
||||
"-- level=2 → شهر/شهرستان (parent_id = id استان)",
|
||||
"-- level=3 → محله/بخش (parent_id = id شهر level=2)",
|
||||
"--",
|
||||
f"-- تعداد: {len(ordered)} رکورد (31 استان + {len(ordered) - 31} زیرمجموعه)",
|
||||
"-- =============================================================================",
|
||||
"",
|
||||
"START TRANSACTION;",
|
||||
"",
|
||||
"SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;",
|
||||
"",
|
||||
"CREATE TABLE IF NOT EXISTS `cities` (",
|
||||
" `id` bigint unsigned NOT NULL AUTO_INCREMENT,",
|
||||
" `title` varchar(255) NOT NULL,",
|
||||
" `code` varchar(50) DEFAULT NULL,",
|
||||
" `parent_id` bigint unsigned DEFAULT NULL,",
|
||||
" `has_children` tinyint(1) NOT NULL DEFAULT 0,",
|
||||
" `level` tinyint unsigned DEFAULT NULL,",
|
||||
" PRIMARY KEY (`id`),",
|
||||
" KEY `cities_parent_id_index` (`parent_id`)",
|
||||
") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;",
|
||||
"",
|
||||
"ALTER TABLE `cities` MODIFY COLUMN `code` varchar(50) DEFAULT NULL;",
|
||||
"",
|
||||
"DELETE FROM `cities`;",
|
||||
"",
|
||||
]
|
||||
|
||||
batch_size = 50
|
||||
for i in range(0, len(ordered), batch_size):
|
||||
batch = ordered[i : i + batch_size]
|
||||
lines.append(
|
||||
"INSERT INTO `cities` (`id`, `title`, `code`, `parent_id`, `has_children`, `level`) VALUES"
|
||||
)
|
||||
values = []
|
||||
for row in batch:
|
||||
parent_id = row.get("parent_id")
|
||||
level = row.get("level")
|
||||
values.append(
|
||||
f" ({row['id']}, {sql_str(normalize_title(row['title']))}, "
|
||||
f"{sql_str(row.get('code'))}, "
|
||||
f"{parent_id if parent_id is not None else 'NULL'}, "
|
||||
f"{sql_bool(row.get('has_children'))}, "
|
||||
f"{level if level is not None else 'NULL'})"
|
||||
)
|
||||
lines.append(",\n".join(values) + ";")
|
||||
lines.append("")
|
||||
|
||||
max_id = max(row["id"] for row in ordered)
|
||||
lines.extend([f"ALTER TABLE `cities` AUTO_INCREMENT = {max_id + 1};", "", "COMMIT;", ""])
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
source = DEFAULT_SOURCE
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "--source" and len(sys.argv) > 2:
|
||||
source = sys.argv[2]
|
||||
|
||||
rows = load_rows(source)
|
||||
OUTPUT.write_text(generate_sql(rows), encoding="utf-8")
|
||||
print(f"Wrote {OUTPUT} ({len(rows)} rows)")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user