Skip to content

Commit e65eb6c

Browse files
committed
update README
1 parent 102336f commit e65eb6c

1 file changed

Lines changed: 154 additions & 38 deletions

File tree

β€ŽREADME.mdβ€Ž

Lines changed: 154 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,78 @@ import OpenAPIURLSession
5151
@main
5252
struct HttpUsageDemo {
5353
static func main() async throws {
54-
55-
let yourAccountToken = ProcessInfo.processInfo.environment["TOKEN"] ?? ""
54+
let token = ProcessInfo.processInfo.environment["TOKEN"] ?? ""
55+
let serverId = ProcessInfo.processInfo.environment["SERVER"] ?? ""
56+
guard !token.isEmpty else {
57+
print("Missing env TOKEN. Example: TOKEN=... swift run HTTPUsageDemo")
58+
return
59+
}
5660

5761
let client = Client(
58-
serverURL: try! Servers.server1(),
62+
serverURL: try! Servers.Server1.url(),
5963
transport: URLSessionTransport(),
60-
middlewares: [AuthenticationMiddleware(token: yourAccountToken)]
64+
middlewares: [AuthenticationMiddleware(token: token)]
6165
)
62-
let response = try await client.getAccount()
66+
let accountResponse = try await client.getAccount()
67+
68+
switch accountResponse {
69+
case .ok(let ok):
70+
let account = try ok.body.json.data
71+
print("Account: \(account?.name ?? "-")")
72+
case .forbidden(let forbidden):
73+
let json = try forbidden.body.json
74+
print("Forbidden: \(json.error ?? "-")")
75+
case .undocumented(let statusCode, let unknownPayload):
76+
print("Unexpected status: \(statusCode), payload: \(unknownPayload)")
77+
}
6378

64-
switch response {
79+
let serversResponse = try await client.getServers()
80+
switch serversResponse {
6581
case .ok(let ok):
66-
if let data = try ok.body.json.data,
67-
let name = data.name {
68-
print("account: \(name)")
82+
let servers = try ok.body.json.data ?? []
83+
print("Servers: \(servers.count)")
84+
if let first = servers.first {
85+
print("First server: \(first.id ?? "-") \(first.name ?? "-") status=\(first.status?.rawValue ?? -1)")
6986
}
87+
case .badRequest(let badRequest):
88+
let json = try badRequest.body.json
89+
print("Bad request: \(json.error ?? "-")")
7090
case .forbidden(let forbidden):
7191
let json = try forbidden.body.json
72-
print(json.error ?? "")
92+
print("Forbidden: \(json.error ?? "-")")
93+
case .notFound(let notFound):
94+
let json = try notFound.body.json
95+
print("Not found: \(json.error ?? "-")")
96+
case .internalServerError(let internalServerError):
97+
let json = try internalServerError.body.json
98+
print("Internal error: \(json.error ?? "-")")
7399
case .undocumented(let statusCode, let unknownPayload):
74-
print("statusCode:\(statusCode), payload: \(unknownPayload)")
100+
print("Unexpected status: \(statusCode), payload: \(unknownPayload)")
101+
}
102+
103+
if !serverId.isEmpty {
104+
let serverResponse = try await client.getServer(path: .init(serverId: serverId))
105+
switch serverResponse {
106+
case .ok(let ok):
107+
let server = try ok.body.json.data
108+
print("Server: \(server?.id ?? "-") \(server?.name ?? "-")")
109+
case .badRequest(let badRequest):
110+
let json = try badRequest.body.json
111+
print("Bad request: \(json.error ?? "-")")
112+
case .notFound(let notFound):
113+
let json = try notFound.body.json
114+
print("Not found: \(json.error ?? "-")")
115+
case .forbidden(let forbidden):
116+
let json = try forbidden.body.json
117+
print("Forbidden: \(json.error ?? "-")")
118+
case .internalServerError(let internalServerError):
119+
let json = try internalServerError.body.json
120+
print("Internal error: \(json.error ?? "-")")
121+
case .undocumented(let statusCode, let unknownPayload):
122+
print("Unexpected status: \(statusCode), payload: \(unknownPayload)")
123+
}
124+
} else {
125+
print("Tip: set env SERVER=... to query a specific server.")
75126
}
76127
}
77128
}
@@ -108,6 +159,9 @@ let package = Package(
108159

109160
```
110161

162+
Note:
163+
- `ExarotonWebSocketAPI.delegate` is `weak`. Keep a strong reference to your handler (e.g. store it as a property), otherwise callbacks may stop unexpectedly.
164+
111165
Use ExarotonWebSocket:
112166

113167
```swift
@@ -119,38 +173,98 @@ import Starscream
119173
struct WebSocketUsageDemo {
120174

121175
static func main() async throws {
122-
123-
let socket = ExarotonWebSocketAPI(
124-
token: ProcessInfo.processInfo.environment["TOKEN"] ?? "your_account_token",
125-
serverId: ProcessInfo.processInfo.environment["SERVER"] ?? "your_server_id",
126-
delegate: ServerEventHandler()
127-
)
128-
129-
socket.client.connect()
130-
try await wait(for: socket.timeout)
131-
132-
let consoleStreamMessage = ExarotonMessage(
133-
stream: .console,
134-
type: StreamType.start,
135-
data: ["tail": 2]
136-
)
137-
socket.client.write(stringData: try consoleStreamMessage.toData) {
138-
print("console stream start completed!")
176+
let token = ProcessInfo.processInfo.environment["TOKEN"] ?? ""
177+
let serverId = ProcessInfo.processInfo.environment["SERVER"] ?? ""
178+
guard !token.isEmpty, !serverId.isEmpty else {
179+
print("Missing env TOKEN or SERVER. Example: TOKEN=... SERVER=... swift run WebSocketUsageDemo")
180+
return
181+
}
182+
183+
let ready = ReadySignal()
184+
let handler = ServerEventHandler(ready: ready)
185+
let socket = ExarotonWebSocketAPI(token: token, serverId: serverId, delegate: handler)
186+
187+
socket.connect()
188+
189+
let didBecomeReady = await ready.wait(seconds: socket.timeout)
190+
guard didBecomeReady else {
191+
print("Timed out waiting for ready")
192+
socket.disconnect()
193+
return
194+
}
195+
196+
try socket.startStream(.console, tail: 10) {
197+
print("console stream start sent")
139198
}
140199

141-
try await wait(for: socket.timeout)
142-
socket.client.disconnect()
200+
try socket.sendConsoleCommand("say Hello from WebSocketUsageDemo") {
201+
print("console command sent")
202+
}
203+
204+
try await sleep(seconds: 3)
205+
try socket.stopStream(.console) {
206+
print("console stream stop sent")
207+
}
208+
209+
try await sleep(seconds: 1)
210+
socket.disconnect()
211+
}
212+
213+
static func sleep(seconds: Double) async throws {
214+
let ns = UInt64(max(0, seconds) * 1_000_000_000)
215+
try await Task.sleep(nanoseconds: ns)
216+
}
217+
}
218+
219+
actor ReadySignal {
220+
private var continuation: CheckedContinuation<Void, Never>?
221+
private var isSignaled = false
222+
223+
func signal() {
224+
isSignaled = true
225+
continuation?.resume()
226+
continuation = nil
143227
}
144228

145-
static func wait(for minutes: Double) async throws {
146-
try await Task.sleep(nanoseconds: UInt64(1_000_000_000 * minutes))
229+
func wait(seconds: Double) async -> Bool {
230+
if isSignaled { return true }
231+
return await withTaskGroup(of: Bool.self) { group in
232+
group.addTask {
233+
await withCheckedContinuation { continuation in
234+
Task { await self._install(continuation) }
235+
}
236+
return true
237+
}
238+
group.addTask {
239+
let ns = UInt64(max(0, seconds) * 1_000_000_000)
240+
try? await Task.sleep(nanoseconds: ns)
241+
return false
242+
}
243+
let result = await group.next() ?? false
244+
group.cancelAll()
245+
return result
246+
}
247+
}
248+
249+
private func _install(_ continuation: CheckedContinuation<Void, Never>) {
250+
if isSignaled {
251+
continuation.resume()
252+
return
253+
}
254+
self.continuation = continuation
147255
}
148256
}
149257

150258
final class ServerEventHandler: ExarotonServerEventHandlerProtocol {
259+
let ready: ReadySignal
260+
261+
init(ready: ReadySignal) {
262+
self.ready = ready
263+
}
151264

152265
func onReady(serverID: String?) {
153266
print("server ready: \(serverID ?? "")")
267+
Task { await ready.signal() }
154268
}
155269

156270
func onConnected() {
@@ -207,19 +321,21 @@ final class ServerEventHandler: ExarotonServerEventHandlerProtocol {
207321
}
208322
}
209323

210-
// MARK: WebSocketDelegate
324+
func onError(_ error: Error) {
325+
print("error: \(error.localizedDescription)")
326+
}
327+
211328
func didReceive(event: Starscream.WebSocketEvent, client: any Starscream.WebSocketClient) {
212-
// all events, if you need process them your self
213329
}
214330
}
215331
```
216332
For More Use Cases:
217333
- πŸ‘‰πŸ» [Send Message][websocket send message cases]
218334
- πŸ‘‰πŸ» [Receive Message][websocket message receive handler]
219335

220-
## Developemnt πŸ‘¨πŸ»β€πŸ’»
336+
## Development πŸ‘¨πŸ»β€πŸ’»
221337

222-
If you want to contribute to this project, you can use your Mac device and install the Xcode`(>= 15.3)` to get start
338+
If you want to contribute to this project, you can use your Mac device and install the Xcode`(>= 15.4)` to get start
223339

224340
Run shell command as follow to get the project and open it with xcode editor:
225341

@@ -261,6 +377,6 @@ If things goes well, you will see the unittests run and success or fail as follo
261377
[Exaroton OpenAPI Doc]: <https://developers.exaroton.com/openapi.yaml>
262378
[Swagger Editor]: <https://editor-next.swagger.io/>
263379
[Swift OpenAPI Generator]: <https://swiftpackageindex.com/apple/swift-openapi-generator>
264-
[openapi http client cases]: <https://github.com/wangzhizhou/ExarotonAPI/blob/main/Tests/ExarotonHTTPTests/ExarotonHTTPTests.swift>
265-
[websocket send message cases]: <https://github.com/wangzhizhou/ExarotonAPI/blob/main/Tests/ExarotonWebSocketTests/ExarotonWebSocketTests.swift>
380+
[openapi http client cases]: <https://github.com/wangzhizhou/ExarotonAPI/blob/main/Tests/ExarotonHTTPTests/ExarotonHTTPUnitTests.swift>
381+
[websocket send message cases]: <https://github.com/wangzhizhou/ExarotonAPI/blob/main/Sources/ExarotonWebSocket/ExarotonWebSocketAPI.swift>
266382
[websocket message receive handler]: <https://github.com/wangzhizhou/ExarotonAPI/blob/main/Tests/ExarotonWebSocketTests/ExarotonWebSocketEventDelegateHandler.swift>

0 commit comments

Comments
Β (0)