Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Latest <- Dev #70

Merged
merged 36 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
dcbe8d8
Add nullable sunrise and sunset hours for specifying when it should s…
GravityWolfNotAmused Jan 13, 2024
b36b6e1
Add logic to parse the time out of steam and BM responses
GravityWolfNotAmused Jan 13, 2024
cd78e7a
Change to using Linq
GravityWolfNotAmused Jan 13, 2024
2b3c17d
Add SunMoon and Time to Steam, and BM.
GravityWolfNotAmused Jan 13, 2024
fad3726
Merge branch 'latest' into sunmoon-tags-and-time-tag-for-steam
GravityWolfNotAmused Jan 13, 2024
7ba2f07
Merge pull request #63 from GravityWolfNotAmused/sunmoon-tags-and-tim…
GravityWolfNotAmused Jan 13, 2024
468c980
Revert "Sunmoon tags and time tag for steam games"
GravityWolfNotAmused Jan 13, 2024
0e1a9da
Merge pull request #64 from GravityWolfNotAmused/revert-63-sunmoon-ta…
GravityWolfNotAmused Jan 13, 2024
bd47625
Push a fake change
GravityWolfNotAmused Jan 13, 2024
d109a91
Add sunmoon tag and time tag
GravityWolfNotAmused Jan 13, 2024
c0a3822
fix linting error
GravityWolfNotAmused Jan 13, 2024
66da2d3
fix lint
GravityWolfNotAmused Jan 13, 2024
88dd8db
Merge pull request #65 from GravityWolfNotAmused/sunmoon-tags-time-tags
GravityWolfNotAmused Jan 13, 2024
588bfc9
Init RCON
GravityWolfNotAmused Jan 13, 2024
b42f2b7
Add Steam Query, and Rcon as data providers
GravityWolfNotAmused Jan 14, 2024
9dd4ea8
Linting V1
GravityWolfNotAmused Jan 14, 2024
88e2244
Linting V2
GravityWolfNotAmused Jan 14, 2024
0032518
Fix logic for SunMoon
GravityWolfNotAmused Jan 15, 2024
be45ab2
Add test cases around sun and moon tag logic.
GravityWolfNotAmused Jan 15, 2024
64a4a15
Merge pull request #67 from GravityWolfNotAmused/sunmoon-tags-time-tags
GravityWolfNotAmused Jan 15, 2024
7979550
Split up Service Information for later updates, first test with Minec…
GravityWolfNotAmused Jan 15, 2024
8a1c771
Merge branch 'dev' into serilog-logging
GravityWolfNotAmused Jan 15, 2024
5276bac
Change to Dependency Injection and Serilog.
GravityWolfNotAmused Jan 15, 2024
99126c4
Fix some conflicts
GravityWolfNotAmused Jan 15, 2024
712adf9
Merge RCON/Query Update with SunMoon
GravityWolfNotAmused Jan 15, 2024
648f62e
Add extensions
GravityWolfNotAmused Jan 15, 2024
449f577
Merge branch 'dev' into serilog-logging
GravityWolfNotAmused Jan 15, 2024
0305f8c
Clean up and small fixes.
GravityWolfNotAmused Jan 15, 2024
f7efcf2
Linting
GravityWolfNotAmused Jan 15, 2024
638d381
lint?
GravityWolfNotAmused Jan 15, 2024
a4f6a3f
Fix
GravityWolfNotAmused Jan 15, 2024
d441cd3
working..
GravityWolfNotAmused Jan 15, 2024
fe67c53
remove extra lines
GravityWolfNotAmused Jan 15, 2024
e5a3f67
Change linting
GravityWolfNotAmused Jan 15, 2024
257e540
Fix issue where null gametype from steam caused error
GravityWolfNotAmused Jul 22, 2024
7873c22
Merge pull request #68 from GravityWolfNotAmused/serilog-logging
GravityWolfNotAmused Jul 22, 2024
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
87 changes: 87 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,90 @@

# CS8618: Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
dotnet_diagnostic.CS8618.severity = suggestion
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_throw_expression = true:suggestion
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_indent_labels = one_less_than_current
csharp_space_around_binary_operators = before_and_after

[*.{cs,vb}]
#### Naming styles ####

# Naming rules

dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i

dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case

dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case

# Symbol specifications

dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.required_modifiers =

dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.required_modifiers =

dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =

# Naming styles

dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case

dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
tab_width = 4
indent_size = 4
end_of_line = lf
insert_final_newline = false
31 changes: 23 additions & 8 deletions DiscordPlayerCountBot.Tests/DockerConfigurationTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using EnvironmentHelper = PlayerCountBot.Tests.Environment.EnvironmentHelper;
using Microsoft.Extensions.DependencyInjection;
using EnvironmentHelper = DiscordPlayerCountBot.Tests.Environment.EnvironmentHelper;

namespace PlayerCountBot.Tests;
namespace DiscordPlayerCountBot.Tests;

[Collection("Configuration Test Suite")]
public class DockerConfigurationTests
Expand All @@ -15,7 +15,10 @@ public async Task DockerConfigurationTestWithAllData()
var bots = new Dictionary<string, Bot>();
var time = -1;

var dockerConfiguration = new DockerConfiguration();
var serviceProvider = new ServiceCollection()
.BuildServiceProvider();

var dockerConfiguration = new DockerConfiguration(serviceProvider);
var configuration = await dockerConfiguration.Configure(false);

bots = configuration.Item1;
Expand All @@ -35,7 +38,10 @@ public async Task DockerConfigurationWithDuplicateAddresses()
{
EnvironmentHelper.SetTestEnvironmentWithDuplicateAddresses();

var dockerConfiguration = new DockerConfiguration();
var services = new ServiceCollection()
.BuildServiceProvider();

var dockerConfiguration = new DockerConfiguration(services);
var configuration = await dockerConfiguration.Configure(false);

EnvironmentHelper.ClearTestEnvironmentVariables();
Expand All @@ -57,7 +63,10 @@ public async Task DockerConfigurationTestWithoutBattleMetrics()
var bots = new Dictionary<string, Bot>();
var time = -1;

var dockerConfiguration = new DockerConfiguration();
var services = new ServiceCollection()
.BuildServiceProvider();

var dockerConfiguration = new DockerConfiguration(services);
var configuration = await dockerConfiguration.Configure(false);

bots = configuration.Item1;
Expand All @@ -80,7 +89,10 @@ public async Task DockerConfigurationTestWithoutApplicationVariables()
var bots = new Dictionary<string, Bot>();
var time = -1;

var dockerConfiguration = new DockerConfiguration();
var services = new ServiceCollection()
.BuildServiceProvider();

var dockerConfiguration = new DockerConfiguration(services);
var configuration = await dockerConfiguration.Configure(false);

bots = configuration.Item1;
Expand All @@ -101,7 +113,10 @@ public async Task DockerConfigurationTestWithoutSteam()
var bots = new Dictionary<string, Bot>();
var time = -1;

var dockerConfiguration = new DockerConfiguration();
var services = new ServiceCollection()
.BuildServiceProvider();

var dockerConfiguration = new DockerConfiguration(services);
var configuration = await dockerConfiguration.Configure(false);

bots = configuration.Item1;
Expand Down
4 changes: 2 additions & 2 deletions DiscordPlayerCountBot.Tests/Environment/EnivronmentHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace PlayerCountBot.Tests.Environment
namespace DiscordPlayerCountBot.Tests.Environment
{
public static class EnvironmentHelper
{
Expand Down Expand Up @@ -83,4 +83,4 @@ public static void ClearTestEnvironmentVariables()
System.Environment.SetEnvironmentVariable("BOT_APPLICATION_VARIABLES", null);
}
}
}
}
4 changes: 1 addition & 3 deletions DiscordPlayerCountBot.Tests/JsonTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using PlayerCountBot.Json;

namespace DiscordPlayerCountBot.Tests;
namespace PlayerCountBot.Tests;

