Adding new example project for Inline- and ReplyMarkup combination

This commit is contained in:
FlorianDahn 2023-09-10 16:58:12 +02:00
parent 54e131d852
commit f7578384e6
11 changed files with 592 additions and 2 deletions

View File

@ -0,0 +1,86 @@
using InlineAndReplyCombination.Forms;
using InlineAndReplyCombination.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Attributes;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Baseclasses
{
public class MultipleChoiceForm : AutoCleanForm
{
[SaveState]
public UserDetails UserDetails { get; set; }
ButtonGrid ReplyButtonGrid;
public String ReplyButtonTitle { get; set; } = "Restart";
protected int CurrentStep = 1;
protected int MaxSteps = 3;
public MultipleChoiceForm()
{
this.Init += MultipleChoiceForm_Init;
}
private async Task MultipleChoiceForm_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
//Reply keyboard
var bf = new ButtonForm();
bf.AddButtonRow(ReplyButtonTitle, "replyButtonID");
ReplyButtonGrid = new ButtonGrid(bf);
ReplyButtonGrid.Title = $"Step {CurrentStep} / {MaxSteps}";
ReplyButtonGrid.KeyboardType = TelegramBotBase.Enums.EKeyboardType.ReplyKeyboard;
ReplyButtonGrid.ButtonClicked += ReplyButtonGrid_ButtonClicked;
AddControl(ReplyButtonGrid);
}
private async Task ReplyButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
if (e.Button == null)
return;
switch (e.Button.Value)
{
case "replyButtonID":
await PressReplyButton();
break;
}
}
public virtual Task PressReplyButton()
{
return Task.CompletedTask;
}
public override Task NavigateTo(FormBase newForm, params object[] args)
{
//Move user details over to navigating form
if (newForm is MultipleChoiceForm mcf)
{
mcf.UserDetails = UserDetails;
}
return base.NavigateTo(newForm, args);
}
}
}

View File

@ -0,0 +1,67 @@
using InlineAndReplyCombination.Baseclasses;
using InlineAndReplyCombination.Forms.Steps;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Forms
{
public class StartForm : AutoCleanForm
{
ButtonGrid buttonGrid;
public StartForm()
{
this.Init += StartForm_Init;
}
private async Task StartForm_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
var bf = new ButtonForm();
bf.AddButtonRow("Start registration", "start");
buttonGrid = new ButtonGrid(bf);
buttonGrid.Title = "Welcome to The InlineAndReplyCombination Bot!";
buttonGrid.ButtonClicked += ButtonGrid_ButtonClicked;
buttonGrid.KeyboardType = TelegramBotBase.Enums.EKeyboardType.ReplyKeyboard;
AddControl(buttonGrid);
}
private async Task ButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
if(e.Button == null)
{
return;
}
switch(e.Button.Value)
{
case "start":
var mf = new MainForm();
mf.UserDetails = new Model.UserDetails();
await NavigateTo(mf);
break;
}
}
}
}

View File

@ -0,0 +1,90 @@
using InlineAndReplyCombination.Baseclasses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Forms.Steps
{
public class MainForm : MultipleChoiceForm
{
ButtonGrid InlineButtonGrid;
public static List<Tuple<String, String>> AllowedInlineInputs = null;
static MainForm()
{
AllowedInlineInputs = new List<Tuple<string, string>>()
{
new("< 18", "<18"),
new("18 to 25", "18t25"),
new("25 to 35", "25t35"),
new("35 to 50", "35t50"),
new("over 50", "o50")
};
}
public MainForm()
{
Init += MainForm_Init;
ReplyButtonTitle = "Start over";
CurrentStep = 1;
}
private async Task MainForm_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
//Inline Keyboard
var bf_ages = new ButtonForm();
//Add all options in a single column
bf_ages.AddSplitted(AllowedInlineInputs.Select(a => new ButtonBase(a.Item1, a.Item2)), 1);
bf_ages.AddButtonRow("Some invalid input", "Invalid");
InlineButtonGrid = new ButtonGrid(bf_ages);
InlineButtonGrid.ConfirmationText = "Thank you";
InlineButtonGrid.Title = "Please choose your age:";
InlineButtonGrid.ButtonClicked += InlineButtonGrid_ButtonClicked;
InlineButtonGrid.KeyboardType = TelegramBotBase.Enums.EKeyboardType.InlineKeyBoard;
AddControl(InlineButtonGrid);
}
private async Task InlineButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
//Not found
if (!AllowedInlineInputs.Any(a => a.Item2 == e.Button.Value))
{
await Device.Send("Invalid input!");
return;
}
this.UserDetails.AgeRange = e.Button?.Value ?? "unknown";
var sf = new SecondForm();
await NavigateTo(sf);
}
public override async Task PressReplyButton()
{
var sf = new StartForm();
await NavigateTo(sf);
}
}
}

