- Bugfix: POST data length was calculated incorrectly resulting in getFile returning HTTP error 400 "invalid file_id".
- Switch to IBM's version of SwiftyJSON for Linux compatibility.
-
Memory leak fixed.
-
Callback_query bug fixed.
-
Message editing requests generation fixed.
-
Better error reporting.
-
Move back to original SwiftyJSON.
-
Library rewritten to use libcurl because Foundation's URLSession is not working reliably on Linux yet.
-
File attachments are now supported (via InputFile). Check testSendPhoto() test in RequestTests.swift for an example.
- Update to Bot API 2.3.1.
-
Linux port, thanks to Andrea de Marco who fixed most of the bugs!
-
Telegram API updated to most recent one.
- Updated to 2016-08-26 Swift toolchain.
-
Added
Examples/shopster-bot
: a sample bot which maintains a shopping list using sqlite3 database. GRDB library is used for working with database. This bot allows creating shared shopping lists in group chats. -
Callback query data used in InlineButtons can now be parsed similarly to plaintext commands using arguments scanner. Simply call
context.args.scanWord()
to fetch a word from callback data and so on. -
Router path
.callback_query
now accepts nil:callback_query(data: nil)
. Pass nil to match any data, then parse it in handler using arguments scanner. -
Router now supports context-sensitive user properties. Pass them to
process
method:
var properties = [String: AnyObject]()
properties["myField"] = myValue
try router.process(update: update, properties: properties)
And use them in handlers:
func myHandler(context: Context) -> Bool {
let myValue = context.properties["myField"] as? MyValueType
// ...
}
Or make a Context
category for easier access to your properties, for example:
extension Context {
var session: Session { return properties["session"] as! Session }
}
-
Added
scanInt64()
to arguments scanner. -
readToken("filename or env var")
is nowreadToken(from: "filename or env var")
-
Project ported to Swift 3.0 Snapshot 2016-06-20 (a). Xcode8 is required.
-
Types and Requests (methods) are now generated automatically from Telegram docs by a Ruby script located in
API/
directory. -
All types and requests are now supported.
-
Optional parameters added to request signatures. This code:
bot.sendMessage(chatId, "text", ["reply_markup": markup])
Can now be written as:
bot.sendMessage(chatId, "text", reply_markup: markup)
You can still pass an array with additional arguments at the end of parameters list if needed.
- Router now supports multiple comma separated paths:
router["List Items", "list"] = onListItems
-
Router is now case insensitive by default.
-
Multiword commands are now supported:
router["list add"] = onListAdd
router["list remove"] = onListRemove
- Router chaining is now supported. Use
handler
method to use Router as a handler:
router1.unmatched = router2.handler
- To force the use of slash, instead of
slash: .required
option use:
router["command", .slashRequired] = handler
Multiple flags can be specified:
router["command", [.caseSensitive, .slashRequired]] = handler
-
context.args.command
is nowcontext.command
. -
New variable:
context.slash
. True, if command was prefixed with a slash. -
router.unknownCommand
handler renamed torouter.unmatched
-
Support
callback_query
in Router. -
JsonObject
protocol renamed toJsonConvertible
. -
Context.message
is now optional. Also, it fallbacks toedited_message
andcallback_query.message
when nil. -
Unknown command handler will no longer treat the first word as a command and will pass the entire string to a handler unchanged.
Context.command
will be empty. -
partialMatchHandler return value is now ignored. It can no longer cancel commands.
-
All types changed from classes to structs.
-
HTTP error codes except 401 (authentication error) are no longer fatal errors. TelegramBot will try to reconnect when encountering them.
- Upgrade to Xcode 8 (Swift 3.0 Preview 1)
- Bugfix: "unknown command" / "unsupported content type" messages are no longer sent to group chats.
- All enums renamed to match Swift 3 guidelines.
- Request function signatures changed:
parameters
label is no longer explicit, added missing enum tosendChatAction
and a few other fixes. - Bugfix:
ReplyKeyboardHide
is now JsonObject. - Bugfix: getMeAsync is now public.
- Bugfix: default parameters now work correctly. For example, to disable notifications for all sendMessage calls, do:
bot.defaultParameters["sendMessage"] = {"disable_notification": true}
Int
now conforms toJsonObject
and can be used as Request's return value.- Fixed existing tests and added more tests.
- When trying to access the message via
context.message
non-optional shortcut and the message was nil initially, a warning will be printed. - Added .new_chat_member router path to hello-bot sample project.
- Ported to
Swift-DEVELOPMENT-SNAPSHOT-2016-06-06-a
.
- Router handlers now take Context and return Bool. Other overloads were removed. This was done to simplify Router usage with closures. Closure signatures had to be specified explicitly, but now they can be inferred automatically.
- Message.from is now Optional.
- Add readConfigurationValue helper function which tries to read a single value from environment variable or from a file.
- Request methods are now snake case like structure fields to match Telegram Bot API docs.
- Examples updated to use the new API.
- Added all types and requests except inline types.
- Added missing fields which appeared in API 2.0 to all types.
- Router now works with Updates instead of Messages.
- Allow using raw JSON in requestAsync / requestSync.
- Chat and user ids are now Int64.
Added ReplyKeyboardMarkup
which can be used with Strings
:
let markup = ReplyKeyboardMarkup()
markup.keyboardStrings = [["/a", "/b"], ["/c", "/d"]]
context.respondAsync("Simple keyboard", parameters: ["reply_markup": markup])
Or with KeyboardButtons
:
let button1 = KeyboardButton()
button1.text = "Request contact"
button1.request_contact = true
let button2 = KeyboardButton()
button2.text = "Request location"
button2.request_location = true
markup.keyboardButtons = [ [ button1, button2 ] ]
context.respondAsync("Another keyboard", parameters: ["reply_markup": markup])
The biggest change in this version is the addition of context
in router handlers.
It's also an API breaking change.
Consider the old code below:
func commandHandler(args: Arguments) {
bot.respondAsync("Hello, \(bot.lastMessage.from.first_name)") { // OK
print("Succesfully sent message to \(bot.lastMessage.from.first_name)!")
// BAD: bot.lastMessage was overwritten by nextMessage() at this point
// and now belongs to another chat and/or user!
bot.respondAsync("Bye!")
// BAD: bot.respondAsync here will send the message to wrong user
// because it uses lastMessage internally!
}
}
You had to copy lastMessage
before using it in async block, which was very error-prone:
func commandHandler(args: Arguments) {
let message = bot.lastMessage
bot.respondAsync("Hello, \(message.from.first_name)") { // OK
print("Succesfully sent message to \(message.from.first_name)!") // OK
bot.respondAsync("Bye!") // STILL BAD, uses bot.lastMessage internally
bot.sendMessage(message.chat.id, "Bye!") // OK
}
}
So, now router handlers have context
parameter which contains:
bot
: a reference to bot.message
: a copy of message.args
: command arguments which can be fetched word-by-word etc.- helper methods like
respondAsync
,respondPrivately(groupText:)
etc.
The code above now works as expected without any additional steps:
func commandHandler(context: Context) {
context.respondAsync("Hello, \(context.message.from.first_name)") { // OK
print("Succesfully sent message to \(context.message.from.first_name)!") // OK
context.respondAsync("Bye!") // OK
bot.sendMessage(context.message.chat.id, "Bye!") // OK
}
}
It's ok to use global
bot
variable, butcontext.bot
is also available. It doesn't matter which one you use.
The hello-bot
and word-reverse-bot
examples have been updated to use the new API.
Some helper methods were added to Context
for frequently used variables.
For example, you can use:
context.fromId
in place ofcontext.message.from.id
context.chatId
in place ofcontext.message.chat.id
context.privateChat
in place ofcontext.message.chat.type == .privateChat
Another big change: router now accepts messages. You can do things like:
router[.newChatMember] = newChatMember
router[.leftChatMember] = leftChatMember
router[.document] = onDocument
etc
func newChatMember(context: Context) throws {
let message = context.message
guard let newChatMember = message.new_chat_member where
newChatMember.id == bot.user.id else { return }
...someone invited bot to chat...
}
In addition to partialMatch
handler there are two new fallback handlers:
router.partialMatch = partialMatchHandler
router.unknownCommand = unknownCommandHandler
router.unsupportedContentType = unsupportedContentTypeHandler
They have a reasonable default implementations, but can be overridden.
bot.lastCommand
,bot.lastMessage
andbot.lastUpdate
are no longer available. Addedbot.lastUpdateId
which can be used for debugging purposes.- Added generic
requestSync
andrequestAsync
requests which can be used for any requests. All other requests now use these functions internally. - All async request completion handlers now consistently return
(result, error)
tuple. Result type is different depending on request. - Supported
array of objects
as request return value, simplifiedgetUpdates
request. - Added
leaveChat
request. Bool
type now conforms toJsonObject
and can be used as request result. SeeleaveChat
for example.