Skip to content

Commit f6ba076

Browse files
committed
net5.0, system.text.json, ITelegramBot interface for mocks
1 parent 03e6ccf commit f6ba076

21 files changed

+137
-1597
lines changed

NetTelegramBotApi.Tests/NetTelegramBotApi.Tests.csproj

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,17 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net461;netcoreapp1.0</TargetFrameworks>
5-
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
6-
<RuntimeFrameworkVersion>1.0.3</RuntimeFrameworkVersion>
4+
<TargetFramework>net5.0</TargetFramework>
75
<RootNamespace>NetTelegramBotApi</RootNamespace>
86
</PropertyGroup>
97

108
<ItemGroup>
11-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
12-
<PackageReference Include="xunit" Version="2.2.0" />
13-
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
14-
</ItemGroup>
15-
16-
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
17-
<Reference Include="System" />
18-
<Reference Include="System.Net.Http" />
19-
<Reference Include="Microsoft.CSharp" />
9+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.10.0" />
10+
<PackageReference Include="xunit" Version="2.4.1" />
11+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
12+
<PrivateAssets>all</PrivateAssets>
13+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
14+
</PackageReference>
2015
</ItemGroup>
2116

2217
<ItemGroup>

NetTelegramBotApi.sln

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
Microsoft Visual Studio Solution File, Format Version 12.00
2-
# Visual Studio 15
3-
VisualStudioVersion = 15.0.26228.4
2+
# Visual Studio Version 16
3+
VisualStudioVersion = 16.0.31313.79
44
MinimumVisualStudioVersion = 10.0.40219.1
55
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{ABC2A4CB-9443-434E-B2EA-E739D288F330}"
66
ProjectSection(SolutionItems) = preProject
7+
appveyor.yml = appveyor.yml
8+
LICENSE = LICENSE
79
README.md = README.md
810
EndProjectSection
911
EndProject
1012
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTelegramBotApi", "NetTelegramBotApi\NetTelegramBotApi.csproj", "{0CA802AD-0F85-4314-8D70-2C5F182C9F42}"
1113
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramBotDemo", "TelegramBotDemo\TelegramBotDemo.csproj", "{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}"
13-
EndProject
1414
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TelegramBotDemo-vNext", "TelegramBotDemo-vNext\TelegramBotDemo-vNext.csproj", "{0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}"
1515
EndProject
16-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetTelegramBotApi.Tests", "NetTelegramBotApi.Tests\NetTelegramBotApi.Tests.csproj", "{82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}"
16+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetTelegramBotApi.Tests", "NetTelegramBotApi.Tests\NetTelegramBotApi.Tests.csproj", "{82AAECA1-D92F-4C7D-9CA8-B9EBACCCCCAF}"
1717
EndProject
1818
Global
1919
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -37,18 +37,6 @@ Global
3737
{0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x64.Build.0 = Release|Any CPU
3838
{0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x86.ActiveCfg = Release|Any CPU
3939
{0CA802AD-0F85-4314-8D70-2C5F182C9F42}.Release|x86.Build.0 = Release|Any CPU
40-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|Any CPU.Build.0 = Debug|Any CPU
42-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|x64.ActiveCfg = Debug|Any CPU
43-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|x64.Build.0 = Debug|Any CPU
44-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|x86.ActiveCfg = Debug|Any CPU
45-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Debug|x86.Build.0 = Debug|Any CPU
46-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|Any CPU.ActiveCfg = Release|Any CPU
47-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|Any CPU.Build.0 = Release|Any CPU
48-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|x64.ActiveCfg = Release|Any CPU
49-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|x64.Build.0 = Release|Any CPU
50-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|x86.ActiveCfg = Release|Any CPU
51-
{E0CDD1D2-E50E-4CD8-97F4-C1AE44DE7E43}.Release|x86.Build.0 = Release|Any CPU
5240
{0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
5341
{0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
5442
{0A5DF37F-F6E0-412E-8B84-AE7120B4D8C5}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -77,4 +65,7 @@ Global
7765
GlobalSection(SolutionProperties) = preSolution
7866
HideSolutionNode = FALSE
7967
EndGlobalSection
68+
GlobalSection(ExtensibilityGlobals) = postSolution
69+
SolutionGuid = {1AE94356-8779-4DAE-A0A5-7F6DE8FC7E48}
70+
EndGlobalSection
8071
EndGlobal

NetTelegramBotApi/ITelegramBot.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Threading.Tasks;
2+
using NetTelegramBotApi.Requests;
3+
using NetTelegramBotApi.Types;
4+
5+
namespace NetTelegramBotApi
6+
{
7+
public interface ITelegramBot
8+
{
9+
Task<T> MakeRequestAsync<T>(RequestBase<T> request);
10+
11+
Update DeserializeUpdate(string json);
12+
}
13+
}

NetTelegramBotApi/NetTelegramBotApi.csproj

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,32 @@
33
<PropertyGroup>
44
<Description>Telegram Bot API library</Description>
55
<AssemblyTitle>NetTelegramBotApi</AssemblyTitle>
6-
<Version>4.2.0</Version>
7-
<TargetFrameworks>net45;net46;netstandard1.3</TargetFrameworks>
8-
<NetStandardImplicitPackageVersion>1.6.0</NetStandardImplicitPackageVersion>
6+
<Version>5.0.0</Version>
7+
<TargetFramework>net5.0</TargetFramework>
98
<AssemblyName>NetTelegramBotApi</AssemblyName>
109
<PackageId>NetTelegramBotApi</PackageId>
1110
<PackageTags>telegram;bot;api</PackageTags>
12-
<PackageReleaseNotes>See https://github.com/justdmitry/NetTelegramBotApi/releases/tag/v4.2.0</PackageReleaseNotes>
13-
<PackageIconUrl>https://raw.githubusercontent.com/justdmitry/NetTelegramBotApi/master/package-icon.gif</PackageIconUrl>
11+
<PackageReleaseNotes>See https://github.com/justdmitry/NetTelegramBotApi/releases/tag/v5.0.0</PackageReleaseNotes>
12+
<PackageIcon>package-icon.png</PackageIcon>
1413
<PackageProjectUrl>https://github.com/justdmitry/NetTelegramBotApi</PackageProjectUrl>
1514
<RepositoryType>git</RepositoryType>
1615
<RepositoryUrl>https://github.com/justdmitry/NetTelegramBotApi.git</RepositoryUrl>
1716
<Authors>Dmitry Popov</Authors>
1817
<Company />
19-
<Copyright>Copyright © Dmitry Popov, 2015-2017</Copyright>
18+
<Copyright>Copyright © Dmitry Popov, 2015-2021</Copyright>
2019
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
20+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2121
</PropertyGroup>
2222

2323
<ItemGroup>
24-
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
24+
<PackageReference Include="System.Text.Json" Version="5.0.0" />
2525
</ItemGroup>
2626

27-
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
28-
<Reference Include="System" />
29-
<Reference Include="System.Net.Http" />
30-
<Reference Include="Microsoft.CSharp" />
31-
</ItemGroup>
32-
33-
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
34-
<Reference Include="System" />
35-
<Reference Include="System.Net.Http" />
36-
<Reference Include="Microsoft.CSharp" />
27+
<ItemGroup>
28+
<None Include="..\package-icon.png">
29+
<Pack>True</Pack>
30+
<PackagePath></PackagePath>
31+
</None>
3732
</ItemGroup>
3833

3934
</Project>

NetTelegramBotApi/Requests/RequestBase.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Net.Http;
3-
using Newtonsoft.Json;
3+
using System.Text.Json;
44

55
namespace NetTelegramBotApi.Requests
66
{
@@ -12,12 +12,12 @@ public RequestBase(string methodName)
1212
}
1313

1414
public string MethodName { get; protected set; }
15-
15+
1616
public abstract HttpContent CreateHttpContent();
1717

1818
protected string JsonSerialize(object value)
1919
{
20-
return JsonConvert.SerializeObject(value, TelegramBot.JsonSettings);
20+
return JsonSerializer.Serialize(value, TelegramBot.JsonOptions);
2121
}
2222
}
2323
}

NetTelegramBotApi/TelegramBot.cs

Lines changed: 45 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,81 @@
11
using System;
2-
using System.Net;
32
using System.Net.Http;
43
using System.Threading.Tasks;
54
using NetTelegramBotApi.Requests;
65
using NetTelegramBotApi.Util;
76
using NetTelegramBotApi.Types;
8-
using Newtonsoft.Json;
7+
using System.Text.Json;
98

109
namespace NetTelegramBotApi
1110
{
12-
public class TelegramBot
11+
public class TelegramBot : ITelegramBot
1312
{
14-
public static readonly JsonSerializerSettings JsonSettings = new JsonSerializerSettings
13+
public static readonly JsonSerializerOptions JsonOptions = new JsonSerializerOptions
1514
{
16-
ContractResolver = new Util.JsonLowerCaseUnderscoreContractResolver(),
17-
NullValueHandling = NullValueHandling.Ignore,
15+
PropertyNamingPolicy = new JsonLowerCaseUnderscoreNamingPolicy(),
16+
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
1817
};
1918

20-
private string accessToken;
21-
22-
private Uri baseAddress;
19+
private readonly string accessToken;
20+
private readonly HttpClient httpClient;
2321

2422
static TelegramBot()
2523
{
26-
JsonSettings.Converters.Add(new UnixDateTimeConverter());
24+
JsonOptions.Converters.Add(new UnixDateTimeConverter());
2725
}
2826

29-
/// <summary>
30-
/// Proxy information for internet access
31-
/// </summary>
32-
public IWebProxy WebProxy { get; set; }
33-
34-
public TelegramBot(string accessToken)
27+
public TelegramBot(string accessToken, HttpClient httpClient)
3528
{
3629
if (string.IsNullOrWhiteSpace(accessToken))
3730
{
38-
throw new ArgumentNullException("accessToken");
31+
throw new ArgumentNullException(nameof(accessToken));
3932
}
4033

4134
this.accessToken = accessToken;
42-
this.baseAddress = new Uri("https://api.telegram.org/bot" + accessToken + "/");
35+
this.httpClient = httpClient ?? new HttpClient();
4336
}
4437

4538
/// <exception cref="BotRequestException">When non-Ok response returned from server.</exception>
4639
public async Task<T> MakeRequestAsync<T>(RequestBase<T> request)
4740
{
48-
using (var client = new HttpClient(MakeHttpMessageHandler()))
41+
var uri = new Uri("https://api.telegram.org/bot" + accessToken + "/" + request.MethodName);
42+
using var httpMessage = new HttpRequestMessage(HttpMethod.Get, uri);
43+
using var postContent = request.CreateHttpContent();
44+
if (postContent != null)
4945
{
50-
client.BaseAddress = baseAddress;
51-
using (var httpMessage = new HttpRequestMessage(HttpMethod.Get, request.MethodName))
52-
{
53-
var postContent = request.CreateHttpContent();
54-
if (postContent != null)
55-
{
56-
httpMessage.Method = HttpMethod.Post;
57-
httpMessage.Content = postContent;
58-
}
59-
60-
using (var response = await client.SendAsync(httpMessage).ConfigureAwait(false))
61-
{
62-
if ((int)response.StatusCode >= 500)
63-
{
64-
// Let's throw exception. It's server fault
65-
response.EnsureSuccessStatusCode();
66-
}
67-
68-
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
69-
var result = DeserializeMessage<BotResponse<T>>(responseText);
70-
if (!result.Ok || !response.IsSuccessStatusCode)
71-
{
72-
var exceptionMessage = $"Request failed (status code {(int)response.StatusCode}): {result.Description}";
73-
throw new BotRequestException(exceptionMessage)
74-
{
75-
StatusCode = response.StatusCode,
76-
ResponseBody = responseText,
77-
Description = result.Description,
78-
ErrorCode = result.ErrorCode,
79-
Parameters = result.Parameters,
80-
};
81-
}
46+
httpMessage.Method = HttpMethod.Post;
47+
httpMessage.Content = postContent;
48+
}
8249

83-
var retVal = result.Result;
84-
var forPostProcessing = retVal as IPostProcessingRequired;
85-
if (forPostProcessing != null)
86-
{
87-
forPostProcessing.PostProcess(accessToken);
88-
}
50+
using var response = await httpClient.SendAsync(httpMessage).ConfigureAwait(false);
51+
if ((int)response.StatusCode >= 500)
52+
{
53+
// Let's throw exception. It's server fault
54+
response.EnsureSuccessStatusCode();
55+
}
8956

90-
return retVal;
91-
}
92-
}
57+
var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
58+
var result = DeserializeMessage<BotResponse<T>>(responseText);
59+
if (!result.Ok || !response.IsSuccessStatusCode)
60+
{
61+
var exceptionMessage = $"Request failed (status code {(int)response.StatusCode}): {result.Description}";
62+
throw new BotRequestException(exceptionMessage)
63+
{
64+
StatusCode = response.StatusCode,
65+
ResponseBody = responseText,
66+
Description = result.Description,
67+
ErrorCode = result.ErrorCode,
68+
Parameters = result.Parameters,
69+
};
9370
}
94-
}
9571

96-
protected virtual HttpClientHandler MakeHttpMessageHandler()
97-
{
98-
return new HttpClientHandler
72+
var retVal = result.Result;
73+
if (retVal is IPostProcessingRequired forPostProcessing)
9974
{
100-
Proxy = WebProxy,
101-
UseProxy = (WebProxy != null)
102-
};
75+
forPostProcessing.PostProcess(accessToken);
76+
}
77+
78+
return retVal;
10379
}
10480

10581
/// <summary>
@@ -112,9 +88,9 @@ public Update DeserializeUpdate(string json)
11288
return DeserializeMessage<Update>(json);
11389
}
11490

115-
protected T DeserializeMessage<T>(string json)
91+
protected static T DeserializeMessage<T>(string json)
11692
{
117-
return JsonConvert.DeserializeObject<T>(json, JsonSettings);
93+
return JsonSerializer.Deserialize<T>(json, JsonOptions);
11894
}
11995
}
12096
}