[Collection("Json Serialization Test Suite")]
public class JsonTests
Expand Down
78 changes: 78 additions & 0 deletions DiscordPlayerCountBot.Tests/SunMoonTagTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
namespace PlayerCountBot.Tests
{
[Collection("Sun & Moon Tag Test Suite")]
public class SunMoonTagTests
{
[Theory(DisplayName = "Test If Should Be Moon", Timeout = 30)]
[InlineData("05:30")]
[InlineData("21:30")]
[InlineData("23:30")]
public void ShouldBeMoonPhase(string time)
{
var success = time.TryGetSunMoonPhase(null, null, out var output);

Assert.True(success, "SunMoon Phase failed to parse");
Assert.True(!string.IsNullOrEmpty(output));
Assert.Equal("🌙", output);
}

[Theory(DisplayName = "Test If Should Be Sun", Timeout = 30)]
[InlineData("06:04")]
[InlineData("15:42")]
[InlineData("19:06")]
public void ShouldBeSunPhase(string time)
{
var success = time.TryGetSunMoonPhase(null, null, out var output);

Assert.True(success, "SunMoon Phase failed to parse");
Assert.True(!string.IsNullOrEmpty(output));
Assert.Equal("☀️", output);
}

[Theory(DisplayName = "Test Invalid Values", Timeout = 30)]
[InlineData("abc")]
[InlineData("")]
[InlineData("not a time value")]
[InlineData("24:30")]
public void ShouldNotParse(string time)
{
var success = time.TryGetSunMoonPhase(null, null, out var output);

Assert.False(success, "SunMoon Phase successfully parsed when it should have failed");
Assert.True(string.IsNullOrEmpty(output), "SunMoon output is not null or empty.");
}

[Theory(DisplayName = "Test custom sunrise and sunset", Timeout = 30)]
[InlineData("05:30")]
[InlineData("21:30")]
[InlineData("23:30")]
[InlineData("06:04")]
[InlineData("15:42")]
[InlineData("19:06")]
public void ShouldOutputCorrectValue(string time)
{
var information = new BotInformation()
{
SunriseHour = 1,
SunsetHour = 21
};

var success = time.TryGetSunMoonPhase(information.SunriseHour, information.SunsetHour, out var output);
var manualProcessingSuccess = TimeOnly.TryParse(time, out var timeOutput);

Assert.True(success, "SunMoon Phase parsing failed");
Assert.True(manualProcessingSuccess, "Manual Parsing SunMoon Phase failed");

var isBetween = timeOutput.Hour >= information.SunriseHour && timeOutput.Hour < information.SunsetHour;
var sunMoonPhase = isBetween ? "☀️" : "🌙";

if (isBetween)
Assert.True(sunMoonPhase.Equals("☀️"), "Time was between sunrise and sunset, but was not a Sun.");

if (!isBetween)
Assert.True(sunMoonPhase.Equals("🌙"), "Time not was between sunrise and sunset, but was not a Moon.");

Assert.Equal(sunMoonPhase, output);
}
}
}
5 changes: 4 additions & 1 deletion DiscordPlayerCountBot.Tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
global using Xunit;

global using PlayerCountBot;
global using PlayerCountBot.Configuration;
global using PlayerCountBot.Tests.Environment;
global using PlayerCountBot.Extensions;
global using PlayerCountBot.Json;
2 changes: 1 addition & 1 deletion DiscordPlayerCountBot/Attributes/AttributeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ public static string GetNameFromAttribute(object obj)
return label;
}
}
}
}
3 changes: 1 addition & 2 deletions DiscordPlayerCountBot/Attributes/NameAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
namespace PlayerCountBot.Attributes
{

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Class)]
public class NameAttribute : Attribute
{
Expand All @@ -11,4 +10,4 @@ public NameAttribute(string name)
Name = name;
}
}
}
}
41 changes: 22 additions & 19 deletions DiscordPlayerCountBot/Bot/Bot.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
namespace PlayerCountBot
using PlayerCountBot.Extensions;
using Microsoft.Extensions.DependencyInjection;

