357 lines
12 KiB
Swift
357 lines
12 KiB
Swift
import Foundation
|
|
import Alamofire
|
|
|
|
/*:
|
|
An error that occurs during stream operations, before an HTTP request is
|
|
made.
|
|
*/
|
|
public enum StreamError: Error {
|
|
//: An error that occurs when a list of Zulip streams is invalid.
|
|
case invalidStreams
|
|
|
|
//: An error that occurs when a list of Zulip principals is invalid.
|
|
case invalidPrincipals
|
|
|
|
//: An error that occurs when a list of Zulip stream names is invalid.
|
|
case invalidStreamNames
|
|
}
|
|
|
|
//: A client for interacting with Zulip's messaging functionality.
|
|
public class Streams {
|
|
private var config: Config
|
|
|
|
/*:
|
|
Initializes a `Streams` client.
|
|
|
|
- Parameters:
|
|
- config: The `Config` to use.
|
|
*/
|
|
public init(config: Config) {
|
|
self.config = config
|
|
}
|
|
|
|
/*:
|
|
Gets all streams that a user can access.
|
|
|
|
- Parameters:
|
|
- includePublic: Whether all public streams should be included.
|
|
- includeSubscribed: Whether all subscribed-to streams should be
|
|
included
|
|
- includeDefault: Whether all default streams should be included.
|
|
- includeActive: Whether all active streams should be included.
|
|
This option will cause a `ZulipError` if the user not an admin.
|
|
- callback: A callback, which will be passed the streams, or an
|
|
error.
|
|
*/
|
|
public func getAll(
|
|
includePublic: Bool = true,
|
|
includeSubscribed: Bool = true,
|
|
includeDefault: Bool = false,
|
|
includeAllActive: Bool = false,
|
|
callback: @escaping (
|
|
[[String: Any]]?,
|
|
Error?
|
|
) -> Void
|
|
) {
|
|
let params = [
|
|
"include_public": includePublic ? "true" : "false",
|
|
"include_subscribed": includeSubscribed ? "true" : "false",
|
|
"include_default": includeDefault ? "true" : "false",
|
|
"include_all_active": includeAllActive ? "true" : "false",
|
|
]
|
|
|
|
makeGetRequest(
|
|
url: self.config.apiURL + "/streams",
|
|
params: params,
|
|
username: config.emailAddress,
|
|
password: config.apiKey,
|
|
callback: { (response) in
|
|
guard
|
|
let streams = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "streams"
|
|
) as? [[String: Any]]
|
|
else {
|
|
callback(
|
|
nil,
|
|
getZulipErrorFromResponse(response: response)
|
|
)
|
|
return
|
|
}
|
|
|
|
callback(streams, nil)
|
|
}
|
|
)
|
|
}
|
|
|
|
/*:
|
|
Gets the ID of a stream.
|
|
|
|
- Parameters:
|
|
- name: The name of the stream.
|
|
- callback: A callback, which will be passed the ID, or an error.
|
|
*/
|
|
public func getID(
|
|
name: String,
|
|
callback: @escaping (Int?, Error?) -> Void
|
|
) {
|
|
let params = [
|
|
"stream": name,
|
|
]
|
|
|
|
makeGetRequest(
|
|
url: self.config.apiURL + "/get_stream_id",
|
|
params: params,
|
|
username: config.emailAddress,
|
|
password: config.apiKey,
|
|
callback: { (response) in
|
|
guard
|
|
let id = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "stream_id"
|
|
) as? Int
|
|
else {
|
|
callback(
|
|
nil,
|
|
getZulipErrorFromResponse(response: response)
|
|
)
|
|
return
|
|
}
|
|
|
|
callback(id, nil)
|
|
}
|
|
)
|
|
}
|
|
|
|
/*:
|
|
Gets the user's subscribed streams.
|
|
|
|
- Parameters:
|
|
- callback: A callback, which will be passed the streams, or an
|
|
error.
|
|
*/
|
|
public func getSubscribed(
|
|
callback: @escaping (
|
|
[[String: Any]]?,
|
|
Error?
|
|
) -> Void
|
|
) {
|
|
makeGetRequest(
|
|
url: self.config.apiURL + "/users/me/subscriptions",
|
|
params: [:],
|
|
username: config.emailAddress,
|
|
password: config.apiKey,
|
|
callback: { (response) in
|
|
guard
|
|
let streams = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "subscriptions"
|
|
) as? [[String: Any]]
|
|
else {
|
|
callback(
|
|
nil,
|
|
getZulipErrorFromResponse(response: response)
|
|
)
|
|
return
|
|
}
|
|
|
|
callback(streams, nil)
|
|
}
|
|
)
|
|
}
|
|
|
|
/*:
|
|
Subscribes a user to streams, or creates them if they do not exist yet.
|
|
|
|
- Parameters:
|
|
- streams: The streams to subscribe a user to.
|
|
- Example: `[["name": "test here"]]`
|
|
- Example: `["name": "test here"], ["name": "announce"]]`
|
|
- inviteOnly: Whether the streams are invite only or not.
|
|
- announce: Whether an announcement should be made that a new
|
|
stream is created if it is.
|
|
- principals: The users to subscribe to the streams. If
|
|
`principals` is empty, the current user will be subscribed.
|
|
- authorizationErrorsFatal: Whether authorization errors should be
|
|
reported in the response.
|
|
- callback: A callback, which will be passed a dictionary where the
|
|
key is user's email, and the value is a list of streams they were
|
|
subscribed to; a dictionary where the key is a user's email, and
|
|
the value is a list of streams they are already subscribed to;
|
|
and a list of names of streams that could not be subscribed to
|
|
because the user was unauthorized; or an error if there is one.
|
|
*/
|
|
public func subscribe(
|
|
streams: [[String: Any]],
|
|
inviteOnly: Bool = false,
|
|
announce: Bool = false,
|
|
principals: [String] = [],
|
|
authorizationErrorsFatal: Bool = true,
|
|
callback: @escaping (
|
|
[String: [String]]?,
|
|
[String: [String]]?,
|
|
[String]?,
|
|
Error?
|
|
) -> Void
|
|
) {
|
|
guard
|
|
let streamsData = try? JSONSerialization.data(
|
|
withJSONObject: streams
|
|
),
|
|
let streamsString = String(
|
|
data: streamsData,
|
|
encoding: String.Encoding.utf8
|
|
)
|
|
else {
|
|
callback(nil, nil, nil, StreamError.invalidStreams)
|
|
return
|
|
}
|
|
|
|
guard
|
|
let principalsData = try? JSONSerialization.data(
|
|
withJSONObject: principals
|
|
),
|
|
let principalsString = String(
|
|
data: principalsData,
|
|
encoding: String.Encoding.utf8
|
|
)
|
|
else {
|
|
callback(nil, nil, nil, StreamError.invalidPrincipals)
|
|
return
|
|
}
|
|
|
|
let params = [
|
|
"subscriptions": streamsString,
|
|
"invite_only": inviteOnly ? "true" : "false",
|
|
"announce": announce ? "true" : "false",
|
|
"principals": principalsString,
|
|
"authorization_errors_fatal":
|
|
authorizationErrorsFatal ? "true" : "false",
|
|
]
|
|
|
|
makePostRequest(
|
|
url: self.config.apiURL + "/users/me/subscriptions",
|
|
params: params,
|
|
username: config.emailAddress,
|
|
password: config.apiKey,
|
|
callback: { (response) in
|
|
if let errorMessage = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "msg"
|
|
) as? String, errorMessage != "" {
|
|
callback(
|
|
nil,
|
|
nil,
|
|
nil,
|
|
ZulipError.error(message: errorMessage)
|
|
)
|
|
return
|
|
}
|
|
|
|
let subscribed = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "subscribed"
|
|
) as? [String: [String]]
|
|
let alreadySubscribed = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "already_subscribed"
|
|
) as? [String: [String]]
|
|
let unauthorized = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "unauthorized"
|
|
) as? [String]
|
|
|
|
callback(subscribed, alreadySubscribed, unauthorized, nil)
|
|
}
|
|
)
|
|
}
|
|
|
|
/*:
|
|
Unsubscribes a user to streams.
|
|
|
|
- Parameters:
|
|
- streamNames: The names of the streams to unsubscribe a user from.
|
|
- Example: `["test here"]`
|
|
- Example: `["test here", "announce"]`
|
|
- principals: The users to unsubscribe from the streams. If
|
|
`principals` is empty, the current user will be subscribed.
|
|
Unsubscribing other users will cause a `ZulipError` if the
|
|
current user is not an admin.
|
|
- callback: A callback, which will be passed a list of names of
|
|
the streams that were unsubscribed from and a list of names of
|
|
the streams that could not be unsubscrived from because the user
|
|
was already subscribed, or an error if there is one.
|
|
*/
|
|
public func unsubscribe(
|
|
streamNames: [String],
|
|
principals: [String] = [],
|
|
callback: @escaping (
|
|
[String]?,
|
|
[String]?,
|
|
Error?
|
|
) -> Void
|
|
) {
|
|
guard
|
|
let streamNamesData = try? JSONSerialization.data(
|
|
withJSONObject: streamNames
|
|
),
|
|
let streamNamesString = String(
|
|
data: streamNamesData,
|
|
encoding: String.Encoding.utf8
|
|
)
|
|
else {
|
|
callback(nil, nil, StreamError.invalidStreamNames)
|
|
return
|
|
}
|
|
|
|
guard
|
|
let principalsData = try? JSONSerialization.data(
|
|
withJSONObject: principals
|
|
),
|
|
let principalsString = String(
|
|
data: principalsData,
|
|
encoding: String.Encoding.utf8
|
|
)
|
|
else {
|
|
callback(nil, nil, StreamError.invalidPrincipals)
|
|
return
|
|
}
|
|
|
|
let params = [
|
|
"subscriptions": streamNamesString,
|
|
"principals": principalsString,
|
|
]
|
|
|
|
makeDeleteRequest(
|
|
url: self.config.apiURL + "/users/me/subscriptions",
|
|
params: params,
|
|
username: config.emailAddress,
|
|
password: config.apiKey,
|
|
callback: { (response) in
|
|
if let errorMessage = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "msg"
|
|
) as? String, errorMessage != "" {
|
|
callback(
|
|
nil,
|
|
nil,
|
|
ZulipError.error(message: errorMessage)
|
|
)
|
|
return
|
|
}
|
|
|
|
let removed = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "removed"
|
|
) as? [String]
|
|
let notSubscribed = getChildFromJSONResponse(
|
|
response: response,
|
|
childKey: "not_subscribed"
|
|
) as? [String]
|
|
|
|
callback(removed, notSubscribed, nil)
|
|
}
|
|
)
|
|
}
|
|
}
|