189 lines
7.4 KiB
C#

using Scalar.AspNetCore;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.DirectoryServices.Protocols;
using System.Runtime.CompilerServices;
SignalIntegration.Instance = new SignalIntegration(AppConfiguration.Instance.SignalAPIEndpointUri,
int.Parse(AppConfiguration.Instance.SignalAPIEndpointPort),
AppConfiguration.Instance.HostPhoneNumber);
LdapIntegration.Instance = new LdapIntegration(AppConfiguration.Instance.LDAPConfig.LDAPserver,
AppConfiguration.Instance.LDAPConfig.Port,
AppConfiguration.Instance.LDAPConfig.Username,
AppConfiguration.Instance.LDAPConfig.Password);
var builder = WebApplication.CreateBuilder(args);
Console.WriteLine("Setting up user check timer");
var userCheckTimer = new CronTimer("*/1 * * * *", "Europe/Vienna", includingSeconds: false);
userCheckTimer.OnOccurence += async (s, ea) =>
{
var memberList = await SignalIntegration.Instance.GetMemberListAsync();
var dci = DataContext.Instance;
var needsSaving = false;
foreach (var memberId in memberList)
{
Console.WriteLine("found member: " + memberId);
var foundUser = dci.Users.Where(u => u.SignalMemberId == memberId).SingleOrDefault();
if (foundUser == null)
{
var newUserContact = await SignalIntegration.Instance.GetContactAsync(memberId);
Console.WriteLine("New user:");
Console.WriteLine($" Name: {newUserContact.Name}");
Console.WriteLine($" MemberId: {memberId}");
User newUser = new User()
{
Name = newUserContact.Name,
SignalMemberId = memberId,
NickName = string.Empty,
IsIntroduced = false,
LdapUserName = string.Empty,
AssociationInProgress = false,
};
dci.Users.Add(newUser);
needsSaving = true;
}
}
if (needsSaving)
{
await dci.SaveChangesAsync();
}
await dci.DisposeAsync();
};
userCheckTimer.Start();
Console.WriteLine("Setting up user intro timer");
var userIntroTimer = new CronTimer("*/1 * * * *", "Europe/Vienna", includingSeconds: false);
userIntroTimer.OnOccurence += async (s, ea) =>
{
var dci = DataContext.Instance;
var introUsers = dci.Users.Where(u => !u.IsIntroduced);
bool needsSaving = false;
foreach (var user in introUsers)
{
await SignalIntegration.Instance.IntroduceUserAsync(user);
user.IsIntroduced = true;
needsSaving = true;
}
if (needsSaving)
{
await dci.SaveChangesAsync();
}
await dci.DisposeAsync();
};
userIntroTimer.Start();
Console.WriteLine("Setting up pick of the day timer");
var pickOfTheDayTimer = new CronTimer("0 8 * * *", "Europe/Vienna", includingSeconds: false);
pickOfTheDayTimer.OnOccurence += async (s, ea) =>
{
var rand = new Random();
var num = rand.NextInt64();
var mod = num % AppConfiguration.Instance.AverageDaysBetweenRequests;
if (mod > 0)
{
Console.WriteLine("Skipping pick of the day today!");
return;
}
var dci = DataContext.Instance;
var luckyUser = await dci.Users.ElementAtAsync((new Random()).Next(await dci.Users.CountAsync()));
var userName = string.IsNullOrEmpty(luckyUser.NickName) ? luckyUser.Name : luckyUser.NickName;
SignalIntegration.Instance.SendMessageToGroupAsync($"Today's chosen person to share a song is: **{userName}**");
SignalIntegration.Instance.SendMessageToUserAsync($"Congratulations, you have been chosen to share a song today!", luckyUser.SignalMemberId);
var suggestion = await dci.SuggestionHelpers.ElementAtAsync((new Random()).Next(await dci.SuggestionHelpers.CountAsync()));
SignalIntegration.Instance.SendMessageToUserAsync($"Today's (optional) suggestion helper to help you pick a song is:\n\n**{suggestion.Title}**\n\n*{suggestion.Description}*", luckyUser.SignalMemberId);
SignalIntegration.Instance.SendMessageToUserAsync($"For now please just share your suggestion with the group - in the future I might ask you to share directly with me or via the website to help me keep track of past suggestions!", luckyUser.SignalMemberId);
};
pickOfTheDayTimer.Start();
var startUserAssociationProcess = (User userToAssociate) =>
{
SignalIntegration.Instance.SendMessageToUserAsync($"Hi, I see you are not associated with any website user yet.", userToAssociate.SignalMemberId);
SignalIntegration.Instance.SendMessageToUserAsync($"If you haven't yet, please navigate to https://users.disi.dev to create a new account.", userToAssociate.SignalMemberId);
SignalIntegration.Instance.SendMessageToUserAsync($"Once you have done so, go to https://sotd.disi.dev, login, navigate to \"Unclaimed Phone Numbers\" and click on the \"Claim\" button to start the claim process.", userToAssociate.SignalMemberId);
SignalIntegration.Instance.SendMessageToUserAsync($"With a future update you will be required to submit songs via your user account - at that point you will be skipped during the selection process if you have not yet claimed your phone number!", userToAssociate.SignalMemberId);
};
Console.WriteLine("Setting up LdapAssociation timer");
var ldapAssociationTimer = new CronTimer("*/10 * * * *", "Europe/Vienna", includingSeconds: false);
ldapAssociationTimer.OnOccurence += async (s, ea) =>
{
var dci = DataContext.Instance;
var nonAssociatedUsers = dci.Users.Where(u => string.IsNullOrEmpty(u.LdapUserName) && !u.AssociationInProgress);
var needsSaving = false;
foreach (var user in nonAssociatedUsers)
{
user.AssociationInProgress = true;
startUserAssociationProcess(user);
user.IsIntroduced = true;
needsSaving = true;
}
if (needsSaving)
{
await dci.SaveChangesAsync();
}
await dci.DisposeAsync();
};
ldapAssociationTimer.Start();
var searchResults = LdapIntegration.Instance.SearchInAD(
AppConfiguration.Instance.LDAPConfig.LDAPQueryBase,
$"(memberOf={AppConfiguration.Instance.LDAPConfig.CrewGroup})",
SearchScope.Subtree
);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddOpenApi();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Auth/Login";
});
builder.Services.AddSingleton<LdapAuthenticationService>();
builder.Services.AddSingleton<PhoneClaimCodeProviderService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
else
{
app.MapOpenApi();
app.MapScalarApiReference();
}
app.UseRouting();
app.UseAuthorization();
app.MapStaticAssets();
app.MapRazorPages()
.WithStaticAssets();
app.MapControllerRoute(
name: "login",
pattern: "{controller=Auth}/{action=Login}"
);
app.MapControllerRoute(
name: "logout",
pattern: "{controller=Auth}/{action=Logout}"
);
app.MapGet("/debug/routes", (IEnumerable<EndpointDataSource> endpointSources) =>
string.Join("\n", endpointSources.SelectMany(source => source.Endpoints)));
app.Run();