Compare commits

..
18 Commits
Author SHA1 Message Date
Florian Dahn b2db44fe4c Update README.md 2019-03-27 14:10:43 +07:00
FlorianDahn 3a78a98b9e Update Readme.md 2019-03-27 14:09:53 +07:00
FlorianDahn b14fa2dc87 - adding new SentData Event in FormBase for User uploads (for Photo, Audio, Video, Contact, Location, Document)
- adding RequestUserLocation and RequestUserContact to Device class
- Update to Device class
- updating examples
- adding example for data upload
- small documentary Updates (Readme.md)
2019-03-27 14:01:48 +07:00
FlorianDahn 5cd54fc746 Merge branch 'master' of https://github.com/MajMcCloud/TelegramBotFramework 2019-03-20 22:24:42 +07:00
FlorianDahn fb68da6ab1 - added request contact to DeviceSession
- added request location to DeviceSession
2019-03-20 22:24:00 +07:00
FlorianDahn 2f7ded8ce5 - added constructor for adding custom config of TelegramBotClient
- added Log all messages to Action events
2019-03-20 22:21:10 +07:00
Florian Dahn 906177a5f9 Update README.md 2019-03-20 17:54:35 +07:00
FlorianDahn 873c91a165 Update Readme 2019-03-20 17:53:06 +07:00
FlorianDahn 46c1acbf99 Update Readme.md 2019-03-20 17:51:40 +07:00
FlorianDahn acd06a6948 Update Testproject/Readme 2019-03-20 17:50:11 +07:00
Florian Dahn a97305fa35 Update README.md 2019-03-20 17:48:18 +07:00
FlorianDahn 16baef0c45 Update Readme 2019-03-20 17:43:50 +07:00
FlorianDahn 211bc55aff - Cleanup of unecessary init calls
- added form1/form2 option to start menu in test project
- added example for different forms with and without event handlers
- added form examples to Readme.md
2019-03-20 17:42:33 +07:00
FlorianDahn 19f3c9c195 Merge branch 'master' of https://github.com/MajMcCloud/TelegramBotFramework 2019-03-20 16:57:15 +07:00
FlorianDahn c6666f72bc - Improvements to system calls
- system calls now async with await
- added start command to example
- added "handled" property to system call event args
2019-03-20 16:57:10 +07:00
Florian Dahn bf7f6f851a Update README.md 2019-03-20 14:00:11 +07:00
FlorianDahn 816bf4cbbe Merge branch 'master' of https://github.com/MajMcCloud/TelegramBotFramework 2019-03-20 13:44:48 +07:00
FlorianDahn da80af86e3 Small fix in Systemcall management 2019-03-20 13:44:44 +07:00
19 changed files with 805 additions and 296 deletions
+339 -242
View File
@@ -8,19 +8,12 @@
[![license](https://img.shields.io/github/license/MajMcCloud/telegrambotframework.svg?style=flat-square&maxAge=2592000&label=License)](https://raw.githubusercontent.com/MajMcCloud/TelegramBotFramework/master/LICENCE.md) [![license](https://img.shields.io/github/license/MajMcCloud/telegrambotframework.svg?style=flat-square&maxAge=2592000&label=License)](https://raw.githubusercontent.com/MajMcCloud/TelegramBotFramework/master/LICENCE.md)
[![downloads](https://img.shields.io/nuget/dt/TelegramBotBase.svg?style=flat-square&label=Package%20Downloads)](https://www.nuget.org/packages/TelegramBotBase) [![downloads](https://img.shields.io/nuget/dt/TelegramBotBase.svg?style=flat-square&label=Package%20Downloads)](https://www.nuget.org/packages/TelegramBotBase)
Hey guys, Test the Testproject: [@TGBaseBot](https://t.me/TGBaseBot)
here we are. After some time and thoughts i give my TelegramBot framework to public.
It is based on C#.
It is a module which is based on the original [TelegramBotLibrary](https://github.com/TelegramBots/Telegram.Bot) you will find in nuget.
It gives you features which will look/feel like WinForms or have a good way to create apps with actions and forms.
--- ---
## Index ## Index
- [Introduction](#introduction)
- [How to Start](#how-to-start) - [How to Start](#how-to-start)
- [Message Handling](#message-handling) - [Message Handling](#message-handling)
* [Example #0 - System Calls](#add-some-system-calls-example-0---system-calls) * [Example #0 - System Calls](#add-some-system-calls-example-0---system-calls)
@@ -33,6 +26,27 @@ It gives you features which will look/feel like WinForms or have a good way to c
* [Example #4 - Registration Formular](#registration-example-example-4---registration-form-test) * [Example #4 - Registration Formular](#registration-example-example-4---registration-form-test)
- [Special Forms](#forms)
* [AlertDialog](#alert-dialog)
* [AutoCleanForm](#autocleanform)
* [PromptDialog](#prompt-dialog)
---
## Introduction
Hey guys,
here we are. After some time and thoughts i give my TelegramBot framework to public.
It is based on C#.
It is a module which is based on the original [TelegramBotLibrary](https://github.com/TelegramBots/Telegram.Bot) you will find in nuget.
It gives you features which will look/feel like WinForms or have a good way to create apps with actions and forms.
--- ---
@@ -41,7 +55,7 @@ It gives you features which will look/feel like WinForms or have a good way to c
Within your empty App your need to put some initial lines including your APIKey to get things started. Within your empty App your need to put some initial lines including your APIKey to get things started.
The "BotBase" Class will manage a lot of things for you, like system calls, action events and so on. The "BotBase" Class will manage a lot of things for you, like system calls, action events and so on.
"StartForm" is your first Formular which every user will get internally redirected to, like a start page, you could redirect from there later in code, so users won't recognize it. "StartForm" is your first Formular which every user will get internally redirected to, like a start page, you could redirect from there later in code, so users won't recognize it.
It needs to be a subclass of "FormBase" you will find in Namespace TelegramBotBase.Form. It needs to be a subclass of "FormBase" you will find in Namespace TelegramBotBase.Base
``` ```
@@ -69,35 +83,45 @@ public class StartForm : FormBase
} }
//Gets invoked during Navigation to this form
public override async Task Init(params object[] param) public override async Task Init(params object[] param)
{ {
} }
//Gets invoked if the form gets opened (with Form.NavigateTo(NewForm))
public override async Task Opened() public override async Task Opened()
{ {
} }
//Gets invoked if the form gets leaved
public override async Task Closed() public override async Task Closed()
{ {
} }
//Gets invoked on every Message/Action/Data in this context
public override async Task Load(MessageResult message) public override async Task Load(MessageResult message)
{ {
await this.Device.Send("Hello world!"); await this.Device.Send("Hello world!");
} }
//Gets invoked on Button clicks
public override async Task Action(MessageResult message) public override async Task Action(MessageResult message)
{ {
} }
//Gets invoked on Data uploades by the user (of type Photo, Audio, Video, Contact, Location, Document)
public override async Task SentData(DataResult data)
{
}
//Gets invoked on every Message/Action/Data to render Design or Response
public override async Task Render(MessageResult message) public override async Task Render(MessageResult message)
{ {
@@ -145,46 +169,46 @@ Below we have 4 options.
``` ```
BotBase<Start> bb = new BotBase<Start>("{YOUR API KEY}"); BotBase<Start> bb = new BotBase<Start>("{YOUR API KEY}");
bb.SystemCalls.Add("/start"); bb.SystemCalls.Add("/start");
bb.SystemCalls.Add("/form1"); bb.SystemCalls.Add("/form1");
bb.SystemCalls.Add("/form2"); bb.SystemCalls.Add("/form2");
bb.SystemCalls.Add("/params"); bb.SystemCalls.Add("/params");
bb.SystemCall += async (s, en) => bb.SystemCall += async (s, en) =>
{ {
switch (en.Command) switch (en.Command)
{ {
case "/form1": case "/form1":
var form1 = new TestForm(); var form1 = new TestForm();
await en.Device.ActiveForm.NavigateTo(form1); await en.Device.ActiveForm.NavigateTo(form1);
break; break;
case "/form2": case "/form2":
var form2 = new TestForm2(); var form2 = new TestForm2();
await en.Device.ActiveForm.NavigateTo(form2); await en.Device.ActiveForm.NavigateTo(form2);
break; break;
case "/params": case "/params":
String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b); String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b);
await en.Device.Send("Your parameters are " + m, replyTo: en.Device.LastMessage); await en.Device.Send("Your parameters are " + m, replyTo: en.Device.LastMessage);
break; break;
} }
}; };
bb.Start(); bb.Start();
``` ```
@@ -199,44 +223,42 @@ On every input the user is sending back to the bot the Action event gets raised.
public class SimpleForm : FormBase public class SimpleForm : FormBase
{ {
public override async Task Opened() public override async Task Opened()
{ {
await this.Device.Send("Hello world!"); await this.Device.Send("Hello world!");
} }
public override async Task Load(MessageResult message) public override async Task Load(MessageResult message)
{ {
//message.MessageText will work also, cause it is a string you could manage a lot different scenerios here //message.MessageText will work also, cause it is a string you could manage a lot different scenerios here
var messageId = message.MessageId; var messageId = message.MessageId;
switch (message.Command) switch (message.Command)
{ {
case "hello": case "hello":
case "hi": case "hi":
//Send him a simple message //Send him a simple message
await this.Device.Send("Hello you there !"); await this.Device.Send("Hello you there !");
break; break;
case "maybe": case "maybe":
//Send him a simple message and reply to the one of himself //Send him a simple message and reply to the one of himself
await this.Device.Send("Maybe what?", replyTo: messageId); await this.Device.Send("Maybe what?", replyTo: messageId);
break; break;
case "bye":
case "ciao":
//Send him a simple message
await this.Device.Send("Ok, take care !");
break;
}
}
case "bye":
case "ciao":
//Send him a simple message
await this.Device.Send("Ok, take care !");
break;
}
}
} }
``` ```
@@ -339,131 +361,131 @@ Maybe, if i got more ideas, i will add other "controls" in the future.
``` ```
public class ProgressTest : AutoCleanForm public class ProgressTest : AutoCleanForm
{
public ProgressTest()
{
this.DeleteMode = eDeleteMode.OnLeavingForm;
}
public override async Task Opened()
{
await this.Device.Send("Welcome to ProgressTest");
}
public override async Task Action(MessageResult message)
{
var call = message.GetData<CallbackData>();
await message.ConfirmAction();
if (call == null)
return;
TelegramBotBase.Controls.ProgressBar Bar = null;
switch (call.Value)
{ {
case "standard":
public ProgressTest() Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.standard);
{ Bar.Device = this.Device;
this.DeleteMode = eDeleteMode.OnLeavingForm;
}
public override async Task Opened() break;
{
await this.Device.Send("Welcome to ProgressTest");
}
public override async Task Action(MessageResult message) case "squares":
{
var call = message.GetData<CallbackData>();
await message.ConfirmAction(); Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squares);
Bar.Device = this.Device;
break;
if (call == null) case "circles":
return;
TelegramBotBase.Controls.ProgressBar Bar = null; Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.circles);
Bar.Device = this.Device;
switch (call.Value) break;
{
case "standard":
Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.standard); case "lines":
Bar.Device = this.Device;
break; Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.lines);
Bar.Device = this.Device;
case "squares": break;
Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squares); case "squaredlines":
Bar.Device = this.Device;
break; Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squaredLines);
Bar.Device = this.Device;
case "circles": break;
Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.circles); case "start":
Bar.Device = this.Device;
break; var sf = new Start();
case "lines": await sf.Init();
Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.lines); await this.NavigateTo(sf);
Bar.Device = this.Device;
break; return;
case "squaredlines":
Bar = new TelegramBotBase.Controls.ProgressBar(0, 100, TelegramBotBase.Controls.ProgressBar.eProgressStyle.squaredLines);
Bar.Device = this.Device;
break;
case "start":
var sf = new Start();
await sf.Init();
await this.NavigateTo(sf);
return;
default:
return;
}
//Render Progress bar and show some "example" progress
await Bar.Render();
this.Controls.Add(Bar);
for (int i = 0; i <= 100; i++)
{
Bar.Value++;
await Bar.Render();
Thread.Sleep(250);
}
}
public override async Task Render(MessageResult message)
{
ButtonForm btn = new ButtonForm();
btn.AddButtonRow(new ButtonBase("Standard", new CallbackData("a", "standard").Serialize()), new ButtonBase("Squares", new CallbackData("a", "squares").Serialize()));
btn.AddButtonRow(new ButtonBase("Circles", new CallbackData("a", "circles").Serialize()), new ButtonBase("Lines", new CallbackData("a", "lines").Serialize()));
btn.AddButtonRow(new ButtonBase("Squared Line", new CallbackData("a", "squaredlines").Serialize()));
btn.AddButtonRow(new ButtonBase("Back to start", new CallbackData("a", "start").Serialize()));
await this.Device.Send("Choose your progress bar:", btn);
}
public override async Task Closed()
{
foreach (var b in this.Controls)
{
await b.Cleanup();
}
await this.Device.Send("Ciao from ProgressTest");
}
default:
return;
} }
//Render Progress bar and show some "example" progress
await Bar.Render();
this.Controls.Add(Bar);
for (int i = 0; i <= 100; i++)
{
Bar.Value++;
await Bar.Render();
Thread.Sleep(250);
}
}
public override async Task Render(MessageResult message)
{
ButtonForm btn = new ButtonForm();
btn.AddButtonRow(new ButtonBase("Standard", new CallbackData("a", "standard").Serialize()), new ButtonBase("Squares", new CallbackData("a", "squares").Serialize()));
btn.AddButtonRow(new ButtonBase("Circles", new CallbackData("a", "circles").Serialize()), new ButtonBase("Lines", new CallbackData("a", "lines").Serialize()));
btn.AddButtonRow(new ButtonBase("Squared Line", new CallbackData("a", "squaredlines").Serialize()));
btn.AddButtonRow(new ButtonBase("Back to start", new CallbackData("a", "start").Serialize()));
await this.Device.Send("Choose your progress bar:", btn);
}
public override async Task Closed()
{
foreach (var b in this.Controls)
{
await b.Cleanup();
}
await this.Device.Send("Ciao from ProgressTest");
}
}
``` ```
### Registration Example (Example #4 - Registration Form Test) ### Registration Example (Example #4 - Registration Form Test)
@@ -473,105 +495,180 @@ To give you an example about the possiblities, i added into the Test project an
``` ```
public class PerForm : AutoCleanForm public class PerForm : AutoCleanForm
{
public String EMail { get; set; }
public String Firstname { get; set; }
public String Lastname { get; set; }
public async override Task Load(MessageResult message)
{
if (message.MessageText.Trim() == "")
return;
if (this.Firstname == null)
{ {
public String EMail { get; set; } this.Firstname = message.MessageText;
return;
}
public String Firstname { get; set; } if (this.Lastname == null)
{
this.Lastname = message.MessageText;
return;
}
public String Lastname { get; set; } if (this.EMail == null)
{
this.EMail = message.MessageText;
return;
}
public async override Task Load(MessageResult message) }
{
if (message.MessageText.Trim() == "")
return;
if (this.Firstname == null) public async override Task Action(MessageResult message)
{ {
this.Firstname = message.MessageText; var call = message.GetData<CallbackData>();
return;
}
if (this.Lastname == null) await message.ConfirmAction();
{
this.Lastname = message.MessageText;
return;
}
if (this.EMail == null) if (call == null)
{ return;
this.EMail = message.MessageText;
return;
}
} switch (call.Value)
{
case "back":
public async override Task Action(MessageResult message) var start = new Start();
{
var call = message.GetData<CallbackData>();
await message.ConfirmAction(); await this.NavigateTo(start);
if (call == null)
return;
switch (call.Value)
{
case "back":
var start = new Start();
await this.NavigateTo(start);
break;
}
}
public async override Task Render(MessageResult message)
{
if (this.Firstname == null)
{
await this.Device.Send("Please sent your firstname:");
return;
}
if (this.Lastname == null)
{
await this.Device.Send("Please sent your lastname:");
return;
}
if (this.EMail == null)
{
await this.Device.Send("Please sent your email address:");
return;
}
String s = "";
s += "Firstname: " + this.Firstname + "\r\n";
s += "Lastname: " + this.Lastname + "\r\n";
s += "E-Mail: " + this.EMail + "\r\n";
ButtonForm bf = new ButtonForm();
bf.AddButtonRow(new ButtonBase("Back", new CallbackData("a", "back").Serialize()));
await this.Device.Send("Your details:\r\n" + s, bf);
}
break;
} }
}
public async override Task Render(MessageResult message)
{
if (this.Firstname == null)
{
await this.Device.Send("Please sent your firstname:");
return;
}
if (this.Lastname == null)
{
await this.Device.Send("Please sent your lastname:");
return;
}
if (this.EMail == null)
{
await this.Device.Send("Please sent your email address:");
return;
}
String s = "";
s += "Firstname: " + this.Firstname + "\r\n";
s += "Lastname: " + this.Lastname + "\r\n";
s += "E-Mail: " + this.EMail + "\r\n";
ButtonForm bf = new ButtonForm();
bf.AddButtonRow(new ButtonBase("Back", new CallbackData("a", "back").Serialize()));
await this.Device.Send("Your details:\r\n" + s, bf);
}
}
``` ```
There is also a second example, where every of these 3 inputs gets requested by a different formular (class). Just for imagination of the possiblites. There is also a second example, where every of these 3 inputs gets requested by a different formular (class). Just for imagination of the possiblites.
Cause its to much Text, i didnt have added it here. You will find it under [TelegramBaseTest/Tests/Register/PerStep.cs](TelegramBaseTest/Tests/Register/PerStep.cs) Cause its to much Text, i didnt have added it here. You will find it under [TelegramBaseTest/Tests/Register/PerStep.cs](TelegramBaseTest/Tests/Register/PerStep.cs)
Beginn there and navigate your way through these Steps in the subfolder. Beginn there and navigate your way through these Steps in the subfolder.
---
## Forms
There are some default types of forms to make the interaction with users easier.
For now we have the following:
- [AlertDialog](#alert-dialog)
Just a simple dialog with one Button.
- [AutoCleanForm](#autocleanform)
A form which needs to be derived from. It will be delete all in the context sent messages to the user after every new message or on leaving the formular and navigates somewhere else.
Makes sense to create a "feeling" of a clean environment for the user. For instance if you have a multilevel menu. This will remove the previously shown menu, and renders the new sub/top level.
- [PromptDialog](#prompt-dialog)
A simple dialog which is able to show multiple buttons and a Text message. The user could select one option and will get redirected to a different form, depending on the click.
### Alert Dialog
```
var fto = new TestForm2();
AlertDialog ad = new AlertDialog("This is a message", "Ok", fto);
await this.NavigateTo(ad);
```
### AutoCleanForm
### Prompt Dialog
#### Without Eventhandler (pre-init of form necessary)
```
PromptDialog pd = new PromptDialog("Please confirm");
pd.AddButton(new ButtonBase("Ok", "ok"));
pd.AddButton(new ButtonBase("Cancel", "cancel"));
var tf = new TestForm2();
pd.ButtonForms.Add("ok", tf);
pd.ButtonForms.Add("cancel", tf);
await this.NavigateTo(pd);
```
#### With Eventhandler (no pre-init of form necessary)
```
PromptDialog pd = new PromptDialog("Please confirm", new ButtonBase("Ok", "ok"), new ButtonBase("Cancel", "cancel"));
pd.ButtonClicked += async (s, en) =>
{
var tf = new TestForm2();
//Remember only to navigate from the current running form. (here it is the prompt dialog, cause we have left the above already)
await pd.NavigateTo(tf);
};
await this.NavigateTo(pd);
```
--- ---
I will add more notes to it soon, so stay tuned. I will add more notes to it soon, so stay tuned.
+10 -2
View File
@@ -21,13 +21,19 @@ namespace TelegramBaseTest
bb.SystemCalls.Add("/start"); bb.SystemCalls.Add("/start");
bb.SystemCalls.Add("/form1"); bb.SystemCalls.Add("/form1");
bb.SystemCalls.Add("/form2"); bb.SystemCalls.Add("/form2");
bb.SystemCalls.Add("/params"); bb.SystemCalls.Add("/params");
bb.SystemCall += async (s, en) => bb.SystemCall += async (s, en) =>
{ {
switch (en.Command) switch (en.Command)
{ {
case "/start":
var start = new Start();
await en.Device.ActiveForm.NavigateTo(start);
break;
case "/form1": case "/form1":
var form1 = new TestForm(); var form1 = new TestForm();
@@ -48,7 +54,9 @@ namespace TelegramBaseTest
String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b); String m = en.Parameters.DefaultIfEmpty("").Aggregate((a, b) => a + " and " + b);
await en.Device.Send("Your parameters are " + m, replyTo: en.Device.LastMessage); await en.Device.Send("Your parameters are: " + m, replyTo: en.Device.LastMessageId);
en.Handled = true;
break; break;
} }
+1
View File
@@ -53,6 +53,7 @@
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tests\ButtonTestForm.cs" /> <Compile Include="Tests\ButtonTestForm.cs" />
<Compile Include="Tests\DataForm.cs" />
<Compile Include="Tests\ProgressTest.cs" /> <Compile Include="Tests\ProgressTest.cs" />
<Compile Include="Tests\Register\PerForm.cs" /> <Compile Include="Tests\Register\PerForm.cs" />
<Compile Include="Tests\Register\PerStep.cs" /> <Compile Include="Tests\Register\PerStep.cs" />
-2
View File
@@ -59,8 +59,6 @@ namespace TelegramBaseTest.Tests
var st = new Start(); var st = new Start();
await st.Init();
await this.NavigateTo(st); await this.NavigateTo(st);
break; break;
+142
View File
@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles;
using Telegram.Bot.Types.ReplyMarkups;
using TelegramBotBase.Base;
using TelegramBotBase.Form;
namespace TelegramBaseTest.Tests
{
public class DataForm : AutoCleanForm
{
public override async Task SentData(DataResult data)
{
String tmp = "";
InputOnlineFile file;
switch (data.Type)
{
case Telegram.Bot.Types.Enums.MessageType.Contact:
tmp += "Firstname: " + data.Contact.FirstName + "\r\n";
tmp += "Lastname: " + data.Contact.LastName + "\r\n";
tmp += "Phonenumber: " + data.Contact.PhoneNumber + "\r\n";
tmp += "UserId: " + data.Contact.UserId + "\r\n";
await this.Device.Send("Your contact: \r\n" + tmp, replyTo: data.MessageId);
break;
case Telegram.Bot.Types.Enums.MessageType.Document:
file = new InputOnlineFile(data.Document.FileId);
await this.Device.SendDocument(file, "Your uploaded document");
break;
case Telegram.Bot.Types.Enums.MessageType.Video:
file = new InputOnlineFile(data.Document.FileId);
await this.Device.SendDocument(file, "Your uploaded video");
break;
case Telegram.Bot.Types.Enums.MessageType.Audio:
file = new InputOnlineFile(data.Document.FileId);
await this.Device.SendDocument(file, "Your uploaded audio");
break;
case Telegram.Bot.Types.Enums.MessageType.Location:
tmp += "Lat: " + data.Location.Latitude + "\r\n";
tmp += "Lng: " + data.Location.Longitude + "\r\n";
await this.Device.Send("Your location: \r\n" + tmp, replyTo: data.MessageId);
break;
case Telegram.Bot.Types.Enums.MessageType.Photo:
InputOnlineFile photo = new InputOnlineFile(data.Photos.Last().FileId);
await this.Device.Send("Your image: ", replyTo: data.MessageId);
await this.Client.TelegramClient.SendPhotoAsync(this.Device.DeviceId, photo);
break;
default:
await this.Device.Send("Unknown response");
break;
}
}
public override async Task Action(MessageResult message)
{
await message.ConfirmAction();
if (message.Handled)
return;
switch (message.RawData)
{
case "contact":
await this.Device.RequestContact();
break;
case "location":
await this.Device.RequestLocation();
break;
case "back":
message.Handled = true;
var start = new Start();
await this.NavigateTo(start);
break;
}
}
public override async Task Render(MessageResult message)
{
ButtonForm bf = new ButtonForm();
bf.AddButtonRow(new ButtonBase("Request User contact", "contact"));
bf.AddButtonRow(new ButtonBase("Request User location", "location"));
bf.AddButtonRow(new ButtonBase("Back", "back"));
InlineKeyboardMarkup ikv = bf;
await this.Device.Send("Please upload a contact, photo, video, audio, document or location.", bf);
}
}
}
-2
View File
@@ -75,8 +75,6 @@ namespace TelegramBaseTest.Tests
var sf = new Start(); var sf = new Start();
await sf.Init();
await this.NavigateTo(sf); await this.NavigateTo(sf);
return; return;
-2
View File
@@ -50,8 +50,6 @@ namespace TelegramBaseTest.Tests
var st = new Start(); var st = new Start();
await st.Init();
await this.NavigateTo(st); await this.NavigateTo(st);
break; break;
+32
View File
@@ -53,6 +53,32 @@ namespace TelegramBaseTest.Tests
await this.NavigateTo(reg); await this.NavigateTo(reg);
break;
case "form1":
var form1 = new TestForm();
await this.NavigateTo(form1);
break;
case "form2":
var form2 = new TestForm2();
await this.NavigateTo(form2);
break;
case "data":
message.Handled = true;
var data = new DataForm();
await this.NavigateTo(data);
break; break;
} }
@@ -68,6 +94,12 @@ namespace TelegramBaseTest.Tests
btn.AddButtonRow(new ButtonBase("#3 Progress Bar", new CallbackData("a", "progress").Serialize())); btn.AddButtonRow(new ButtonBase("#3 Progress Bar", new CallbackData("a", "progress").Serialize()));
btn.AddButtonRow(new ButtonBase("#4 Registration Example", new CallbackData("a", "registration").Serialize())); btn.AddButtonRow(new ButtonBase("#4 Registration Example", new CallbackData("a", "registration").Serialize()));
btn.AddButtonRow(new ButtonBase("#5 Form1 Command", new CallbackData("a", "form1").Serialize()));
btn.AddButtonRow(new ButtonBase("#6 Form2 Command", new CallbackData("a", "form2").Serialize()));
btn.AddButtonRow(new ButtonBase("#7 Data Handling", new CallbackData("a", "data").Serialize()));
await this.Device.Send("Choose your test:", btn); await this.Device.Send("Choose your test:", btn);
} }
-2
View File
@@ -51,8 +51,6 @@ namespace TelegramBaseTest.Tests
var tf = new TestForm2(); var tf = new TestForm2();
await tf.Init();
await this.NavigateTo(tf); await this.NavigateTo(tf);
break; break;
+22 -8
View File
@@ -48,33 +48,43 @@ namespace TelegramBaseTest.Tests
var tf = new TestForm(); var tf = new TestForm();
await tf.Init();
await this.NavigateTo(tf); await this.NavigateTo(tf);
} }
else if (call.Value == "alert") else if (call.Value == "alert")
{ {
var fto = new TestForm2(); var fto = new TestForm2();
await fto.Init();
AlertDialog ad = new AlertDialog("This is a message", "Ok", fto); AlertDialog ad = new AlertDialog("This is a message", "Ok", fto);
await this.NavigateTo(ad); await this.NavigateTo(ad);
} }
else if (call.Value == "prompt") else if (call.Value == "prompt")
{ {
PromptDialog pd = new PromptDialog("Please confirm", new ButtonBase("Ok", "ok"), new ButtonBase("Cancel", "cancel")); PromptDialog pd = new PromptDialog("Please confirm");
pd.AddButton(new ButtonBase("Ok", "ok"));
pd.AddButton(new ButtonBase("Cancel", "cancel"));
var tf = new TestForm2(); var tf = new TestForm2();
await tf.Init();
pd.ButtonForms.Add("ok", tf); pd.ButtonForms.Add("ok", tf);
pd.ButtonForms.Add("cancel", tf); pd.ButtonForms.Add("cancel", tf);
await this.NavigateTo(pd); await this.NavigateTo(pd);
} }
else if (call.Value == "promptevt")
{
PromptDialog pd = new PromptDialog("Please confirm", new ButtonBase("Ok", "ok"), new ButtonBase("Cancel", "cancel"));
pd.ButtonClicked += async (s, en) =>
{
var tf = new TestForm2();
await pd.NavigateTo(tf);
};
await this.NavigateTo(pd);
}
} }
@@ -98,7 +108,11 @@ namespace TelegramBaseTest.Tests
//btn.AddButtonRow(new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1")), new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1"))); //btn.AddButtonRow(new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1")), new ButtonBase("Zum Testformular 1", CallbackData.Create("navigate", "testform1")));
btn.AddButtonRow(new ButtonBase("Information Prompt", CallbackData.Create("navigate", "alert")), new ButtonBase("Confirmation Prompt", CallbackData.Create("navigate", "prompt"))); btn.AddButtonRow(new ButtonBase("Information Prompt", CallbackData.Create("navigate", "alert")));
btn.AddButtonRow(new ButtonBase("Confirmation Prompt without event", CallbackData.Create("navigate", "prompt")));
btn.AddButtonRow(new ButtonBase("Confirmation Prompt with event", CallbackData.Create("navigate", "promptevt")));
await this.Device.SendPhoto(bmp, "Test", btn); await this.Device.SendPhoto(bmp, "Test", btn);
+129
View File
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using Telegram.Bot.Types.InputFiles;
namespace TelegramBotBase.Base
{
/// <summary>
/// Returns a class to manage attachments within messages.
/// </summary>
public class DataResult : ResultBase
{
public Telegram.Bot.Args.MessageEventArgs RawMessageData { get; set; }
public Contact Contact
{
get
{
return this.Message.Contact;
}
}
public Location Location
{
get
{
return this.Message.Location;
}
}
public Document Document
{
get
{
return this.Message.Document;
}
}
public Audio Audio
{
get
{
return this.Message.Audio;
}
}
public Video Video
{
get
{
return this.Message.Video;
}
}
public PhotoSize[] Photos
{
get
{
return this.Message.Photo;
}
}
public Telegram.Bot.Types.Enums.MessageType Type
{
get
{
return this.RawMessageData?.Message?.Type ?? Telegram.Bot.Types.Enums.MessageType.Unknown;
}
}
/// <summary>
/// Returns the FileId of the first reachable element.
/// </summary>
public String FileId
{
get
{
return (this.Document?.FileId ??
this.Audio?.FileId ??
this.Video?.FileId ??
this.Photos.FirstOrDefault()?.FileId);
}
}
public DataResult(Telegram.Bot.Args.MessageEventArgs rawdata)
{
this.RawMessageData = rawdata;
this.Message = rawdata.Message;
}
public DataResult(MessageResult message)
{
this.RawMessageData = message.RawMessageData;
this.Message = message.Message;
}
public async Task<InputOnlineFile> DownloadDocument()
{
var encryptedContent = new System.IO.MemoryStream(this.Document.FileSize);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Document.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, this.Document.FileName);
}
public async Task<InputOnlineFile> DownloadVideo()
{
var encryptedContent = new System.IO.MemoryStream(this.Video.FileSize);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(this.Video.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, "");
}
public async Task<InputOnlineFile> DownloadPhoto(int index)
{
var photo = this.Photos[index];
var encryptedContent = new System.IO.MemoryStream(photo.FileSize);
var file = await this.Client.TelegramClient.GetInfoAndDownloadFileAsync(photo.FileId, encryptedContent);
return new InputOnlineFile(encryptedContent, "");
}
}
}
+28
View File
@@ -44,6 +44,10 @@ namespace TelegramBotBase.Form
} }
/// <summary>
/// Gets invoked if gets navigated to this form
/// </summary>
/// <returns></returns>
public virtual async Task Opened() public virtual async Task Opened()
{ {
@@ -62,17 +66,41 @@ namespace TelegramBotBase.Form
} }
/// <summary>
/// Gets invoked if the form gets loaded and on every message belongs to this context
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public virtual async Task Load(MessageResult message) public virtual async Task Load(MessageResult message)
{ {
} }
/// <summary>
/// Gets invoked if the user has clicked a button.
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public virtual async Task Action(MessageResult message) public virtual async Task Action(MessageResult message)
{ {
} }
/// <summary>
/// Gets invoked if the user has sent some media (Photo, Audio, Video, Contact, Location, Document)
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public virtual async Task SentData(DataResult message)
{
}
/// <summary>
/// Gets invoked at the end of the cycle to "Render" text, images, buttons, etc...
/// </summary>
/// <param name="message"></param>
/// <returns></returns>
public virtual async Task Render(MessageResult message) public virtual async Task Render(MessageResult message)
{ {
+1 -1
View File
@@ -62,7 +62,7 @@ namespace TelegramBotBase.Base
} }
/// <summary> /// <summary>
/// Is this a system call ? Starts with a slash and command /// Is this a system call ? Starts with a slash '/' and a command
/// </summary> /// </summary>
public bool IsSystemCall public bool IsSystemCall
{ {
+5 -1
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Sessions; using TelegramBotBase.Sessions;
namespace TelegramBotBase.Base namespace TelegramBotBase.Base
@@ -22,6 +23,8 @@ namespace TelegramBotBase.Base
public bool Handled { get; set; } = false; public bool Handled { get; set; } = false;
public Message OriginalMessage { get; set; }
public SystemCallEventArgs() public SystemCallEventArgs()
{ {
@@ -29,10 +32,11 @@ namespace TelegramBotBase.Base
} }
public SystemCallEventArgs(String Command, List<String> Parameters, long DeviceId, DeviceSession Device) public SystemCallEventArgs(String Command, List<String> Parameters, Message Message, long DeviceId, DeviceSession Device)
{ {
this.Command = Command; this.Command = Command;
this.Parameters = Parameters; this.Parameters = Parameters;
this.OriginalMessage = Message;
this.DeviceId = DeviceId; this.DeviceId = DeviceId;
this.Device = Device; this.Device = Device;
} }
+42 -16
View File
@@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Telegram.Bot;
using TelegramBotBase.Base; using TelegramBotBase.Base;
using TelegramBotBase.Form; using TelegramBotBase.Form;
using TelegramBotBase.Sessions; using TelegramBotBase.Sessions;
@@ -42,6 +43,8 @@ namespace TelegramBotBase
private static object __evSystemCall = new object(); private static object __evSystemCall = new object();
public delegate Task SystemCallEventHandler(object sender, SystemCallEventArgs e);
private static object __evException = new object(); private static object __evException = new object();
private static object __evUnhandledCall = new object(); private static object __evUnhandledCall = new object();
@@ -95,6 +98,23 @@ namespace TelegramBotBase
this.Sessions.Client = this.Client; this.Sessions.Client = this.Client;
} }
/// <summary>
/// Simple start of your Bot with the APIKey and a TelegramBotClient instance.
/// </summary>
/// <param name="apiKey"></param>
/// <param name="client"></param>
public BotBase(String apiKey, TelegramBotClient client)
{
this.APIKey = apiKey;
this.Client = new Base.MessageClient(this.APIKey, client);
this.SystemCalls = new List<string>();
this.Sessions = new SessionBase();
this.Sessions.Client = this.Client;
}
/// <summary> /// <summary>
/// Simple start of your Bot with the APIKey and a proxyAdress /// Simple start of your Bot with the APIKey and a proxyAdress
/// </summary> /// </summary>
@@ -219,10 +239,11 @@ namespace TelegramBotBase
//Is this a systemcall ? //Is this a systemcall ?
if (e.IsSystemCall && this.SystemCalls.Contains(e.SystemCommand)) if (e.IsSystemCall && this.SystemCalls.Contains(e.SystemCommand))
{ {
var sce = new SystemCallEventArgs(e.SystemCommand, e.SystemCallParameters, ds.DeviceId, ds); var sce = new SystemCallEventArgs(e.SystemCommand, e.SystemCallParameters, e.Message, ds.DeviceId, ds);
OnSystemCall(sce); await OnSystemCall(sce);
return; if (sce.Handled)
return;
} }
FormBase activeForm = null; FormBase activeForm = null;
@@ -246,6 +267,13 @@ namespace TelegramBotBase
//Loading Event //Loading Event
await activeForm.Load(e); await activeForm.Load(e);
//Is Attachment ? (Photo, Audio, Video, Contact, Location, Document)
if (e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Contact | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Document | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Location |
e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Photo | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Video | e.Message.Type == Telegram.Bot.Types.Enums.MessageType.Audio)
{
await activeForm.SentData(new DataResult(e));
}
//Render Event //Render Event
if (!activeForm.FormSwitched) if (!activeForm.FormSwitched)
await activeForm.Render(e); await activeForm.Render(e);
@@ -258,6 +286,12 @@ namespace TelegramBotBase
{ {
try try
{ {
if (LogAllMessages)
{
DeviceSession ds2 = this.Sessions.GetSession(e.DeviceId);
OnMessage(new MessageIncomeResult(e.DeviceId, ds2, e));
}
Client_TryAction(sender, e); Client_TryAction(sender, e);
} }
catch (Exception ex) catch (Exception ex)
@@ -379,21 +413,13 @@ namespace TelegramBotBase
/// <summary> /// <summary>
/// Will be called if a system call gets raised /// Will be called if a system call gets raised
/// </summary> /// </summary>
public event EventHandler<SystemCallEventArgs> SystemCall public event SystemCallEventHandler SystemCall;
{
add
{
this.__Events.AddHandler(__evSystemCall, value);
}
remove
{
this.__Events.RemoveHandler(__evSystemCall, value);
}
}
public void OnSystemCall(SystemCallEventArgs e)
public async Task OnSystemCall(SystemCallEventArgs e)
{ {
(this.__Events[__evSystemCall] as EventHandler<SystemCallEventArgs>)?.Invoke(this, e); if (this.SystemCall != null)
await SystemCall(this, e);
} }
/// <summary> /// <summary>
+9 -2
View File
@@ -38,6 +38,15 @@ namespace TelegramBotBase.Form
this.Buttons = Buttons.ToList(); this.Buttons = Buttons.ToList();
} }
/// <summary>
/// Adds one Button
/// </summary>
/// <param name="button"></param>
public void AddButton(ButtonBase button)
{
this.Buttons.Add(button);
}
public override async Task Action(MessageResult message) public override async Task Action(MessageResult message)
{ {
var call = message.GetData<CallbackData>(); var call = message.GetData<CallbackData>();
@@ -50,7 +59,6 @@ namespace TelegramBotBase.Form
await message.DeleteMessage(); await message.DeleteMessage();
ButtonBase button = this.Buttons.FirstOrDefault(a => a.Value == call.Value); ButtonBase button = this.Buttons.FirstOrDefault(a => a.Value == call.Value);
if (button == null) if (button == null)
@@ -73,7 +81,6 @@ namespace TelegramBotBase.Form
{ {
ButtonForm btn = new ButtonForm(); ButtonForm btn = new ButtonForm();
var buttons = this.Buttons.Select(a => new ButtonBase(a.Text, CallbackData.Create("action", a.Value))).ToList(); var buttons = this.Buttons.Select(a => new ButtonBase(a.Text, CallbackData.Create("action", a.Value))).ToList();
btn.AddButtonRow(buttons); btn.AddButtonRow(buttons);
+2 -2
View File
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben: // übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.1.0")] [assembly: AssemblyVersion("1.4.0.0")]
[assembly: AssemblyFileVersion("1.3.1.0")] [assembly: AssemblyFileVersion("1.4.0.0")]
+35 -7
View File
@@ -114,6 +114,7 @@ namespace TelegramBotBase.Sessions
try try
{ {
var m = await this.Client.TelegramClient.EditMessageTextAsync(this.DeviceId, messageId, text, replyMarkup: markup); var m = await this.Client.TelegramClient.EditMessageTextAsync(this.DeviceId, messageId, text, replyMarkup: markup);
return m; return m;
} }
catch catch
@@ -149,6 +150,8 @@ namespace TelegramBotBase.Sessions
try try
{ {
m = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification)); m = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification));
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
} }
catch (ApiRequestException ex) catch (ApiRequestException ex)
{ {
@@ -159,9 +162,6 @@ namespace TelegramBotBase.Sessions
return null; return null;
} }
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
return m; return m;
} }
@@ -183,6 +183,8 @@ namespace TelegramBotBase.Sessions
try try
{ {
m = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification)); m = await (this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, text, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification));
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
} }
catch (ApiRequestException ex) catch (ApiRequestException ex)
{ {
@@ -193,8 +195,6 @@ namespace TelegramBotBase.Sessions
return null; return null;
} }
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
return m; return m;
} }
@@ -222,6 +222,8 @@ namespace TelegramBotBase.Sessions
try try
{ {
m = await this.Client.TelegramClient.SendPhotoAsync(this.DeviceId, file, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification); m = await this.Client.TelegramClient.SendPhotoAsync(this.DeviceId, file, replyToMessageId: replyTo, replyMarkup: markup, disableNotification: disableNotification);
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
} }
catch (ApiRequestException ex) catch (ApiRequestException ex)
{ {
@@ -232,8 +234,6 @@ namespace TelegramBotBase.Sessions
return null; return null;
} }
OnMessageSent(new MessageSentEventArgs(m.MessageId, m));
return m; return m;
} }
@@ -334,6 +334,34 @@ namespace TelegramBotBase.Sessions
await this.Client.TelegramClient.SendChatActionAsync(this.DeviceId, action); await this.Client.TelegramClient.SendChatActionAsync(this.DeviceId, action);
} }
/// <summary>
/// Requests the contact from the user.
/// </summary>
/// <param name="buttonText"></param>
/// <param name="requestMessage"></param>
/// <param name="OneTimeOnly"></param>
/// <returns></returns>
public async Task<Message> RequestContact(String buttonText = "Send your contact", String requestMessage = "Give me your phone number!", bool OneTimeOnly = true)
{
var rck = new ReplyKeyboardMarkup(KeyboardButton.WithRequestContact(buttonText));
rck.OneTimeKeyboard = OneTimeOnly;
return await this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, requestMessage, replyMarkup: rck);
}
/// <summary>
/// Requests the location from the user.
/// </summary>
/// <param name="buttonText"></param>
/// <param name="requestMessage"></param>
/// <param name="OneTimeOnly"></param>
/// <returns></returns>
public async Task<Message> RequestLocation(String buttonText = "Send your location", String requestMessage = "Give me your location!", bool OneTimeOnly = true)
{
var rcl = new ReplyKeyboardMarkup(KeyboardButton.WithRequestLocation(buttonText));
rcl.OneTimeKeyboard = OneTimeOnly;
return await this.Client.TelegramClient.SendTextMessageAsync(this.DeviceId, requestMessage, replyMarkup: rcl);
}
/// <summary> /// <summary>
/// Deletes a message /// Deletes a message
/// </summary> /// </summary>
+1
View File
@@ -51,6 +51,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Base\ButtonClickedEventArgs.cs" /> <Compile Include="Base\ButtonClickedEventArgs.cs" />
<Compile Include="Base\ControlBase.cs" /> <Compile Include="Base\ControlBase.cs" />
<Compile Include="Base\DataResult.cs" />
<Compile Include="Base\MessageClient.cs" /> <Compile Include="Base\MessageClient.cs" />
<Compile Include="Base\MessageIncomeResult.cs" /> <Compile Include="Base\MessageIncomeResult.cs" />
<Compile Include="Base\MessageResult.cs" /> <Compile Include="Base\MessageResult.cs" />