Skip to content

Releases: deploy-f/botf

[v0.17.3] Registered filters

23 Sep 21:12
Compare
Choose a tag to compare

Registered filters: FilterSuccessfulPayment and FilterPreCheckoutQuery

[v0.17.2] Fixed UpdateContextExtensions methods

23 Sep 20:51
Compare
Choose a tag to compare
  • The IUpdateContext extension methods GetSafeChatId() and GetSafeUserId now checking values from more types of Updates
  • Added new IUpdateContext extensions methods: GetSafeChat() and GetSafeUser()
  • Added filters: FilterSuccessfulPayment and FilterPreCheckoutQuery

[v0.17] Fixed updates of messages containing photos

09 May 16:11
59457a9
Compare
Choose a tag to compare

Explanation of a fix

Now your messages containing photos are updating correctly while handling CallbackQuery from Telegram.

Here is 4 scenarios:

1st
First message with photo, second - without.
What should happen: the 1st will be deleted and the second will be sent.

2st
No photo in the 1st message, but there is in the 2nd.
What should happen: the 1st will be deleted and the second will be sent

3st
No photo in the 1st message, neither in the 2nd.
What should happen: 1st message would be updated without deletion

4st
There is a photo in the 1st and in the 2nd message.
What should happen: by default Botf will just update 1st message with a new photo. But if you specify UpdateMessagePolicy via Context.SetUpdateMsgPolicy() to UpdateMessagePolicy.DeleteAndSend so the 1st message would be deleted and Botf will send a new one with a new photo and text.

You can find code examples here

[v0.15] New era of handler's filters

11 Nov 08:28
Compare
Choose a tag to compare

New pre-built filters

Regex filter

Now you can use regex template to select a specific message and handle it. Pass the template to named parameter Param in filter's constuctor for Filters.Regex filter.

[Filter(Filters.Regex, Param: "Hello .*!")]
[On(Handle.Unknown)]
public void UnknownTextHello()
{
   PushL("Hey!");
}

Filters have their own attribute

Use the Filter() attribute to specify filters rather than passing it in the On() attribute

[On(Handle.Unknown)]
[Filter(Filters.Text)]
public void UnknownNewTextHandler()
{
   Reply();
   PushL("Unknown text message");
   Context.StopHandling();
}

Combination of filters for single handler

Now you can specify many filters and use boolean operators for it.

[On(Handle.Unknown)]
[Filter(Filters.Text)]
[Filter(And: Filters.Regex, Param: "Hello .*!")]
public void UnknownTextHello()
{
   Reply();
   PushL("Hey!");
   Context.StopHandling();
}

Added new filters:

  • Filters.NotGlobalState
  • Filters.CurrentGlobalState
  • Filters.Regex
  • Filters.PrivateChat
  • Filters.GroupChat
  • Filters.Type

👉 Full example you can see HERE

[0.14.2] Send now returns Message object

14 Oct 18:59
Compare
Choose a tag to compare
  • Send and Update methods returns Message object
  • Controller has new property MessageId. Set MessageId to update needed message with Update method.

👉 Example is here

[v0.14] New era of controller's state and improvements in Unknown handlers

06 Aug 22:48
Compare
Choose a tag to compare

Q() supports classes !

That time has come! Now you can do this:

var foo = new ExampleClass
{
    IntField = 25,
    StringProp = "very looooong string with many words"
};
Button("Click me", Q(HandleIt, foo));

....
[Action]
void HandleIt(ExampleClass foo)
{
    PushL($"StringProp: {foo.StringProp}");
}

Looks like magic but it works!

Example is here

Controller state saving and restoring

Now you can save controller's state acros the updates. "State" means controller's fields and properties.
To save the state you have to mark it with [State] attribute.
It looks like that:

class Example : BotController
{
    [State]
    int intField;
    
    ...
}

intField will be saved between user's updates.

Fully featured example is located here

improved Unknown handlers

Beginning from v0.14 you have ability to make many of Unknown handlers in your code.
Second thing is that you can use filters to decide when botf has to call your handler.

See the complete example of the new feature here

[v0.13] Web Apps support

27 Jul 21:42
Compare
Choose a tag to compare

🕸Telegram bot WebApps is now supporting in BotF

See the code example here

[0.12] Sending photos, Url buttons

09 Apr 18:39
Compare
Choose a tag to compare

Sending photos

Now you can send photo via calling Photo("http://path.to/photo.png")

Url buttons

If you pass valid url into payload in the button, the button will be a link.

Example:

[Action("/start")]
void Start()
{
    // Add the photo to message
    Photo("https://avatars.githubusercontent.com/u/59260433");
    Push("Hello from deploy-f");
    Button("Got to botf repo", "https://github.com/deploy-f/botf");
}

[v0.11] Argument binding for Guid type

04 Apr 18:15
Compare
Choose a tag to compare

Now you can pass Guid argument into callback/action methods:

[Action("/start", "start")]
void Start()
{
    var guid = Guid.NewGuid();
    Push("Click the button");
    Button($"guid: {guid}", Q(GuidArgumentButtonHandler, guid));
}

[Action]
async Task GuidArgumentButtonHandler(Guid guid)
{
    Push($"value: {guid}");
}

[v0.10] Timeout for chain flow

29 Mar 16:33
Compare
Choose a tag to compare

There were an issue the chain was hanging in memory if user does not answer the chain request (calls like AwaitText(), AwaitUpdate() and AwaitQuery()) and that cause memory leaks.

We've added a mechanism to break this dangling chains by the timeout.

How to configure this option

Add a key into connection string with name chain_timeout and set the value in TimeSpan format (value 0:0:5 - means 5 seconds, 0:5 - 5 minutes, etc).

ℹ️ Default value is 1 hour

Example:

"botf": "123456:MAHHFJSMFNJASKFNSALVDMD?chain_timeout=0:2"

How to handle timeout

We've added new type to handle these events - Handle.ChainTimeout
Example of a code:

[On(Handle.ChainTimeout)]
void ChainTimeout()
{
    PushL("timeout");
}

Or you can specify custom handle for any of calls AwaitText(), AwaitUpdate() and AwaitQuery() by passing a delegate with your custom implementation
Example:

var name = await AwaitText(() => Send("Use /start to try again"));