Skip to content

Instantly share code, notes, and snippets.

@harmankang
Created November 14, 2022 19:58
Show Gist options
  • Save harmankang/7f5b2cdf5a9ae0bffcb33853823708a5 to your computer and use it in GitHub Desktop.
Save harmankang/7f5b2cdf5a9ae0bffcb33853823708a5 to your computer and use it in GitHub Desktop.
Telegram API -sendMessage and -sendDocument using URLSession (Swift)
// URLSession wrapper to send messages and text files to Telegram chat.
final class TelegramAPI {
/// -sendMessage endpoint
private let sendMessageEndpoint: String
/// -sendDocument endpoint
private let sendDocumentEndpoint: String
/// Unique identifier for the target chat or username of the target channel
private let chatId: String
// MARK: Init
init(token: String /* = YOUR_BOT_TOKEN*/, chatId: String /* = YOUR_CHAT_ID*/) {
self.sendMessageEndpoint = "https://api.telegram.org/bot\(token)/sendMessage"
self.sendDocumentEndpoint = "https://api.telegram.org/bot\(token)/sendDocument"
self.chatId = chatId
}
// MARK: API
/// Send a message to a Telegram chat.
public func send(message: String) {
do {
let session = URLSession.shared
let request = NSMutableURLRequest(url: URL(string: sendMessageEndpoint)!)
request.httpMethod = "POST"
let encoder = JSONEncoder()
let payload = TelegramParameters(chat_id: chatId, text: message)
let encodedPayload = try encoder.encode(payload)
guard let parameters = String(bytes: encodedPayload, encoding: .utf8) else { return }
request.httpBody = parameters.data(using: .utf8)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
let task = session.dataTask(with: request as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in
if let data = data, let responseData = String(data: data, encoding: .utf8) {
print("TelegramAPI -send received data contents: ", responseData)
}
if let error = error {
print("TelegramAPI -send failed with error: ", error)
}
}
task.resume()
} catch let e {
print("TelegramAPI -send failed to make cURL request due to error: ", e)
}
}
/// Send a text file to a Telegram chat.
/// - Parameters:
/// - contents: Contents for text file.
/// - filename: Filename ending in ".txt"
public func sendTextFile(contents: String, filename: String) {
if let contentsData = contents.data(using: .utf8) {
let session = URLSession.shared
let parameters = ["chat_id": "\(chatId)"]
let request = NSMutableURLRequest(url: URL(string: sendDocumentEndpoint)!)
request.httpMethod = "POST"
let boundary = "Boundary-\(NSUUID().uuidString)"
request.httpBody = makeHTTPBody(withParameters: parameters, fileData: contentsData, boundary: boundary, filename: filename, mimeType: "text/plain")
request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
let task = session.dataTask(with: request as URLRequest) { (data: Data?, response: URLResponse?, error: Error?) in
if let data = data, let responseData = String(data: data, encoding: .utf8) {
print("TelegramAPI -sendReport received data contents: ", responseData)
}
if let error = error {
print("TelegramAPI -sendReport failed with error: ", error)
}
}
task.resume()
}
}
/// Create Data representation for message body of HTTP POST request to -sendDocument.
/// - Parameters:
/// - params:
/// - fileData: Document data that is being sent to Telegram.
/// - boundary: A short string used to separate key/value parameters in body when using multipart/form-data content type.
/// - filename: Filename for the document uploaded to Telegram.
/// - mimeType: MIME type for file (e.g. plain/text for text file)
/// - Returns: Data for HTTP message body.
private func makeHTTPBody(withParameters params: [String: String]?, fileData: Data, boundary: String, filename: String, mimeType: String) -> Data {
let lineBreak = "\r\n"
var body = Data()
if let parameters = params {
for (key, value) in parameters {
body.append("--\(boundary + lineBreak)")
body.append("Content-Disposition: form-data; name=\"\(key)\"\(lineBreak + lineBreak)")
body.append("\(value + lineBreak)")
}
}
let fieldName = "document"
body.append("--\(boundary + lineBreak)")
body.append("Content-Disposition: form-data; name=\"\(fieldName)\"; filename=\"\(filename)\"\(lineBreak)")
body.append("Content-Type: \(mimeType + lineBreak + lineBreak)")
body.append(fileData)
body.append(lineBreak)
body.append("--\(boundary)--\(lineBreak)")
return body
}
}
fileprivate extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}
fileprivate struct TelegramParameters: Codable {
let chat_id: String
let text: String
// ... add additional parameters as required
}
@harmankang
Copy link
Author

Usage

// Initialize with token and chat id
let telegram = TelegramAPI(token: "YOUR_TOKEN", chatId: "CHAT_ID")

// Send message
telegram.send(message: "Hello")

// Send text file
telegram.sendTextFile(contents: "Hello, \n\n Goodbye.", filename: "file.txt")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment