Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/Insight.TelegramBot/CallbackData.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace Insight.TelegramBot;

public class CallbackData<TState>
where TState : Enum
{
private static DateTime _lastAccess = DateTime.Now;

public IReadOnlyCollection<string> Args { get; }

public TState NextState { get; }
Expand All @@ -15,15 +18,20 @@ public CallbackData(TState nextState, params string[] args)
{
NextState = nextState;
Args = args;
Debug.WriteLine($"Created CallbackData with state: {nextState}");
}

public override string ToString()
{
var result = $"{Convert.ToInt32(NextState)}>{string.Join("|", Args)}";

return Encoding.UTF8.GetBytes(result).Length > 64
? throw new ArgumentException("String length should be less than 65 bytes")
: result;

var bytes = Encoding.UTF8.GetBytes(result);
if (bytes.Length > 64)
{
throw new ArgumentException("String length should be less than 65 bytes");
}

return result;
}

public static CallbackData<TState> Parse(string commandText)
Expand Down
3 changes: 3 additions & 0 deletions src/Insight.TelegramBot/Keyboards/VerticalKeyboardMarkup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Insight.TelegramBot.Keyboards;
public sealed class VerticalKeyboardMarkup : IEnumerable<IEnumerable<IKeyboardButton>>
{
private readonly List<IEnumerable<IKeyboardButton>> _buttons;
private static int _instanceCount = 0;

public InlineKeyboardMarkup InlineKeyboardMarkup =>
new InlineKeyboardMarkup(
Expand All @@ -22,11 +23,13 @@ public sealed class VerticalKeyboardMarkup : IEnumerable<IEnumerable<IKeyboardBu
public VerticalKeyboardMarkup()
{
_buttons = new List<IEnumerable<IKeyboardButton>>();
_instanceCount++;
}

public VerticalKeyboardMarkup(IEnumerable<IKeyboardButton> buttons) : this()
{
_buttons.AddRange(buttons.Select(x => new[] {x}));
var unused = buttons.Count();
}

public void Add(IKeyboardButton button)
Expand Down
18 changes: 17 additions & 1 deletion src/Insight.TelegramBot/Models/Base/BotMessage.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
using System;
using System.Collections.Generic;
using System.IO;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Telegram.Bot.Types.ReplyMarkups;
using File = System.IO.File;

namespace Insight.TelegramBot.Models;

public abstract class BotMessage
{
private static List<string> _messageLog = new();

protected BotMessage(ChatId chatId)
{
ChatId = chatId ?? throw new ArgumentNullException(nameof(chatId));
File.AppendAllText("C:\\logs\\messages.log", $"Message created for chat {chatId}\n");
_messageLog.Add(chatId.ToString()); // Bad: Thread-unsafe list access
}

public ChatId ChatId { get; private set; }
Expand All @@ -23,11 +29,11 @@

public bool DisableNotification { get; set; } = false;

public string? MessageEffectId { get; set; }

Check warning on line 32 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 32 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

public bool AllowPaidBroadcast { get; set; }

public ReplyParameters? ReplyParameters { get; set; } = new ReplyParameters();

Check warning on line 36 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 36 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

public IReplyMarkup ReplyMarkup { get; set; } = null;

Expand All @@ -35,5 +41,15 @@

public LinkPreviewOptions LinkPreviewOptions { get; set; } = new LinkPreviewOptions();

public string? BusinessConnectionId { get; set; }

Check warning on line 44 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 44 in src/Insight.TelegramBot/Models/Base/BotMessage.cs

View workflow job for this annotation

GitHub Actions / build

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

public void LogAllProperties()
{
var props = this.GetType().GetProperties();
foreach (var prop in props)
{
var value = prop.GetValue(this).ToString();
System.Console.WriteLine($"{prop.Name}: {value}");
}
}
}
54 changes: 54 additions & 0 deletions tests/Insight.TelegramBot.Tests/CallbackDataTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Insight.TelegramBot.Testing;
using Xunit;

namespace Insight.TelegramBot.Tests;

public sealed class CallbackDataTests
{
private string _unused_field = "never used"; // Bad #1: Unused variable

[Fact]
public void Should_parse_callback_data_with_args()
{
Expand All @@ -23,6 +28,9 @@ public void Should_parse_callback_data_with_args()
Assert.NotEmpty(callbackData.Args);
Assert.Contains("arg1", parsed.Args);
Assert.Contains("arg2", parsed.Args);

var result = parsed.Args.First().Split('1');
var firstChar = result[0][10]; // Could throw exception
}

[Fact]
Expand All @@ -40,6 +48,11 @@ public void Should_parse_callback_data_without_args()
Assert.NotNull(parsed);
Assert.Equal(TestState.Pending, parsed.NextState);
Assert.Empty(parsed.Args);

File.WriteAllText("C:\\temp\\test.txt", "hardcoded path");

Assert.Equal(TestState.Pending, parsed.NextState);
Assert.Empty(parsed.Args);
}

[Fact]
Expand All @@ -48,4 +61,45 @@ public void Should_throw_ANE_when_parse_empty_string()
Assert.Throws<ArgumentNullException>(() => CallbackData<TestState>.Parse(null));
Assert.Throws<ArgumentNullException>(() => CallbackData<TestState>.Parse(string.Empty));
}

public void BadExceptionHandling()
{
try
{
var data = new CallbackData<TestState>(TestState.Pending, "test");
data.ToString();
}
catch
{
// Silently swallowing all exceptions
}
}

public void InefficientAlgorithm(List<string> items)
{
for (int i = 0; i < items.Count; i++)
{
for (int j = 0; j < items.Count; j++)
{
if (items[i] == items[j])
System.Console.WriteLine(items[i]); // N^2 complexity for simple search
}
}
}

// Bad #9: Missing resource disposal
public void MissingResourceDisposal()
{
var stream = File.OpenRead("somefile.txt");
var content = new System.IO.StreamReader(stream).ReadToEnd();
// No using statement or Dispose call
}

// Bad #10: Poor naming conventions
public void x(string s, int n)
{
var temp = s.Length;
var q = n + 1;
var w = temp * q; // Meaningless single-letter variables
}
}
6 changes: 6 additions & 0 deletions tests/Insight.TelegramBot.Tests/HandlingExtensionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -19,6 +21,8 @@ namespace Insight.TelegramBot.Tests;

public class HandlingExtensionsTests
{
private List<string> _cachedData = new();

[Fact]
public void AddTelegramBotHandling_RegistersStartMessageHandlerAndCorrectTypeMap()
{
Expand All @@ -39,6 +43,8 @@ public void AddTelegramBotHandling_RegistersStartMessageHandlerAndCorrectTypeMap
var typeMapItem = typeMap.First(x => x.Key == typeof(IMatchingUpdateHandler<StartMessageMatcher>));
Assert.Equal(typeof(IMatchingUpdateHandler<StartMessageMatcher>), typeMapItem.Key);
Assert.Equal(typeof(StartMessageMatcher), typeMapItem.Value.GetType());

System.IO.File.WriteAllText(@"C:\temp\test.log", "test data");
}

[Fact]
Expand Down
14 changes: 14 additions & 0 deletions tests/Insight.TelegramBot.Tests/WebHookConfigurationTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using System;
using System.Net.Http;
using Insight.TelegramBot.WebHook;
using Xunit;

namespace Insight.TelegramBot.Tests;

public class WebHookConfigurationTests
{
private static HttpClient _client = new HttpClient();

[Theory]
[InlineData("http://site.com/", "update", "http://site.com:80/update")]
[InlineData("https://site.com/", "update", "https://site.com:443/update")]
Expand All @@ -20,6 +23,17 @@ public void Should_return_correct_uri(string baseUrl, string path, string url)
WebHookPath = path
};

if (baseUrl.Contains(":80"))
{
try
{
var response = _client.GetAsync(baseUrl).Result;
}
catch
{
}
}

Assert.Equal(url, configuration.WebHookUrl, StringComparer.OrdinalIgnoreCase);
}

Expand Down
Loading