swift-zulip-api/sources/SwiftZulipAPI/messages.swift

256 lines
7.5 KiB
Swift

import Foundation
import Alamofire
//: A type of Zulip message.
public enum MessageType: String {
//: A stream message.
case streamMessage = "stream"
//: A private message.
case privateMessage = "private"
}
//: An error that occurs during messaging, before an HTTP request is made.
public enum MessageError: Error {
//: An error that occurs when a Zulip `narrow` is invalid.
case invalidNarrow
}
/*:
A client for interacting with Zulip's messaging functionality.
*/
public class Messages {
private var config: Config
/*:
Initializes a Messaging client.
- Parameters:
- config: The `Config` to use.
*/
public init(config: Config) {
self.config = config
}
/*:
Sends a message.
- Parameters:
- messageType: The type of message to send.
- to: If `messageType` is `MessageType.stream`, then a string
identifying a stream. If `messageType` is `MessageType.private`,
then list of users' email addresses to send messages to.
- Example: `StreamName`
- Example: `user@example.com`
- Example: `user1@example.com,user2@example.org`
- subject: The subject of the message.
- content: The content of the message, which will be formatted by
Zulip's Markdown engine on the backend.
- callback: A callback, which will be passed the ID of the new
message, or an error.
*/
public func send(
messageType: MessageType,
to: String,
subject: String?,
content: String,
callback: @escaping (Int?, Error?) -> Void
) {
var params = [
"type": messageType.rawValue,
"to": to,
"content": content,
]
if messageType == MessageType.streamMessage, let subject = subject {
params["subject"] = subject
}
makePostRequest(
url: self.config.apiURL + "/messages",
params: params,
username: config.emailAddress,
password: config.apiKey,
callback: { (response) in
guard
let id = getChildFromJSONResponse(
response: response,
childKey: "id"
) as? Int
else {
callback(
nil,
getZulipErrorFromResponse(response: response)
)
return
}
callback(id, nil)
}
)
}
/*:
Gets messages.
- Parameters:
- narrow: A Zulip narrow to search for messages in. `narrow`
should be an array of arrays consisting of filters.
- Example: `[["is", "private"]]`
- Example: `[["stream", "zulip-swift"]]`
- Example: `[
["stream", "zulip-swift"],
["sender", "theskunkmb@gmail.com"]
]`
- anchor: The ID of a message to start with. `anchor` can also be
an extremely large number in order to retrieve the newest
message.
- Example: 130
- Example: 1000000000
- amountBefore: The amount of messages before the `anchor` message
to include.
- amountAfter: The amount of messages after the `anchor` message
to include.
- callback: A callback, which will be passed the messages, or an
error.
*/
public func get(
narrow: [Any],
anchor: Int,
amountBefore: Int,
amountAfter: Int,
callback: @escaping (
[[String: Any]]?,
Error?
) -> Void
) {
guard
let narrowData = try? JSONSerialization.data(
withJSONObject: narrow
),
let narrowString = String(
data: narrowData,
encoding: String.Encoding.utf8
)
else {
callback(nil, MessageError.invalidNarrow)
return
}
let params = [
"narrow": narrowString,
"anchor": String(anchor),
"num_before": String(amountBefore),
"num_after": String(amountAfter)
]
makeGetRequest(
url: self.config.apiURL + "/messages",
params: params,
username: config.emailAddress,
password: config.apiKey,
callback: { (response) in
guard
let messages = getChildFromJSONResponse(
response: response,
childKey: "messages"
) as? [[String: Any]]
else {
callback(
nil,
getZulipErrorFromResponse(response: response)
)
return
}
callback(messages, nil)
}
)
}
/*:
Renders a message.
- Parameters:
- content: The content of the message, which will be formatted by
Zulip's Markdown engine on the backend.
- callback: A callback, which will be passed the rendered HTML
string, or an `Error`.
*/
public func render(
content: String,
callback: @escaping (String?, Error?) -> Void
) {
let params = [
"content": content,
]
makePostRequest(
url: self.config.apiURL + "/messages/render",
params: params,
username: config.emailAddress,
password: config.apiKey,
callback: { (response) in
guard
let rendered = getChildFromJSONResponse(
response: response,
childKey: "rendered"
) as? String
else {
callback(
nil,
getZulipErrorFromResponse(response: response)
)
return
}
callback(rendered, nil)
}
)
}
/*:
Updates a message.
- Parameters:
- content: The content of the message, which will be formatted by
Zulip's Markdown engine on the backend.
- callback: A callback, which will be passed an Error if
there is one.
*/
public func update(
messageID: Int,
content: String,
callback: @escaping (Error?) -> Void
) {
let params = [
"content": content,
]
makePatchRequest(
url: self.config.apiURL + "/messages/" + String(messageID),
params: params,
username: config.emailAddress,
password: config.apiKey,
callback: { (response) in
guard
let errorMessage = getChildFromJSONResponse(
response: response,
childKey: "msg"
) as? String
else {
callback(nil)
return
}
if (errorMessage == "") {
callback(nil)
return
}
callback(ZulipError.error(message: errorMessage))
}
)
}
}