turkiyem 1.10.3 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,7 @@ Türkiye'de toplu taşıma verileri onlarca farklı belediye sitesi, API ve veri
65
65
  | Şehir | Kaynak | Hat | Durak | Canlı Konum | Sefer Saatleri |
66
66
  |-------|--------|:---:|:-----:|:-----------:|:--------------:|
67
67
  | **Ankara** | EGO Genel Müdürlüğü | ✅ | — | — | ✅ |
68
- | **İstanbul** | IETT (GTFS + SOAP) | ✅ | | ✅ | ✅ |
68
+ | **İstanbul** | IETT (GTFS + SOAP) | ✅ | | ✅ | ✅ |
69
69
  | **Adana** | Adana Büyükşehir Belediyesi | ✅ | ✅ | — | ✅ |
70
70
  | **Antalya** | Antalya Büyükşehir Belediyesi | ✅ | ✅ | — | ✅ |
71
71
  | **Bursa** | Burulaş (Bursakart API) | ✅ | ✅ | ✅ | ✅ |
@@ -93,8 +93,8 @@ Türkiye'de toplu taşıma verileri onlarca farklı belediye sitesi, API ve veri
93
93
  - İzmir genel eczane arama ve lokasyon bilgisi
94
94
  - Telefon numarası ve harita bağlantısı gösterimi
95
95
 
96
- ### 📍 Canlı Araç Takibi
97
- - **İstanbul (IETT):** Anlık araç konumu, yön, yakın durak bilgisi
96
+ ### 📍 Canlı Araç Takibi ve Ekstra Veriler
97
+ - **İstanbul (IETT):** Anlık araç konumu, yön, yakın durak bilgisi. İBB/IETT'nin tüm hat listeleri, durak listeleri, mevcut garajları, canlı kaza lokasyonları ve anlık donanım verileri.
98
98
  - **Bursa (Burulaş):** Plaka, hız, doluluk oranı gösterimi
99
99
 
100
100
  ### 🌍 Deprem Bilgileri (AFAD)
@@ -270,6 +270,18 @@ turkiyem sehir izmir
270
270
  turkiyem durak konak
271
271
  ```
272
272
 
273
+ ### İBB/IETT Özel Sorguları
274
+
275
+ ```bash
276
+ turkiyem ibb hatlar # Tüm IETT hatlarını listeler
277
+ turkiyem ibb hatlar 34 # "34" içeren hatları listeler
278
+ turkiyem ibb duraklar # Tüm IETT duraklarını listeler
279
+ turkiyem ibb duraklar 10001 # "10001" koduyla eşleşen durakları bulur
280
+ turkiyem ibb filo # Sahadaki tüm araçların konum ve hız bilgisi
281
+ turkiyem ibb garaj # Garaj adları ve koordinat bilgileri
282
+ turkiyem ibb kaza # Güncel kaza lokasyonlarını göster
283
+ ```
284
+
273
285
  ### Canlı Konum
274
286
 
275
287
  ```bash
@@ -364,6 +376,7 @@ turkiyem/
364
376
  │ │ ├── hava.js # Hava durumu komutları
365
377
  │ │ ├── doviz.js # TCMB döviz komutu
366
378
  │ │ ├── menu.js # İnteraktif menü sistemi
379
+ │ │ ├── ibb.js # IBB/IETT genel servisleri
367
380
  │ │ └── temizle.js # Cache temizleme
368
381
  │ ├── services/
369
382
  │ │ ├── egoService.js # Ankara EGO API
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "turkiyem",
3
- "version": "1.10.3",
3
+ "version": "1.11.0",
4
4
  "description": "Türkiye Toplu Taşıma ve Deprem CLI aracı - AFAD deprem verileri, EGO hat saatleri ve IETT SOAP/GTFS bilgileri",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
- import ora from 'ora';
3
2
  import prompts from 'prompts';
4
3
  import boxen from 'boxen';
