@blunking/codexlink 0.1.2 → 0.1.10

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.
@@ -59,7 +59,7 @@ function Test-TelegramTokenFormat {
59
59
  return $Value -match '^\d{6,}:[A-Za-z0-9_-]{20,}$'
60
60
  }
61
61
 
62
- function Test-AllowedChatIdsFormat {
62
+ function Test-AllowedChatIdsFormat {
63
63
  param([string]$Value)
64
64
  if (-not $Value) { return $false }
65
65
  $parts = @($Value -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ })
@@ -69,9 +69,143 @@ function Test-AllowedChatIdsFormat {
69
69
  return $false
70
70
  }
71
71
  }
72
- return $true
73
- }
74
-
72
+ return $true
73
+ }
74
+
75
+ function Invoke-TelegramSetupRequest {
76
+ param(
77
+ [string]$Token,
78
+ [string]$Method,
79
+ [hashtable]$Body = @{}
80
+ )
81
+
82
+ $uri = "https://api.telegram.org/bot$Token/$Method"
83
+ try {
84
+ return Invoke-RestMethod -Method Post -Uri $uri -ContentType "application/json" -Body ($Body | ConvertTo-Json -Depth 10) -TimeoutSec 35
85
+ } catch {
86
+ $message = $_.Exception.Message
87
+ if ($_.ErrorDetails -and $_.ErrorDetails.Message) {
88
+ $message = $_.ErrorDetails.Message
89
+ }
90
+ throw "Telegram $Method fehlgeschlagen: $message"
91
+ }
92
+ }
93
+
94
+ function Get-TelegramBotInfo {
95
+ param([string]$Token)
96
+ $response = Invoke-TelegramSetupRequest -Token $Token -Method "getMe"
97
+ if (-not $response.ok) {
98
+ throw "Telegram Bot Token wurde von Telegram abgelehnt."
99
+ }
100
+ return $response.result
101
+ }
102
+
103
+ function Get-TelegramUpdatesForSetup {
104
+ param(
105
+ [string]$Token,
106
+ [long]$Offset = 0,
107
+ [int]$TimeoutSeconds = 0
108
+ )
109
+
110
+ $body = @{
111
+ timeout = $TimeoutSeconds
112
+ limit = 20
113
+ allowed_updates = @("message", "edited_message", "channel_post")
114
+ }
115
+ if ($Offset -gt 0) {
116
+ $body["offset"] = $Offset
117
+ }
118
+ $response = Invoke-TelegramSetupRequest -Token $Token -Method "getUpdates" -Body $body
119
+ if (-not $response.ok) {
120
+ return @()
121
+ }
122
+ return @($response.result)
123
+ }
124
+
125
+ function Get-TelegramUpdateId {
126
+ param($Update)
127
+ try {
128
+ return [long]$Update.update_id
129
+ } catch {
130
+ return 0
131
+ }
132
+ }
133
+
134
+ function Get-TelegramChatFromUpdate {
135
+ param($Update)
136
+
137
+ $message = $null
138
+ if ($Update.message) {
139
+ $message = $Update.message
140
+ } elseif ($Update.edited_message) {
141
+ $message = $Update.edited_message
142
+ } elseif ($Update.channel_post) {
143
+ $message = $Update.channel_post
144
+ }
145
+
146
+ if (-not $message -or -not $message.chat -or -not $message.chat.id) {
147
+ return $null
148
+ }
149
+
150
+ $chat = $message.chat
151
+ $title = ""
152
+ if ($chat.title) {
153
+ $title = [string]$chat.title
154
+ } elseif ($chat.username) {
155
+ $title = "@" + [string]$chat.username
156
+ } elseif ($chat.first_name -or $chat.last_name) {
157
+ $title = ((@($chat.first_name, $chat.last_name) | Where-Object { $_ }) -join " ")
158
+ }
159
+
160
+ return [ordered]@{
161
+ chat_id = [string]$chat.id
162
+ chat_type = [string]$chat.type
163
+ title = $title
164
+ update_id = Get-TelegramUpdateId -Update $Update
165
+ }
166
+ }
167
+
168
+ function Wait-TelegramPairingChat {
169
+ param(
170
+ [string]$Token,
171
+ $BotInfo,
172
+ [int]$TimeoutSeconds = 90
173
+ )
174
+
175
+ $baseline = Get-TelegramUpdatesForSetup -Token $Token -TimeoutSeconds 0
176
+ $offset = 0
177
+ foreach ($update in $baseline) {
178
+ $offset = [Math]::Max($offset, (Get-TelegramUpdateId -Update $update) + 1)
179
+ }
180
+
181
+ $botName = if ($BotInfo.username) { "@" + [string]$BotInfo.username } else { "deinen Bot" }
182
+ Write-Host ""
183
+ Write-Host "Telegram Pairing" -ForegroundColor Cyan
184
+ Write-Host "Oeffne Telegram und sende jetzt eine neue Nachricht an $botName." -ForegroundColor White
185
+ Write-Host "Fuer Gruppen: Bot in die Gruppe einladen und dort kurz '$botName connect' schreiben." -ForegroundColor DarkGray
186
+ Write-Host "Ich erkenne die Chat-ID automatisch. Du musst keine ID suchen." -ForegroundColor DarkGray
187
+ Write-Host ""
188
+
189
+ $deadline = (Get-Date).AddSeconds($TimeoutSeconds)
190
+ while ((Get-Date) -lt $deadline) {
191
+ $remaining = [Math]::Max(1, [int]([Math]::Ceiling(($deadline - (Get-Date)).TotalSeconds)))
192
+ $pollTimeout = [Math]::Min(10, $remaining)
193
+ $updates = Get-TelegramUpdatesForSetup -Token $Token -Offset $offset -TimeoutSeconds $pollTimeout
194
+ foreach ($update in $updates) {
195
+ $updateId = Get-TelegramUpdateId -Update $update
196
+ if ($updateId -gt 0) {
197
+ $offset = [Math]::Max($offset, $updateId + 1)
198
+ }
199
+ $chat = Get-TelegramChatFromUpdate -Update $update
200
+ if ($chat -and $chat.chat_id) {
201
+ return $chat
202
+ }
203
+ }
204
+ }
205
+
206
+ return $null
207
+ }
208
+
75
209
  function Prompt-RequiredValue {
76
210
  param(
77
211
  [string]$Prompt,
@@ -148,53 +282,58 @@ if (-not (Test-AllowedChatIdsFormat -Value $currentAllowedChatIds)) {
148
282
  $currentAllowedChatIds = [string]$envValues["TELEGRAM_ALLOWED_CHAT_ID"]
149
283
  }
150
284
 
151
- $needsToken = -not (Test-TelegramTokenFormat -Value $currentToken)
152
- $needsChatIds = -not (Test-AllowedChatIdsFormat -Value $currentAllowedChatIds)
153
- $changed = $false
154
-
155
- if ($EnsureConfigured -and -not $needsToken -and -not $needsChatIds) {
156
- $result = [ordered]@{
157
- ok = $true
158
- changed = $false
159
- profile = $profileAgent
160
- state_dir = $stateDir
161
- env_path = $envPath
162
- missing = @()
163
- }
164
- if ($Json) {
165
- $result | ConvertTo-Json -Depth 6
166
- } else {
167
- Write-Host "Telegram ist bereits eingerichtet fuer Profil '$profileAgent'." -ForegroundColor Green
168
- Write-Host "State-Ordner: $stateDir"
169
- }
170
- exit 0
171
- }
172
-
173
- if ($EnsureConfigured -and $Json -and ($needsToken -or $needsChatIds)) {
174
- $missing = @()
175
- if ($needsToken) { $missing += "bot_token" }
176
- if ($needsChatIds) { $missing += "allowed_chat_ids" }
177
- [ordered]@{
178
- ok = $false
179
- changed = $false
180
- profile = $profileAgent
181
- state_dir = $stateDir
182
- env_path = $envPath
183
- missing = $missing
184
- } | ConvertTo-Json -Depth 6
185
- exit 2
186
- }
285
+ $needsToken = -not (Test-TelegramTokenFormat -Value $currentToken)
286
+ $needsChatIds = -not (Test-AllowedChatIdsFormat -Value $currentAllowedChatIds)
287
+ $changed = $false
288
+ $tokenWasPrompted = $false
289
+
290
+ if ($EnsureConfigured -and -not $needsToken -and -not $needsChatIds) {
291
+ $result = [ordered]@{
292
+ ok = $true
293
+ changed = $false
294
+ profile = $profileAgent
295
+ state_dir = $stateDir
296
+ env_path = $envPath
297
+ missing = @()
298
+ optional = @()
299
+ }
300
+ if ($Json) {
301
+ $result | ConvertTo-Json -Depth 6
302
+ } else {
303
+ Write-Host "Telegram ist bereits eingerichtet fuer Profil '$profileAgent'." -ForegroundColor Green
304
+ Write-Host "State-Ordner: $stateDir"
305
+ }
306
+ exit 0
307
+ }
308
+
309
+ if ($EnsureConfigured -and $Json -and $needsToken) {
310
+ $missing = @()
311
+ if ($needsToken) { $missing += "bot_token" }
312
+ [ordered]@{
313
+ ok = $false
314
+ changed = $false
315
+ profile = $profileAgent
316
+ state_dir = $stateDir
317
+ env_path = $envPath
318
+ missing = $missing
319
+ optional = @(
320
+ "allowed_chat_ids"
321
+ )
322
+ } | ConvertTo-Json -Depth 6
323
+ exit 2
324
+ }
187
325
 
188
326
  if (-not $Json) {
189
327
  Write-Host ""
190
328
  Write-Host "CodexLink Telegram Setup" -ForegroundColor Cyan
191
329
  Write-Host "Profil: $profileAgent"
192
330
  Write-Host "Lokaler State-Ordner: $stateDir"
193
- Write-Host ""
194
- Write-Host "Ich speichere die Telegram-Werte automatisch an die richtige lokale Stelle." -ForegroundColor DarkGray
195
- Write-Host "Du musst keine .env-Datei selbst suchen." -ForegroundColor DarkGray
196
- Write-Host ""
197
- }
331
+ Write-Host ""
332
+ Write-Host "Ich speichere die Telegram-Werte automatisch an die richtige lokale Stelle." -ForegroundColor DarkGray
333
+ Write-Host "Du musst keine .env-Datei selbst suchen." -ForegroundColor DarkGray
334
+ Write-Host "Die Chat-ID wird automatisch erkannt. Du musst sie nicht wissen." -ForegroundColor DarkGray
335
+ Write-Host ""
336
+ }
198
337
 
199
338
  if ($needsToken) {
200
339
  $currentToken = Prompt-RequiredValue `
@@ -202,19 +341,39 @@ if ($needsToken) {
202
341
  -CurrentValue $currentToken `
203
342
  -Validator { param($v) Test-TelegramTokenFormat -Value $v } `
204
343
  -ErrorMessage "Bitte einen gueltigen Telegram Bot Token eingeben. Beispiel: 123456789:ABC..."
205
- $envValues["BLUN_TELEGRAM_BOT_TOKEN"] = $currentToken
206
- $changed = $true
207
- }
208
-
209
- if ($needsChatIds) {
210
- $currentAllowedChatIds = Prompt-RequiredValue `
211
- -Prompt "Erlaubte Chat ID(s), komma-getrennt" `
212
- -CurrentValue $currentAllowedChatIds `
213
- -Validator { param($v) Test-AllowedChatIdsFormat -Value $v } `
214
- -ErrorMessage "Bitte mindestens eine numerische Chat-ID eingeben. Mehrere IDs mit Komma trennen."
215
- $envValues["BLUN_TELEGRAM_ALLOWED_CHAT_ID"] = (($currentAllowedChatIds -split "," | ForEach-Object { $_.Trim() } | Where-Object { $_ }) -join ",")
216
- $changed = $true
217
- }
344
+ $envValues["BLUN_TELEGRAM_BOT_TOKEN"] = $currentToken
345
+ $changed = $true
346
+ $tokenWasPrompted = $true
347
+ }
348
+
349
+ if ($needsChatIds -and -not $Json) {
350
+ try {
351
+ $botInfo = Get-TelegramBotInfo -Token $currentToken
352
+ $shouldPair = $tokenWasPrompted -or (-not $EnsureConfigured)
353
+ if ($shouldPair) {
354
+ $pairedChat = Wait-TelegramPairingChat -Token $currentToken -BotInfo $botInfo -TimeoutSeconds 90
355
+ if ($pairedChat -and $pairedChat.chat_id) {
356
+ $currentAllowedChatIds = [string]$pairedChat.chat_id
357
+ $envValues["BLUN_TELEGRAM_ALLOWED_CHAT_ID"] = $currentAllowedChatIds
358
+ $envValues["BLUN_TELEGRAM_PAIRING_DONE"] = "1"
359
+ $changed = $true
360
+ $label = if ($pairedChat.title) { "$($pairedChat.title) ($($pairedChat.chat_type))" } else { $pairedChat.chat_type }
361
+ Write-Host "Gekoppelt: $label -> $currentAllowedChatIds" -ForegroundColor Green
362
+ } else {
363
+ $envValues["BLUN_TELEGRAM_PAIRING_DONE"] = "1"
364
+ Write-Host "Keine Telegram-Nachricht erkannt. Ich starte ohne Allowlist; du kannst spaeter erneut `blun-codex telegram-setup` ausfuehren." -ForegroundColor Yellow
365
+ }
366
+ } else {
367
+ Write-Host "Hinweis: keine Chat-Allowlist gesetzt. Der Bot akzeptiert aktuell alle Chats, die er sehen kann." -ForegroundColor Yellow
368
+ }
369
+ } catch {
370
+ if ($tokenWasPrompted) {
371
+ throw
372
+ }
373
+ Write-Host $_.Exception.Message -ForegroundColor Yellow
374
+ Write-Host "Ich starte ohne Allowlist; du kannst spaeter erneut `blun-codex telegram-setup` ausfuehren." -ForegroundColor Yellow
375
+ }
376
+ }
218
377
 
219
378
  $envValues["BLUN_TELEGRAM_AGENT_NAME"] = $profileAgent
220
379
  $envValues["BLUN_TELEGRAM_STATE_DIR"] = $stateDir