first commit
This commit is contained in:
commit
17393a47d3
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.vs
|
||||||
|
EnumSerializer.Generator/bin
|
||||||
|
EnumSerializer.Generator/obj
|
||||||
|
TelegramBot/bin
|
||||||
|
TelegramBot/obj
|
||||||
165
EnumSerializer.Generator/EnumConverterGenerator.cs
Normal file
165
EnumSerializer.Generator/EnumConverterGenerator.cs
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Microsoft.CodeAnalysis.Text;
|
||||||
|
using Scriban;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace EnumSerializer.Generator {
|
||||||
|
|
||||||
|
|
||||||
|
[Generator]
|
||||||
|
public class EnumConverterGenerator : IIncrementalGenerator {
|
||||||
|
const string JsonConverterAttribute = "Newtonsoft.Json.JsonConverterAttribute";
|
||||||
|
|
||||||
|
public void Initialize(IncrementalGeneratorInitializationContext context) {
|
||||||
|
IncrementalValuesProvider<EnumDeclarationSyntax> enumDeclarations = context.SyntaxProvider
|
||||||
|
.CreateSyntaxProvider(
|
||||||
|
predicate: static (s, _) => IsSyntaxTargetForGeneration(s),
|
||||||
|
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
|
||||||
|
.Where(static m => m is not null)!;
|
||||||
|
|
||||||
|
IncrementalValueProvider<(Compilation, ImmutableArray<EnumDeclarationSyntax>)> compilationAndEnums
|
||||||
|
= context.CompilationProvider.Combine(enumDeclarations.Collect());
|
||||||
|
|
||||||
|
context.RegisterSourceOutput(compilationAndEnums,
|
||||||
|
static (spc, source) => Execute(source.Item1, source.Item2, spc));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsSyntaxTargetForGeneration(SyntaxNode node) {
|
||||||
|
return node is EnumDeclarationSyntax e && e.AttributeLists.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static EnumDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext context) {
|
||||||
|
// we know the node is a EnumDeclarationSyntax thanks to IsSyntaxTargetForGeneration
|
||||||
|
var enumDeclarationSyntax = (EnumDeclarationSyntax)context.Node;
|
||||||
|
|
||||||
|
// loop through all the attributes on the method
|
||||||
|
foreach(AttributeListSyntax attributeListSyntax in enumDeclarationSyntax.AttributeLists) {
|
||||||
|
foreach(AttributeSyntax attributeSyntax in attributeListSyntax.Attributes) {
|
||||||
|
if(context.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol
|
||||||
|
is not IMethodSymbol attributeSymbol) {
|
||||||
|
// weird, we couldn't get the symbol, ignore it
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
INamedTypeSymbol attributeContainingTypeSymbol = attributeSymbol.ContainingType;
|
||||||
|
string fullName = attributeContainingTypeSymbol.ToDisplayString();
|
||||||
|
|
||||||
|
// Is the attribute the [JsonConverterAttribute] attribute?
|
||||||
|
if(fullName == JsonConverterAttribute) {
|
||||||
|
// return the enum
|
||||||
|
return enumDeclarationSyntax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we didn't find the attribute we were looking for
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Execute(
|
||||||
|
Compilation compilation,
|
||||||
|
ImmutableArray<EnumDeclarationSyntax> enums,
|
||||||
|
SourceProductionContext context) {
|
||||||
|
if(enums.IsDefaultOrEmpty) {
|
||||||
|
// nothing to do yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<EnumDeclarationSyntax> distinctEnums = enums.Distinct();
|
||||||
|
|
||||||
|
List<EnumInfo> enumsToProcess = GetTypesToGenerate(compilation, distinctEnums, context.CancellationToken);
|
||||||
|
if(enumsToProcess.Count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Template template = Template.Parse(SourceGenerationHelper.ConverterTemplate);
|
||||||
|
foreach(var enumToProcess in enumsToProcess) {
|
||||||
|
var result = SourceGenerationHelper.GenerateConverterClass(template, enumToProcess);
|
||||||
|
context.AddSource(
|
||||||
|
hintName: $"{enumToProcess.Name}Converter.g.cs",
|
||||||
|
sourceText: SourceText.From(result, Encoding.UTF8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<EnumInfo> GetTypesToGenerate(
|
||||||
|
Compilation compilation,
|
||||||
|
IEnumerable<EnumDeclarationSyntax> enums, CancellationToken ct) {
|
||||||
|
var enumsToProcess = new List<EnumInfo>();
|
||||||
|
INamedTypeSymbol? enumAttribute = compilation.GetTypeByMetadataName(JsonConverterAttribute);
|
||||||
|
if(enumAttribute is null) {
|
||||||
|
// nothing to do if this type isn't available
|
||||||
|
return enumsToProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var enumDeclarationSyntax in enums) {
|
||||||
|
// stop if we're asked to
|
||||||
|
ct.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
SemanticModel semanticModel = compilation.GetSemanticModel(enumDeclarationSyntax.SyntaxTree);
|
||||||
|
if(semanticModel.GetDeclaredSymbol(enumDeclarationSyntax, cancellationToken: ct)
|
||||||
|
is not INamedTypeSymbol enumSymbol) {
|
||||||
|
// report diagnostic, something went wrong
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string name = enumSymbol.Name;
|
||||||
|
string nameSpace = enumSymbol.ContainingNamespace.IsGlobalNamespace
|
||||||
|
? string.Empty
|
||||||
|
: enumSymbol.ContainingNamespace.ToString();
|
||||||
|
|
||||||
|
string fullyQualifiedName = enumSymbol.ToString();
|
||||||
|
|
||||||
|
var enumMembers = enumSymbol.GetMembers();
|
||||||
|
var members = new List<KeyValuePair<string, string>>(enumMembers.Length);
|
||||||
|
|
||||||
|
foreach(var member in enumMembers) {
|
||||||
|
if(member is not IFieldSymbol field
|
||||||
|
|| field.ConstantValue is null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? displayName = null;
|
||||||
|
foreach(var attribute in member.GetAttributes()) {
|
||||||
|
if(attribute.AttributeClass is null
|
||||||
|
|| attribute.AttributeClass.Name != "DisplayAttribute") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var namedArgument in attribute.NamedArguments) {
|
||||||
|
if(namedArgument.Key == "Name" && namedArgument.Value.Value?.ToString() is { } dn) {
|
||||||
|
displayName = dn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
members.Add(new(
|
||||||
|
member.Name,
|
||||||
|
displayName ?? ToSnakeCase(member.Name)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
enumsToProcess.Add(new(
|
||||||
|
name: name,
|
||||||
|
ns: nameSpace,
|
||||||
|
fullyQualifiedName: fullyQualifiedName,
|
||||||
|
members: members
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return enumsToProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string ToSnakeCase(string name) =>
|
||||||
|
string.Concat(name.Select((x, i) => i > 0 && char.IsUpper(x)
|
||||||
|
? $"_{x}"
|
||||||
|
: x.ToString())
|
||||||
|
).ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
EnumSerializer.Generator/EnumInfo.cs
Normal file
27
EnumSerializer.Generator/EnumInfo.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace EnumSerializer.Generator {
|
||||||
|
|
||||||
|
|
||||||
|
public readonly struct EnumInfo {
|
||||||
|
public readonly string Name;
|
||||||
|
public readonly string FullyQualifiedName;
|
||||||
|
public readonly string Namespace;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Key is the enum name.
|
||||||
|
/// </summary>
|
||||||
|
public readonly List<KeyValuePair<string, string>> Members;
|
||||||
|
|
||||||
|
public EnumInfo(
|
||||||
|
string name,
|
||||||
|
string ns,
|
||||||
|
string fullyQualifiedName,
|
||||||
|
List<KeyValuePair<string, string>> members) {
|
||||||
|
Name = name;
|
||||||
|
Namespace = ns;
|
||||||
|
Members = members;
|
||||||
|
FullyQualifiedName = fullyQualifiedName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
EnumSerializer.Generator/EnumSerializer.Generator.csproj
Normal file
25
EnumSerializer.Generator/EnumSerializer.Generator.csproj
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<IncludeBuildOutput>false</IncludeBuildOutput>
|
||||||
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
|
<EnableNETAnalyzers>True</EnableNETAnalyzers>
|
||||||
|
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- The following libraries include the source generator interfaces and types we need -->
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.0.0" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
|
||||||
|
<PackageReference Include="Scriban" Version="5.4.4" GeneratePathProperty="true" PrivateAssets="all" />
|
||||||
|
|
||||||
|
<!-- This ensures the library will be packaged as a source generator when we use `dotnet pack` -->
|
||||||
|
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
|
||||||
|
|
||||||
|
<TargetPathWithTargetPlatformMoniker Include="$(PKGScriban)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
19
EnumSerializer.Generator/README.md
Normal file
19
EnumSerializer.Generator/README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Enum Converter Generator
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
Telegram.Bot library relies on [Json.NET converters](https://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm)
|
||||||
|
to map JSON input to various enums and vice versa.
|
||||||
|
|
||||||
|
It's rather tedious and repeating task. So that's where C# source generators come to help.
|
||||||
|
|
||||||
|
`EnumSerializer.Generator` looks for enums
|
||||||
|
annotated with `[JsonConverter(typeof(TEnumConverter))]` attribute and generates a converter that handles all possible enum values for us.
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
This project is heavily inspired by the series of posts by Andrew Lock [Creating an incremental generator](https://andrewlock.net/creating-a-source-generator-part-1-creating-an-incremental-source-generator/) and [NetEscapades.EnumGenerators
|
||||||
|
](https://github.com/andrewlock/NetEscapades.EnumGenerators) project.
|
||||||
|
|
||||||
|
We use Alexandre Mutel's [Scriban](https://github.com/scriban/scriban) templating engine to generate
|
||||||
|
converter class output.
|
||||||
81
EnumSerializer.Generator/SourceGenerationHelper.cs
Normal file
81
EnumSerializer.Generator/SourceGenerationHelper.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Scriban;
|
||||||
|
|
||||||
|
namespace EnumSerializer.Generator {
|
||||||
|
|
||||||
|
|
||||||
|
public static class SourceGenerationHelper {
|
||||||
|
internal const string ConverterTemplate = @"//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by the EnumSerializer.Generator source generator
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
{{~ if enum_namespace ~}}
|
||||||
|
namespace {{ enum_namespace }}{
|
||||||
|
{{~ end ~}}
|
||||||
|
|
||||||
|
internal partial class {{ enum_name }}Converter : JsonConverter<{{ enum_name }}>
|
||||||
|
{
|
||||||
|
public override void WriteJson(JsonWriter writer, {{ enum_name }} value, JsonSerializer serializer) =>
|
||||||
|
writer.WriteValue(value switch
|
||||||
|
{
|
||||||
|
{{~ for enum_member in enum_members ~}}
|
||||||
|
{{ enum_name }}.{{enum_member.key}} => ""{{ enum_member.value }}"",
|
||||||
|
{{~ end ~}}
|
||||||
|
{{~ if has_unknown_member ~}}
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
{{~ else ~}}
|
||||||
|
({{ enum_name }})0 => ""unknown"",
|
||||||
|
_ => throw new NotSupportedException(),
|
||||||
|
{{~ end ~}}
|
||||||
|
});
|
||||||
|
|
||||||
|
public override {{ enum_name }} ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
{{ enum_name }} existingValue,
|
||||||
|
bool hasExistingValue,
|
||||||
|
JsonSerializer serializer
|
||||||
|
) =>
|
||||||
|
JToken.ReadFrom(reader).Value<string>() switch
|
||||||
|
{
|
||||||
|
{{~ for enum_member in enum_members ~}}
|
||||||
|
""{{ enum_member.value }}"" => {{ enum_name }}.{{ enum_member.key }},
|
||||||
|
{{~ end ~}}
|
||||||
|
{{~ if has_unknown_member ~}}
|
||||||
|
_ => {{ enum_name }}.Unknown,
|
||||||
|
{{~ else ~}}
|
||||||
|
_ => 0,
|
||||||
|
{{~ end ~}}
|
||||||
|
};
|
||||||
|
}}";
|
||||||
|
|
||||||
|
public static string GenerateConverterClass(Template template, EnumInfo enumToGenerate) {
|
||||||
|
var hasUnknownMember = enumToGenerate.Members.Any(
|
||||||
|
e => string.Equals(e.Value, "Unknown", StringComparison.OrdinalIgnoreCase)
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = template.Render(new {
|
||||||
|
EnumNamespace = enumToGenerate.Namespace,
|
||||||
|
EnumName = enumToGenerate.Name,
|
||||||
|
EnumMembers = enumToGenerate.Members,
|
||||||
|
HasUnknownMember = hasUnknownMember
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
TelegramBot.sln
Normal file
31
TelegramBot.sln
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.31112.23
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBot", "TelegramBot\TelegramBot.csproj", "{3616387D-AE43-4A5C-836A-D719CA5C96E9}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnumSerializer.Generator", "EnumSerializer.Generator\EnumSerializer.Generator.csproj", "{22004504-B8B9-48F4-A2B2-9D18748BF252}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{3616387D-AE43-4A5C-836A-D719CA5C96E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3616387D-AE43-4A5C-836A-D719CA5C96E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3616387D-AE43-4A5C-836A-D719CA5C96E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3616387D-AE43-4A5C-836A-D719CA5C96E9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{22004504-B8B9-48F4-A2B2-9D18748BF252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{22004504-B8B9-48F4-A2B2-9D18748BF252}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{22004504-B8B9-48F4-A2B2-9D18748BF252}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{22004504-B8B9-48F4-A2B2-9D18748BF252}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {33D9A7F3-619F-47CB-A8ED-80416CD00338}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
36
TelegramBot/Args/ApiRequestEventArgs.cs
Normal file
36
TelegramBot/Args/ApiRequestEventArgs.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Args {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data for MakingApiRequest event
|
||||||
|
/// </summary>
|
||||||
|
public class ApiRequestEventArgs : EventArgs {
|
||||||
|
/// <summary>
|
||||||
|
/// Bot API Request
|
||||||
|
/// </summary>
|
||||||
|
public IRequest Request {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP Request Message
|
||||||
|
/// </summary>
|
||||||
|
public HttpRequestMessage? HttpRequestMessage {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
/// <param name="httpRequestMessage"></param>
|
||||||
|
public ApiRequestEventArgs(IRequest request, HttpRequestMessage? httpRequestMessage = default) {
|
||||||
|
Request = request;
|
||||||
|
HttpRequestMessage = httpRequestMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
TelegramBot/Args/ApiResponseEventArgs.cs
Normal file
36
TelegramBot/Args/ApiResponseEventArgs.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Args {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data for ApiResponseReceived event
|
||||||
|
/// </summary>
|
||||||
|
public class ApiResponseEventArgs {
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP response received from API
|
||||||
|
/// </summary>
|
||||||
|
public HttpResponseMessage ResponseMessage {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event arguments of this request
|
||||||
|
/// </summary>
|
||||||
|
public ApiRequestEventArgs ApiRequestEventArgs {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize an <see cref="ApiRequestEventArgs"/> object
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="responseMessage">HTTP response received from API</param>
|
||||||
|
/// <param name="apiRequestEventArgs">Event arguments of this request</param>
|
||||||
|
public ApiResponseEventArgs(
|
||||||
|
HttpResponseMessage responseMessage,
|
||||||
|
ApiRequestEventArgs apiRequestEventArgs) {
|
||||||
|
ResponseMessage = responseMessage;
|
||||||
|
ApiRequestEventArgs = apiRequestEventArgs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
TelegramBot/AsyncEventHandler`T.cs
Normal file
15
TelegramBot/AsyncEventHandler`T.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
#pragma warning disable 1591
|
||||||
|
|
||||||
|
namespace Telegram.Bot {
|
||||||
|
|
||||||
|
#pragma warning disable CA1711
|
||||||
|
public delegate ValueTask AsyncEventHandler<in TArgs>(
|
||||||
|
#pragma warning restore CA1711
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
TArgs args,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
);
|
||||||
|
}
|
||||||
25
TelegramBot/Converters/BanTimeUnixDateTimeConverter.cs
Normal file
25
TelegramBot/Converters/BanTimeUnixDateTimeConverter.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class BanTimeUnixDateTimeConverter : UnixDateTimeConverter {
|
||||||
|
public override object? ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
|
||||||
|
var nonNullable = Nullable.GetUnderlyingType(objectType) is null;
|
||||||
|
|
||||||
|
return reader.TokenType == JsonToken.Integer && reader.Value is 0L
|
||||||
|
? nonNullable ? default : null
|
||||||
|
: base.ReadJson(reader, objectType, existingValue, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) {
|
||||||
|
if(value is null || value.Equals(default(DateTime))) {
|
||||||
|
writer.WriteValue(0);
|
||||||
|
} else {
|
||||||
|
base.WriteJson(writer, value, serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
TelegramBot/Converters/ChatIdConverter.cs
Normal file
28
TelegramBot/Converters/ChatIdConverter.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class ChatIdConverter : JsonConverter<ChatId> {
|
||||||
|
public override void WriteJson(JsonWriter writer, ChatId value, JsonSerializer serializer) {
|
||||||
|
if(value.Username != null) {
|
||||||
|
writer.WriteValue(value.Username);
|
||||||
|
} else {
|
||||||
|
writer.WriteValue(value.Identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ChatId ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
ChatId existingValue,
|
||||||
|
bool hasExistingValue,
|
||||||
|
JsonSerializer serializer) {
|
||||||
|
var value = JToken.ReadFrom(reader).Value<string>();
|
||||||
|
return new ChatId(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
TelegramBot/Converters/ChatMemberConverter.cs
Normal file
50
TelegramBot/Converters/ChatMemberConverter.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class ChatMemberConverter : JsonConverter {
|
||||||
|
static readonly TypeInfo BaseType = typeof(ChatMember).GetTypeInfo();
|
||||||
|
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanConvert(Type objectType) =>
|
||||||
|
BaseType.IsAssignableFrom(objectType.GetTypeInfo());
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||||
|
var jo = JObject.FromObject(value);
|
||||||
|
jo.WriteTo(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object existingValue,
|
||||||
|
JsonSerializer serializer) {
|
||||||
|
var jo = JObject.Load(reader);
|
||||||
|
var status = jo["status"].ToObject<ChatMemberStatus>();
|
||||||
|
|
||||||
|
var actualType = status switch {
|
||||||
|
ChatMemberStatus.Creator => typeof(ChatMemberOwner),
|
||||||
|
ChatMemberStatus.Administrator => typeof(ChatMemberAdministrator),
|
||||||
|
ChatMemberStatus.Member => typeof(ChatMemberMember),
|
||||||
|
ChatMemberStatus.Left => typeof(ChatMemberLeft),
|
||||||
|
ChatMemberStatus.Kicked => typeof(ChatMemberBanned),
|
||||||
|
ChatMemberStatus.Restricted => typeof(ChatMemberRestricted),
|
||||||
|
_ => throw new JsonSerializationException($"Unknown chat member status value of '{jo["status"]}'")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove status because status property only has getter
|
||||||
|
jo.Remove("status");
|
||||||
|
var value = Activator.CreateInstance(actualType);
|
||||||
|
serializer.Populate(jo.CreateReader(), value);
|
||||||
|
|
||||||
|
return value!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
TelegramBot/Converters/InputFileConverter.cs
Normal file
49
TelegramBot/Converters/InputFileConverter.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class InputFileConverter : JsonConverter {
|
||||||
|
public override bool CanConvert(Type objectType) =>
|
||||||
|
objectType.GetTypeInfo().IsSubclassOf(typeof(InputFileStream));
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||||
|
var input = (IInputFile)value;
|
||||||
|
switch(input.FileType) {
|
||||||
|
case FileType.Stream:
|
||||||
|
writer.WriteValue(null as object);
|
||||||
|
break;
|
||||||
|
case FileType.Id when value is InputTelegramFile file:
|
||||||
|
writer.WriteValue(file.FileId);
|
||||||
|
break;
|
||||||
|
case FileType.Url when value is InputOnlineFile file:
|
||||||
|
writer.WriteValue(file.Url);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException("File Type is not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object existingValue,
|
||||||
|
JsonSerializer serializer) {
|
||||||
|
var value = JToken.ReadFrom(reader).Value<string>();
|
||||||
|
if(value is null) {
|
||||||
|
return new InputFileStream(Stream.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Uri.TryCreate(value, UriKind.Absolute, out _)
|
||||||
|
? new InputOnlineFile(value)
|
||||||
|
: new InputTelegramFile(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
TelegramBot/Converters/InputMediaConverter.cs
Normal file
45
TelegramBot/Converters/InputMediaConverter.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class InputMediaConverter : InputFileConverter {
|
||||||
|
public override bool CanConvert(Type objectType) => typeof(InputMedia) == objectType;
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||||
|
var inputMediaType = (InputMedia)value;
|
||||||
|
switch(inputMediaType.FileType) {
|
||||||
|
case FileType.Id:
|
||||||
|
case FileType.Url:
|
||||||
|
base.WriteJson(writer, value, serializer);
|
||||||
|
break;
|
||||||
|
case FileType.Stream:
|
||||||
|
writer.WriteValue($"attach://{inputMediaType.FileName}");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException("File Type not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object existingValue,
|
||||||
|
JsonSerializer serializer) {
|
||||||
|
var value = JToken.ReadFrom(reader).Value<string>();
|
||||||
|
|
||||||
|
if(value is null) {
|
||||||
|
return null!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.StartsWith("attach://", StringComparison.InvariantCulture)
|
||||||
|
? new(Stream.Null, value.Substring(9))
|
||||||
|
: new InputMedia(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
TelegramBot/Converters/MenuButtonConverter.cs
Normal file
48
TelegramBot/Converters/MenuButtonConverter.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Converters {
|
||||||
|
|
||||||
|
|
||||||
|
internal class MenuButtonConverter : JsonConverter {
|
||||||
|
static readonly TypeInfo BaseType = typeof(MenuButton).GetTypeInfo();
|
||||||
|
|
||||||
|
public override bool CanWrite => false;
|
||||||
|
public override bool CanRead => true;
|
||||||
|
public override bool CanConvert(Type objectType) =>
|
||||||
|
BaseType.IsAssignableFrom(objectType.GetTypeInfo());
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
|
||||||
|
var jo = JObject.FromObject(value);
|
||||||
|
jo.WriteTo(writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(
|
||||||
|
JsonReader reader,
|
||||||
|
Type objectType,
|
||||||
|
object existingValue,
|
||||||
|
JsonSerializer serializer) {
|
||||||
|
var jo = JObject.Load(reader);
|
||||||
|
var typeToken = jo["type"];
|
||||||
|
var status = typeToken.ToObject<MenuButtonType>();
|
||||||
|
|
||||||
|
var actualType = status switch {
|
||||||
|
MenuButtonType.Default => typeof(MenuButtonDefault),
|
||||||
|
MenuButtonType.Commands => typeof(MenuButtonCommands),
|
||||||
|
MenuButtonType.WebApp => typeof(MenuButtonWebApp),
|
||||||
|
_ => throw new JsonSerializationException($"Unknown menu button type value of '{typeToken}'")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove status because status property only has getter
|
||||||
|
jo.Remove("type");
|
||||||
|
var value = Activator.CreateInstance(actualType);
|
||||||
|
serializer.Populate(jo.CreateReader(), value);
|
||||||
|
|
||||||
|
return value!;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
TelegramBot/Exceptions/ApiRequestException.cs
Normal file
99
TelegramBot/Exceptions/ApiRequestException.cs
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
using System;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Exceptions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an API error
|
||||||
|
/// </summary>
|
||||||
|
// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global
|
||||||
|
#pragma warning disable CA1032
|
||||||
|
public class ApiRequestException : RequestException
|
||||||
|
#pragma warning restore CA1032
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error code.
|
||||||
|
/// </summary>
|
||||||
|
public virtual int ErrorCode {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains information about why a request was unsuccessful.
|
||||||
|
/// </summary>
|
||||||
|
// ReSharper disable once UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable once MemberCanBePrivate.Global
|
||||||
|
public ResponseParameters? Parameters {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
public ApiRequestException(string message)
|
||||||
|
: base(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="errorCode">The error code.</param>
|
||||||
|
public ApiRequestException(string message, int errorCode)
|
||||||
|
: base(message) =>
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||||
|
/// <param name="innerException">
|
||||||
|
/// The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic)
|
||||||
|
/// if no inner exception is specified.
|
||||||
|
/// </param>
|
||||||
|
public ApiRequestException(string message, Exception innerException)
|
||||||
|
: base(message, innerException) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message.</param>
|
||||||
|
/// <param name="errorCode">The error code.</param>
|
||||||
|
/// <param name="innerException">The inner exception.</param>
|
||||||
|
public ApiRequestException(string message, int errorCode, Exception innerException)
|
||||||
|
: base(message, innerException) =>
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message</param>
|
||||||
|
/// <param name="errorCode">The error code</param>
|
||||||
|
/// <param name="parameters">Response parameters</param>
|
||||||
|
public ApiRequestException(string message, int errorCode, ResponseParameters? parameters)
|
||||||
|
: base(message) {
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
Parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ApiRequestException"/> class
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message</param>
|
||||||
|
/// <param name="errorCode">The error code</param>
|
||||||
|
/// <param name="parameters">Response parameters</param>
|
||||||
|
/// <param name="innerException">The inner exception</param>
|
||||||
|
public ApiRequestException(
|
||||||
|
string message,
|
||||||
|
int errorCode,
|
||||||
|
ResponseParameters? parameters,
|
||||||
|
Exception innerException)
|
||||||
|
: base(message, innerException) {
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
Parameters = parameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52
TelegramBot/Exceptions/ApiResponse.cs
Normal file
52
TelegramBot/Exceptions/ApiResponse.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Exceptions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents failed API response
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class ApiResponse {
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error message.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Description {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the error code.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int ErrorCode {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains information about why a request was unsuccessful.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ResponseParameters? Parameters {
|
||||||
|
get; private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes an instance of <see cref="ApiResponse"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="errorCode">Error code</param>
|
||||||
|
/// <param name="description">Error message</param>
|
||||||
|
/// <param name="parameters">Information about why a request was unsuccessful</param>
|
||||||
|
public ApiResponse(
|
||||||
|
int errorCode,
|
||||||
|
string description,
|
||||||
|
ResponseParameters? parameters) {
|
||||||
|
ErrorCode = errorCode;
|
||||||
|
Description = description;
|
||||||
|
Parameters = parameters;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
TelegramBot/Exceptions/DefaultExceptionParser.cs
Normal file
23
TelegramBot/Exceptions/DefaultExceptionParser.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Exceptions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default implementation of <see cref="IExceptionParser"/> that always returns <see cref="ApiRequestException"/>
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultExceptionParser : IExceptionParser {
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ApiRequestException Parse(ApiResponse apiResponse) {
|
||||||
|
if(apiResponse is null) {
|
||||||
|
throw new ArgumentNullException(nameof(apiResponse));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(
|
||||||
|
message: apiResponse.Description,
|
||||||
|
errorCode: apiResponse.ErrorCode,
|
||||||
|
parameters: apiResponse.Parameters
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
TelegramBot/Exceptions/IExceptionParser.cs
Normal file
15
TelegramBot/Exceptions/IExceptionParser.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Telegram.Bot.Exceptions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses unsuccessful responses from Telegram Bot API to make specific exceptions
|
||||||
|
/// </summary>
|
||||||
|
public interface IExceptionParser {
|
||||||
|
/// <summary>
|
||||||
|
/// Parses HTTP response and constructs a specific exception out of it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="apiResponse">ApiResponse with an error</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
ApiRequestException Parse(ApiResponse apiResponse);
|
||||||
|
}
|
||||||
|
}
|
||||||
73
TelegramBot/Exceptions/RequestException.cs
Normal file
73
TelegramBot/Exceptions/RequestException.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Exceptions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request error
|
||||||
|
/// </summary>
|
||||||
|
#pragma warning disable CA1032
|
||||||
|
public class RequestException : Exception
|
||||||
|
#pragma warning restore CA1032
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <see cref="HttpStatusCode"/> of the received response
|
||||||
|
/// </summary>
|
||||||
|
public HttpStatusCode? HttpStatusCode {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">The message that describes the error.</param>
|
||||||
|
public RequestException(string message)
|
||||||
|
: base(message) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">
|
||||||
|
/// The error message that explains the reason for the exception.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="innerException">
|
||||||
|
/// The exception that is the cause of the current exception, or a null reference
|
||||||
|
/// (Nothing in Visual Basic) if no inner exception is specified.
|
||||||
|
/// </param>
|
||||||
|
public RequestException(string message, Exception innerException)
|
||||||
|
: base(message, innerException) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">
|
||||||
|
/// The error message that explains the reason for the exception.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="httpStatusCode">
|
||||||
|
/// <see cref="HttpStatusCode"/> of the received response
|
||||||
|
/// </param>
|
||||||
|
public RequestException(string message, HttpStatusCode httpStatusCode)
|
||||||
|
: base(message) =>
|
||||||
|
HttpStatusCode = httpStatusCode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestException"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message">
|
||||||
|
/// The error message that explains the reason for the exception.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="httpStatusCode">
|
||||||
|
/// <see cref="HttpStatusCode"/> of the received response
|
||||||
|
/// </param>
|
||||||
|
/// <param name="innerException">
|
||||||
|
/// The exception that is the cause of the current exception, or a null reference
|
||||||
|
/// (Nothing in Visual Basic) if no inner exception is specified.
|
||||||
|
/// </param>
|
||||||
|
public RequestException(string message, HttpStatusCode httpStatusCode, Exception innerException)
|
||||||
|
: base(message, innerException) =>
|
||||||
|
HttpStatusCode = httpStatusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
TelegramBot/Extensions/Extensions.cs
Normal file
15
TelegramBot/Extensions/Extensions.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Extensions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension Methods
|
||||||
|
/// </summary>
|
||||||
|
internal static class ObjectExtensions {
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static T ThrowIfNull<T>(this T? value, string parameterName) =>
|
||||||
|
value ?? throw new ArgumentNullException(parameterName);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
TelegramBot/Extensions/HttpContentExtensions.cs
Normal file
55
TelegramBot/Extensions/HttpContentExtensions.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Extensions {
|
||||||
|
|
||||||
|
internal static class HttpContentExtensions {
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static void AddStreamContent(
|
||||||
|
this MultipartFormDataContent multipartContent,
|
||||||
|
Stream content,
|
||||||
|
string name,
|
||||||
|
string? fileName = default) {
|
||||||
|
fileName ??= name;
|
||||||
|
var contentDisposition = $@"form-data; name=""{name}""; filename=""{fileName}""".EncodeUtf8();
|
||||||
|
|
||||||
|
// It will be dispose of after the request is made
|
||||||
|
#pragma warning disable CA2000
|
||||||
|
var mediaPartContent = new StreamContent(content) {
|
||||||
|
Headers =
|
||||||
|
{
|
||||||
|
{"Content-Type", "application/octet-stream"},
|
||||||
|
{"Content-Disposition", contentDisposition}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#pragma warning restore CA2000
|
||||||
|
|
||||||
|
multipartContent.Add(mediaPartContent, name, fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static void AddContentIfInputFileStream(
|
||||||
|
this MultipartFormDataContent multipartContent,
|
||||||
|
params IInputMedia[] inputMedia) {
|
||||||
|
foreach(var input in inputMedia) {
|
||||||
|
if(input.Media.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: input.Media.Content!,
|
||||||
|
name: input.Media.FileName!
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input is IInputMediaThumb mediaThumb &&
|
||||||
|
mediaThumb.Thumb?.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: mediaThumb.Thumb.Content!,
|
||||||
|
name: mediaThumb.Thumb.FileName!
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
97
TelegramBot/Extensions/HttpResponseMessageExtensions.cs
Normal file
97
TelegramBot/Extensions/HttpResponseMessageExtensions.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Exceptions;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Extensions {
|
||||||
|
|
||||||
|
|
||||||
|
internal static class HttpResponseMessageExtensions {
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialize body from HttpContent into <typeparamref name="T"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="httpResponse"><see cref="HttpResponseMessage"/> instance</param>
|
||||||
|
/// <param name="guard"></param>
|
||||||
|
/// <typeparam name="T">Type of the resulting object</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="RequestException">
|
||||||
|
/// Thrown when body in the response can not be deserialized into <typeparamref name="T"/>
|
||||||
|
/// </exception>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static async Task<T> DeserializeContentAsync<T>(
|
||||||
|
this HttpResponseMessage httpResponse,
|
||||||
|
Func<T, bool> guard)
|
||||||
|
where T : class {
|
||||||
|
Stream? contentStream = null;
|
||||||
|
|
||||||
|
if(httpResponse.Content is null) {
|
||||||
|
throw new RequestException(
|
||||||
|
message: "Response doesn't contain any content",
|
||||||
|
httpStatusCode: httpResponse.StatusCode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
T? deserializedObject;
|
||||||
|
|
||||||
|
try {
|
||||||
|
contentStream = await httpResponse.Content
|
||||||
|
.ReadAsStreamAsync()
|
||||||
|
.ConfigureAwait(continueOnCapturedContext: false);
|
||||||
|
|
||||||
|
deserializedObject = contentStream
|
||||||
|
.DeserializeJsonFromStream<T>();
|
||||||
|
} catch(Exception exception) {
|
||||||
|
throw CreateRequestException(
|
||||||
|
httpResponse: httpResponse,
|
||||||
|
message: "Required properties not found in response",
|
||||||
|
exception: exception
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(deserializedObject is null) {
|
||||||
|
throw CreateRequestException(
|
||||||
|
httpResponse: httpResponse,
|
||||||
|
message: "Required properties not found in response"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(guard(deserializedObject)) {
|
||||||
|
throw CreateRequestException(
|
||||||
|
httpResponse: httpResponse,
|
||||||
|
message: "Required properties not found in response"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deserializedObject;
|
||||||
|
} finally {
|
||||||
|
#if NETCOREAPP3_1_OR_GREATER
|
||||||
|
if(contentStream is not null) {
|
||||||
|
await contentStream.DisposeAsync().ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
contentStream?.Dispose();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
static RequestException CreateRequestException(
|
||||||
|
HttpResponseMessage httpResponse,
|
||||||
|
string message,
|
||||||
|
Exception? exception = default
|
||||||
|
) =>
|
||||||
|
exception is null
|
||||||
|
? new(
|
||||||
|
message: message,
|
||||||
|
httpStatusCode: httpResponse.StatusCode
|
||||||
|
)
|
||||||
|
: new(
|
||||||
|
message: message,
|
||||||
|
httpStatusCode: httpResponse.StatusCode,
|
||||||
|
innerException: exception
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
TelegramBot/Extensions/StreamExtensions.cs
Normal file
31
TelegramBot/Extensions/StreamExtensions.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Extensions {
|
||||||
|
|
||||||
|
|
||||||
|
internal static class StreamExtensions {
|
||||||
|
/// <summary>
|
||||||
|
/// Deserialized JSON in Stream into <typeparamref name="T"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"><see cref="Stream"/> with content</param>
|
||||||
|
/// <typeparam name="T">Type of the resulting object</typeparam>
|
||||||
|
/// <returns>Deserialized instance of <typeparamref name="T" /> or <c>null</c></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
public static T? DeserializeJsonFromStream<T>(this Stream? stream)
|
||||||
|
where T : class {
|
||||||
|
if(stream is null || !stream.CanRead) {
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var streamReader = new StreamReader(stream);
|
||||||
|
using var jsonTextReader = new JsonTextReader(streamReader);
|
||||||
|
|
||||||
|
var jsonSerializer = JsonSerializer.CreateDefault();
|
||||||
|
var searchResult = jsonSerializer.Deserialize<T>(jsonTextReader);
|
||||||
|
|
||||||
|
return searchResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
TelegramBot/Extensions/StringExtensions.cs
Normal file
14
TelegramBot/Extensions/StringExtensions.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Extensions {
|
||||||
|
|
||||||
|
|
||||||
|
internal static class StringExtensions {
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
internal static string EncodeUtf8(this string value) =>
|
||||||
|
new(Encoding.UTF8.GetBytes(value).Select(c => Convert.ToChar(c)).ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
97
TelegramBot/ITelegramBotClient.cs
Normal file
97
TelegramBot/ITelegramBotClient.cs
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Args;
|
||||||
|
using Telegram.Bot.Exceptions;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
|
||||||
|
namespace Telegram.Bot {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A client interface to use the Telegram Bot API
|
||||||
|
/// </summary>
|
||||||
|
// [PublicAPI]
|
||||||
|
public interface ITelegramBotClient {
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
bool LocalBotServer {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the bot from bot token. For example, for the bot token
|
||||||
|
/// "1234567:4TT8bAc8GHUspu3ERYn-KGcvsvGB9u_n4ddy", the bot id is "1234567".
|
||||||
|
/// Token format is not public API so this property is optional and may stop working
|
||||||
|
/// in the future if Telegram changes it's token format.
|
||||||
|
/// </summary>
|
||||||
|
long? BotId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Timeout for requests
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan Timeout {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Instance of <see cref="IExceptionParser"/> to parse errors from Bot API into
|
||||||
|
/// <see cref="ApiRequestException"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This property is not thread safe</remarks>
|
||||||
|
IExceptionParser ExceptionsParser {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs before sending a request to API
|
||||||
|
/// </summary>
|
||||||
|
event AsyncEventHandler<ApiRequestEventArgs>? OnMakingApiRequest;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs after receiving the response to an API request
|
||||||
|
/// </summary>
|
||||||
|
event AsyncEventHandler<ApiResponseEventArgs>? OnApiResponseReceived;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send a request to Bot API
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResponse">Type of expected result in the response object</typeparam>
|
||||||
|
/// <param name="request">API request object</param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns>Result of the API request</returns>
|
||||||
|
Task<TResponse> MakeRequestAsync<TResponse>(
|
||||||
|
IRequest<TResponse> request,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test the API token
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns><c>true</c> if token is valid</returns>
|
||||||
|
Task<bool> TestApiAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to download a file. Get <paramref name="filePath"/> by calling
|
||||||
|
/// <see cref="TelegramBotClientExtensions.GetFileAsync(ITelegramBotClient, string, CancellationToken)"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath">Path to file on server</param>
|
||||||
|
/// <param name="destination">Destination stream to write file to</param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentException">filePath is <c>null</c>, empty or too short</exception>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="destination"/> is <c>null</c></exception>
|
||||||
|
Task DownloadFileAsync(
|
||||||
|
string filePath,
|
||||||
|
Stream destination,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
TelegramBot/Polling/Abstractions/IUpdateHandler.cs
Normal file
47
TelegramBot/Polling/Abstractions/IUpdateHandler.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Processes <see cref="Update"/>s and errors.
|
||||||
|
/// <para>See <see cref="DefaultUpdateHandler"/> for a simple implementation</para>
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public interface IUpdateHandler {
|
||||||
|
/// <summary>
|
||||||
|
/// Handles an <see cref="Update"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient">
|
||||||
|
/// The <see cref="ITelegramBotClient"/> instance of the bot receiving the <see cref="Update"/>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="update">The <see cref="Update"/> to handle</param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// The <see cref="CancellationToken"/> which will notify that method execution should be cancelled
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task HandleUpdateAsync(ITelegramBotClient botClient, Update update, CancellationToken cancellationToken);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles an <see cref="Exception"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient">
|
||||||
|
/// The <see cref="ITelegramBotClient"/> instance of the bot receiving the <see cref="Exception"/>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="exception">The <see cref="Exception"/> to handle</param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// The <see cref="CancellationToken"/> which will notify that method execution should be cancelled
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task HandlePollingErrorAsync(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
Exception exception,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
35
TelegramBot/Polling/Abstractions/IUpdateReceiver.cs
Normal file
35
TelegramBot/Polling/Abstractions/IUpdateReceiver.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Requests new <see cref="Update"/>s and processes them using provided <see cref="IUpdateHandler"/> instance
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public interface IUpdateReceiver {
|
||||||
|
/// <summary>
|
||||||
|
/// Starts receiving <see cref="Update"/>s invoking <see cref="IUpdateHandler.HandleUpdateAsync"/>
|
||||||
|
/// for each <see cref="Update"/>.
|
||||||
|
/// <para>This method will block if awaited.</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updateHandler">
|
||||||
|
/// The <see cref="IUpdateHandler"/> used for processing <see cref="Update"/>s
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// The <see cref="CancellationToken"/> with which you can stop receiving
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="Task"/> that will be completed when cancellation will be requested through
|
||||||
|
/// <paramref name="cancellationToken"/>
|
||||||
|
/// </returns>
|
||||||
|
Task ReceiveAsync(
|
||||||
|
IUpdateHandler updateHandler,
|
||||||
|
CancellationToken cancellationToken = default
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
64
TelegramBot/Polling/Abstractions/ReceiverOptions.cs
Normal file
64
TelegramBot/Polling/Abstractions/ReceiverOptions.cs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Options to configure getUpdates requests
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public sealed class ReceiverOptions {
|
||||||
|
int? _limit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of the first update to be returned. Will be ignored if
|
||||||
|
/// <see cref="ThrowPendingUpdates"/> is set to <c>true</c>.
|
||||||
|
/// </summary>
|
||||||
|
public int? Offset {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates which <see cref="UpdateType"/>s are allowed to be received.
|
||||||
|
/// In case of <c>null</c> the previous setting will be used
|
||||||
|
/// </summary>
|
||||||
|
public UpdateType[]? AllowedUpdates {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limits the number of updates to be retrieved. Values between 1-100 are accepted.
|
||||||
|
/// Defaults to 100 when is set to <c>null</c>.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||||
|
/// Thrown when the value doesn't satisfies constraints
|
||||||
|
/// </exception>
|
||||||
|
public int? Limit {
|
||||||
|
get => _limit;
|
||||||
|
set {
|
||||||
|
if(value is < 1 or > 100) {
|
||||||
|
throw new ArgumentOutOfRangeException(
|
||||||
|
paramName: nameof(value),
|
||||||
|
actualValue: value,
|
||||||
|
message: $"'{nameof(Limit)}' can not be less than 1 or greater than 100"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_limit = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if all pending <see cref="Update"/>s should be thrown out before start
|
||||||
|
/// polling. If set to <c>true</c> <see cref="AllowedUpdates"/> should be set to not
|
||||||
|
/// <c>null</c>, otherwise <see cref="AllowedUpdates"/> will effectively be set to
|
||||||
|
/// receive all <see cref="Update"/>s.
|
||||||
|
/// </summary>
|
||||||
|
public bool ThrowPendingUpdates {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,143 @@
|
|||||||
|
#if NETCOREAPP3_1_OR_GREATER
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Requests;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supports asynchronous iteration over <see cref="Update"/>s
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public class BlockingUpdateReceiver : IAsyncEnumerable<Update> {
|
||||||
|
readonly ReceiverOptions? _receiverOptions;
|
||||||
|
readonly ITelegramBotClient _botClient;
|
||||||
|
readonly Func<Exception, CancellationToken, Task>? _pollingErrorHandler;
|
||||||
|
|
||||||
|
int _inProcess;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="BlockingUpdateReceiver"/> for the specified <see cref="ITelegramBotClient"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient">The <see cref="ITelegramBotClient"/> used for making GetUpdates calls</param>
|
||||||
|
/// <param name="receiverOptions"></param>
|
||||||
|
/// <param name="pollingErrorHandler">
|
||||||
|
/// The function used to handle <see cref="Exception"/>s thrown by ReceiveUpdates
|
||||||
|
/// </param>
|
||||||
|
public BlockingUpdateReceiver(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
ReceiverOptions? receiverOptions = default,
|
||||||
|
Func<Exception, CancellationToken, Task>? pollingErrorHandler = default) {
|
||||||
|
_botClient = botClient ?? throw new ArgumentNullException(nameof(botClient));
|
||||||
|
_receiverOptions = receiverOptions;
|
||||||
|
_pollingErrorHandler = pollingErrorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="IAsyncEnumerator{Update}"/>. This method may only be called once.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// The <see cref="CancellationToken"/> with which you can stop receiving
|
||||||
|
/// </param>
|
||||||
|
public IAsyncEnumerator<Update> GetAsyncEnumerator(CancellationToken cancellationToken = default) {
|
||||||
|
if(Interlocked.CompareExchange(ref _inProcess, 1, 0) == 1) {
|
||||||
|
throw new InvalidOperationException(nameof(GetAsyncEnumerator) + " may only be called once");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Enumerator(receiver: this, cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Enumerator : IAsyncEnumerator<Update> {
|
||||||
|
readonly BlockingUpdateReceiver _receiver;
|
||||||
|
readonly CancellationTokenSource _cts;
|
||||||
|
readonly CancellationToken _token;
|
||||||
|
readonly UpdateType[]? _allowedUpdates;
|
||||||
|
readonly int? _limit;
|
||||||
|
|
||||||
|
Update[] _updateArray = Array.Empty<Update>();
|
||||||
|
int _updateIndex;
|
||||||
|
int _messageOffset;
|
||||||
|
bool _updatesThrown;
|
||||||
|
|
||||||
|
public Enumerator(BlockingUpdateReceiver receiver, CancellationToken cancellationToken) {
|
||||||
|
_receiver = receiver;
|
||||||
|
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default);
|
||||||
|
_token = _cts.Token;
|
||||||
|
_messageOffset = receiver._receiverOptions?.Offset ?? 0;
|
||||||
|
_limit = receiver._receiverOptions?.Limit ?? default;
|
||||||
|
_allowedUpdates = receiver._receiverOptions?.AllowedUpdates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<bool> MoveNextAsync() {
|
||||||
|
_token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
_updateIndex += 1;
|
||||||
|
|
||||||
|
return _updateIndex < _updateArray.Length
|
||||||
|
? new(true)
|
||||||
|
: new(ReceiveUpdatesAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<bool> ReceiveUpdatesAsync() {
|
||||||
|
var shouldThrowPendingUpdates = (
|
||||||
|
_updatesThrown,
|
||||||
|
_receiver._receiverOptions?.ThrowPendingUpdates ?? false
|
||||||
|
);
|
||||||
|
|
||||||
|
if(shouldThrowPendingUpdates is (false, true)) {
|
||||||
|
try {
|
||||||
|
_messageOffset = await _receiver._botClient.ThrowOutPendingUpdatesAsync(
|
||||||
|
cancellationToken: _token
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// ignored
|
||||||
|
} finally {
|
||||||
|
_updatesThrown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateArray = Array.Empty<Update>();
|
||||||
|
_updateIndex = 0;
|
||||||
|
|
||||||
|
while(_updateArray.Length == 0) {
|
||||||
|
try {
|
||||||
|
_updateArray = await _receiver._botClient
|
||||||
|
.MakeRequestAsync(
|
||||||
|
request: new GetUpdatesRequest {
|
||||||
|
Offset = _messageOffset,
|
||||||
|
Timeout = (int)_receiver._botClient.Timeout.TotalSeconds,
|
||||||
|
Limit = _limit,
|
||||||
|
AllowedUpdates = _allowedUpdates,
|
||||||
|
},
|
||||||
|
cancellationToken: _token
|
||||||
|
)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
throw;
|
||||||
|
} catch(Exception ex) when(_receiver._pollingErrorHandler is not null) {
|
||||||
|
await _receiver._pollingErrorHandler(ex, _token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_messageOffset = _updateArray[^1].Id + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Update Current => _updateArray[_updateIndex];
|
||||||
|
|
||||||
|
public ValueTask DisposeAsync() {
|
||||||
|
_cts.Cancel();
|
||||||
|
_cts.Dispose();
|
||||||
|
return new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@ -0,0 +1,215 @@
|
|||||||
|
#if NETCOREAPP3_1_OR_GREATER
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Requests;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supports asynchronous iteration over <see cref="Update"/>s.
|
||||||
|
/// <para>Updates are received on a different thread and enqueued.</para>
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public class QueuedUpdateReceiver : IAsyncEnumerable<Update> {
|
||||||
|
readonly ITelegramBotClient _botClient;
|
||||||
|
readonly ReceiverOptions? _receiverOptions;
|
||||||
|
readonly Func<Exception, CancellationToken, Task>? _pollingErrorHandler;
|
||||||
|
|
||||||
|
int _inProcess;
|
||||||
|
Enumerator? _enumerator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="QueuedUpdateReceiver"/> for the specified <see cref="ITelegramBotClient"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient">The <see cref="ITelegramBotClient"/> used for making GetUpdates calls</param>
|
||||||
|
/// <param name="receiverOptions"></param>
|
||||||
|
/// <param name="pollingErrorHandler">
|
||||||
|
/// The function used to handle <see cref="Exception"/>s thrown by GetUpdates requests
|
||||||
|
/// </param>
|
||||||
|
public QueuedUpdateReceiver(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
ReceiverOptions? receiverOptions = default,
|
||||||
|
Func<Exception, CancellationToken, Task>? pollingErrorHandler = default) {
|
||||||
|
_botClient = botClient ?? throw new ArgumentNullException(nameof(botClient));
|
||||||
|
_receiverOptions = receiverOptions;
|
||||||
|
_pollingErrorHandler = pollingErrorHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates how many <see cref="Update"/>s are ready to be returned the enumerator
|
||||||
|
/// </summary>
|
||||||
|
public int PendingUpdates => _enumerator?.PendingUpdates ?? 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="IAsyncEnumerator{Update}"/>. This method may only be called once.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">
|
||||||
|
/// The <see cref="CancellationToken"/> with which you can stop receiving
|
||||||
|
/// </param>
|
||||||
|
public IAsyncEnumerator<Update> GetAsyncEnumerator(CancellationToken cancellationToken = default) {
|
||||||
|
if(Interlocked.CompareExchange(ref _inProcess, 1, 0) == 1) {
|
||||||
|
throw new InvalidOperationException(nameof(GetAsyncEnumerator) + " may only be called once");
|
||||||
|
}
|
||||||
|
|
||||||
|
_enumerator = new(receiver: this, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
|
return _enumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Enumerator : IAsyncEnumerator<Update> {
|
||||||
|
readonly QueuedUpdateReceiver _receiver;
|
||||||
|
readonly CancellationTokenSource _cts;
|
||||||
|
readonly CancellationToken _token;
|
||||||
|
readonly UpdateType[]? _allowedUpdates;
|
||||||
|
readonly int? _limit;
|
||||||
|
|
||||||
|
Exception? _uncaughtException;
|
||||||
|
|
||||||
|
readonly Channel<Update> _channel;
|
||||||
|
Update? _current;
|
||||||
|
|
||||||
|
int _pendingUpdates;
|
||||||
|
int _messageOffset;
|
||||||
|
|
||||||
|
public int PendingUpdates => _pendingUpdates;
|
||||||
|
|
||||||
|
public Enumerator(QueuedUpdateReceiver receiver, CancellationToken cancellationToken) {
|
||||||
|
_receiver = receiver;
|
||||||
|
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default);
|
||||||
|
_token = _cts.Token;
|
||||||
|
_messageOffset = receiver._receiverOptions?.Offset ?? 0;
|
||||||
|
_limit = receiver._receiverOptions?.Limit ?? default;
|
||||||
|
_allowedUpdates = receiver._receiverOptions?.AllowedUpdates;
|
||||||
|
|
||||||
|
_channel = Channel.CreateUnbounded<Update>(
|
||||||
|
new() {
|
||||||
|
SingleReader = true,
|
||||||
|
SingleWriter = true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#pragma warning disable CA2016
|
||||||
|
Task.Run(ReceiveUpdatesAsync);
|
||||||
|
#pragma warning restore CA2016
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<bool> MoveNextAsync() {
|
||||||
|
if(_uncaughtException is not null) {
|
||||||
|
throw _uncaughtException;
|
||||||
|
}
|
||||||
|
|
||||||
|
_token.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
if(_channel.Reader.TryRead(out _current)) {
|
||||||
|
Interlocked.Decrement(ref _pendingUpdates);
|
||||||
|
return new(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(ReadAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task<bool> ReadAsync() {
|
||||||
|
_current = await _channel.Reader.ReadAsync(_token).ConfigureAwait(false);
|
||||||
|
Interlocked.Decrement(ref _pendingUpdates);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task ReceiveUpdatesAsync() {
|
||||||
|
if(_receiver._receiverOptions?.ThrowPendingUpdates is true) {
|
||||||
|
try {
|
||||||
|
_messageOffset = await _receiver._botClient.ThrowOutPendingUpdatesAsync(
|
||||||
|
cancellationToken: _token
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!_cts.IsCancellationRequested) {
|
||||||
|
try {
|
||||||
|
Update[] updateArray = await _receiver._botClient
|
||||||
|
.MakeRequestAsync(
|
||||||
|
request: new GetUpdatesRequest {
|
||||||
|
Offset = _messageOffset,
|
||||||
|
Timeout = (int)_receiver._botClient.Timeout.TotalSeconds,
|
||||||
|
AllowedUpdates = _allowedUpdates,
|
||||||
|
Limit = _limit,
|
||||||
|
},
|
||||||
|
cancellationToken: _token
|
||||||
|
)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
if(updateArray.Length > 0) {
|
||||||
|
_messageOffset = updateArray[^1].Id + 1;
|
||||||
|
|
||||||
|
Interlocked.Add(ref _pendingUpdates, updateArray.Length);
|
||||||
|
|
||||||
|
ChannelWriter<Update> writer = _channel.Writer;
|
||||||
|
foreach(Update update in updateArray) {
|
||||||
|
// ReSharper disable once RedundantAssignment
|
||||||
|
var success = writer.TryWrite(update);
|
||||||
|
Debug.Assert(success, "TryWrite should succeed as we are using an unbounded channel");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
#pragma warning disable CA1031
|
||||||
|
catch(Exception ex)
|
||||||
|
#pragma warning restore CA1031
|
||||||
|
{
|
||||||
|
Debug.Assert(_uncaughtException is null);
|
||||||
|
|
||||||
|
// If there is no errorHandler or the errorHandler throws, stop receiving
|
||||||
|
if(_receiver._pollingErrorHandler is null) {
|
||||||
|
_uncaughtException = ex;
|
||||||
|
_cts.Cancel();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await _receiver._pollingErrorHandler(ex, _token).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
#pragma warning disable CA1031
|
||||||
|
catch(Exception errorHandlerException)
|
||||||
|
#pragma warning restore CA1031
|
||||||
|
{
|
||||||
|
_uncaughtException = new AggregateException(
|
||||||
|
message: "Exception was not caught by the errorHandler.",
|
||||||
|
ex,
|
||||||
|
errorHandlerException
|
||||||
|
);
|
||||||
|
_cts.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_uncaughtException is not null) {
|
||||||
|
#pragma warning disable CA2201
|
||||||
|
_uncaughtException = new(
|
||||||
|
message: "Exception was not caught by the errorHandler.",
|
||||||
|
innerException: _uncaughtException
|
||||||
|
);
|
||||||
|
#pragma warning restore CA2201
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Update Current => _current!; // _current being null indicates MoveNextAsync was never called
|
||||||
|
|
||||||
|
public ValueTask DisposeAsync() {
|
||||||
|
_cts.Cancel();
|
||||||
|
_cts.Dispose();
|
||||||
|
return new();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
46
TelegramBot/Polling/DefaultUpdateHandler.cs
Normal file
46
TelegramBot/Polling/DefaultUpdateHandler.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A very simple <see cref="IUpdateHandler"/> implementation
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public class DefaultUpdateHandler : IUpdateHandler {
|
||||||
|
readonly Func<ITelegramBotClient, Update, CancellationToken, Task> _updateHandler;
|
||||||
|
readonly Func<ITelegramBotClient, Exception, CancellationToken, Task> _pollingErrorHandler;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="DefaultUpdateHandler"/> with the specified callback functions
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="updateHandler">The function to invoke when an update is received</param>
|
||||||
|
/// <param name="pollingErrorHandler">The function to invoke when an error occurs</param>
|
||||||
|
public DefaultUpdateHandler(
|
||||||
|
Func<ITelegramBotClient, Update, CancellationToken, Task> updateHandler,
|
||||||
|
Func<ITelegramBotClient, Exception, CancellationToken, Task> pollingErrorHandler) {
|
||||||
|
_updateHandler = updateHandler ?? throw new ArgumentNullException(nameof(updateHandler));
|
||||||
|
_pollingErrorHandler = pollingErrorHandler ?? throw new ArgumentNullException(nameof(pollingErrorHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task HandleUpdateAsync(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
Update update,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
) =>
|
||||||
|
await _updateHandler(botClient, update, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task HandlePollingErrorAsync(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
Exception exception,
|
||||||
|
CancellationToken cancellationToken
|
||||||
|
) =>
|
||||||
|
await _pollingErrorHandler(botClient, exception, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
TelegramBot/Polling/DefaultUpdateReceiver.cs
Normal file
106
TelegramBot/Polling/DefaultUpdateReceiver.cs
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
//using JetBrains.Annotations;
|
||||||
|
using Telegram.Bot.Requests;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A simple <see cref="IUpdateReceiver"/>> implementation that requests new updates and handles them sequentially
|
||||||
|
/// </summary>
|
||||||
|
//[PublicAPI]
|
||||||
|
public class DefaultUpdateReceiver : IUpdateReceiver {
|
||||||
|
static readonly Update[] EmptyUpdates = Array.Empty<Update>();
|
||||||
|
|
||||||
|
readonly ITelegramBotClient _botClient;
|
||||||
|
readonly ReceiverOptions? _receiverOptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new <see cref="DefaultUpdateReceiver"/> with the specified <see cref="ITelegramBotClient"/>>
|
||||||
|
/// instance and optional <see cref="ReceiverOptions"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient">The <see cref="ITelegramBotClient"/> used for making GetUpdates calls</param>
|
||||||
|
/// <param name="receiverOptions">Options used to configure getUpdates requests</param>
|
||||||
|
public DefaultUpdateReceiver(
|
||||||
|
ITelegramBotClient botClient,
|
||||||
|
ReceiverOptions? receiverOptions = default) {
|
||||||
|
_botClient = botClient ?? throw new ArgumentNullException(nameof(botClient));
|
||||||
|
_receiverOptions = receiverOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public async Task ReceiveAsync(
|
||||||
|
IUpdateHandler updateHandler,
|
||||||
|
CancellationToken cancellationToken = default) {
|
||||||
|
if(updateHandler is null) {
|
||||||
|
throw new ArgumentNullException(nameof(updateHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
var allowedUpdates = _receiverOptions?.AllowedUpdates;
|
||||||
|
var limit = _receiverOptions?.Limit ?? default;
|
||||||
|
var messageOffset = _receiverOptions?.Offset ?? 0;
|
||||||
|
var emptyUpdates = EmptyUpdates;
|
||||||
|
|
||||||
|
if(_receiverOptions?.ThrowPendingUpdates is true) {
|
||||||
|
try {
|
||||||
|
messageOffset = await _botClient.ThrowOutPendingUpdatesAsync(
|
||||||
|
cancellationToken: cancellationToken
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!cancellationToken.IsCancellationRequested) {
|
||||||
|
var timeout = (int)_botClient.Timeout.TotalSeconds;
|
||||||
|
var updates = emptyUpdates;
|
||||||
|
try {
|
||||||
|
var request = new GetUpdatesRequest {
|
||||||
|
Limit = limit,
|
||||||
|
Offset = messageOffset,
|
||||||
|
Timeout = timeout,
|
||||||
|
AllowedUpdates = allowedUpdates,
|
||||||
|
};
|
||||||
|
updates = await _botClient.MakeRequestAsync(
|
||||||
|
request: request,
|
||||||
|
cancellationToken:
|
||||||
|
cancellationToken
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
#pragma warning disable CA1031
|
||||||
|
catch(Exception exception)
|
||||||
|
#pragma warning restore CA1031
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
await updateHandler.HandlePollingErrorAsync(
|
||||||
|
botClient: _botClient,
|
||||||
|
exception: exception,
|
||||||
|
cancellationToken: cancellationToken
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach(var update in updates) {
|
||||||
|
try {
|
||||||
|
await updateHandler.HandleUpdateAsync(
|
||||||
|
botClient: _botClient,
|
||||||
|
update: update,
|
||||||
|
cancellationToken: cancellationToken
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
|
||||||
|
messageOffset = update.Id + 1;
|
||||||
|
} catch(OperationCanceledException) {
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
TelegramBot/Polling/TelegramBotClientExtensions.cs
Normal file
42
TelegramBot/Polling/TelegramBotClientExtensions.cs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Telegram.Bot.Requests;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Polling {
|
||||||
|
|
||||||
|
|
||||||
|
internal static class TelegramBotClientExtensions {
|
||||||
|
/// <summary>
|
||||||
|
/// Will attempt to throw the last update using offset set to -1.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="botClient"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns>
|
||||||
|
/// Update ID of the last <see cref="Update"/> increased by 1 if there were any
|
||||||
|
/// </returns>
|
||||||
|
internal static async Task<int> ThrowOutPendingUpdatesAsync(
|
||||||
|
this ITelegramBotClient botClient,
|
||||||
|
CancellationToken cancellationToken = default) {
|
||||||
|
var request = new GetUpdatesRequest {
|
||||||
|
Limit = 1,
|
||||||
|
Offset = -1,
|
||||||
|
Timeout = 0,
|
||||||
|
AllowedUpdates = Array.Empty<UpdateType>(),
|
||||||
|
};
|
||||||
|
var updates = await botClient.MakeRequestAsync(request: request, cancellationToken: cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
#if NETCOREAPP3_1_OR_GREATER
|
||||||
|
if(updates.Length > 0) {
|
||||||
|
return updates[^1].Id + 1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (updates.Length > 0) { return updates[updates.Length - 1].Id + 1; }
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
TelegramBot/Properties/AssemblyInfo.cs
Normal file
6
TelegramBot/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Telegram.Bot.Tests.Unit")]
|
||||||
|
[assembly: InternalsVisibleTo("Telegram.Bot.Tests.Integ")]
|
||||||
|
[assembly: CLSCompliant(false)]
|
||||||
83
TelegramBot/Requests/Abstractions/Documentation.cs
Normal file
83
TelegramBot/Requests/Abstractions/Documentation.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#nullable disable
|
||||||
|
#pragma warning disable 169
|
||||||
|
#pragma warning disable CA1823
|
||||||
|
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
namespace Telegram.Bot.Requests.Abstractions {
|
||||||
|
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedType.Global
|
||||||
|
internal abstract class Documentation {
|
||||||
|
Documentation() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of special entities that appear in the caption, which can be specified instead of
|
||||||
|
/// <see cref="Types.Enums.ParseMode"/>
|
||||||
|
/// </summary>
|
||||||
|
object CaptionEntities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of special entities that appear in message text, which can be specified instead of
|
||||||
|
/// <see cref="Types.Enums.ParseMode"/>
|
||||||
|
/// </summary>
|
||||||
|
object Entities;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mode for parsing entities in the new caption. See
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#formatting-options">formatting</a>
|
||||||
|
/// options for more details.
|
||||||
|
/// </summary>
|
||||||
|
object ParseMode;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of the inline message
|
||||||
|
/// </summary>
|
||||||
|
object InlineMessageId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An <see cref="InlineKeyboardMarkup">inline keyboard</see>
|
||||||
|
/// </summary>
|
||||||
|
object InlineReplyMarkup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional interface options. An <see cref="InlineKeyboardMarkup">inline keyboard</see>,
|
||||||
|
/// <see cref="ReplyKeyboardMarkup">custom reply keyboard</see>, instructions to
|
||||||
|
/// <see cref="ReplyKeyboardRemove">remove reply keyboard</see> or to
|
||||||
|
/// <see cref="ForceReplyMarkup">force a reply</see> from the user.
|
||||||
|
/// </summary>
|
||||||
|
object ReplyMarkup;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the message silently. Users will receive a notification with no sound.
|
||||||
|
/// </summary>
|
||||||
|
object DisableNotification;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the message is a reply, ID of the original message
|
||||||
|
/// </summary>
|
||||||
|
object ReplyToMessageId;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass <c>true</c>, if the message should be sent even if the specified replied-to message is not found
|
||||||
|
/// </summary>
|
||||||
|
object AllowSendingWithoutReply;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Thumbnail of the file sent; can be ignored if thumbnail generation for the file is supported
|
||||||
|
/// server-side. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail's
|
||||||
|
/// width and height should not exceed 320. Ignored if the file is not uploaded using
|
||||||
|
/// multipart/form-data. Thumbnails can't be reused and can be only uploaded as a new file, so
|
||||||
|
/// you can pass "attach://<file_attach_name>" if the thumbnail was uploaded using
|
||||||
|
/// multipart/form-data under <file_attach_name>
|
||||||
|
/// </summary>
|
||||||
|
object Thumb;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Protects the contents of sent messages from forwarding and saving
|
||||||
|
/// </summary>
|
||||||
|
object ProtectContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
TelegramBot/Requests/Abstractions/IChatTargetable.cs
Normal file
18
TelegramBot/Requests/Abstractions/IChatTargetable.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Requests.Abstractions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request having <see cref="ChatId"/> parameter
|
||||||
|
/// </summary>
|
||||||
|
public interface IChatTargetable {
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format @channelusername)
|
||||||
|
/// </summary>
|
||||||
|
ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
TelegramBot/Requests/Abstractions/IRequest.cs
Normal file
38
TelegramBot/Requests/Abstractions/IRequest.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedTypeParameter
|
||||||
|
namespace Telegram.Bot.Requests.Abstractions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request to Bot API
|
||||||
|
/// </summary>
|
||||||
|
public interface IRequest {
|
||||||
|
/// <summary>
|
||||||
|
/// HTTP method of request
|
||||||
|
/// </summary>
|
||||||
|
HttpMethod Method {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// API method name
|
||||||
|
/// </summary>
|
||||||
|
string MethodName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows this object to be used as a response in webhooks
|
||||||
|
/// </summary>
|
||||||
|
bool IsWebhookResponse {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate content of HTTP message
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Content of HTTP request</returns>
|
||||||
|
HttpContent? ToHttpContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
11
TelegramBot/Requests/Abstractions/IRequest`T.cs
Normal file
11
TelegramBot/Requests/Abstractions/IRequest`T.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Telegram.Bot.Requests.Abstractions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request to Bot API
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResponse">Type of result expected in result</typeparam>
|
||||||
|
// ReSharper disable once UnusedTypeParameter
|
||||||
|
public interface IRequest<TResponse> : IRequest {
|
||||||
|
}
|
||||||
|
}
|
||||||
15
TelegramBot/Requests/Abstractions/IUserTargetable.cs
Normal file
15
TelegramBot/Requests/Abstractions/IUserTargetable.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Telegram.Bot.Requests.Abstractions {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a request having <see cref="UserId"/> parameter
|
||||||
|
/// </summary>
|
||||||
|
public interface IUserTargetable {
|
||||||
|
/// <summary>
|
||||||
|
/// User identifier
|
||||||
|
/// </summary>
|
||||||
|
long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send answers to callback queries sent from
|
||||||
|
/// <see cref="Types.ReplyMarkups.InlineKeyboardMarkup">inline keyboards</see>. The answer will be
|
||||||
|
/// displayed to the user as a notification at the top of the chat screen or as an alert. On success,
|
||||||
|
/// <c>true</c> is returned.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Alternatively, the user can be redirected to the specified Game URL.For this option to work, you
|
||||||
|
/// must first create a game for your bot via <c>@Botfather</c> and accept the terms. Otherwise, you
|
||||||
|
/// may use links like <c>t.me/your_bot? start = XXXX</c> that open your bot with a parameter.
|
||||||
|
/// </remarks>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class AnswerCallbackQueryRequest : RequestBase<bool> {
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the query to be answered
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string CallbackQueryId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text of the notification. If not specified, nothing will be shown to the user, 0-200 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Text {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, an alert will be shown by the client instead of a notification at the top of
|
||||||
|
/// the chat screen. Defaults to <c>false</c>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ShowAlert {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// URL that will be opened by the user's client. If you have created a
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#game">Game</a> and accepted the conditions
|
||||||
|
/// via <c>@Botfather</c>, specify the URL that opens your game — note that this will only work
|
||||||
|
/// if the query comes from a callback_game button.
|
||||||
|
/// <para>
|
||||||
|
/// Otherwise, you may use links like <c>t.me/your_bot? start = XXXX</c> that open your bot with
|
||||||
|
/// a parameter
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Url {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum amount of time in seconds that the result of the callback query may be cached
|
||||||
|
/// client-side. Telegram apps will support caching starting in version 3.14. Defaults to 0
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? CacheTime {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with callbackQueryId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callbackQueryId">Unique identifier for the query to be answered</param>
|
||||||
|
public AnswerCallbackQueryRequest(string callbackQueryId)
|
||||||
|
: base("answerCallbackQuery") {
|
||||||
|
CallbackQueryId = callbackQueryId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to delete the list of the bot’s commands for the given
|
||||||
|
/// <see cref="Scope">scope</see> and <see cref="LanguageCode">user language</see>. After deletion,
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#determining-list-of-commands">higher level commands</a>
|
||||||
|
/// will be shown to affected users. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class DeleteMyCommandsRequest : RequestBase<bool> {
|
||||||
|
/// <summary>
|
||||||
|
/// An object, describing scope of users for which the commands are relevant.
|
||||||
|
/// Defaults to <see cref="BotCommandScopeDefault"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public BotCommandScope? Scope {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A two-letter ISO 639-1 language code. If empty, commands will be applied to all users
|
||||||
|
/// from the given <see cref="Scope">Scope</see>, for whose language there are no dedicated
|
||||||
|
/// commands
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? LanguageCode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public DeleteMyCommandsRequest()
|
||||||
|
: base("deleteMyCommands") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get the current list of the bot’s commands for the given <see cref="Scope">scope</see>
|
||||||
|
/// and <see cref="LanguageCode">user language</see>. Returns Array of <see cref="BotCommand"/> on success.
|
||||||
|
/// If commands aren't set, an empty list is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetMyCommandsRequest : RequestBase<BotCommand[]> {
|
||||||
|
/// <summary>
|
||||||
|
/// An object, describing scope of users. Defaults to <see cref="BotCommandScopeDefault"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public BotCommandScope? Scope {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A two-letter ISO 639-1 language code or an empty string
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? LanguageCode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public GetMyCommandsRequest()
|
||||||
|
: base("getMyCommands") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to change the list of the bot’s commands. See
|
||||||
|
/// <a href="https://core.telegram.org/bots#commands"/> for more details about bot commands.
|
||||||
|
/// Returns <c>true</c> on success
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetMyCommandsRequest : RequestBase<bool> {
|
||||||
|
/// <summary>
|
||||||
|
/// A list of bot commands to be set as the list of the bot’s commands.
|
||||||
|
/// At most 100 commands can be specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public IEnumerable<BotCommand> Commands {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An object, describing scope of users for which the commands are relevant.
|
||||||
|
/// Defaults to <see cref="BotCommandScopeDefault"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public BotCommandScope? Scope {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A two-letter ISO 639-1 language code. If empty, commands will be applied to all users
|
||||||
|
/// from the given <see cref="Scope"/>, for whose language there are no dedicated commands
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? LanguageCode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with commands
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="commands">A list of bot commands to be set</param>
|
||||||
|
public SetMyCommandsRequest(IEnumerable<BotCommand> commands)
|
||||||
|
: base("setMyCommands") {
|
||||||
|
Commands = commands;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get basic info about a file and prepare it for downloading. For the moment,
|
||||||
|
/// bots can download files of up to 20MB in size. On success, a <see cref="File"/> object is
|
||||||
|
/// returned. The file can then be downloaded via the link
|
||||||
|
/// <c>https://api.telegram.org/file/bot<token>/<file_path></c>, where
|
||||||
|
/// <c><file_path></c> is taken from the response. It is guaranteed that the link will be valid
|
||||||
|
/// for at least 1 hour. When the link expires, a new one can be requested by calling
|
||||||
|
/// <see cref="GetFileRequest"/> again.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// You can use <see cref="ITelegramBotClient.DownloadFileAsync"/> or
|
||||||
|
/// <see cref="TelegramBotClientExtensions.GetInfoAndDownloadFileAsync"/> methods to download the file
|
||||||
|
/// </remarks>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetFileRequest : RequestBase<File> {
|
||||||
|
/// <summary>
|
||||||
|
/// File identifier to get info about
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string FileId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with <see cref="FileId"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileId">File identifier to get info about</param>
|
||||||
|
public GetFileRequest(string fileId)
|
||||||
|
: base("getFile") {
|
||||||
|
FileId = fileId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get a list of profile pictures for a user. Returns a
|
||||||
|
/// <see cref="UserProfilePhotos"/> object.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetUserProfilePhotosRequest : RequestBase<UserProfilePhotos>, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sequential number of the first photo to be returned. By default, all photos are returned
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Offset {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limits the number of photos to be retrieved. Values between 1-100 are accepted. Defaults to 100
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Limit {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public GetUserProfilePhotosRequest(long userId)
|
||||||
|
: base("getUserProfilePhotos") {
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get the current value of the bot’s menu button in a private chat, or the default menu button.
|
||||||
|
/// Returns <see cref="MenuButton"/> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetChatMenuButtonRequest : RequestBase<MenuButton> {
|
||||||
|
/// <summary>
|
||||||
|
/// Optional. Unique identifier for the target private chat. If not specified, default bot’s menu button
|
||||||
|
/// will be changed
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public long? ChatId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public GetChatMenuButtonRequest()
|
||||||
|
: base("getChatMenuButton") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
TelegramBot/Requests/Available methods/GetMeRequest.cs
Normal file
22
TelegramBot/Requests/Available methods/GetMeRequest.cs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A simple method for testing your bot’s auth token. Requires no parameters. Returns basic information
|
||||||
|
/// about the bot in form of a <see cref="User"/> object.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetMeRequest : ParameterlessRequest<User> {
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public GetMeRequest()
|
||||||
|
: base("getMe") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get the current default administrator rights of the bot.
|
||||||
|
/// Returns <see cref="ChatAdministratorRights"/> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetMyDefaultAdministratorRightsRequest : RequestBase<ChatAdministratorRights> {
|
||||||
|
/// <summary>
|
||||||
|
/// Pass <c>true</c> to get default administrator rights of the bot in channels. Otherwise, default administrator
|
||||||
|
/// rights of the bot for groups and supergroups will be returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ForChannels {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public GetMyDefaultAdministratorRightsRequest()
|
||||||
|
: base("getMyDefaultAdministratorRights") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to close the bot instance before moving it from one local server to another.
|
||||||
|
/// You need to delete the webhook before calling this method to ensure that the bot isn't launched
|
||||||
|
/// again after server restart. The method will return error 429 in the first 10 minutes after the
|
||||||
|
/// bot is launched. Returns True on success. Requires no parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#close"/>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class CloseRequest : ParameterlessRequest<bool> {
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public CloseRequest() : base("close") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to log out from the cloud Bot API server before launching the bot locally.
|
||||||
|
/// You <b>must</b> log out the bot before running it locally, otherwise there is no guarantee
|
||||||
|
/// that the bot will receive updates. After a successful call, you can immediately log in on
|
||||||
|
/// a local server, but will not be able to log in back to the cloud Bot API server for 10
|
||||||
|
/// minutes. Returns <c>true</c> on success. Requires no parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#logout"/>
|
||||||
|
public class LogOutRequest : ParameterlessRequest<bool> {
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request
|
||||||
|
/// </summary>
|
||||||
|
public LogOutRequest() : base("logOut") {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to ban a user in a group, a supergroup or a channel. In the case of supergroups
|
||||||
|
/// and channels, the user will not be able to return to the chat on their own using invite links,
|
||||||
|
/// etc., unless <see cref="UnbanChatMemberRequest">unbanned</see> first. The bot must be an
|
||||||
|
/// administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class BanChatMemberRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Date when the user will be unbanned. If user is banned for more than 366 days or less
|
||||||
|
/// than 30 seconds from the current time they are considered to be banned forever.
|
||||||
|
/// Applied for supergroups and channels only.
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? UntilDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True to delete all messages from the chat for the user that is being removed. If
|
||||||
|
/// <c>false</c>, the user will be able to see messages in the group that were sent before
|
||||||
|
/// the user was removed. Always True for supergroups and channels.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? RevokeMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public BanChatMemberRequest(ChatId chatId, long userId)
|
||||||
|
: base("banChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this request to ban a channel chat in a supergroup or a channel. The owner of the chat will not be able
|
||||||
|
/// to send messages and join live streams on behalf of the chat, unless it is unbanned first. The bot must be
|
||||||
|
/// an administrator in the supergroup or channel for this to work and must have the appropriate administrator
|
||||||
|
/// rights. Returns <c>true</c> on success
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class BanChatSenderChatRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier of the target sender chat
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long SenderChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Date when the sender chat will be unbanned, unix time. If the chat is banned for more than 366 days or
|
||||||
|
/// less than 30 seconds from the current time they are considered to be banned forever.
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? UntilDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and senderChatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="senderChatId">
|
||||||
|
/// Unique identifier of the target sender chat
|
||||||
|
/// </param>
|
||||||
|
public BanChatSenderChatRequest(ChatId chatId, long senderChatId)
|
||||||
|
: base("banChatSenderChat") {
|
||||||
|
ChatId = chatId;
|
||||||
|
SenderChatId = senderChatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this request to approve a chat join request. The bot must be an administrator in the chat for this to
|
||||||
|
/// work and must have the <see cref="ChatPermissions.CanInviteUsers"/> administrator right.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class ApproveChatJoinRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier of the target user
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public ApproveChatJoinRequest(ChatId chatId, long userId)
|
||||||
|
: base("approveChatJoinRequest") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to create an additional invite link for a chat. The bot must be an
|
||||||
|
/// administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
|
/// The link can be revoked using the method <see cref="RevokeChatInviteLinkRequest"/>.
|
||||||
|
/// Returns the new invite link as <see cref="Types.ChatInviteLink"/> object.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class CreateChatInviteLinkRequest : RequestBase<ChatInviteLink>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invite link name; 0-32 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Name {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Point in time when the link will expire
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? ExpireDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of users that can be members of the chat simultaneously after joining the
|
||||||
|
/// chat via this invite link; 1-99999
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? MemberLimit {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to <c>true</c>, if users joining the chat via the link need to be approved by chat administrators.
|
||||||
|
/// If <c>true</c>, <see cref="MemberLimit"/> can't be specified
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CreatesJoinRequest {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public CreateChatInviteLinkRequest(ChatId chatId)
|
||||||
|
: base("createChatInviteLink") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this request to decline a chat join request. The bot must be an administrator in the chat for this to
|
||||||
|
/// work and must have the <see cref="ChatPermissions.CanInviteUsers"/> administrator right.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class DeclineChatJoinRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier of the target user
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public DeclineChatJoinRequest(ChatId chatId, long userId)
|
||||||
|
: base("declineChatJoinRequest") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to edit a non-primary invite link created by the bot. The bot must be an administrator
|
||||||
|
/// in the chat for this to work and must have the appropriate admin rights. Returns the edited invite
|
||||||
|
/// link as a <see cref="Types.ChatInviteLink"/> object.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class EditChatInviteLinkRequest : RequestBase<ChatInviteLink>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The invite link to edit
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string InviteLink {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invite link name; 0-32 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Name {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Point in time when the link will expire
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? ExpireDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of users that can be members of the chat simultaneously after joining the
|
||||||
|
/// chat via this invite link; 1-99999
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? MemberLimit {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to <c>true</c>, if users joining the chat via the link need to be approved by chat administrators.
|
||||||
|
/// If <c>true</c>, <see cref="MemberLimit"/> can't be specified
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CreatesJoinRequest {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and inviteLink
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="inviteLink">The invite link to edit</param>
|
||||||
|
public EditChatInviteLinkRequest(ChatId chatId, string inviteLink)
|
||||||
|
: base("editChatInviteLink") {
|
||||||
|
ChatId = chatId;
|
||||||
|
InviteLink = inviteLink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to generate a new primary invite link for a chat; any previously generated primary
|
||||||
|
/// link is revoked. The bot must be an administrator in the chat for this to work and must have the
|
||||||
|
/// appropriate admin rights. Returns the new invite link as <c>string</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class ExportChatInviteLinkRequest : RequestBase<string>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public ExportChatInviteLinkRequest(ChatId chatId)
|
||||||
|
: base("exportChatInviteLink") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to revoke an invite link created by the bot. If the primary link is revoked, a new
|
||||||
|
/// link is automatically generated. The bot must be an administrator in the chat for this to work and
|
||||||
|
/// must have the appropriate admin rights. Returns the revoked invite link as
|
||||||
|
/// <see cref="ChatInviteLink"/> object.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class RevokeChatInviteLinkRequest : RequestBase<ChatInviteLink>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The invite link to revoke
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string InviteLink {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and inviteLink
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="inviteLink">The invite link to revoke</param>
|
||||||
|
public RevokeChatInviteLinkRequest(ChatId chatId, string inviteLink)
|
||||||
|
: base("revokeChatInviteLink") {
|
||||||
|
ChatId = chatId;
|
||||||
|
InviteLink = inviteLink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to delete a chat photo. Photos can't be changed for private chats. The bot
|
||||||
|
/// must be an administrator in the chat for this to work and must have the appropriate
|
||||||
|
/// admin rights. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class DeleteChatPhotoRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public DeleteChatPhotoRequest(ChatId chatId)
|
||||||
|
: base("deleteChatPhoto") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to delete a group sticker set from a supergroup. The bot must be an administrator
|
||||||
|
/// in the chat for this to work and must have the appropriate admin rights. Use the field
|
||||||
|
/// <see cref="Types.Chat.CanSetStickerSet"/> optionally returned in <see cref="GetChatRequest"/>
|
||||||
|
/// requests to check if the bot can use this method. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class DeleteChatStickerSetRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public DeleteChatStickerSetRequest(ChatId chatId)
|
||||||
|
: base("deleteChatStickerSet") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get a list of administrators in a chat. On success, returns an Array of
|
||||||
|
/// <see cref="ChatMember"/> objects that contains information about all chat administrators
|
||||||
|
/// except other bots. If the chat is a group or a supergroup and no administrators were appointed,
|
||||||
|
/// only the creator will be returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetChatAdministratorsRequest : RequestBase<ChatMember[]>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public GetChatAdministratorsRequest(ChatId chatId)
|
||||||
|
: base("getChatAdministrators") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get the number of members in a chat. Returns <c>int</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetChatMemberCountRequest : RequestBase<int>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public GetChatMemberCountRequest(ChatId chatId)
|
||||||
|
: base("getChatMemberCount") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get information about a member of a chat. Returns a <see cref="ChatMember"/>
|
||||||
|
/// object on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetChatMemberRequest : RequestBase<ChatMember>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public GetChatMemberRequest(ChatId chatId, long userId)
|
||||||
|
: base("getChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get the number of members in a chat. Returns <c>int</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
[Obsolete("Use GetChatMemberCountRequest instead")]
|
||||||
|
public class GetChatMembersCountRequest : RequestBase<int>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public GetChatMembersCountRequest(ChatId chatId)
|
||||||
|
: base("getChatMembersCount") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Converters;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to get up to date information about the chat (current name of the user for
|
||||||
|
/// one-on-one conversations, current username of a user, group or channel, etc.).
|
||||||
|
/// Returns a <see cref="Chat"/> object on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class GetChatRequest : RequestBase<Chat>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
[JsonConverter(typeof(ChatIdConverter))]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public GetChatRequest(ChatId chatId)
|
||||||
|
: base("getChat") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to ban a user in a group, a supergroup or a channel. In the case of supergroups and
|
||||||
|
/// channels, the user will not be able to return to the chat on their own using invite links, etc.,
|
||||||
|
/// unless <see cref="UnbanChatMemberRequest">unbanned</see> first. The bot must be an administrator
|
||||||
|
/// in the chat for this to work and must have the appropriate admin rights. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("Use BanChatMemberRequest instead")]
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class KickChatMemberRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Date when the user will be unbanned. If user is banned for more than 366 days or less than
|
||||||
|
/// 30 seconds from the current time they are considered to be banned forever. Applied for
|
||||||
|
/// supergroups and channels only.
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? UntilDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True to delete all messages from the chat for the user that is being removed. If
|
||||||
|
/// <c>false</c>, the user will be able to see messages in the group that were sent before
|
||||||
|
/// the user was removed. Always True for supergroups and channels.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? RevokeMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public KickChatMemberRequest(ChatId chatId, long userId)
|
||||||
|
: base("kickChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method for your bot to leave a group, supergroup or channel. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class LeaveChatRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target supergroup or channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public LeaveChatRequest(ChatId chatId)
|
||||||
|
: base("leaveChat") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to add a message to the list of pinned messages in a chat. If the chat is not a
|
||||||
|
/// private chat, the bot must be an administrator in the chat for this to work and must have the
|
||||||
|
/// '<see cref="ChatPermissions.CanPinMessages"/>' admin right in a supergroup or
|
||||||
|
/// '<see cref="ChatMemberAdministrator.CanEditMessages"/>' admin right in a channel.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class PinChatMessageRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of a message to pin
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int MessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and messageId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="messageId">Identifier of a message to pin</param>
|
||||||
|
public PinChatMessageRequest(ChatId chatId, int messageId)
|
||||||
|
: base("pinChatMessage") {
|
||||||
|
ChatId = chatId;
|
||||||
|
MessageId = messageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,145 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to promote or demote a user in a supergroup or a channel. The bot must be
|
||||||
|
/// an administrator in the chat for this to work and must have the appropriate admin rights.
|
||||||
|
/// Pass <c>false</c> for all boolean parameters to demote a user. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class PromoteChatMemberRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator's presence in the chat is hidden
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? IsAnonymous {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can access the chat event log, chat statistics, message
|
||||||
|
/// statistics in channels, see channel members, see anonymous administrators in supergroups
|
||||||
|
/// and ignore slow mode. Implied by any other administrator privilege
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanManageChat {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can create channel posts, channels only
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanPostMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can edit messages of other users and can pin messages,
|
||||||
|
/// channels only
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanEditMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can delete messages of other users
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanDeleteMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can manage voice chats
|
||||||
|
/// </summary>
|
||||||
|
[Obsolete("This property will be removed in the next major version, use CanManageVideoChat instead")]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanManageVoiceChat {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can manage video chats
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanManageVideoChat {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can restrict, ban or unban chat members
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanRestrictMembers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can add new administrators with a subset of their own
|
||||||
|
/// privileges or demote administrators that he has promoted, directly or indirectly
|
||||||
|
/// (promoted by administrators that were appointed by him)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanPromoteMembers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can change chat title, photo and other settings
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanChangeInfo {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can invite new users to the chat
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanInviteUsers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the administrator can pin messages, supergroups only
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? CanPinMessages {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public PromoteChatMemberRequest(ChatId chatId, long userId)
|
||||||
|
: base("promoteChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to restrict a user in a supergroup. The bot must be an administrator in the
|
||||||
|
/// supergroup for this to work and must have the appropriate admin rights. Pass <c>true</c>
|
||||||
|
/// for all permissions to lift restrictions from a user. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class RestrictChatMemberRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New user permissions
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatPermissions Permissions {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Date when restrictions will be lifted for the user, unix time. If user is restricted for
|
||||||
|
/// more than 366 days or less than 30 seconds from the current time, they are considered to
|
||||||
|
/// be restricted forever.
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? UntilDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, userId and new user permissions
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
/// <param name="permissions">New user permissions</param>
|
||||||
|
public RestrictChatMemberRequest(ChatId chatId, long userId, ChatPermissions permissions)
|
||||||
|
: base("restrictChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
Permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to set a custom title for an administrator in a supergroup promoted by the bot.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatAdministratorCustomTitleRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New custom title for the administrator; 0-16 characters, emoji are not allowed
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string CustomTitle {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, userId and customTitle
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
/// <param name="customTitle">
|
||||||
|
/// New custom title for the administrator; 0-16 characters, emoji are not allowed
|
||||||
|
/// </param>
|
||||||
|
public SetChatAdministratorCustomTitleRequest(ChatId chatId, long userId, string customTitle)
|
||||||
|
: base("setChatAdministratorCustomTitle") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
CustomTitle = customTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to change the description of a group, a supergroup or a channel.
|
||||||
|
/// The bot must be an administrator in the chat for this to work and must have the
|
||||||
|
/// appropriate admin rights. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatDescriptionRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New chat Description, 0-255 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Description {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public SetChatDescriptionRequest(ChatId chatId)
|
||||||
|
: base("setChatDescription") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to set default chat permissions for all members. The bot must be an administrator
|
||||||
|
/// in the group or a supergroup for this to work and must have the can_restrict_members admin rights.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatPermissionsRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New default chat permissions
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatPermissions Permissions {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and new default permissions
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="permissions">New default chat permissions</param>
|
||||||
|
public SetChatPermissionsRequest(ChatId chatId, ChatPermissions permissions)
|
||||||
|
: base("setChatPermissions") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Permissions = permissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to set a new profile photo for the chat. Photos can't be changed for private
|
||||||
|
/// chats. The bot must be an administrator in the chat for this to work and must have the appropriate
|
||||||
|
/// admin rights. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatPhotoRequest : FileRequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New chat photo, uploaded using multipart/form-data
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public InputFileStream Photo {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and photo
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="photo">New chat photo, uploaded using multipart/form-data</param>
|
||||||
|
public SetChatPhotoRequest(ChatId chatId, InputFileStream photo)
|
||||||
|
: base("setChatPhoto") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Photo = photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent? ToHttpContent() =>
|
||||||
|
Photo.FileType switch {
|
||||||
|
FileType.Stream => ToMultipartFormDataContent("photo", Photo),
|
||||||
|
_ => base.ToHttpContent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to set a new group sticker set for a supergroup. The bot must be an administrator in
|
||||||
|
/// the chat for this to work and must have the appropriate admin rights. Use the field
|
||||||
|
/// <see cref="Chat.CanSetStickerSet"/> optionally returned in <see cref="GetChatRequest"/> requests to
|
||||||
|
/// check if the bot can use this method. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatStickerSetRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the sticker set to be set as the group sticker set
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string StickerSetName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and new stickerSetName
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="stickerSetName">Name of the sticker set to be set as the group sticker set</param>
|
||||||
|
public SetChatStickerSetRequest(ChatId chatId, string stickerSetName)
|
||||||
|
: base("setChatStickerSet") {
|
||||||
|
ChatId = chatId;
|
||||||
|
StickerSetName = stickerSetName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to change the title of a chat. Titles can't be changed for private chats.
|
||||||
|
/// The bot must be an administrator in the chat for this to work and must have the appropriate
|
||||||
|
/// admin rights. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SetChatTitleRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New chat title, 1-255 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Title {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and title
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="title">New chat title, 1-255 characters</param>
|
||||||
|
public SetChatTitleRequest(ChatId chatId, string title)
|
||||||
|
: base("setChatTitle") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Title = title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to unban a previously banned user in a supergroup or channel. The user will
|
||||||
|
/// <b>not</b> return to the group or channel automatically, but will be able to join via link,
|
||||||
|
/// etc. The bot must be an administrator for this to work. By default, this method guarantees
|
||||||
|
/// that after the call the user is not a member of the chat, but will be able to join it.
|
||||||
|
/// So if the user is a member of the chat they will also be <b>removed</b> from the chat.
|
||||||
|
/// If you don't want this, use the parameter <see cref="OnlyIfBanned"/>. Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class UnbanChatMemberRequest : RequestBase<bool>, IChatTargetable, IUserTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long UserId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Do nothing if the user is not banned
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? OnlyIfBanned {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and userId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="userId">Unique identifier of the target user</param>
|
||||||
|
public UnbanChatMemberRequest(ChatId chatId, long userId)
|
||||||
|
: base("unbanChatMember") {
|
||||||
|
ChatId = chatId;
|
||||||
|
UserId = userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this request to unban a previously banned channel chat in a supergroup or channel. The bot must be an
|
||||||
|
/// administrator for this to work and must have the appropriate administrator rights. Returns <c>true</c>
|
||||||
|
/// on success
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class UnbanChatSenderChatRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier of the target sender chat
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public long SenderChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and senderChatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="senderChatId">
|
||||||
|
/// Unique identifier of the target sender chat
|
||||||
|
/// </param>
|
||||||
|
public UnbanChatSenderChatRequest(ChatId chatId, long senderChatId)
|
||||||
|
: base("unbanChatSenderChat") {
|
||||||
|
ChatId = chatId;
|
||||||
|
SenderChatId = senderChatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to clear the list of pinned messages in a chat. If the chat is not a private chat,
|
||||||
|
/// the bot must be an administrator in the chat for this to work and must have the
|
||||||
|
/// '<see cref="ChatMemberAdministrator.CanPinMessages"/>' admin right in a supergroup or
|
||||||
|
/// '<see cref="ChatMemberAdministrator.CanEditMessages"/>' admin right in a channel.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class UnpinAllChatMessagesRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public UnpinAllChatMessagesRequest(ChatId chatId)
|
||||||
|
: base("unpinAllChatMessages") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,45 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to remove a message from the list of pinned messages in a chat. If the chat is not
|
||||||
|
/// a private chat, the bot must be an administrator in the chat for this to work and must have the
|
||||||
|
/// '<see cref="ChatMemberAdministrator.CanPinMessages"/>' admin right in a supergroup or
|
||||||
|
/// '<see cref="ChatMemberAdministrator.CanEditMessages"/>' admin right in a channel.
|
||||||
|
/// Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class UnpinChatMessageRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of a message to unpin. If not specified, the most recent pinned message
|
||||||
|
/// (by sending date) will be unpinned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? MessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
public UnpinChatMessageRequest(ChatId chatId)
|
||||||
|
: base("unpinChatMessage") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to copy messages of any kind. Service messages and invoice messages can't be copied.
|
||||||
|
/// The method is analogous to the method <see cref="ForwardMessageRequest"/>, but the copied message
|
||||||
|
/// doesn't have a link to the original message. Returns the <see cref="Types.MessageId"/> of the
|
||||||
|
/// sent <see cref="Message"/> on success.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class CopyMessageRequest : RequestBase<MessageId>, IChatTargetable {
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the chat where the original message was sent
|
||||||
|
/// (or channel username in the format <c>@channelusername</c>)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId FromChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message identifier in the chat specified in <see cref="FromChatId"/>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int MessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// New caption for media, 0-1024 characters after entities parsing.
|
||||||
|
/// If not specified, the original caption is kept
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Caption {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.CaptionEntities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? CaptionEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, fromChatId and messageId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="fromChatId">
|
||||||
|
/// Unique identifier for the chat where the original message was sent
|
||||||
|
/// (or channel username in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="messageId">
|
||||||
|
/// Message identifier in the chat specified in <see cref="FromChatId"/>
|
||||||
|
/// </param>
|
||||||
|
public CopyMessageRequest(ChatId chatId, ChatId fromChatId, int messageId)
|
||||||
|
: base("copyMessage") {
|
||||||
|
ChatId = chatId;
|
||||||
|
FromChatId = fromChatId;
|
||||||
|
MessageId = messageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to forward messages of any kind. Service messages can't be forwarded. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class ForwardMessageRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Unique identifier for the chat where the original message was sent
|
||||||
|
/// (or channel username in the format <c>@channelusername</c>)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId FromChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Message identifier in the chat specified in <see cref="FromChatId"/>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int MessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, fromChatId and messageId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="fromChatId">
|
||||||
|
/// Unique identifier for the chat where the original message was sent
|
||||||
|
/// (or channel username in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="messageId">
|
||||||
|
/// Message identifier in the chat specified in <see cref="FromChatId"/>
|
||||||
|
/// </param>
|
||||||
|
public ForwardMessageRequest(ChatId chatId, ChatId fromChatId, int messageId)
|
||||||
|
: base("forwardMessage") {
|
||||||
|
ChatId = chatId;
|
||||||
|
FromChatId = fromChatId;
|
||||||
|
MessageId = messageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to edit live location messages. A location can be edited until its
|
||||||
|
/// <see cref="Types.Location.LivePeriod"/> expires or editing is explicitly disabled by a call to
|
||||||
|
/// <see cref="StopInlineMessageLiveLocationRequest"/>. On success True is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class EditInlineMessageLiveLocationRequest : RequestBase<bool> {
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.InlineMessageId"/>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string InlineMessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Latitude of new location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Latitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Longitude of new location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Longitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The radius of uncertainty for the location, measured in meters; 0-1500
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public float? HorizontalAccuracy {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Direction in which the user is moving, in degrees. Must be between 1 and 360 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Heading {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum distance for proximity alerts about approaching another chat member, in meters. Must be
|
||||||
|
/// between 1 and 100000 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ProximityAlertRadius {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InlineKeyboardMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with inlineMessageId, latitude and longitude
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inlineMessageId">Identifier of the inline message</param>
|
||||||
|
/// <param name="latitude">Latitude of new location</param>
|
||||||
|
/// <param name="longitude">Longitude of new location</param>
|
||||||
|
public EditInlineMessageLiveLocationRequest(string inlineMessageId, double latitude, double longitude)
|
||||||
|
: base("editMessageLiveLocation") {
|
||||||
|
InlineMessageId = inlineMessageId;
|
||||||
|
Latitude = latitude;
|
||||||
|
Longitude = longitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to edit live location messages. A location can be edited until its
|
||||||
|
/// <see cref="Types.Location.LivePeriod"/> expires or editing is explicitly disabled by a call to
|
||||||
|
/// <see cref="StopMessageLiveLocationRequest"/>. On success the edited <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class EditMessageLiveLocationRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of the message to edit
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int MessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Latitude of new location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Latitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Longitude of new location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Longitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The radius of uncertainty for the location, measured in meters; 0-1500
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public float? HorizontalAccuracy {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Direction in which the user is moving, in degrees. Must be between 1 and 360 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Heading {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum distance for proximity alerts about approaching another chat member, in meters.
|
||||||
|
/// Must be between 1 and 100000 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ProximityAlertRadius {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.InlineReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InlineKeyboardMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, messageId, latitude and longitude
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="messageId">Identifier of the message to edit</param>
|
||||||
|
/// <param name="latitude">Latitude of new location</param>
|
||||||
|
/// <param name="longitude">Longitude of new location</param>
|
||||||
|
public EditMessageLiveLocationRequest(ChatId chatId, int messageId, double latitude, double longitude)
|
||||||
|
: base("editMessageLiveLocation") {
|
||||||
|
ChatId = chatId;
|
||||||
|
MessageId = messageId;
|
||||||
|
Latitude = latitude;
|
||||||
|
Longitude = longitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send point on the map. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendLocationRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Latitude of the location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Latitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Longitude of the location
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Longitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Period in seconds for which the location will be updated, should be between 60 and 86400
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? LivePeriod {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For live locations, a direction in which the user is moving, in degrees.
|
||||||
|
/// Must be between 1 and 360 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Heading {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// For live locations, a maximum distance for proximity alerts about approaching another
|
||||||
|
/// chat member, in meters. Must be between 1 and 100000 if specified.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ProximityAlertRadius {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends the message silently. Users will receive a notification with no sound.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the message is a reply, ID of the original message
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass <c>true</c>, if the message should be sent even if the specified replied-to message is not found
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, latitude and longitude
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="latitude">Latitude of the location</param>
|
||||||
|
/// <param name="longitude">Longitude of the location</param>
|
||||||
|
public SendLocationRequest(ChatId chatId, double latitude, double longitude)
|
||||||
|
: base("sendLocation") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Latitude = latitude;
|
||||||
|
Longitude = longitude;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,141 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send information about a venue. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendVenueRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Latitude of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Latitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Longitude of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public double Longitude {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Title {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Address of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Address {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Foursquare identifier of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? FoursquareId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Foursquare type of the venue, if known. (For example, “arts_entertainment/default”,
|
||||||
|
/// “arts_entertainment/aquarium” or “food/icecream”.)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? FoursquareType {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Google Places identifier of the venue
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? GooglePlaceId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Google Places type of the venue.
|
||||||
|
/// (See <a href="https://developers.google.com/places/web-service/supported_types">supported types</a>.)
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? GooglePlaceType {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, location, venue title and address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="latitude">Latitude of the venue</param>
|
||||||
|
/// <param name="longitude">Longitude of the venue</param>
|
||||||
|
/// <param name="title">Name of the venue</param>
|
||||||
|
/// <param name="address">Address of the venue</param>
|
||||||
|
public SendVenueRequest(
|
||||||
|
ChatId chatId,
|
||||||
|
double latitude,
|
||||||
|
double longitude,
|
||||||
|
string title,
|
||||||
|
string address) : base("sendVenue") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Latitude = latitude;
|
||||||
|
Longitude = longitude;
|
||||||
|
Title = title;
|
||||||
|
Address = address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to stop updating a live location message before <see cref="Types.Location.LivePeriod"/> expires. On success True is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class StopInlineMessageLiveLocationRequest : RequestBase<bool> {
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.InlineMessageId"/>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string InlineMessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.InlineReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InlineKeyboardMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with inlineMessageId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inlineMessageId">Identifier of the inline message</param>
|
||||||
|
public StopInlineMessageLiveLocationRequest(string inlineMessageId)
|
||||||
|
: base("stopMessageLiveLocation") {
|
||||||
|
InlineMessageId = inlineMessageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to stop updating a live location message before
|
||||||
|
/// <see cref="Types.Location.LivePeriod"/> expires. On success the sent
|
||||||
|
/// <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class StopMessageLiveLocationRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Identifier of the sent message
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public int MessageId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.InlineReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InlineKeyboardMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and messageId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="messageId">Identifier of the sent message</param>
|
||||||
|
public StopMessageLiveLocationRequest(ChatId chatId, int messageId)
|
||||||
|
: base("stopMessageLiveLocation") {
|
||||||
|
ChatId = chatId;
|
||||||
|
MessageId = messageId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Extensions;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send animation files (GIF or H.264/MPEG-4 AVC video without sound). On success,
|
||||||
|
/// the sent <see cref="Message"/> is returned. Bots can currently send animation files of up to
|
||||||
|
/// 50 MB in size, this limit may be changed in the future.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendAnimationRequest : FileRequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Animation to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send an animation
|
||||||
|
/// that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram
|
||||||
|
/// to get an animation from the Internet, or upload a new animation using multipart/form-data
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public InputOnlineFile Animation {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration of sent animation in seconds
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Duration {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Animation width
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Width {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Animation height
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Height {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.Thumb"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InputMedia? Thumb {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Animation caption (may also be used when resending animation by
|
||||||
|
/// <see cref="InputTelegramFile.FileId"/>), 0-1024 characters after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Caption {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.CaptionEntities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? CaptionEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and animation
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="animation">
|
||||||
|
/// Animation to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send an animation
|
||||||
|
/// that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to
|
||||||
|
/// get an animation from the Internet, or upload a new animation using multipart/form-data
|
||||||
|
/// </param>
|
||||||
|
public SendAnimationRequest(ChatId chatId, InputOnlineFile animation)
|
||||||
|
: base("sendAnimation") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Animation = animation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent? ToHttpContent() {
|
||||||
|
HttpContent? httpContent;
|
||||||
|
if(Animation.FileType == FileType.Stream || Thumb?.FileType == FileType.Stream) {
|
||||||
|
var multipartContent = GenerateMultipartFormDataContent("animation", "thumb");
|
||||||
|
if(Animation.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Animation.Content!,
|
||||||
|
name: "animation",
|
||||||
|
fileName: Animation.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Thumb?.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Thumb.Content!,
|
||||||
|
name: "thumb",
|
||||||
|
fileName: Thumb.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContent = multipartContent;
|
||||||
|
} else {
|
||||||
|
httpContent = base.ToHttpContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,166 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Extensions;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send audio files, if you want Telegram clients to display them in the music
|
||||||
|
/// player. Your audio must be in the .MP3 or .M4A format. On success, the sent <see cref="Message"/>
|
||||||
|
/// is returned. Bots can currently send audio files of up to 50 MB in size, this limit may be
|
||||||
|
/// changed in the future.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendAudioRequest : FileRequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Audio file to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send an audio
|
||||||
|
/// file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for
|
||||||
|
/// Telegram to get an audio file from the Internet, or upload a new one using multipart/form-data
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public InputOnlineFile Audio {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Audio caption, 0-1024 characters after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Caption {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.CaptionEntities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? CaptionEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration of the audio in seconds
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? Duration {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performer
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Performer {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Track name
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Title {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.Thumb"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InputMedia? Thumb {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and audio
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="audio">
|
||||||
|
/// Audio file to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send an audio
|
||||||
|
/// file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for
|
||||||
|
/// Telegram to get an audio file from the Internet, or upload a new one using multipart/form-data
|
||||||
|
/// </param>
|
||||||
|
public SendAudioRequest(ChatId chatId, InputOnlineFile audio)
|
||||||
|
: base("sendAudio") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Audio = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent? ToHttpContent() {
|
||||||
|
HttpContent? httpContent;
|
||||||
|
if(Audio.FileType == FileType.Stream || Thumb?.FileType == FileType.Stream) {
|
||||||
|
var multipartContent = GenerateMultipartFormDataContent("audio", "thumb");
|
||||||
|
if(Audio.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Audio.Content!,
|
||||||
|
name: "audio",
|
||||||
|
fileName: Audio.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Thumb?.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Thumb.Content!,
|
||||||
|
name: "thumb",
|
||||||
|
fileName: Thumb.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContent = multipartContent;
|
||||||
|
} else {
|
||||||
|
httpContent = base.ToHttpContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this request when you need to tell the user that something is happening on the bot’s side.
|
||||||
|
/// The status is set for 5 seconds or less (when a message arrives from your bot, Telegram clients
|
||||||
|
/// clear its typing status). Returns <c>true</c> on success.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Example: The <a href="https://t.me/imagebot">ImageBot</a> needs some time to process a request
|
||||||
|
/// and upload the image. Instead of sending a text message along the lines of “Retrieving image,
|
||||||
|
/// please wait…”, the bot may use <see cref="SendChatActionRequest"/> with
|
||||||
|
/// <see cref="Action"/> = <see cref="ChatAction.UploadPhoto"/>. The user will see a “sending photo”
|
||||||
|
/// status for the bot.
|
||||||
|
/// <para>
|
||||||
|
/// We only recommend using this method when a response from the bot will take a <b>noticeable</b>
|
||||||
|
/// amount of time to arrive.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendChatActionRequest : RequestBase<bool>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Type of action to broadcast. Choose one, depending on what the user is about to receive:
|
||||||
|
/// <see cref="ChatAction.Typing"/> for <see cref="SendMessageRequest">text messages</see>,
|
||||||
|
/// <see cref="ChatAction.UploadPhoto"/> for <see cref="SendPhotoRequest">photos</see>,
|
||||||
|
/// <see cref="ChatAction.RecordVideo"/> or <see cref="ChatAction.UploadVideo"/> for
|
||||||
|
/// <see cref="SendVideoRequest">videos</see>, <see cref="ChatAction.RecordVoice"/> or
|
||||||
|
/// <see cref="ChatAction.UploadVoice"/> for <see cref="SendVoiceRequest">voice notes</see>,
|
||||||
|
/// <see cref="ChatAction.UploadDocument"/> for <see cref="SendDocumentRequest">general files</see>,
|
||||||
|
/// <see cref="ChatAction.FindLocation"/> for <see cref="SendLocationRequest">location data</see>,
|
||||||
|
/// <see cref="ChatAction.RecordVideoNote"/> or <see cref="ChatAction.UploadVideoNote"/> for
|
||||||
|
/// <see cref="SendVideoNoteRequest">video notes</see>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatAction Action {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request chatId and action
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="action">
|
||||||
|
/// Type of action to broadcast. Choose one, depending on what the user is about to receive
|
||||||
|
/// </param>
|
||||||
|
public SendChatActionRequest(ChatId chatId, ChatAction action)
|
||||||
|
: base("sendChatAction") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Action = action;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send phone contacts. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendContactRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contact's phone number
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string PhoneNumber {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contact's first name
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string FirstName {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contact's last name
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? LastName {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional data about the contact in the form of a vCard, 0-2048 bytes
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Vcard {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, phoneNumber and firstName
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="phoneNumber">Contact's phone number</param>
|
||||||
|
/// <param name="firstName">Contact's first name</param>
|
||||||
|
public SendContactRequest(ChatId chatId, string phoneNumber, string firstName)
|
||||||
|
: base("sendContact") {
|
||||||
|
ChatId = chatId;
|
||||||
|
PhoneNumber = phoneNumber;
|
||||||
|
FirstName = firstName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
using EmojiEnum = Telegram.Bot.Types.Enums.Emoji;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send an animated emoji that will display a random value. On success,
|
||||||
|
/// the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendDiceRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Emoji on which the dice throw animation is based. Defaults to <see cref="EmojiEnum.Dice"/>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public Emoji? Emoji {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)</param>
|
||||||
|
public SendDiceRequest(ChatId chatId)
|
||||||
|
: base("sendDice") {
|
||||||
|
ChatId = chatId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Extensions;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send general files. On success, the sent <see cref="Message"/>
|
||||||
|
/// is returned. Bots can currently send files of any type of up to 50 MB in size,
|
||||||
|
/// this limit may be changed in the future.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendDocumentRequest : FileRequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// File to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send a file that
|
||||||
|
/// exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram
|
||||||
|
/// to get a file from the Internet, or upload a new one using multipart/form-data
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public InputOnlineFile Document {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.Thumb"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public InputMedia? Thumb {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Document caption (may also be used when resending documents by file_id), 0-1024 characters
|
||||||
|
/// after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Caption {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.CaptionEntities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? CaptionEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disables automatic server-side content type detection for files uploaded using multipart/form-data
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableContentTypeDetection {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and document
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="document">
|
||||||
|
/// File to send. Pass a <see cref="InputTelegramFile.FileId"/> as string to send a file that
|
||||||
|
/// exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram
|
||||||
|
/// to get a file from the Internet, or upload a new one using multipart/form-data
|
||||||
|
/// </param>
|
||||||
|
public SendDocumentRequest(ChatId chatId, InputOnlineFile document)
|
||||||
|
: base("sendDocument") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Document = document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent? ToHttpContent() {
|
||||||
|
HttpContent? httpContent;
|
||||||
|
if(Document.FileType == FileType.Stream || Thumb?.FileType == FileType.Stream) {
|
||||||
|
var multipartContent = GenerateMultipartFormDataContent("document", "thumb");
|
||||||
|
if(Document.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Document.Content!,
|
||||||
|
name: "document",
|
||||||
|
fileName: Document.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Thumb?.FileType == FileType.Stream) {
|
||||||
|
multipartContent.AddStreamContent(
|
||||||
|
content: Thumb.Content!,
|
||||||
|
name: "thumb",
|
||||||
|
fileName: Thumb.FileName
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpContent = multipartContent;
|
||||||
|
} else {
|
||||||
|
httpContent = base.ToHttpContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return httpContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Extensions;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send a group of photos, videos, documents or audios as an album. Documents and
|
||||||
|
/// audio files can be only grouped in an album with messages of the same type. On success, an array
|
||||||
|
/// of <see cref="Message"/>s that were sent is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendMediaGroupRequest : FileRequestBase<Message[]>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An array describing messages to be sent, must include 2-10 items
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public IEnumerable<IAlbumInputMedia> Media {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a request with chatId and media
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">
|
||||||
|
/// Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="media">An array describing messages to be sent, must include 2-10 items</param>
|
||||||
|
public SendMediaGroupRequest(ChatId chatId, IEnumerable<IAlbumInputMedia> media)
|
||||||
|
: base("sendMediaGroup") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Media = media;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent ToHttpContent() {
|
||||||
|
var httpContent = GenerateMultipartFormDataContent();
|
||||||
|
httpContent.AddContentIfInputFileStream(Media.Cast<IInputMedia>().ToArray());
|
||||||
|
return httpContent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send text messages. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendMessageRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text of the message to be sent, 1-4096 characters after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Text {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.Entities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? Entities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disables link previews for links in this message
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableWebPagePreview {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="text">Text of the message to be sent, 1-4096 characters after entities parsing</param>
|
||||||
|
public SendMessageRequest(ChatId chatId, string text)
|
||||||
|
: base("sendMessage") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,114 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.InputFiles;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send photos. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendPhotoRequest : FileRequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Photo to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send a photo that
|
||||||
|
/// exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to
|
||||||
|
/// get a photo from the Internet, or upload a new photo using multipart/form-data. The photo
|
||||||
|
/// must be at most 10 MB in size. The photo's width and height must not exceed 10000 in total.
|
||||||
|
/// Width and height ratio must be at most 20
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public InputOnlineFile Photo {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Photo caption (may also be used when resending photos by <see cref="InputTelegramFile.FileId"/>),
|
||||||
|
/// 0-1024 characters after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Caption {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ParseMode"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.CaptionEntities"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? CaptionEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId and photo
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="photo">
|
||||||
|
/// Photo to send. Pass a <see cref="InputTelegramFile.FileId"/> as String to send a photo that
|
||||||
|
/// exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to
|
||||||
|
/// get a photo from the Internet, or upload a new photo using multipart/form-data. The photo
|
||||||
|
/// must be at most 10 MB in size. The photo's width and height must not exceed 10000 in total.
|
||||||
|
/// Width and height ratio must be at most 20</param>
|
||||||
|
public SendPhotoRequest(ChatId chatId, InputOnlineFile photo)
|
||||||
|
: base("sendPhoto") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Photo = photo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override HttpContent? ToHttpContent() =>
|
||||||
|
Photo.FileType switch {
|
||||||
|
FileType.Stream => ToMultipartFormDataContent(fileParameterName: "photo", inputFile: Photo),
|
||||||
|
_ => base.ToHttpContent()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using Telegram.Bot.Requests.Abstractions;
|
||||||
|
using Telegram.Bot.Types;
|
||||||
|
using Telegram.Bot.Types.Enums;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
|
namespace Telegram.Bot.Requests {
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use this method to send a native poll. On success, the sent <see cref="Message"/> is returned.
|
||||||
|
/// </summary>
|
||||||
|
[JsonObject(MemberSerialization.OptIn, NamingStrategyType = typeof(SnakeCaseNamingStrategy))]
|
||||||
|
public class SendPollRequest : RequestBase<Message>, IChatTargetable {
|
||||||
|
/// <inheritdoc />
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public ChatId ChatId {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Poll question, 1-300 characters
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public string Question {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of answer options, 2-10 strings 1-100 characters each
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(Required = Required.Always)]
|
||||||
|
public IEnumerable<string> Options {
|
||||||
|
get;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True, if the poll needs to be anonymous, defaults to True
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? IsAnonymous {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Poll type, defaults to <see cref="PollType.Regular"/>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public PollType? Type {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowsMultipleAnswers {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 0-based identifier of the correct answer option, required for polls in quiz mode
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? CorrectOptionId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a
|
||||||
|
/// quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public string? Explanation {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mode for parsing entities in the explanation. See
|
||||||
|
/// <a href="https://core.telegram.org/bots/api#formatting-options">formatting options</a>
|
||||||
|
/// for more details.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public ParseMode? ExplanationParseMode {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of special entities that appear in the poll explanation, which can be specified instead
|
||||||
|
/// of <see cref="ParseMode"/>
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IEnumerable<MessageEntity>? ExplanationEntities {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Amount of time in seconds the poll will be active after creation, 5-600. Can't be used
|
||||||
|
/// together with <see cref="CloseDate"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? OpenPeriod {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Point in time when the poll will be automatically closed. Must be at least 5 and no more
|
||||||
|
/// than 600 seconds in the future. Can't be used together with <see cref="OpenPeriod"/>.
|
||||||
|
/// </summary>
|
||||||
|
[JsonConverter(typeof(UnixDateTimeConverter))]
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public DateTime? CloseDate {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass True, if the poll needs to be immediately closed. This can be useful for poll preview.
|
||||||
|
/// </summary>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? IsClosed {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.DisableNotification"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? DisableNotification {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ProtectContent"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? ProtectContent {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyToMessageId"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public int? ReplyToMessageId {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.AllowSendingWithoutReply"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public bool? AllowSendingWithoutReply {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="Abstractions.Documentation.ReplyMarkup"/>
|
||||||
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
|
public IReplyMarkup? ReplyMarkup {
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new request with chatId, question and <see cref="PollOption"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chatId">Unique identifier for the target chat or username of the target channel
|
||||||
|
/// (in the format <c>@channelusername</c>)
|
||||||
|
/// </param>
|
||||||
|
/// <param name="question">Poll question, 1-300 characters</param>
|
||||||
|
/// <param name="options">A list of answer options, 2-10 strings 1-100 characters each</param>
|
||||||
|
public SendPollRequest(ChatId chatId, string question, IEnumerable<string> options)
|
||||||
|
: base("sendPoll") {
|
||||||
|
ChatId = chatId;
|
||||||
|
Question = question;
|
||||||
|
Options = options;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user