4
+ import { withSpinner } from '../utils/spinnerWrapper.js';
5
5
  import { fetchEarthquakes, fetchByMagnitude } from '../services/afadService.js';
6
6
  import { createEarthquakeTable } from '../utils/display.js';
7
7
 
@@ -42,41 +42,35 @@ async function displayPaginatedEarthquakes(earthquakes) {
42
42
  }
43
43
 
44
44
  export async function depremSon24() {
45
- const spinner = ora('AFAD verileri alınıyor (son 24 saat)...').start();
46
-
47
- try {
48
- const earthquakes = await fetchEarthquakes('son24');
49
-
50
- if (!earthquakes || earthquakes.length === 0) {
51
- spinner.info('Son 24 saatte kayıtlı deprem bulunamadı.');
52
- return;
53
- }
54
-
55
- spinner.succeed(`${earthquakes.length} deprem bulundu (son 24 saat)`);
56
- console.log('');
57
- await displayPaginatedEarthquakes(earthquakes);
58
- } catch (err) {
59
- spinner.fail(boxen(chalk.red(err.message), { padding: 1, borderColor: 'red' }));
45
+ const earthquakes = await withSpinner(
46
+ 'AFAD verileri alınıyor (son 24 saat)...',
47
+ () => fetchEarthquakes('son24')
48
+ );
49
+
50
+ if (!earthquakes) return; // fail message already printed by wrapper
51
+ if (earthquakes.length === 0) {
52
+ console.log(chalk.yellow('Son 24 saatte kayıtlı deprem bulunamadı.'));
53
+ return;
60
54
  }
55
+
56
+ console.log(chalk.green(`✔ ${earthquakes.length} deprem bulundu (son 24 saat)\n`));
57
+ await displayPaginatedEarthquakes(earthquakes);
61
58
  }
62
59
 
63
60
  export async function deprem7Gun() {
64
- const spinner = ora('AFAD verileri alınıyor (son 7 gün)...').start();
65
-
66
- try {
67
- const earthquakes = await fetchEarthquakes('7gun');
68
-
69
- if (!earthquakes || earthquakes.length === 0) {
70
- spinner.info('Son 7 günde kayıtlı deprem bulunamadı.');
71
- return;
72
- }
73
-
74
- spinner.succeed(`${earthquakes.length} deprem bulundu (son 7 gün)`);
75
- console.log('');
76
- await displayPaginatedEarthquakes(earthquakes);
77
- } catch (err) {
78
- spinner.fail(boxen(chalk.red(err.message), { padding: 1, borderColor: 'red' }));
61
+ const earthquakes = await withSpinner(
62
+ 'AFAD verileri alınıyor (son 7 gün)...',
63
+ () => fetchEarthquakes('7gun')
64
+ );
65
+
66
+ if (!earthquakes) return;
67
+ if (earthquakes.length === 0) {
68
+ console.log(chalk.yellow('Son 7 günde kayıtlı deprem bulunamadı.'));
69
+ return;
79
70
  }
71
+
72
+ console.log(chalk.green(`✔ ${earthquakes.length} deprem bulundu (son 7 gün)\n`));
73
+ await displayPaginatedEarthquakes(earthquakes);
80
74
  }
81
75
 
82
76
  export async function depremBuyukluk(value) {
@@ -86,20 +80,17 @@ export async function depremBuyukluk(value) {
86
80
  return;
87
81
  }
88
82
 
89
- const spinner = ora(`Büyüklüğü >= ${min} olan depremler aranıyor...`).start();
90
-
91
- try {
92
- const earthquakes = await fetchByMagnitude(min);
83
+ const earthquakes = await withSpinner(
84
+ `Büyüklüğü >= ${min} olan depremler aranıyor...`,
85
+ () => fetchByMagnitude(min)
86
+ );
93
87
 
94
- if (!earthquakes || earthquakes.length === 0) {
95
- spinner.info(`Büyüklüğü >= ${min} olan deprem bulunamadı (son 7 gün).`);
96
- return;
97
- }
98
-
99
- spinner.succeed(`${earthquakes.length} deprem bulundu (büyüklük >= ${min})`);
100
- console.log('');
101
- await displayPaginatedEarthquakes(earthquakes);
102
- } catch (err) {
103
- spinner.fail(boxen(chalk.red(err.message), { padding: 1, borderColor: 'red' }));
88
+ if (!earthquakes) return;
89
+ if (earthquakes.length === 0) {
90
+ console.log(chalk.yellow(`Büyüklüğü >= ${min} olan deprem bulunamadı (son 7 gün).`));
91
+ return;
104
92
  }
93
+
94
+ console.log(chalk.green(`✔ ${earthquakes.length} deprem bulundu (büyüklük >= ${min})\n`));
95
+ await displayPaginatedEarthquakes(earthquakes);
105
96
  }
@@ -15,17 +15,20 @@ export async function durakSorgula(stopId) {
15
15
  }
16
16
 
17
17
  const city = getCity();
18
- if (city === 'adana') {
19
- await queryAdanaStop(stopId);
20
- } else if (city === 'antalya') {
21
- await queryAntalyaStop(stopId);
22
- } else if (city === 'bursa') {
23
- await queryBursaStop(stopId);
24
- } else if (city === 'izmir') {
25
- await queryIzmirStop(stopId);
18
+ const cityHandlers = {
19
+ adana: queryAdanaStop,
20
+ antalya: queryAntalyaStop,
21
+ bursa: queryBursaStop,
22
+ izmir: queryIzmirStop
23
+ };
24
+
25
+ const handler = cityHandlers[city];
26
+ if (handler) {
27
+ await handler(stopId);
26
28
  } else {
27
- console.log(chalk.yellow('Durak sorgulaması şu an sadece Adana, Antalya, Bursa ve İzmir için destekleniyor.'));
28
- console.log(chalk.cyan('Şehri değiştirmek için: turkiyem sehir adana | antalya | bursa | izmir'));
29
+ const supported = Object.keys(cityHandlers).join(' | ');
30
+ console.log(chalk.yellow(`Durak sorgulaması şu an sadece Adana, Antalya, Bursa ve İzmir için destekleniyor.`));
31
+ console.log(chalk.cyan(`Şehri değiştirmek için: turkiyem sehir ${supported}`));
29
32
  return;
30
33
  }
31
34
  }
@@ -47,26 +47,24 @@ export async function hatSorgula(hatNo) {
47
47
  return;
48
48
  }
49
49
 
50
- if (city === 'ankara') {
51
- await queryEgo(hatNo);
52
- } else if (city === 'istanbul') {
53
- await queryIett(hatNo);
54
- } else if (city === 'adana') {
55
- await queryAdana(hatNo);
56
- } else if (city === 'antalya') {
57
- await queryAntalya(hatNo);
58
- } else if (city === 'bursa') {
59
- await queryBursa(hatNo);
60
- } else if (city === 'izmir') {
61
- await queryIzmir(hatNo);
62
- } else if (city === 'trabzon') {
63
- await queryTrabzon(hatNo);
64
- } else if (city === 'samsun') {
65
- await querySamsun(hatNo);
66
- } else if (city === 'mersin') {
67
- await queryMersin(hatNo);
50
+ const handlers = {
51
+ ankara: queryEgo,
52
+ istanbul: queryIett,
53
+ adana: queryAdana,
54
+ antalya: queryAntalya,
55
+ bursa: queryBursa,
56
+ izmir: queryIzmir,
57
+ trabzon: queryTrabzon,
58
+ samsun: querySamsun,
59
+ mersin: queryMersin
60
+ };
61
+
62
+ const handler = handlers[city];
63
+ if (handler) {
64
+ await handler(hatNo);
68
65
  } else {
69
- console.log(chalk.red(`Desteklenmeyen şehir: ${city}. ankara, istanbul, adana, antalya, bursa, izmir, trabzon, samsun veya mersin seçin.`));
66
+ const supportedList = Object.keys(handlers).join(', ');
67
+ console.log(chalk.red(`Desteklenmeyen şehir: ${city}. Lütfen şu şehirlerden birini seçin: ${supportedList}.`));
70
68
  }
71
69
  }
72
70
 
@@ -0,0 +1,176 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import {
4
+ fetchIettAllRoutes,
5
+ fetchIettAllStops,
6
+ fetchIettGarages,
7
+ fetchIettFleetPositions,
8
+ fetchIettAccidentLocations,
9
+ } from '../services/iettService.js';
10
+ import {
11
+ createIbbHatListTable,
12
+ createIbbDurakListTable,
13
+ createIbbGarajTable,
14
+ createIbbFiloKonumTable,
15
+ createIbbKazaTable,
16
+ } from '../utils/display.js';
17
+
18
+ /**
19
+ * İBB/IETT hat listesi sorgula.
20
+ * Opsiyonel arama parametresiyle filtrele.
21
+ */
22
+ export async function ibbHatlar(arama) {
23
+ const spinner = ora('İBB/IETT hat listesi alınıyor...').start();
24
+ try {
25
+ const routes = await fetchIettAllRoutes(arama || undefined);
26
+
27
+ if (!routes || routes.length === 0) {
28
+ spinner.info(chalk.yellow(arama
29
+ ? `"${arama}" aramasıyla eşleşen IETT hattı bulunamadı.`
30
+ : 'IETT hat verisi bulunamadı.'));
31
+ return;
32
+ }
33
+
34
+ // Eğer arama varsa ve tam veri geldiyse client-side filtre
35
+ let filtered = routes;
36
+ if (arama && routes.length > 10) {
37
+ const query = arama.toUpperCase();
38
+ filtered = routes.filter(r => {
39
+ const code = (r.SHATKODU || r.HAT_KODU || '').toUpperCase();
40
+ const name = (r.HATADI || r.HAT_ADI || '').toUpperCase();
41
+ return code.includes(query) || name.includes(query);
42
+ });
43
+ if (filtered.length === 0) {
44
+ spinner.info(chalk.yellow(`"${arama}" aramasıyla eşleşen IETT hattı bulunamadı.`));
45
+ return;
46
+ }
47
+ }
48
+
49
+ spinner.succeed(`İBB/IETT hat listesi alındı (${filtered.length} hat)`);
50
+ console.log('');
51
+ console.log(chalk.white.bold(' İBB/IETT Hat Listesi'));
52
+ if (filtered.length > 50) {
53
+ console.log(chalk.gray(` Toplam ${filtered.length} hat bulundu. İlk 50 tanesi gösteriliyor.`));
54
+ console.log(chalk.gray(` Filtrelemek için: turkiyem ibb hatlar <arama>`));
55
+ console.log(createIbbHatListTable(filtered.slice(0, 50)));
56
+ } else {
57
+ console.log(createIbbHatListTable(filtered));
58
+ }
59
+ } catch (err) {
60
+ spinner.fail(chalk.red(err.message));
61
+ }
62
+ }
63
+
64
+ /**
65
+ * İBB/IETT durak listesi sorgula.
66
+ * Opsiyonel arama parametresiyle filtrele.
67
+ */
68
+ export async function ibbDuraklar(arama) {
69
+ const spinner = ora('İBB/IETT durak listesi alınıyor...').start();
70
+ try {
71
+ const stops = await fetchIettAllStops(arama || undefined);
72
+
73
+ if (!stops || stops.length === 0) {
74
+ spinner.info(chalk.yellow(arama
75
+ ? `"${arama}" aramasıyla eşleşen IETT durağı bulunamadı.`
76
+ : 'IETT durak verisi bulunamadı.'));
77
+ return;
78
+ }
79
+
80
+ let filtered = stops;
81
+ if (arama && stops.length > 10) {
82
+ const query = arama.toUpperCase();
83
+ filtered = stops.filter(s => {
84
+ const code = String(s.DURAKKODU || s.DURAK_KODU || '').toUpperCase();
85
+ const name = (s.DURAKADI || s.DURAK_ADI || '').toUpperCase();
86
+ return code.includes(query) || name.includes(query);
87
+ });
88
+ if (filtered.length === 0) {
89
+ spinner.info(chalk.yellow(`"${arama}" aramasıyla eşleşen IETT durağı bulunamadı.`));
90
+ return;
91
+ }
92
+ }
93
+
94
+ spinner.succeed(`İBB/IETT durak listesi alındı (${filtered.length} durak)`);
95
+ console.log('');
96
+ console.log(chalk.white.bold(' İBB/IETT Durak Listesi'));
97
+ if (filtered.length > 50) {
98
+ console.log(chalk.gray(` Toplam ${filtered.length} durak bulundu. İlk 50 tanesi gösteriliyor.`));
99
+ console.log(chalk.gray(` Filtrelemek için: turkiyem ibb duraklar <arama>`));
100
+ console.log(createIbbDurakListTable(filtered.slice(0, 50)));
101
+ } else {
102
+ console.log(createIbbDurakListTable(filtered));
103
+ }
104
+ } catch (err) {
105
+ spinner.fail(chalk.red(err.message));
106
+ }
107
+ }
108
+
109
+ /**
110
+ * IETT tüm filo araç konumlarını göster.
111
+ */
112
+ export async function ibbFilo() {
113
+ const spinner = ora('İBB/IETT filo araç konumları alınıyor...').start();
114
+ try {
115
+ const vehicles = await fetchIettFleetPositions();
116
+
117
+ if (!vehicles || vehicles.length === 0) {
118
+ spinner.info(chalk.yellow('IETT filo konum verisi bulunamadı.'));
119
+ return;
120
+ }
121
+
122
+ spinner.succeed(`İBB/IETT filo konum verisi alındı (${vehicles.length} araç)`);
123
+ console.log('');
124
+ console.log(chalk.white.bold(' İBB/IETT Filo Araç Konumları'));
125
+ if (vehicles.length > 50) {
126
+ console.log(chalk.gray(` Toplam ${vehicles.length} araç. İlk 50 tanesi gösteriliyor.`));
127
+ }
128
+ console.log(createIbbFiloKonumTable(vehicles));
129
+ } catch (err) {
130
+ spinner.fail(chalk.red(err.message));
131
+ }
132
+ }
133
+
134
+ /**
135
+ * IETT garaj bilgilerini göster.
136
+ */
137
+ export async function ibbGaraj() {
138
+ const spinner = ora('İBB/IETT garaj bilgileri alınıyor...').start();
139
+ try {
140
+ const garages = await fetchIettGarages();
141
+
142
+ if (!garages || garages.length === 0) {
143
+ spinner.info(chalk.yellow('IETT garaj verisi bulunamadı.'));
144
+ return;
145
+ }
146
+
147
+ spinner.succeed(`İBB/IETT garaj bilgileri alındı (${garages.length} garaj)`);
148
+ console.log('');
149
+ console.log(chalk.white.bold(' İBB/IETT Garaj Bilgileri'));
150
+ console.log(createIbbGarajTable(garages));
151
+ } catch (err) {
152
+ spinner.fail(chalk.red(err.message));
153
+ }
154
+ }
155
+
156
+ /**
157
+ * IETT kaza lokasyonlarını göster.
158
+ */
159
+ export async function ibbKaza() {
160
+ const spinner = ora('İBB/IETT kaza lokasyonları alınıyor...').start();
161
+ try {
162
+ const accidents = await fetchIettAccidentLocations();
163
+
164
+ if (!accidents || accidents.length === 0) {
165
+ spinner.info(chalk.yellow('Şu an kayıtlı kaza lokasyonu bulunmuyor.'));
166
+ return;
167
+ }
168
+
169
+ spinner.succeed(`İBB/IETT kaza lokasyonları alındı (${accidents.length} kayıt)`);
170
+ console.log('');
171
+ console.log(chalk.white.bold(' İBB/IETT Kaza Lokasyonları'));
172
+ console.log(createIbbKazaTable(accidents));
173
+ } catch (err) {
174
+ spinner.fail(chalk.red(err.message));
175
+ }
176
+ }
@@ -0,0 +1,251 @@
1
+ import chalk from 'chalk';
2
+ import { withSpinner } from '../utils/spinnerWrapper.js';
3
+ import {
4
+ getWaterOutages,
5
+ getDamStatus,
6
+ getDamAndWells,
7
+ getDailyWaterProduction,
8
+ getWaterProductionDistribution,
9
+ getBranches,
10
+ getCashDesks,
11
+ getWeeklyWaterAnalysis,
12
+ getPeripheryWaterAnalysis,
13
+ getDamWaterQuality
14
+ } from '../services/izsuService.js';
15
+ import {
16
+ createWaterOutagesTable,
17
+ createDamStatusTable,
18
+ createWaterProductionTable,
19
+ createBranchesTable
20
+ } from '../utils/display.js';
21
+ import boxen from 'boxen';
22
+
23
+ async function displayWaterOutages() {
24
+ const result = await withSpinner(
25
+ 'Su kesintileri verisi alınıyor...',
26
+ getWaterOutages,
27
+ 'Su kesintileri verisi başarıyla alındı!'
28
+ );
29
+
30
+ if (!result || result.length === 0) {
31
+ console.log(chalk.yellow('\nŞu anda planlı veya arıza kaynaklı su kesintisi bulunmamaktadır.'));
32
+ return;
33
+ }
34
+
35
+ console.log(chalk.bold.cyan('\n🚿 İZSU Su Kesintileri:\n'));
36
+ console.log(createWaterOutagesTable(result));
37
+ }
38
+
39
+ async function displayDamStatus() {
40
+ const result = await withSpinner(
41
+ 'Baraj ve kuyu verileri alınıyor...',
42
+ () => Promise.all([getDamStatus(), getDamAndWells()]),
43
+ 'Baraj ve kuyu verileri başarıyla alındı!'
44
+ );
45
+
46
+ if (!result) return;
47
+ const [dams, damsAndWells] = result;
48
+
49
+ if (!dams || dams.length === 0) {
50
+ console.log(chalk.red('\nBaraj verisi bulunamadı.'));
51
+ } else {
52
+ console.log(chalk.bold.cyan('\n💧 İZSU Baraj Doluluk Durumları:\n'));
53
+ console.log(createDamStatusTable(dams));
54
+ }
55
+
56
+ if (damsAndWells && damsAndWells.length > 0) {
57
+ console.log(chalk.bold.cyan('\n🚰 Baraj ve Kuyular:\n'));
58
+ damsAndWells.forEach(dw => {
59
+ console.log(chalk.green(`- ${dw.Adi || 'Bilinmeyen'}`));
60
+ });
61
+ }
62
+ }
63
+
64
+ async function displayWaterProduction(options) {
65
+ if (options.gunluk) {
66
+ const result = await withSpinner(
67
+ 'Günlük su üretimi verisi alınıyor...',
68
+ getDailyWaterProduction,
69
+ 'Günlük su üretimi verisi başarıyla alındı!'
70
+ );
71
+
72
+ if (!result || !result.BarajKuyuUretimleri || result.BarajKuyuUretimleri.length === 0) {
73
+ console.log(chalk.yellow('\nGünlük su üretimi verisi bulunamadı.'));
74
+ return;
75
+ }
76
+
77
+ console.log(chalk.bold.cyan(`\n🌊 İZSU Günlük Su Üretimi (${result.UretimTarihi.split('T')[0]}):\n`));
78
+ console.log(createWaterProductionTable(result));
79
+ } else {
80
+ const year = options.yil || new Date().getFullYear();
81
+ const result = await withSpinner(
82
+ `${year} yılı su üretimi verisi alınıyor...`,
83
+ () => getWaterProductionDistribution(year),
84
+ `${year} yılı su üretimi verisi başarıyla alındı!`
85
+ );
86
+
87
+ if (!result || result.length === 0) {
88
+ console.log(chalk.yellow(`\n${year} yılına ait üretim dağılımı bulunamadı.`));
89
+ return;
90
+ }
91
+
92
+ console.log(chalk.bold.cyan(`\n🌊 İZSU Su Üretimi Dağılımı (${year}):\n`));
93
+
94
+ // Group by month
95
+ const groupedByMonth = {};
96
+ result.forEach(item => {
97
+ if (!groupedByMonth[item.Ay]) groupedByMonth[item.Ay] = [];
98
+ groupedByMonth[item.Ay].push(item);
99
+ });
100
+
101
+ Object.keys(groupedByMonth).sort((a, b) => b - a).forEach(month => {
102
+ console.log(chalk.bold.yellow(`${month}. Ay`));
103
+ console.log(createWaterProductionTable({ BarajKuyuUretimleri: groupedByMonth[month] }));
104
+ });
105
+ }
106
+ }
107
+
108
+ async function displayBranches(options) {
109
+ if (options.vezne) {
110
+ const result = await withSpinner(
111
+ 'Vezneler verisi alınıyor...',
112
+ getCashDesks,
113
+ 'Vezneler verisi başarıyla alındı!'
114
+ );
115
+
116
+ if (!result || result.length === 0) {
117
+ console.log(chalk.yellow('\nVezne bulunamadı.'));
118
+ return;
119
+ }
120
+
121
+ console.log(chalk.bold.cyan('\n💳 İZSU Vezneleri:\n'));
122
+ console.log(createBranchesTable(result, true));
123
+ } else {
124
+ const result = await withSpinner(
125
+ 'Şubeler verisi alınıyor...',
126
+ getBranches,
127
+ 'Şubeler verisi başarıyla alındı!'
128
+ );
129
+
130
+ if (!result || result.length === 0) {
131
+ console.log(chalk.yellow('\nŞube bulunamadı.'));
132
+ return;
133
+ }
134
+
135
+ console.log(chalk.bold.cyan('\n🏢 İZSU Şubeleri:\n'));
136
+ console.log(createBranchesTable(result, false));
137
+ }
138
+ }
139
+
140
+ async function displayAnalysis(options) {
141
+ if (options.cevre) {
142
+ const result = await withSpinner(
143
+ 'Çevre ilçe su analizi raporları alınıyor...',
144
+ getPeripheryWaterAnalysis,
145
+ 'Çevre ilçe analiz verisi başarıyla alındı!'
146
+ );
147
+
148
+ if (!result || result.length === 0) {
149
+ console.log(chalk.yellow('\nAnaliz verisi bulunamadı.'));
150
+ return;
151
+ }
152
+
153
+ console.log(chalk.bold.cyan('\n🔬 Çevre İlçe Su Analizleri:\n'));
154
+ result.forEach(ilce => {
155
+ console.log(chalk.bold.yellow(`📍 ${ilce.IlceAdi || 'Bilinmeyen İlçe'}`));
156
+ if (ilce.Noktalar && ilce.Noktalar.length > 0) {
157
+ ilce.Noktalar.forEach(nokta => {
158
+ console.log(` 🔸 ${nokta.Adres || nokta.NoktaKodu || 'Bilinmeyen Nokta'}`);
159
+ });
160
+ }
161
+ });
162
+ console.log(chalk.gray(`\nNot: Tüm parametreler için detaylar çok uzun olduğu için sadece analiz noktaları gösterilmektedir.`));
163
+
164
+ } else if (options.baraj) {
165
+ const result = await withSpinner(
166
+ 'Baraj su kalite raporları alınıyor...',
167
+ getDamWaterQuality,
168
+ 'Baraj kalite verisi başarıyla alındı!'
169
+ );
170
+
171
+ if (!result || !result.BarajAnalizleri || result.BarajAnalizleri.length === 0) {
172
+ console.log(chalk.yellow('\nAnaliz verisi bulunamadı.'));
173
+ return;
174
+ }
175
+
176
+ console.log(chalk.bold.cyan('\n📊 Baraj Su Kalite Raporları:\n'));
177
+ result.BarajAnalizleri.forEach(baraj => {
178
+ console.log(chalk.bold.green(`🌊 ${baraj.BarajAdi || 'Bilinmeyen Baraj'}`));
179
+ console.log(` Tarih: ${baraj.Tarih ? baraj.Tarih.split('T')[0] : '-'}`);
180
+ });
181
+ console.log(chalk.gray(`\nNot: Tüm parametreler için detaylar çok uzun olduğu için sadece baraj listesi gösterilmektedir.`));
182
+
183
+ } else {
184
+ const result = await withSpinner(
185
+ 'Haftalık su analizi raporları alınıyor...',
186
+ getWeeklyWaterAnalysis,
187
+ 'Haftalık analiz verisi başarıyla alındı!'
188
+ );
189
+
190
+ if (!result || result.length === 0) {
191
+ console.log(chalk.yellow('\nAnaliz verisi bulunamadı.'));
192
+ return;
193
+ }
194
+
195
+ console.log(chalk.bold.cyan('\n🔬 Haftalık Su Analizleri:\n'));
196
+ if (result.TumAnalizler && result.TumAnalizler.length > 0) {
197
+ result.TumAnalizler.forEach(analiz => {
198
+ console.log(chalk.bold.yellow(`📍 ${analiz.NoktaTanimi || 'Bilinmeyen Nokta'}`));
199
+ console.log(` Tarih: ${analiz.Tarih ? analiz.Tarih.split('T')[0] : '-'}`);
200
+ });
201
+ }
202
+ console.log(chalk.gray(`\nNot: Tüm parametreler için detaylar çok uzun olduğu için sadece analiz noktaları gösterilmektedir.`));
203
+ }
204
+ }
205
+
206
+ export function registerIzsuCommands(program) {
207
+ const izsuCmd = program
208
+ .command('izsu')
209
+ .description('İZSU açık veri servisleri (Kesintiler, Barajlar, Üretim, Şubeler)');
210
+
211
+ izsuCmd
212
+ .command('kesinti')
213
+ .description('Mevcut su kesintilerini listeler')
214
+ .action(async () => {
215
+ await displayWaterOutages();
216
+ });
217
+
218
+ izsuCmd
219
+ .command('baraj')
220
+ .description('Barajların ve kuyuların güncel durumunu listeler')
221
+ .action(async () => {
222
+ await displayDamStatus();
223
+ });
224
+
225
+ izsuCmd
226
+ .command('uretim')
227
+ .description('Su üretimi verilerini listeler (Varsayılan: yıllık dağılım)')
228
+ .option('-g, --gunluk', 'Günlük su üretimini gösterir')
229
+ .option('-y, --yil <year>', 'Belirtilen yıla ait su üretim dağılımını gösterir', new Date().getFullYear().toString())
230
+ .action(async (options) => {
231
+ await displayWaterProduction(options);
232
+ });
233
+
234
+ izsuCmd
235
+ .command('sube')
236
+ .description('İZSU şubelerini ve veznelerini listeler (Varsayılan: Şubeler)')
237
+ .option('-v, --vezne', 'Sadece vezneleri gösterir')
238
+ .action(async (options) => {
239
+ await displayBranches(options);
240
+ });
241
+
242
+ izsuCmd
243
+ .command('analiz')
244
+ .description('Su analizi raporlarını listeler')
245
+ .option('-h, --haftalik', 'Haftalık su analiz raporlarını gösterir')
246
+ .option('-c, --cevre', 'Çevre ilçe su analiz raporlarını gösterir')
247
+ .option('-b, --baraj', 'Baraj su kalite raporlarını gösterir')
248
+ .action(async (options) => {
249
+ await displayAnalysis(options);
250
+ });
251
+ }