View File

@ -0,0 +1,89 @@
using InlineAndReplyCombination.Baseclasses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Forms.Steps
{
public class SecondForm : MultipleChoiceForm
{
ButtonGrid InlineButtonGrid;
public static List<Tuple<String, String>> AllowedInlineInputs = null;
static SecondForm()
{
AllowedInlineInputs = new List<Tuple<string, string>>()
{
new("Green", "green"),
new("Yellow", "yellow"),
new("Red", "red"),
new("Purple", "purple"),
new("Black", "black"),
new("Gold", "gold")
};
}
public SecondForm()
{
Init += SecondForm_Init;
ReplyButtonTitle = "Go back";
CurrentStep = 2;
}
private async Task SecondForm_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
//Inline Keyboard
var bf_ages = new ButtonForm();
//Add all options in a single column
bf_ages.AddSplitted(AllowedInlineInputs.Select(a => new ButtonBase(a.Item1, a.Item2)), 1);
InlineButtonGrid = new ButtonGrid(bf_ages);
InlineButtonGrid.ConfirmationText = "Thank you";
InlineButtonGrid.Title = "Please choose your favourite color:";
InlineButtonGrid.ButtonClicked += InlineButtonGrid_ButtonClicked;
InlineButtonGrid.KeyboardType = TelegramBotBase.Enums.EKeyboardType.InlineKeyBoard;
AddControl(InlineButtonGrid);
}
private async Task InlineButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
//Not found
if (!AllowedInlineInputs.Any(a => a.Item2 == e.Button.Value))
{
await Device.Send("Invalid input!");
return;
}
this.UserDetails.FavouriteColor = e.Button?.Value ?? "unknown";
var tf = new ThirdForm();
await NavigateTo(tf);
}
public override async Task PressReplyButton()
{
var mf = new MainForm();
await NavigateTo(mf);
}
}
}

View File

@ -0,0 +1,83 @@
using InlineAndReplyCombination.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TelegramBotBase.Attributes;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Forms.Steps
{
public class Summary : AutoCleanForm
{
[SaveState]
public UserDetails UserDetails { get; set; }
ButtonGrid ReplyButtonGrid { get; set; }
public Summary()
{
Init += Summary_Init;
}
private async Task Summary_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
var bf = new ButtonForm();
bf.AddButtonRow("Go back", "back");
bf.AddButtonRow("Return to Start", "start");
ReplyButtonGrid = new ButtonGrid(bf);
ReplyButtonGrid.Title = "Thank you for your time!";
ReplyButtonGrid.ButtonClicked += ReplyButtonGrid_ButtonClicked;
AddControl(ReplyButtonGrid);
}
public override async Task Load(MessageResult message)
{
if (UserDetails == null)
{
var sf = new StartForm();
await NavigateTo(sf);
return;
}
await Device.Send($"Your inputs are:\r\n\r\nYour age: {UserDetails.AgeRange}\r\nYour favourite color: {UserDetails.FavouriteColor}\r\nYour favourite city: {UserDetails.FavouriteCity}");
}
private async Task ReplyButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
switch (e.Button.Value ?? "")
{
case "start":
var sf = new StartForm();
await NavigateTo(sf);
break;
case "back":
var tf = new ThirdForm();
tf.UserDetails = UserDetails;
await NavigateTo(tf);
break;
}
}
}
}

View File

