#!/usr/bin/env python3 """List point alarm registrations page by page into SQLite, screen or CSV/TXT.""" from __future__ import annotations import argparse import logging import sys from pathlib import Path from common import ApiError, ConfigurationError, IklimClient, configure_logging from point_alarm import ( MAX_PAGE_SIZE, PointAlarmService, PointStore, fetch_pages, parse_polygon, print_records, prompt_export, timestamped_path, write_records, ) BASE_DIR = Path(__file__).resolve().parent def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser( description=( "iklim.co nokta alarm kayıtlarını /v1/alarms/points/page ile listeler. " "Sonuçlar SQLite'a (registrationId anahtarlı) yazılır; varsayılan olarak ekrana " "basılır, --output ile CSV/TXT'ye yazılır." ), formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( "--account-id", help=( "Sorgulanacak hesap ID'si; yalnızca en az POWER_USER yetkisiyle verilebilir (aksi halde " "HTTP 403). Verilmezse sunucu kendi hesabınıza daraltır; normal kullanıcılar vermemelidir" ), ) parser.add_argument( "--recipient-id", action="append", default=[], help="Alıcı ID'sine göre süz; birden fazla kez verilebilir", ) parser.add_argument( "--polygon", help="Poligon kesişim filtresi: 'lng,lat;lng,lat;...' (en az 4 nokta, kapalı halka)", ) parser.add_argument( "--page-number", type=int, help="Yalnızca bu sayfayı getir (0'dan başlar); verilmezse tüm sayfalar gezilir", ) parser.add_argument( "--page-size", type=int, default=MAX_PAGE_SIZE, help=f"Sayfa boyutu, 1-{MAX_PAGE_SIZE} (varsayılan: {MAX_PAGE_SIZE})", ) parser.add_argument( "--output", type=Path, help=( "Çıktı dosyası (.csv noktalı virgüllü, .txt JSON Lines); dosya adına " "zaman soneki eklenir (dosya-YYYYmmdd-HHMMSS.csv). Verilmezse ekrana yazılır" ), ) parser.add_argument( "--db", type=Path, default=BASE_DIR / "iklim-sandbox.db", help="SQLite dosyası (varsayılan: iklim-sandbox.db)", ) parser.add_argument( "--debug-log", type=Path, default=BASE_DIR / "logs" / "iklim-api-debug.log", help="Maskelenmiş HTTP debug log dosyası", ) args = parser.parse_args() if not 1 <= args.page_size <= MAX_PAGE_SIZE: parser.error(f"--page-size 1-{MAX_PAGE_SIZE} aralığında olmalıdır") if args.page_number is not None and args.page_number < 0: parser.error("--page-number 0 veya daha büyük olmalıdır") return args def main() -> int: args = parse_args() configure_logging(args.debug_log) store = None try: polygon = parse_polygon(args.polygon) if args.polygon else None client = IklimClient.from_env(BASE_DIR / ".env") service = PointAlarmService(client) store = PointStore(args.db) summary = fetch_pages( service, store, account_id=args.account_id, recipient_ids=args.recipient_id or None, polygon=polygon, page_size=args.page_size, page_number=args.page_number, ) records = store.records(None, summary.registration_ids) webhooks = store.webhooks_of(records) if args.output: path = timestamped_path(args.output) write_records(path, records, webhooks) print(f"{len(records)} kayıt yazıldı: {path.resolve()}") else: print_records(records, webhooks) if args.page_number is None and summary.missing: logging.warning( "Sunucu %s kayıt bildirdi, %s benzersiz kayıt alındı (%s eksik). Sayfalama sırasında " "kayıt eklenmiş/silinmiş olabilir; komutu yeniden çalıştırın.", summary.total_records, summary.distinct, summary.missing, ) if summary.duplicates: logging.warning("Sayfalar arasında %s tekrar eden kayıt görüldü.", summary.duplicates) if not args.output: prompt_export(store, args.account_id) except (ConfigurationError, ApiError, OSError) as exc: logging.error("İşlem durduruldu: %s", exc) return 1 finally: if store: store.close() return 0 if __name__ == "__main__": sys.exit(main())