diff --git a/Models/Message.cs b/Models/Message.cs index 03aca13..367ab61 100644 --- a/Models/Message.cs +++ b/Models/Message.cs @@ -24,7 +24,7 @@ public class Message public Channel Channel { get; set; } - +//TODO: these are nicities to make it OOP, but it couples them with their respective platform interfaces (and connections!) [NonSerialized] public Func Reply; diff --git a/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs b/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs index 5dc6e9e..31c97e7 100644 --- a/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs +++ b/ProtocolInterfaces/DiscordInterface/DiscordInterface.cs @@ -15,16 +15,22 @@ using System.Reactive.Linq; namespace vassago.ProtocolInterfaces.DiscordInterface; + //data received + //translate data to internal type + //store + //ship off to behaver + public class DiscordInterface { - internal const string PROTOCOL = "discord"; + internal static string PROTOCOL { get => "discord"; } internal DiscordSocketClient client; private bool eventsSignedUp = false; private static readonly SemaphoreSlim discordChannelSetup = new(1, 1); private Channel protocolAsChannel; - public async Task Init(string token) + public async Task Init(string config) { + var token = config; await SetupDiscordChannel(); client = new DiscordSocketClient(new DiscordSocketConfig() { GatewayIntents = GatewayIntents.All }); @@ -147,6 +153,7 @@ public class DiscordInterface } await Behaver.Instance.ActOn(m); m.ActedOn = true; // for its own ruposess it might act on it later, but either way, fuck it, we checked. + // ...but we don't save? } private Task UserJoined(SocketGuildUser arg) @@ -312,7 +319,8 @@ public class DiscordInterface c = Rememberer.RememberChannel(c); - var selfAccountInChannel = c.Users.FirstOrDefault(a => a.ExternalId == client.CurrentUser.Id.ToString()); + //Console.WriteLine($"no one knows how to make good tooling. c.users.first, which needs client currentuser id tostring. c: {c}, c.Users {c.Users}, client: {client}, client.CurrentUser: {client.CurrentUser}, client.currentUser.Id: {client.CurrentUser.Id}"); + var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == client.CurrentUser.Id.ToString()); if(selfAccountInChannel == null) { selfAccountInChannel = UpsertAccount(client.CurrentUser, c); @@ -351,9 +359,9 @@ public class DiscordInterface { Console.WriteLine($"acc's user: {acc.IsUser?.Id}"); } - acc ??= new Account() { + acc ??= new Account() { IsUser = Rememberer.SearchUser(u => u.Accounts.Any(a => a.ExternalId == discordUser.Id.ToString() && a.Protocol == PROTOCOL)) - ?? new User() + ?? new User() }; acc.Username = discordUser.Username; @@ -401,4 +409,4 @@ public class DiscordInterface return msg.AddReactionAsync(emote); } -} \ No newline at end of file +} diff --git a/ProtocolInterfaces/TwitchInterface/TwitchInterface.cs b/ProtocolInterfaces/TwitchInterface/TwitchInterface.cs index 4f99112..418a39c 100644 --- a/ProtocolInterfaces/TwitchInterface/TwitchInterface.cs +++ b/ProtocolInterfaces/TwitchInterface/TwitchInterface.cs @@ -1,11 +1,11 @@ +using RestSharp; using System.Security.Cryptography.X509Certificates; using System.Text.RegularExpressions; -using RestSharp; -using TwitchLib.Api; using TwitchLib.Api.Helix.Models.Users.GetUsers; -using TwitchLib.Client; +using TwitchLib.Api; using TwitchLib.Client.Events; using TwitchLib.Client.Models; +using TwitchLib.Client; using TwitchLib.Communication.Clients; using TwitchLib.Communication.Models; using vassago.Behavior; @@ -13,27 +13,26 @@ using vassago.Models; namespace vassago.TwitchInterface; +internal class unifiedTwitchMessage +{ + public unifiedTwitchMessage(ChatMessage chatMessage){} +} + public class TwitchInterface { internal const string PROTOCOL = "twitch"; - private bool eventsSignedUp = false; - private ChattingContext _db; - private static SemaphoreSlim twitchChannelSetup = new SemaphoreSlim(1, 1); + private static SemaphoreSlim channelSetupSemaphpore = new SemaphoreSlim(1, 1); private Channel protocolAsChannel; + private Account selfAccountInProtocol; TwitchClient client; - TwitchAPI api; - public TwitchInterface() - { - _db = new ChattingContext(); - } private async Task SetupTwitchChannel() { - await twitchChannelSetup.WaitAsync(); + await channelSetupSemaphpore.WaitAsync(); try { - protocolAsChannel = _db.Channels.FirstOrDefault(c => c.ParentChannel == null && c.Protocol == PROTOCOL); + protocolAsChannel = Rememberer.SearchChannel(c => c.ParentChannel == null && c.Protocol == PROTOCOL); if (protocolAsChannel == null) { protocolAsChannel = new Channel() @@ -47,17 +46,23 @@ public class TwitchInterface ReactionsPossible = false, ExternalId = null, Protocol = PROTOCOL, - SubChannels = new List() + SubChannels = [] }; + protocolAsChannel.DisplayName = "twitch (itself)"; protocolAsChannel.SendMessage = (t) => { throw new InvalidOperationException($"twitch itself cannot accept text"); }; protocolAsChannel.SendFile = (f, t) => { throw new InvalidOperationException($"twitch itself cannot send file"); }; - _db.Channels.Add(protocolAsChannel); - _db.SaveChanges(); + protocolAsChannel = Rememberer.RememberChannel(protocolAsChannel); + Console.WriteLine($"protocol as channle added; {protocolAsChannel}"); } + else + { + Console.WriteLine($"twitch, channel with id {protocolAsChannel.Id}, already exists"); + } + //protocolAsChan } finally { - twitchChannelSetup.Release(); + channelSetupSemaphpore.Release(); } } @@ -81,69 +86,46 @@ public class TwitchInterface client.OnWhisperReceived += Client_OnWhisperReceivedAsync; client.OnConnected += Client_OnConnected; - Console.WriteLine("twitch client 1 connecting..."); client.Connect(); Console.WriteLine("twitch client 1 connected"); - - // Console.WriteLine("twitch API client connecting..."); - // api = new TwitchAPI(); - // Console.WriteLine("can I just use the same creds as the other client?"); - // api.Settings.ClientId = tc.username; - // api.Settings.AccessToken = tc.oauth; - // try{ - // var neckbreads = await api.Helix.Moderation.GetModeratorsAsync("silvermeddlists"); - // Console.WriteLine($"{neckbreads?.Data?.Count()} shabby beards that need to be given up on"); - // } - // catch(Exception e){ - // Console.Error.WriteLine(e); - // } - // Console.WriteLine("k."); } private async void Client_OnWhisperReceivedAsync(object sender, OnWhisperReceivedArgs e) { + //data received Console.WriteLine($"whisper#{e.WhisperMessage.Username}[{DateTime.Now}][{e.WhisperMessage.DisplayName} [id={e.WhisperMessage.Username}]][msg id: {e.WhisperMessage.MessageId}] {e.WhisperMessage.Message}"); - var old = _db.Messages.FirstOrDefault(m => m.ExternalId == e.WhisperMessage.MessageId && m.Protocol == PROTOCOL); - if (old != null) - { - Console.WriteLine($"[whisperreceived]: {e.WhisperMessage.MessageId}? already seent it. Internal id: {old.Id}"); - return; - } - var m = UpsertMessage(e.WhisperMessage); - m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM; - m.MentionsMe = Regex.IsMatch(e.WhisperMessage.Message?.ToLower(), $"\\b@{e.WhisperMessage.BotUsername.ToLower()}\\b"); - await _db.SaveChangesAsync(); + //translate to internal, upsert + var m = UpsertMessage(e.WhisperMessage); + m.Reply = (t) => { return Task.Run(() => { client.SendWhisper(e.WhisperMessage.Username, t); }); }; + m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM; + //act on await Behaver.Instance.ActOn(m); - await _db.SaveChangesAsync(); + m.ActedOn = true; + //TODO: remember it again? } private async void Client_OnMessageReceivedAsync(object sender, OnMessageReceivedArgs e) { + //data eived Console.WriteLine($"#{e.ChatMessage.Channel}[{DateTime.Now}][{e.ChatMessage.DisplayName} [id={e.ChatMessage.Username}]][msg id: {e.ChatMessage.Id}] {e.ChatMessage.Message}"); - var old = _db.Messages.FirstOrDefault(m => m.ExternalId == e.ChatMessage.Id && m.Protocol == PROTOCOL); - if (old != null) - { - Console.WriteLine($"[messagereceived]: {e.ChatMessage.Id}? already seent it"); - return; - } - Console.WriteLine($"[messagereceived]: {e.ChatMessage.Id}? new to me."); - var m = UpsertMessage(e.ChatMessage); - m.MentionsMe = Regex.IsMatch(e.ChatMessage.Message?.ToLower(), $"@{e.ChatMessage.BotUsername.ToLower()}\\b") || - e.ChatMessage.ChatReply?.ParentUserLogin == e.ChatMessage.BotUsername; - await _db.SaveChangesAsync(); + //translate to internal, upsert + var m = UpsertMessage(e.ChatMessage); + m.Reply = (t) => { return Task.Run(() => { client.SendReply(e.ChatMessage.Channel, e.ChatMessage.Id, t); }); }; + m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.Normal; + //act on await Behaver.Instance.ActOn(m); - await _db.SaveChangesAsync(); + m.ActedOn = true; + //TODO: remember again? } - private async void Client_OnConnected(object sender, OnConnectedArgs e) + private void Client_OnConnected(object sender, OnConnectedArgs e) { Console.WriteLine($"twitch marking selfaccount as seeninchannel {protocolAsChannel.Id}"); - var selfAccount = UpsertAccount(e.BotUsername, protocolAsChannel.Id); - Behaver.Instance.MarkSelf(selfAccount); - - await _db.SaveChangesAsync(); + selfAccountInProtocol = UpsertAccount(e.BotUsername, protocolAsChannel); + selfAccountInProtocol.DisplayName = e.BotUsername; + Behaver.Instance.MarkSelf(selfAccountInProtocol); Console.WriteLine($"Connected to {e.AutoJoinChannel}"); } @@ -158,61 +140,95 @@ public class TwitchInterface Console.WriteLine($"{e.DateTime.ToString()}: {e.BotUsername} - {e.Data}"); } - private Account UpsertAccount(string username, Guid inChannel) + private Account UpsertAccount(string username, Channel inChannel) { - var seenInChannel = _db.Channels.FirstOrDefault(c => c.Id == inChannel); - var acc = _db.Accounts.FirstOrDefault(ui => ui.ExternalId == username && ui.SeenInChannel.Id == inChannel); - if (acc == null) + var acc = Rememberer.SearchAccount(ui => ui.ExternalId == username && ui.SeenInChannel.ExternalId == inChannel.ToString()); + Console.WriteLine($"upserting account, retrieved {acc?.Id}."); + if (acc != null) { - acc = new Account(); - acc.SeenInChannel = seenInChannel; - _db.Accounts.Add(acc); + Console.WriteLine($"acc's usser: {acc.IsUser?.Id}"); } + acc ??= new Account() { + IsUser = Rememberer.SearchUser( + u => u.Accounts.Any(a => a.ExternalId == username && a.Protocol == PROTOCOL)) + ?? new vassago.Models.User() + }; + acc.Username = username; acc.ExternalId = username; - //acc.IsBot = + //acc.IsBot = false? there is a way to tell, but you have to go back through the API acc.Protocol = PROTOCOL; + acc.SeenInChannel = inChannel; - acc.IsUser = _db.Users.FirstOrDefault(u => u.Accounts.Any(a => a.ExternalId == acc.ExternalId && a.Protocol == acc.Protocol)); - if (acc.IsUser == null) + Console.WriteLine($"we asked rememberer to search for acc's user. {acc.IsUser?.Id}"); + if (acc.IsUser != null) { - acc.IsUser = new vassago.Models.User() { Accounts = new List() { acc } }; - _db.Users.Add(acc.IsUser); + Console.WriteLine($"user has record of {acc.IsUser.Accounts?.Count ?? 0} accounts"); + } + acc.IsUser ??= new vassago.Models.User() { Accounts = [acc] }; + if (inChannel.Users?.Count > 0) + { + Console.WriteLine($"channel has {inChannel.Users.Count} accounts"); + } + Rememberer.RememberAccount(acc); + inChannel.Users ??= []; + if (!inChannel.Users.Contains(acc)) + { + inChannel.Users.Add(acc); + Rememberer.RememberChannel(inChannel); } return acc; } private Channel UpsertChannel(string channelName) { - Channel c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == channelName && ci.Protocol == PROTOCOL); + Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == channelName + && ci.Protocol == PROTOCOL); if (c == null) { - c = new Channel(); - _db.Channels.Add(c); + Console.WriteLine($"couldn't find channel under protocol {PROTOCOL} with externalId {channelName}"); + c = new Channel() + { + Users = [] + }; } + c.DisplayName = channelName; c.ExternalId = channelName; c.ChannelType = vassago.Models.Enumerations.ChannelType.Normal; - c.Messages = c.Messages ?? new List(); + c.Messages ??= []; c.Protocol = PROTOCOL; c.ParentChannel = protocolAsChannel; c.SubChannels = c.SubChannels ?? new List(); c.SendMessage = (t) => { return Task.Run(() => { client.SendMessage(channelName, t); }); }; c.SendFile = (f, t) => { throw new InvalidOperationException($"twitch cannot send files"); }; + c = Rememberer.RememberChannel(c); + + var selfAccountInChannel = c.Users?.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId.ToString()); + if(selfAccountInChannel == null) + { + selfAccountInChannel = UpsertAccount(selfAccountInProtocol.Username, c); + } + return c; } private Channel UpsertDMChannel(string whisperWith) { - Channel c = _db.Channels.FirstOrDefault(ci => ci.ExternalId == $"w_{whisperWith}" && ci.Protocol == PROTOCOL); +Channel c = Rememberer.SearchChannel(ci => ci.ExternalId == $"w_{whisperWith}" + && ci.Protocol == PROTOCOL); if (c == null) { - c = new Channel(); - _db.Channels.Add(c); + Console.WriteLine($"couldn't find channel under protocol {PROTOCOL}, whisper with {whisperWith}"); + c = new Channel() + { + Users = [] + }; } + c.DisplayName = $"Whisper: {whisperWith}"; c.ExternalId = $"w_{whisperWith}"; c.ChannelType = vassago.Models.Enumerations.ChannelType.DM; - c.Messages = c.Messages ?? new List(); + c.Messages ??= []; c.Protocol = PROTOCOL; c.ParentChannel = protocolAsChannel; c.SubChannels = c.SubChannels ?? new List(); @@ -229,50 +245,59 @@ public class TwitchInterface }); }; c.SendFile = (f, t) => { throw new InvalidOperationException($"twitch cannot send files"); }; - return c; - } + c = Rememberer.RememberChannel(c); - private Message UpsertMessage(ChatMessage chatMessage) - { - var m = _db.Messages.FirstOrDefault(mi => mi.ExternalId == chatMessage.Id); - if (m == null) + var selfAccountInChannel = c.Users.FirstOrDefault(a => a.ExternalId == selfAccountInProtocol.ExternalId.ToString()); + if(selfAccountInChannel == null) { - m = new Message(); - m.Protocol = PROTOCOL; - _db.Messages.Add(m); - m.Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc); + selfAccountInChannel = UpsertAccount(selfAccountInChannel.Username, c); } + return c; + } + + //n.b., I see you future adam. "we should unify these, they're redundant". + //ah, but that's the trick, they aren't! twitchlib has a common base class, but + //none of the features we care about are on it! + private Message UpsertMessage(ChatMessage chatMessage) + { + var m = Rememberer.SearchMessage(mi => mi.ExternalId == chatMessage.Id && mi.Protocol == PROTOCOL) + ?? new() + { + Protocol = PROTOCOL, + Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc) + }; m.Content = chatMessage.Message; m.ExternalId = chatMessage.Id; m.Channel = UpsertChannel(chatMessage.Channel); - m.Author = UpsertAccount(chatMessage.Username, m.Channel.Id); - m.Author.SeenInChannel = m.Channel; - + m.Author = UpsertAccount(chatMessage.Username, m.Channel); //TODO: m.channel, instead, for consistency + m.Author.SeenInChannel = m.Channel;//TODO: should be handled in UpsertAccount + m.MentionsMe = Regex.IsMatch(m.Content?.ToLower(), $"\\b@{selfAccountInProtocol.Username.ToLower()}\\b"); m.Reply = (t) => { return Task.Run(() => { client.SendReply(chatMessage.Channel, chatMessage.Id, t); }); }; m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); }; + Rememberer.RememberMessage(m); return m; } + //n.b., I see you future adam. "we should unify these, they're redundant". + //ah, but that's the trick, they aren't! twitchlib has a common base class, but + //none of the features we care about are on it! private Message UpsertMessage(WhisperMessage whisperMessage) { - var m = _db.Messages.FirstOrDefault(mi => mi.ExternalId == whisperMessage.MessageId); - if (m == null) - { - m = new Message(); - m.Protocol = PROTOCOL; - _db.Messages.Add(m); - m.Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc); - } - + //WhisperMessage.Id corresponds to chatMessage.Id. \*eye twitch* + var m = Rememberer.SearchMessage(mi => mi.ExternalId == whisperMessage.MessageId && mi.Protocol == PROTOCOL) + ?? new() + { + Protocol = PROTOCOL, + Timestamp = (DateTimeOffset)DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc) + }; m.Content = whisperMessage.Message; m.ExternalId = whisperMessage.MessageId; m.Channel = UpsertDMChannel(whisperMessage.Username); - m.Channel.ChannelType = vassago.Models.Enumerations.ChannelType.DM; - m.Author = UpsertAccount(whisperMessage.Username, m.Channel.Id); - m.Author.SeenInChannel = m.Channel; - + m.Author = UpsertAccount(whisperMessage.Username, m.Channel); + m.MentionsMe = Regex.IsMatch(m.Content?.ToLower(), $"\\b@{selfAccountInProtocol.Username.ToLower()}\\b"); m.Reply = (t) => { return Task.Run(() => { client.SendWhisper(whisperMessage.Username, t); }); }; m.React = (e) => { throw new InvalidOperationException($"twitch cannot react"); }; + Rememberer.RememberMessage(m); return m; } @@ -287,4 +312,4 @@ public class TwitchInterface client.SendMessage(channelTarget, "o7"); client.LeaveChannel(channelTarget); } -} \ No newline at end of file +} diff --git a/Rememberer.cs b/Rememberer.cs index 8d8d830..3cfca8a 100644 --- a/Rememberer.cs +++ b/Rememberer.cs @@ -6,105 +6,160 @@ using Microsoft.EntityFrameworkCore; public static class Rememberer { + private static readonly SemaphoreSlim dbAccessSemaphore = new(1, 1); private static readonly ChattingContext db = new(); + public static Account SearchAccount(Expression> predicate) { - return db.Accounts.Include(a => a.IsUser).FirstOrDefault(predicate); + Account toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Accounts.Include(a => a.IsUser).FirstOrDefault(predicate); + dbAccessSemaphore.Release(); + return toReturn; } public static List SearchAccounts(Expression> predicate) { - return db.Accounts.Where(predicate).ToList(); + List toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Accounts.Where(predicate).ToList(); + dbAccessSemaphore.Release(); + return toReturn; } public static Attachment SearchAttachment(Expression> predicate) { - return db.Attachments.FirstOrDefault(predicate); + Attachment toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Attachments.FirstOrDefault(predicate); + dbAccessSemaphore.Release(); + return toReturn; } public static Channel SearchChannel(Expression> predicate) { - return db.Channels.FirstOrDefault(predicate); + Channel toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Channels.FirstOrDefault(predicate); + dbAccessSemaphore.Release(); + return toReturn; } public static Message SearchMessage(Expression> predicate) { - return db.Messages.FirstOrDefault(predicate); + Message toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Messages.FirstOrDefault(predicate); + dbAccessSemaphore.Release(); + return toReturn; } public static User SearchUser(Expression> predicate) { - return db.Users.Include(u => u.Accounts).FirstOrDefault(predicate); + User toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Users.Where(predicate).Include(u => u.Accounts).FirstOrDefault(predicate); + dbAccessSemaphore.Release(); + return toReturn; } public static void RememberAccount(Account toRemember) { - toRemember.IsUser ??= new User{ Accounts = [toRemember]}; + dbAccessSemaphore.Wait(); + toRemember.IsUser ??= new User { Accounts = [toRemember] }; db.Update(toRemember.IsUser); db.SaveChanges(); + dbAccessSemaphore.Release(); } public static void RememberAttachment(Attachment toRemember) { - toRemember.Message ??= new Message() { Attachments = [toRemember]}; + dbAccessSemaphore.Wait(); + toRemember.Message ??= new Message() { Attachments = [toRemember] }; db.Update(toRemember.Message); db.SaveChanges(); + dbAccessSemaphore.Release(); } public static Channel RememberChannel(Channel toRemember) { + dbAccessSemaphore.Wait(); db.Update(toRemember); db.SaveChanges(); + dbAccessSemaphore.Release(); return toRemember; } public static void RememberMessage(Message toRemember) { - toRemember.Channel ??= new (){ Messages = [toRemember] }; + dbAccessSemaphore.Wait(); + toRemember.Channel ??= new() { Messages = [toRemember] }; db.Update(toRemember.Channel); db.SaveChanges(); + dbAccessSemaphore.Release(); } public static void RememberUser(User toRemember) { + dbAccessSemaphore.Wait(); db.Users.Update(toRemember); - db.SaveChanges(); + dbAccessSemaphore.Release(); } public static void ForgetAccount(Account toForget) { var user = toForget.IsUser; var usersOnlyAccount = user.Accounts?.Count == 1; - - if(usersOnlyAccount) + + if (usersOnlyAccount) { Rememberer.ForgetUser(user); } else { + dbAccessSemaphore.Wait(); db.Accounts.Remove(toForget); db.SaveChanges(); + dbAccessSemaphore.Release(); } } public static void ForgetChannel(Channel toForget) { + dbAccessSemaphore.Wait(); db.Channels.Remove(toForget); - db.SaveChanges(); + dbAccessSemaphore.Release(); } public static void ForgetUser(User toForget) { + dbAccessSemaphore.Wait(); db.Users.Remove(toForget); - db.SaveChanges(); + dbAccessSemaphore.Release(); } public static List AccountsOverview() { - return [..db.Accounts]; + List toReturn; + dbAccessSemaphore.Wait(); + toReturn = [.. db.Accounts]; + dbAccessSemaphore.Release(); + return toReturn; } public static List ChannelsOverview() { - return [..db.Channels.Include(u => u.SubChannels).Include(c => c.ParentChannel)]; + List toReturn; + dbAccessSemaphore.Wait(); + toReturn = [.. db.Channels.Include(u => u.SubChannels).Include(c => c.ParentChannel)]; + dbAccessSemaphore.Release(); + return toReturn; } public static Channel ChannelDetail(Guid Id) { - return db.Channels.Find(Id); - // .Include(u => u.SubChannels) - // .Include(u => u.Users) - // .Include(u => u.ParentChannel); + Channel toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Channels.Find(Id); + dbAccessSemaphore.Release(); + return toReturn; + // .Include(u => u.SubChannels) + // .Include(u => u.Users) + // .Include(u => u.ParentChannel); } public static List UsersOverview() { - return db.Users.ToList(); + List toReturn; + dbAccessSemaphore.Wait(); + toReturn = db.Users.ToList(); + dbAccessSemaphore.Release(); + return toReturn; } -} \ No newline at end of file +} diff --git a/WebInterface/Controllers/api/ChannelsControler.cs b/WebInterface/Controllers/api/ChannelsControler.cs index 3001123..30b08b8 100644 --- a/WebInterface/Controllers/api/ChannelsControler.cs +++ b/WebInterface/Controllers/api/ChannelsControler.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using vassago.Models; -using vassago.ProtocolInterfaces.DiscordInterface; namespace vassago.Controllers.api;