Files
clawdbot/apps/macos/Sources/Clawdbot/ConnectionsStore+Lifecycle.swift
2026-01-04 16:24:17 +01:00

159 lines
5.3 KiB
Swift

import ClawdbotProtocol
import Foundation
extension ConnectionsStore {
func start() {
guard !self.isPreview else { return }
guard self.pollTask == nil else { return }
self.pollTask = Task.detached { [weak self] in
guard let self else { return }
await self.refresh(probe: true)
await self.loadConfig()
while !Task.isCancelled {
try? await Task.sleep(nanoseconds: UInt64(self.interval * 1_000_000_000))
await self.refresh(probe: false)
}
}
}
func stop() {
self.pollTask?.cancel()
self.pollTask = nil
}
func refresh(probe: Bool) async {
guard !self.isRefreshing else { return }
self.isRefreshing = true
defer { self.isRefreshing = false }
do {
let params: [String: AnyCodable] = [
"probe": AnyCodable(probe),
"timeoutMs": AnyCodable(8000),
]
let snap: ProvidersStatusSnapshot = try await GatewayConnection.shared.requestDecoded(
method: .providersStatus,
params: params,
timeoutMs: 12000)
self.snapshot = snap
self.lastSuccess = Date()
self.lastError = nil
} catch {
self.lastError = error.localizedDescription
}
}
func startWhatsAppLogin(force: Bool, autoWait: Bool = true) async {
guard !self.whatsappBusy else { return }
self.whatsappBusy = true
defer { self.whatsappBusy = false }
var shouldAutoWait = false
do {
let params: [String: AnyCodable] = [
"force": AnyCodable(force),
"timeoutMs": AnyCodable(30000),
]
let result: WhatsAppLoginStartResult = try await GatewayConnection.shared.requestDecoded(
method: .webLoginStart,
params: params,
timeoutMs: 35000)
self.whatsappLoginMessage = result.message
self.whatsappLoginQrDataUrl = result.qrDataUrl
self.whatsappLoginConnected = nil
shouldAutoWait = autoWait && result.qrDataUrl != nil
} catch {
self.whatsappLoginMessage = error.localizedDescription
self.whatsappLoginQrDataUrl = nil
self.whatsappLoginConnected = nil
}
await self.refresh(probe: true)
if shouldAutoWait {
Task { await self.waitWhatsAppLogin() }
}
}
func waitWhatsAppLogin(timeoutMs: Int = 120_000) async {
guard !self.whatsappBusy else { return }
self.whatsappBusy = true
defer { self.whatsappBusy = false }
do {
let params: [String: AnyCodable] = [
"timeoutMs": AnyCodable(timeoutMs),
]
let result: WhatsAppLoginWaitResult = try await GatewayConnection.shared.requestDecoded(
method: .webLoginWait,
params: params,
timeoutMs: Double(timeoutMs) + 5000)
self.whatsappLoginMessage = result.message
self.whatsappLoginConnected = result.connected
if result.connected {
self.whatsappLoginQrDataUrl = nil
}
} catch {
self.whatsappLoginMessage = error.localizedDescription
}
await self.refresh(probe: true)
}
func logoutWhatsApp() async {
guard !self.whatsappBusy else { return }
self.whatsappBusy = true
defer { self.whatsappBusy = false }
do {
let result: WhatsAppLogoutResult = try await GatewayConnection.shared.requestDecoded(
method: .webLogout,
params: nil,
timeoutMs: 15000)
self.whatsappLoginMessage = result.cleared
? "Logged out and cleared credentials."
: "No WhatsApp session found."
self.whatsappLoginQrDataUrl = nil
} catch {
self.whatsappLoginMessage = error.localizedDescription
}
await self.refresh(probe: true)
}
func logoutTelegram() async {
guard !self.telegramBusy else { return }
self.telegramBusy = true
defer { self.telegramBusy = false }
do {
let result: TelegramLogoutResult = try await GatewayConnection.shared.requestDecoded(
method: .telegramLogout,
params: nil,
timeoutMs: 15000)
if result.envToken == true {
self.configStatus = "Telegram token still set via env; config cleared."
} else {
self.configStatus = result.cleared
? "Telegram token cleared."
: "No Telegram token configured."
}
await self.loadConfig()
} catch {
self.configStatus = error.localizedDescription
}
await self.refresh(probe: true)
}
}
private struct WhatsAppLoginStartResult: Codable {
let qrDataUrl: String?
let message: String
}
private struct WhatsAppLoginWaitResult: Codable {
let connected: Bool
let message: String
}
private struct WhatsAppLogoutResult: Codable {
let cleared: Bool
}
private struct TelegramLogoutResult: Codable {
let cleared: Bool
let envToken: Bool?
}