81 行
2.9 KiB
Swift
81 行
2.9 KiB
Swift
|
|
import Foundation
|
||
|
|
|
||
|
|
public final class ImClient: NSObject, URLSessionWebSocketDelegate, @unchecked Sendable {
|
||
|
|
|
||
|
|
public weak var delegate: ImEventDelegate?
|
||
|
|
private var webSocketTask: URLSessionWebSocketTask?
|
||
|
|
private var session: URLSession?
|
||
|
|
private let wsURL: URL
|
||
|
|
private let token: String
|
||
|
|
private let appId: String
|
||
|
|
private var shouldReconnect = false
|
||
|
|
|
||
|
|
public init(wsURL: URL, token: String, appId: String) {
|
||
|
|
self.wsURL = wsURL
|
||
|
|
self.token = token
|
||
|
|
self.appId = appId
|
||
|
|
super.init()
|
||
|
|
}
|
||
|
|
|
||
|
|
public func connect() {
|
||
|
|
shouldReconnect = true
|
||
|
|
var request = URLRequest(url: wsURL)
|
||
|
|
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
|
||
|
|
session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
|
||
|
|
webSocketTask = session?.webSocketTask(with: request)
|
||
|
|
webSocketTask?.resume()
|
||
|
|
receiveMessage()
|
||
|
|
}
|
||
|
|
|
||
|
|
private func receiveMessage() {
|
||
|
|
webSocketTask?.receive { [weak self] result in
|
||
|
|
switch result {
|
||
|
|
case .success(let message):
|
||
|
|
if case .string(let text) = message {
|
||
|
|
self?.handleMessage(text)
|
||
|
|
}
|
||
|
|
self?.receiveMessage()
|
||
|
|
case .failure(let error):
|
||
|
|
self?.delegate?.imClientDidError(error.localizedDescription)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private func handleMessage(_ text: String) {
|
||
|
|
guard let data = text.data(using: .utf8),
|
||
|
|
let msg = try? JSONDecoder().decode(ImMessage.self, from: data) else { return }
|
||
|
|
if msg.chatType == .group {
|
||
|
|
delegate?.imClientDidReceiveGroupMessage(msg)
|
||
|
|
} else {
|
||
|
|
delegate?.imClientDidReceiveMessage(msg)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public func sendMessage(toId: String, chatType: ChatType, msgType: MsgType, content: String) {
|
||
|
|
let payload: [String: Any] = [
|
||
|
|
"type": "chat.send",
|
||
|
|
"data": ["appId": appId, "toId": toId, "chatType": chatType.rawValue,
|
||
|
|
"msgType": msgType.rawValue, "content": content]
|
||
|
|
]
|
||
|
|
guard let data = try? JSONSerialization.data(withJSONObject: payload),
|
||
|
|
let text = String(data: data, encoding: .utf8) else { return }
|
||
|
|
webSocketTask?.send(.string(text)) { _ in }
|
||
|
|
}
|
||
|
|
|
||
|
|
public func disconnect() {
|
||
|
|
shouldReconnect = false
|
||
|
|
webSocketTask?.cancel(with: .normalClosure, reason: nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask,
|
||
|
|
didOpenWithProtocol protocol: String?) {
|
||
|
|
delegate?.imClientDidConnect()
|
||
|
|
}
|
||
|
|
|
||
|
|
public func urlSession(_ session: URLSession, webSocketTask: URLSessionWebSocketTask,
|
||
|
|
didCloseWith closeCode: URLSessionWebSocketTask.CloseCode, reason: Data?) {
|
||
|
|
let reasonStr = reason.flatMap { String(data: $0, encoding: .utf8) }
|
||
|
|
delegate?.imClientDidDisconnect(reason: reasonStr)
|
||
|
|
}
|
||
|
|
}
|