@ -0,0 +1,89 @@
using InlineAndReplyCombination.Baseclasses;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
using Telegram.Bot.Types;
using TelegramBotBase.Base;
using TelegramBotBase.Controls.Hybrid;
using TelegramBotBase.Form;
namespace InlineAndReplyCombination.Forms.Steps
{
public class ThirdForm : MultipleChoiceForm
{
ButtonGrid InlineButtonGrid;
public static List<Tuple<String, String>> AllowedInlineInputs = null;
static ThirdForm()
{
AllowedInlineInputs = new List<Tuple<string, string>>()
{
new("Berlin", "Berlin"),
new("Vienna", "Vienna"),
new("Rome", "Rome"),
new("London", "London"),
new("Moscow", "Moscow"),
new("Bukarest", "Bukarest")
};
}
public ThirdForm()
{
Init += SecondForm_Init;
ReplyButtonTitle = "Go back";
CurrentStep = 3;
}
private async Task SecondForm_Init(object sender, TelegramBotBase.Args.InitEventArgs e)
{
//Inline Keyboard
var bf_ages = new ButtonForm();
//Add all options in a single column
bf_ages.AddSplitted(AllowedInlineInputs.Select(a => new ButtonBase(a.Item1, a.Item2)), 1);
InlineButtonGrid = new ButtonGrid(bf_ages);
InlineButtonGrid.ConfirmationText = "Thank you";
InlineButtonGrid.Title = "Please choose your favourite city:";
InlineButtonGrid.ButtonClicked += InlineButtonGrid_ButtonClicked;
InlineButtonGrid.KeyboardType = TelegramBotBase.Enums.EKeyboardType.InlineKeyBoard;
AddControl(InlineButtonGrid);
}
private async Task InlineButtonGrid_ButtonClicked(object sender, TelegramBotBase.Args.ButtonClickedEventArgs e)
{
//Not found
if (!AllowedInlineInputs.Any(a => a.Item2 == e.Button.Value))
{
await Device.Send("Invalid input!");
return;
}
this.UserDetails.FavouriteCity = e.Button?.Value ?? "unknown";
var sum = new Summary();
sum.UserDetails = this.UserDetails;
await NavigateTo(sum);
}
public override async Task PressReplyButton()
{
var sf = new SecondForm();
await NavigateTo(sf);
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\TelegramBotBase\TelegramBotBase.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InlineAndReplyCombination.Model
{
[DebuggerDisplay("{AgeRange}, {FavouriteColor}, {FavouriteCity}")]
public class UserDetails
{
public String AgeRange { get; set; }
public String FavouriteColor { get; set; }
public String FavouriteCity { get; set; }
}
}

View File

@ -0,0 +1,41 @@
using InlineAndReplyCombination.Forms;
using TelegramBotBase;
using TelegramBotBase.Builder;
namespace InlineAndReplyCombination
{
internal class Program
{
public static BotBase BotBaseInstance { get; private set; }
static async Task Main(string[] args)
{
BotBaseInstance = BotBaseBuilder.Create()
.WithAPIKey(Environment.GetEnvironmentVariable("API_KEY") ??
throw new Exception("API_KEY is not set"))
.DefaultMessageLoop()
.WithStartForm<StartForm>()
.NoProxy()
.DefaultCommands()
.UseJSON(Path.Combine(Directory.GetCurrentDirectory(), "states.json"))
.UseEnglish()
.Build();
await BotBaseInstance.UploadBotCommands();
await BotBaseInstance.Start();
Console.WriteLine("Telegram Bot started");
Console.ReadLine();
await BotBaseInstance.Stop();
}
}
}

View File

@ -1035,4 +1035,8 @@ method of BotBase.
Having already a web application and want to add a TelegramBot side-by-side with it running ? Here is an example how you could do it.
- [Examples/BotAndWebApplication](Examples/BotAndWebApplication)
- [Examples/BotAndWebApplication](Examples/BotAndWebApplication)
Want to use Inline- and ReplyMarkup at the same time ? Here is an example how you can do that:
- [Examples/InlineAndReplyCombination](Examples/InlineAndReplyCombination)

View File

@ -28,7 +28,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotBase.Extensions.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCoreBot", "Examples\EFCoreBot\EFCoreBot.csproj", "{261BED47-0404-4A9A-86FC-047DE42A7D25}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotAndWebApplication", "Examples\BotAndWebApplication\BotAndWebApplication.csproj", "{52EA3201-02E8-46F5-87C4-B4752C8A815C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotAndWebApplication", "Examples\BotAndWebApplication\BotAndWebApplication.csproj", "{52EA3201-02E8-46F5-87C4-B4752C8A815C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InlineAndReplyCombination", "Examples\InlineAndReplyCombination\InlineAndReplyCombination.csproj", "{067E8EBE-F90A-4AFF-A0FF-20578216486E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -72,6 +74,10 @@ Global
{52EA3201-02E8-46F5-87C4-B4752C8A815C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{52EA3201-02E8-46F5-87C4-B4752C8A815C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{52EA3201-02E8-46F5-87C4-B4752C8A815C}.Release|Any CPU.Build.0 = Release|Any CPU
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{067E8EBE-F90A-4AFF-A0FF-20578216486E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -84,6 +90,7 @@ Global
{889B170E-32E9-4F26-BB04-8D06EA367857} = {E3193182-6FDA-4FA3-AD26-A487291E7681}
{261BED47-0404-4A9A-86FC-047DE42A7D25} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
{52EA3201-02E8-46F5-87C4-B4752C8A815C} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
{067E8EBE-F90A-4AFF-A0FF-20578216486E} = {BFA71E3F-31C0-4FC1-A320-4DCF704768C5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {59CB40E1-9FA7-4867-A56F-4F418286F057}