Skip to content

ZhuchoG/TDLibKit

 
 

Repository files navigation

TDLibKit

CI

TDLibKit is a native Swift wrapper for TDLib with support for iOS, macOS, watchOS and even tvOS.

Powered by pre-built multi-platform TDLibFramework implementation of TDLib and generated sources with tl2swift

Installation

Xcode

  1. Install Latest Xcode
  2. Add https://github.com/Swiftgram/TDLibKit as SPM dependency in Project > Swift Packages. This could take a while cause it downloads ~300mb zip file with binary from TDLibFramework dependency
  3. Add TDLibKit as your target dependency.
  4. Add libz.1.tbd and libc++.1.tbd as your target dependencies.
  5. If something is not accesible from TDLibFramework, make sure to add libSystem.B.tbd for all platforms and libc++abi.tbd if you're building non-macOS app. Source
  6. Code!

Cocoapods

Integration requires similar to TDLibFramework Cocoapods & Flutter guide adaptation.

Usage

Library provides multiple API interfaces based on different approaches

  • Async/Await syntax & do/catch. Available for iOS 13.0+, macOS 10.15+, watchOS 6.0+, tvOS 13.0+
  • Completion handlers & closures

Create Client & API instance

import TDLibKit
let client = TdClientImpl()
let api = TdApi(client: client)

Synchronious requests

Only for methods with "Can be called synchronously" in docs

let query = SetLogVerbosityLevel(newVerbosityLevel: 5)
do {
    let result = try api.client.execute(query: DTO(query))
    if let resultDict = result {
        print("Response: \(resultDict)")
    } else {
        print("Empty result")
    }
} catch {
    print("Error in SetLogVerbosityLevel request \(error.localizedDescription)")
}

Async requests

You must run at least empty updates handler to get responses for async requests.

api.client.run { _ in }

Async/Await

do {
    let chatHistory = try await api.getChatHistory(
        chatId: chatId,
        fromMessageId: 0,
        limit: 50,
        offset: 0,
        onlyLocal: false // Request remote messages from server
    )

    for message in chatHistory.messages {
    switch message.content {
        case .messageText(let text):
            print(text.text.text)
            
        case .messageAnimation:
            print("<Animation>")
            
        case .messagePhoto(let photo):
            print("<Photo>\n\(photo.caption.text)")
            
        case .messageSticker(let sticker):
            print(sticker.sticker.emoji)
            
        case .messageVideo(let video):
            print("<Video>\n\(video.caption.text)")
            
            // ...
            
        default:
            print("Unknown message content \(message.content)")
        }
    }
} catch {
    print("Error in getChatHistory \(error)")
}

Completion Handlers

try? api.getChatHistory(
    chatId: chatId,
    fromMessageId: 0,
    limit: 50,
    offset: 0,
    onlyLocal: false, // Request remote messages from server
    completion: { result in
        // Handle Errors
        if case .failure(let error) = result {
            print("Error in getChatHistory request \(error.localizedDescription)")
        } else if let messages = try? result.get().messages {
            // Handle messages
            for message in messages {
                switch message.content {
                case .messageText(let text):
                    print(text.text.text)
                    
                case .messageAnimation:
                    print("<Animation>")
                    
                case .messagePhoto(let photo):
                    print("<Photo>\n\(photo.caption.text)")
                    
                case .messageSticker(let sticker):
                    print(sticker.sticker.emoji)
                    
                case .messageVideo(let video):
                    print("<Video>\n\(video.caption.text)")
                    
                    // ...
                    
                default:
                    print("Unknown message content \(message.content)")
                }
            }
        }
    }
)

Listen for updates

api.client.run {
    do {
        let update = try api.decoder.decode(Update.self, from: $0)
        switch update {
            case .updateNewMessage(let newMsg):
                switch newMsg.message.content {
                    case .messageText(let text):
                        print("Text Message: \(text.text.text)")
                    default:
                        break
                }
            case .updateMessageEdited:
                break
                
            // ... etc

            default:
                print("Unhandled Update \(update)")
                break
        }
    } catch {
        print("Error in update handler \(error.localizedDescription)")
    }
}

Logging

You can pass additional parameter with Logger type to log "send, receive, execute" and custom entries.

import TDLibKit
public final class StdOutLogger: Logger {
    
    let queue: DispatchQueue
    
    public init() {
        queue = DispatchQueue(label: "Logger", qos: .userInitiated)
    }
    
    public func log(_ message: String, type: LoggerMessageType?) {
        queue.async {
            var fisrtLine = "---------------------------"
            if let type = type {
                fisrtLine = ">> \(type.description): ---------------"
            }
            print("""
                \(fisrtLine)
                \(message)
                ---------------------------
                """)
        }
    }
}


let client = TdClientImpl(completionQueue: .main, logger: StdOutLogger())

Build

You can find more about build process in Github Actions file.

Credits

License

MIT

About

Native Swift wrapper for Telegram's TDLib. Available on iOS, macOS, watchOS and tvOS.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Swift 99.9%
  • Other 0.1%