namespace PlayerCountBot
{

[Name("Bot")]
public class Bot : LoggableClass
{
public DiscordSocketClient DiscordClient { get; set; }
public Dictionary<int, IServerInformationProvider> DataProviders { get; set; } = new();
public Dictionary<string, string> ApplicationTokens { get; set; } = new();
public readonly DiscordSocketClient DiscordClient;
public readonly BotInformation Information;
public readonly Dictionary<DataProvider, IServerInformationProvider> DataProviders = new();
public readonly Dictionary<string, string> ApplicationTokens = new();

public Bot(BotInformation info, Dictionary<string, string> applicationTokens) : base(info)
public Bot(BotInformation info, Dictionary<string, string> applicationTokens, IServiceProvider services)
{
if (info is null) throw new ArgumentNullException(nameof(info));
if (applicationTokens is null) throw new ArgumentException(nameof(applicationTokens));

ApplicationTokens = applicationTokens;
Information = info;

DiscordClient = new DiscordSocketClient(new DiscordSocketConfig()
{
HandlerTimeout = null
});

InitDataProviders();
}

public void InitDataProviders()
{
DataProviders.Add((int)DataProvider.STEAM, new SteamProvider(Information!));
DataProviders.Add((int)DataProvider.CFX, new CFXProvider(Information!));
DataProviders.Add((int)DataProvider.MINECRAFT, new MinecraftProvider(Information!));
DataProviders.Add((int)DataProvider.BATTLEMETRICS, new BattleMetricsProvider(Information!));
DataProviders = services.GetServices<IServerInformationProvider>()
.ToDictionary(value => value.GetRequiredProviderType());
}

public async Task StartAsync(bool shouldStart)
Expand All @@ -38,7 +36,7 @@ public async Task StartAsync(bool shouldStart)
Information.Address = await AddressHelper.ResolveAddress(Information.Address);
}

Info($"Loaded {Information.Name} at address and port: {Information.Address}, {Information.ProviderType}");
Info($"Loaded {Information.Name} ({Information.Id}) at address and port: {Information.Address}, {(DataProvider)Information.ProviderType}");
await DiscordClient.LoginAndStartAsync(Information.Token, Information.Address, shouldStart);
}

Expand All @@ -49,20 +47,25 @@ public async Task StopAsync()

public async Task UpdateAsync()
{
var dataProviderType = EnumHelper.GetDataProvider(Information!.ProviderType);
var dataProviderInt = EnumHelper.GetDataProvider(Information!.ProviderType);

if (dataProviderType != Information.ProviderType)
if (dataProviderInt != Information.ProviderType)
{
Warn($"Config for bot at address: {Information.Address} has an invalid provider type: {Information.ProviderType}");
Warn($"Config for bot at address: {Information.Address} has an invalid provider type: {Information.ProviderType}", Information.Id.ToString());
}

var activityInteger = EnumHelper.GetActivityType(Information.Status);

if (Information.Status != activityInteger)
{
Warn($"Config for bot at address: {Information.Address} has an invalid activity type: {Information.Status}");
Warn($"Config for bot at address: {Information.Address} has an invalid activity type: {Information.Status}", Information.Id.ToString());
}

var dataProviderType = (DataProvider)dataProviderInt;

if (!DataProviders.ContainsKey(dataProviderType))
throw new Exception($"Missing Data Provider for Type: {dataProviderType}");

var dataProvider = DataProviders[dataProviderType];
var serverInformation = await dataProvider.GetServerInformation(Information, ApplicationTokens);

Expand Down
3 changes: 1 addition & 2 deletions DiscordPlayerCountBot/Bot/BotConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public class BotConfig
public Dictionary<string, string> ApplicationTokens { get; set; } = new();
public void CreateDefaults()
{

ServerInformation.Add(new()
{
Name = "TestBot",
Expand All @@ -22,4 +21,4 @@ public void CreateDefaults()
ApplicationTokens.Add("BattleMetricsKey", "Here");
}
}
}
}
Loading
Loading