NetTelegramBotApi/Types/ForceReply.cs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
using System;
2-
using Newtonsoft.Json;
2+
using System.Text.Json.Serialization;
33

44
namespace NetTelegramBotApi.Types
55
{
66
/// <summary>
7-
/// Upon receiving a message with this object, Telegram clients will display a reply interface to the user
8-
/// (act as if the user has selected the bot‘s message and tapped ’Reply').
9-
/// This can be extremely useful if you want to create user-friendly step-by-step interfaces
7+
/// Upon receiving a message with this object, Telegram clients will display a reply interface to the user
8+
/// (act as if the user has selected the bot‘s message and tapped ’Reply').
9+
/// This can be extremely useful if you want to create user-friendly step-by-step interfaces
1010
/// without having to sacrifice privacy mode.
1111
/// <see cref="https://core.telegram.org/bots/api#forcereply">See more info on Telegram site</see>
1212
/// </summary>
@@ -18,25 +18,25 @@ public class ForceReply : ReplyMarkupBase
1818
/// <remarks>
1919
/// In original Telegram API, member is called 'ForceReply', but in C# it's forbidden to have properties with same name as class
2020
/// </remarks>
21-
[JsonProperty("force_reply")]
21+
[JsonPropertyName("force_reply")]
2222
public bool Force { get; set; }
2323

2424
/// <summary>
25-
/// Optional. Use this parameter if you want to force reply from specific users only.
26-
/// Targets:
27-
/// 1) users that are @mentioned in the text of the Message object;
25+
/// Optional. Use this parameter if you want to force reply from specific users only.
26+
/// Targets:
27+
/// 1) users that are @mentioned in the text of the Message object;
2828
/// 2) if the bot's message is a reply (has reply_to_message_id), sender of the original message.
2929
/// </summary>
3030
/// <example>
31-
/// A poll bot for groups runs in privacy mode (only receives commands, replies to its messages and mentions).
32-
/// There could be two ways to create a new poll:
33-
/// 1) Explain the user how to send a command with parameters (e.g. /newpoll question answer1 answer2).
31+
/// A poll bot for groups runs in privacy mode (only receives commands, replies to its messages and mentions).
32+
/// There could be two ways to create a new poll:
33+
/// 1) Explain the user how to send a command with parameters (e.g. /newpoll question answer1 answer2).
3434
/// May be appealing for hardcore users but lacks modern day polish.
35-
/// 2) Guide the user through a step-by-step process. ‘Please send me your question’,
36-
/// ‘Cool, now let’s add the first answer option‘, ’Great.
35+
/// 2) Guide the user through a step-by-step process. ‘Please send me your question’,
36+
/// ‘Cool, now let’s add the first answer option‘, ’Great.
3737
/// Keep adding answer options, then send /done when you‘re ready’.
38-
/// The last option is definitely more attractive. And if you use ForceReply in your bot‘s questions,
39-
/// it will receive the user’s answers even if it only receives replies, commands and mentions — without any
38+
/// The last option is definitely more attractive. And if you use ForceReply in your bot‘s questions,
39+
/// it will receive the user’s answers even if it only receives replies, commands and mentions — without any
4040
/// extra work for the user.
4141
/// </example>
4242
public bool Selective { get; set; }

0 commit comments

Comments
 (0)