diff --git a/BirthdayBot/BackgroundServiceRunner.vb b/BirthdayBot/BackgroundServiceRunner.vb
index 0d8c5d8..f132c07 100644
--- a/BirthdayBot/BackgroundServiceRunner.vb
+++ b/BirthdayBot/BackgroundServiceRunner.vb
@@ -40,7 +40,7 @@ Class BackgroundServiceRunner
' Delay a bit before we start (or continue) work.
Await Task.Delay(Interval * 1000, WorkerCancel.Token)
- ' Start background tasks.
+ ' Execute background tasks.
Dim tasks As New List(Of Task)
For Each service In Workers
tasks.Add(service.OnTick(_tickCount))
diff --git a/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb b/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
index fac7736..3cfa0f7 100644
--- a/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
+++ b/BirthdayBot/BackgroundServices/BirthdayRoleUpdate.vb
@@ -58,23 +58,25 @@ Class BirthdayRoleUpdate
Dim channel As SocketTextChannel = Nothing
Dim announce As (String, String)
Dim announceping As Boolean
- SyncLock BotInstance.KnownGuilds
- If Not BotInstance.KnownGuilds.ContainsKey(guild.Id) Then Return 0
- Dim gs = BotInstance.KnownGuilds(guild.Id)
- tz = gs.TimeZone
- users = gs.Users
- announce = gs.AnnounceMessages
- announceping = gs.AnnouncePing
- If gs.AnnounceChannelId.HasValue Then channel = guild.GetTextChannel(gs.AnnounceChannelId.Value)
- If gs.RoleId.HasValue Then role = guild.GetRole(gs.RoleId.Value)
+ If Not BotInstance.GuildCache.ContainsKey(guild.Id) Then Return 0 ' guild not yet fully loaded; skip processing
+
+ Dim gs = BotInstance.GuildCache(guild.Id)
+ With gs
+ tz = .TimeZone
+ users = .Users
+ announce = .AnnounceMessages
+ announceping = .AnnouncePing
+
+ If .AnnounceChannelId.HasValue Then channel = guild.GetTextChannel(gs.AnnounceChannelId.Value)
+ If .RoleId.HasValue Then role = guild.GetRole(gs.RoleId.Value)
If role Is Nothing Then
- gs.RoleWarningNonexist = True
+ .RoleWarningNonexist = True
Return 0
Else
- gs.RoleWarningNonexist = False
+ .RoleWarningNonexist = False
End If
- End SyncLock
+ End With
' Determine who's currently having a birthday
Dim birthdays = GetGuildCurrentBirthdays(users, tz)
@@ -100,9 +102,7 @@ Class BirthdayRoleUpdate
' Update warning flag
Dim updateError = Not correctRolePermissions Or gotForbidden
- SyncLock BotInstance.KnownGuilds
- BotInstance.KnownGuilds(guild.Id).RoleWarningPermission = updateError
- End SyncLock
+ BotInstance.GuildCache(guild.Id).RoleWarningPermission = updateError
' Quit now if the warning flag was set. Announcement data is not available.
If updateError Then Return 0
diff --git a/BirthdayBot/BackgroundServices/GuildStatistics.vb b/BirthdayBot/BackgroundServices/GuildStatistics.vb
index bd55f3d..82233b8 100644
--- a/BirthdayBot/BackgroundServices/GuildStatistics.vb
+++ b/BirthdayBot/BackgroundServices/GuildStatistics.vb
@@ -11,8 +11,8 @@ Class GuildStatistics
End Sub
Public Overrides Async Function OnTick(tick As Integer) As Task
- ' Activate roughly every 5 hours (interval: 45)
- If tick Mod 400 <> 2 Then Return
+ ' Activate roughly every 2 hours (interval: 45)
+ If tick Mod 160 <> 2 Then Return
Dim count = BotInstance.DiscordClient.Guilds.Count
Log($"Currently in {count} guild(s).")
diff --git a/BirthdayBot/BirthdayBot.vb b/BirthdayBot/BirthdayBot.vb
index 47685bd..1787f3d 100644
--- a/BirthdayBot/BirthdayBot.vb
+++ b/BirthdayBot/BirthdayBot.vb
@@ -1,4 +1,5 @@
-Imports BirthdayBot.CommandsCommon
+Imports System.Collections.Concurrent
+Imports BirthdayBot.CommandsCommon
Imports Discord
Imports Discord.Net
Imports Discord.WebSocket
@@ -25,13 +26,12 @@ Class BirthdayBot
End Get
End Property
- ''' SyncLock when using. The lock object is itself.
- Friend ReadOnly Property KnownGuilds As Dictionary(Of ULong, GuildStateInformation)
+ Friend ReadOnly Property GuildCache As ConcurrentDictionary(Of ULong, GuildStateInformation)
Public Sub New(conf As Configuration, dc As DiscordSocketClient)
Config = conf
_client = dc
- KnownGuilds = New Dictionary(Of ULong, GuildStateInformation)
+ GuildCache = New ConcurrentDictionary(Of ULong, GuildStateInformation)
_worker = New BackgroundServiceRunner(Me)
@@ -72,20 +72,16 @@ Class BirthdayBot
_client.Dispose()
End Function
- Private Function LoadGuild(g As SocketGuild) As Task Handles _client.JoinedGuild, _client.GuildAvailable
- SyncLock KnownGuilds
- If Not KnownGuilds.ContainsKey(g.Id) Then
- Dim gi = GuildStateInformation.LoadSettingsAsync(Config.DatabaseSettings, g.Id).GetAwaiter().GetResult()
- KnownGuilds.Add(g.Id, gi)
- End If
- End SyncLock
- Return Task.CompletedTask
+ Private Async Function LoadGuild(g As SocketGuild) As Task Handles _client.JoinedGuild, _client.GuildAvailable
+ If Not GuildCache.ContainsKey(g.Id) Then
+ Dim gi = Await GuildStateInformation.LoadSettingsAsync(Config.DatabaseSettings, g.Id)
+ GuildCache.TryAdd(g.Id, gi)
+ End If
End Function
Private Function DiscardGuild(g As SocketGuild) As Task Handles _client.LeftGuild
- SyncLock KnownGuilds
- KnownGuilds.Remove(g.Id)
- End SyncLock
+ Dim rm As GuildStateInformation = Nothing
+ GuildCache.TryRemove(g.Id, rm)
Return Task.CompletedTask
End Function
@@ -115,18 +111,14 @@ Class BirthdayBot
' Ban and role warning check
Dim roleWarningText As String
- SyncLock KnownGuilds
- Dim gi = KnownGuilds(channel.Guild.Id)
-
- ' Skip ban check if user is a manager
- If Not gi.IsUserModerator(author) Then
- If gi.IsUserBlockedAsync(author.Id).GetAwaiter().GetResult() Then
- Return
- End If
+ Dim gi = GuildCache(channel.Guild.Id)
+ ' Skip ban check if user is a manager
+ If Not gi.IsUserModerator(author) Then
+ If gi.IsUserBlockedAsync(author.Id).GetAwaiter().GetResult() Then
+ Return
End If
-
- roleWarningText = gi.IssueRoleWarning
- End SyncLock
+ End If
+ roleWarningText = gi.IssueRoleWarning
Try
If roleWarningText IsNot Nothing Then
diff --git a/BirthdayBot/BirthdayBot.vbproj b/BirthdayBot/BirthdayBot.vbproj
index 338ac7c..18a8aa5 100644
--- a/BirthdayBot/BirthdayBot.vbproj
+++ b/BirthdayBot/BirthdayBot.vbproj
@@ -4,7 +4,7 @@
Exe
BirthdayBot
netcoreapp2.0
- 1.1.2
+ 1.2.0
Noiiko
Discord bot for birthday reminders.
diff --git a/BirthdayBot/Data/GuildStateInformation.vb b/BirthdayBot/Data/GuildStateInformation.vb
index 48ae930..579eff8 100644
--- a/BirthdayBot/Data/GuildStateInformation.vb
+++ b/BirthdayBot/Data/GuildStateInformation.vb
@@ -31,22 +31,24 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property IssueRoleWarning As String
Get
- If DateTimeOffset.UtcNow - _roleLastWarning > RoleWarningInterval Then
- _roleLastWarning = DateTimeOffset.UtcNow
- Else
+ SyncLock Me
+ If DateTimeOffset.UtcNow - _roleLastWarning > RoleWarningInterval Then
+ _roleLastWarning = DateTimeOffset.UtcNow
+ Else
+ Return Nothing
+ End If
+
+ If RoleWarningUnset Or RoleWarningNonexist Then
+ Return "Warning: A birthday role must be configured before this bot can function properly. " +
+ "Update the designated role with `bb.config role (role name/ID)`."
+ End If
+ If RoleWarningPermission Then
+ Return "Warning: This bot is unable to set the birthday role onto users. " +
+ "Make sure that this bot has the Manage Roles permission and is not placed below the birthday role."
+ End If
+
Return Nothing
- End If
-
- If RoleWarningUnset Or RoleWarningNonexist Then
- Return "Warning: A birthday role must be configured before this bot can function properly. " +
- "Update the designated role with `bb.config role (role name/ID)`."
- End If
- If RoleWarningPermission Then
- Return "Warning: This bot is unable to set the birthday role onto users. " +
- "Make sure that this bot has the Manage Roles permission and is not placed below the birthday role."
- End If
-
- Return Nothing
+ End SyncLock
End Get
End Property
@@ -65,7 +67,9 @@ Friend Class GuildStateInformation
'''
Friend ReadOnly Property RoleWarningUnset As Boolean
Get
- Return _bdayRole Is Nothing
+ SyncLock Me
+ Return _bdayRole Is Nothing
+ End SyncLock
End Get
End Property
@@ -75,9 +79,11 @@ Friend Class GuildStateInformation
Public ReadOnly Property Users As IEnumerable(Of GuildUserSettings)
Get
Dim items As New List(Of GuildUserSettings)
- For Each item In _userCache.Values
- items.Add(item)
- Next
+ SyncLock Me
+ For Each item In _userCache.Values
+ items.Add(item)
+ Next
+ End SyncLock
Return items
End Get
End Property
@@ -87,7 +93,9 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property RoleId As ULong?
Get
- Return _bdayRole
+ SyncLock Me
+ Return _bdayRole
+ End SyncLock
End Get
End Property
@@ -96,7 +104,9 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property AnnounceChannelId As ULong?
Get
- Return _announceCh
+ SyncLock Me
+ Return _announceCh
+ End SyncLock
End Get
End Property
@@ -105,7 +115,9 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property TimeZone As String
Get
- Return _tz
+ SyncLock Me
+ Return _tz
+ End SyncLock
End Get
End Property
@@ -114,7 +126,9 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property IsModerated As Boolean
Get
- Return _moderated
+ SyncLock Me
+ Return _moderated
+ End SyncLock
End Get
End Property
@@ -123,7 +137,9 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property ModeratorRole As ULong?
Get
- Return _modRole
+ SyncLock Me
+ Return _modRole
+ End SyncLock
End Get
End Property
@@ -132,17 +148,20 @@ Friend Class GuildStateInformation
'''
Public ReadOnly Property AnnounceMessages As (String, String)
Get
- Return (_announceMsg, _announceMsgPl)
+ SyncLock Me
+ Return (_announceMsg, _announceMsgPl)
+ End SyncLock
End Get
End Property
'''
''' Gets whether to ping users in the announcement message instead of displaying their names.
'''
- '''
Public ReadOnly Property AnnouncePing As Boolean
Get
- Return _announcePing
+ SyncLock Me
+ Return _announcePing
+ End SyncLock
End Get
End Property
@@ -174,17 +193,22 @@ Friend Class GuildStateInformation
''' Gets user information from this guild. If the user doesn't exist in the backing database,
''' a new instance is created which is capable of adding the user to the database.
'''
- '''
+ '''
+ ''' For users with the Known property set to False, be sure to call
+ ''' if the resulting object is otherwise unused.
+ '''
Public Function GetUser(userId As ULong) As GuildUserSettings
- If _userCache.ContainsKey(userId) Then
- Return _userCache(userId)
- End If
+ SyncLock Me
+ If _userCache.ContainsKey(userId) Then
+ Return _userCache(userId)
+ End If
- ' No result. Create a blank entry and add it to the list, in case it
- ' gets referenced later regardless of if having been updated or not.
- Dim blank As New GuildUserSettings(_GuildId, userId)
- _userCache.Add(userId, blank)
- Return blank
+ ' No result. Create a blank entry and add it to the list, in case it
+ ' gets updated and then referenced later.
+ Dim blank As New GuildUserSettings(_GuildId, userId)
+ _userCache.Add(userId, blank)
+ Return blank
+ End SyncLock
End Function
'''
@@ -192,12 +216,13 @@ Friend Class GuildStateInformation
'''
Public Async Function DeleteUserAsync(userId As ULong) As Task
Dim user As GuildUserSettings = Nothing
- If _userCache.TryGetValue(userId, user) Then
- Await user.DeleteAsync(_db)
- Else
- Return
- End If
- _userCache.Remove(userId)
+ SyncLock Me
+ If Not _userCache.TryGetValue(userId, user) Then
+ Return
+ End If
+ _userCache.Remove(userId)
+ End SyncLock
+ Await user.DeleteAsync(_db)
End Function
'''
@@ -208,6 +233,8 @@ Friend Class GuildStateInformation
Public Async Function IsUserBlockedAsync(userId As ULong) As Task(Of Boolean)
If IsModerated Then Return True
+ ' Block list is not cached, thus doing a database lookup
+ ' TODO cache block list?
Using db = Await _db.OpenConnectionAsync()
Using c = db.CreateCommand()
c.CommandText = $"select * from {BackingTableBans} " +
@@ -229,9 +256,11 @@ Friend Class GuildStateInformation
'''
Public Function IsUserModerator(user As SocketGuildUser) As Boolean
If user.GuildPermissions.ManageGuild Then Return True
- If ModeratorRole.HasValue Then
- If user.Roles.Where(Function(r) r.Id = ModeratorRole.Value).Count > 0 Then Return True
- End If
+ SyncLock Me
+ If ModeratorRole.HasValue Then
+ If user.Roles.Where(Function(r) r.Id = ModeratorRole.Value).Count > 0 Then Return True
+ End If
+ End SyncLock
IsUserModerator = False
End Function
@@ -240,6 +269,7 @@ Friend Class GuildStateInformation
''' Adds the specified user to the block list, preventing them from issuing commands.
'''
Public Async Function BlockUserAsync(userId As ULong) As Task
+ ' TODO cache block list?
Using db = Await _db.OpenConnectionAsync()
Using c = db.CreateCommand()
c.CommandText = $"insert into {BackingTableBans} (guild_id, user_id) " +
@@ -257,6 +287,7 @@ Friend Class GuildStateInformation
''' Removes the specified user from the block list.
'''
Public Async Function UnbanUserAsync(userId As ULong) As Task
+ ' TODO cache block list?
Using db = Await _db.OpenConnectionAsync()
Using c = db.CreateCommand()
c.CommandText = $"delete from {BackingTableBans} where " +
@@ -269,46 +300,60 @@ Friend Class GuildStateInformation
End Using
End Function
- Public Async Function UpdateRoleAsync(roleId As ULong) As Task
- _bdayRole = roleId
- _roleLastWarning = New DateTimeOffset
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateRole(roleId As ULong)
+ SyncLock Me
+ _bdayRole = roleId
+ _roleLastWarning = New DateTimeOffset
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateAnnounceChannelAsync(channelId As ULong?) As Task
- _announceCh = channelId
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateAnnounceChannel(channelId As ULong?)
+ SyncLock Me
+ _announceCh = channelId
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateTimeZoneAsync(tzString As String) As Task
- _tz = tzString
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateTimeZone(tzString As String)
+ SyncLock Me
+ _tz = tzString
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateModeratedModeAsync(isModerated As Boolean) As Task
- _moderated = isModerated
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateModeratedMode(isModerated As Boolean)
+ SyncLock Me
+ _moderated = isModerated
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateModeratorRoleAsync(roleId As ULong?) As Task
- _modRole = roleId
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateModeratorRole(roleId As ULong?)
+ SyncLock Me
+ _modRole = roleId
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateAnnounceMessageAsync(message As String, plural As Boolean) As Task
- If plural Then
- _announceMsgPl = message
- Else
- _announceMsg = message
- End If
+ Public Sub UpdateAnnounceMessage(message As String, plural As Boolean)
+ SyncLock Me
+ If plural Then
+ _announceMsgPl = message
+ Else
+ _announceMsg = message
+ End If
- Await UpdateDatabaseAsync()
- End Function
+ UpdateDatabase()
+ End SyncLock
+ End Sub
- Public Async Function UpdateAnnouncePingAsync(value As Boolean) As Task
- _announcePing = value
- Await UpdateDatabaseAsync()
- End Function
+ Public Sub UpdateAnnouncePing(value As Boolean)
+ SyncLock Me
+ _announcePing = value
+ UpdateDatabase()
+ End SyncLock
+ End Sub
#Region "Database"
Public Const BackingTable = "settings"
@@ -374,8 +419,8 @@ Friend Class GuildStateInformation
''' Updates the backing database with values from this instance
''' This is a non-asynchronous operation. That may be bad.
'''
- Private Async Function UpdateDatabaseAsync() As Task
- Using db = Await _db.OpenConnectionAsync()
+ Private Sub UpdateDatabase()
+ Using db = _db.OpenConnectionAsync().GetAwaiter().GetResult()
Using c = db.CreateCommand()
c.CommandText = $"update {BackingTable} set " +
"role_id = @RoleId, " +
@@ -433,9 +478,9 @@ Friend Class GuildStateInformation
End With
c.Parameters.Add("@AnnouncePing", NpgsqlDbType.Boolean).Value = _announcePing
c.Prepare()
- Await c.ExecuteNonQueryAsync()
+ c.ExecuteNonQuery()
End Using
End Using
- End Function
+ End Sub
#End Region
End Class
diff --git a/BirthdayBot/UserInterface/ListingCommands.vb b/BirthdayBot/UserInterface/ListingCommands.vb
index d0869f0..f185e09 100644
--- a/BirthdayBot/UserInterface/ListingCommands.vb
+++ b/BirthdayBot/UserInterface/ListingCommands.vb
@@ -24,11 +24,7 @@ Class ListingCommands
' Creates a file with all birthdays.
Private Async Function CmdList(param As String(), reqChannel As SocketTextChannel, reqUser As SocketGuildUser) As Task
' For now, we're restricting this command to moderators only. This may turn into an option later.
- Dim reqMod As Boolean
- SyncLock Instance.KnownGuilds
- reqMod = Instance.KnownGuilds(reqChannel.Guild.Id).IsUserModerator(reqUser)
- End SyncLock
- If Not reqMod Then
+ If Not Instance.GuildCache(reqChannel.Guild.Id).IsUserModerator(reqUser) Then
Await reqChannel.SendMessageAsync(":x: Only bot moderators may use this command.")
Return
End If
@@ -126,10 +122,7 @@ Class ListingCommands
''' Users currently not in the guild are not included in the result.
'''
Private Async Function LoadList(guild As SocketGuild, escapeFormat As Boolean) As Task(Of List(Of ListItem))
- Dim ping As Boolean
- SyncLock Instance.KnownGuilds
- ping = Instance.KnownGuilds(guild.Id).AnnouncePing
- End SyncLock
+ Dim ping = Instance.GuildCache(guild.Id).AnnouncePing
Using db = Await BotConfig.DatabaseSettings.OpenConnectionAsync()
Using c = db.CreateCommand()
diff --git a/BirthdayBot/UserInterface/ManagerCommands.vb b/BirthdayBot/UserInterface/ManagerCommands.vb
index a392cfe..a9a852f 100644
--- a/BirthdayBot/UserInterface/ManagerCommands.vb
+++ b/BirthdayBot/UserInterface/ManagerCommands.vb
@@ -42,11 +42,7 @@ Friend Class ManagerCommands
Private Async Function CmdConfigDispatch(param As String(), reqChannel As SocketTextChannel, reqUser As SocketGuildUser) As Task
' Ignore those without the proper permissions.
' Requires either the manage guild permission or to be in the moderators role
- Dim allowed As Boolean
- SyncLock Instance.KnownGuilds
- allowed = Instance.KnownGuilds(reqUser.Guild.Id).IsUserModerator(reqUser)
- End SyncLock
- If Not allowed Then
+ If Not Instance.GuildCache(reqUser.Guild.Id).IsUserModerator(reqUser) Then
Await reqChannel.SendMessageAsync(":x: This command may only be used by bot moderators.")
Return
End If
@@ -88,9 +84,7 @@ Friend Class ManagerCommands
ElseIf role.Id = reqChannel.Guild.EveryoneRole.Id Then
Await reqChannel.SendMessageAsync(":x: You cannot set that as the birthday role.")
Else
- SyncLock Instance.KnownGuilds
- Instance.KnownGuilds(guild.Id).UpdateRoleAsync(role.Id).Wait()
- End SyncLock
+ Instance.GuildCache(guild.Id).UpdateRole(role.Id)
Await reqChannel.SendMessageAsync($":white_check_mark: The birthday role has been set as **{role.Name}**.")
End If
End Function
@@ -116,9 +110,7 @@ Friend Class ManagerCommands
Return
End If
- SyncLock Instance.KnownGuilds
- Instance.KnownGuilds(reqChannel.Guild.Id).UpdateAnnouncePingAsync(setting).Wait()
- End SyncLock
+ Instance.GuildCache(reqChannel.Guild.Id).UpdateAnnouncePing(setting)
Await reqChannel.SendMessageAsync(result)
End Function
@@ -126,18 +118,15 @@ Friend Class ManagerCommands
Private Async Function ScmdChannel(param As String(), reqChannel As SocketTextChannel) As Task
If param.Length = 1 Then
' No extra parameter. Unset announcement channel.
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
+ Dim gi = Instance.GuildCache(reqChannel.Guild.Id)
- ' Extra detail: Show a unique message if a channel hadn't been set prior.
- If Not gi.AnnounceChannelId.HasValue Then
- reqChannel.SendMessageAsync(":x: There is no announcement channel set. Nothing to unset.").Wait()
- Return
- End If
-
- gi.UpdateAnnounceChannelAsync(Nothing).Wait()
- End SyncLock
+ ' Extra detail: Show a unique message if a channel hadn't been set prior.
+ If Not gi.AnnounceChannelId.HasValue Then
+ reqChannel.SendMessageAsync(":x: There is no announcement channel set. Nothing to unset.").Wait()
+ Return
+ End If
+ gi.UpdateAnnounceChannel(Nothing)
Await reqChannel.SendMessageAsync(":white_check_mark: The announcement channel has been unset.")
Else
' Parameter check: This needs a channel mention to function.
@@ -156,10 +145,8 @@ Friend Class ManagerCommands
End If
' Update the value
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
- gi.UpdateAnnounceChannelAsync(chId).Wait()
- End SyncLock
+ Dim gi = Instance.GuildCache(reqChannel.Guild.Id)
+ gi.UpdateAnnounceChannel(chId)
' Report the success
Await reqChannel.SendMessageAsync($":white_check_mark: The announcement channel is now set to <#{chId}>.")
@@ -178,9 +165,7 @@ Friend Class ManagerCommands
If role Is Nothing Then
Await reqChannel.SendMessageAsync(RoleInputError)
Else
- SyncLock Instance.KnownGuilds
- Instance.KnownGuilds(guild.Id).UpdateModeratorRoleAsync(role.Id).Wait()
- End SyncLock
+ Instance.GuildCache(guild.Id).UpdateModeratorRole(role.Id)
Await reqChannel.SendMessageAsync($":white_check_mark: The moderator role is now **{role.Name}**.")
End If
End Function
@@ -189,17 +174,15 @@ Friend Class ManagerCommands
Private Async Function ScmdZone(param As String(), reqChannel As SocketTextChannel) As Task
If param.Length = 1 Then
' No extra parameter. Unset guild default time zone.
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
+ Dim gi = Instance.GuildCache(reqChannel.Guild.Id)
- ' Extra detail: Show a unique message if there is no set zone.
- If Not gi.AnnounceChannelId.HasValue Then
- reqChannel.SendMessageAsync(":x: A default zone is not set. Nothing to unset.").Wait()
- Return
- End If
+ ' Extra detail: Show a unique message if there is no set zone.
+ If Not gi.AnnounceChannelId.HasValue Then
+ reqChannel.SendMessageAsync(":x: A default zone is not set. Nothing to unset.").Wait()
+ Return
+ End If
- gi.UpdateTimeZoneAsync(Nothing).Wait()
- End SyncLock
+ gi.UpdateTimeZone(Nothing)
Await reqChannel.SendMessageAsync(":white_check_mark: The default time zone preference has been removed.")
Else
@@ -213,10 +196,7 @@ Friend Class ManagerCommands
End Try
' Update value
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
- gi.UpdateTimeZoneAsync(zone).Wait()
- End SyncLock
+ Instance.GuildCache(reqChannel.Guild.Id).UpdateTimeZone(zone)
' Report the success
Await reqChannel.SendMessageAsync($":white_check_mark: The server's time zone has been set to **{zone}**.")
@@ -238,26 +218,23 @@ Friend Class ManagerCommands
Return
End If
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
- Dim isBanned = gi.IsUserBlockedAsync(inputId).GetAwaiter().GetResult()
-
- If doBan Then
- If Not isBanned Then
- gi.BlockUserAsync(inputId).Wait()
- reqChannel.SendMessageAsync(":white_check_mark: User has been blocked.").Wait()
- Else
- reqChannel.SendMessageAsync(":white_check_mark: User is already blocked.").Wait()
- End If
+ Dim gi = Instance.GuildCache(reqChannel.Guild.Id)
+ Dim isBanned = Await gi.IsUserBlockedAsync(inputId)
+ If doBan Then
+ If Not isBanned Then
+ Await gi.BlockUserAsync(inputId)
+ reqChannel.SendMessageAsync(":white_check_mark: User has been blocked.").Wait()
Else
- If isBanned Then
- gi.UnbanUserAsync(inputId).Wait()
- reqChannel.SendMessageAsync(":white_check_mark: User is now unblocked.").Wait()
- Else
- reqChannel.SendMessageAsync(":white_check_mark: The specified user has not been blocked.").Wait()
- End If
+ reqChannel.SendMessageAsync(":white_check_mark: User is already blocked.").Wait()
End If
- End SyncLock
+ Else
+ If isBanned Then
+ Await gi.UnbanUserAsync(inputId)
+ reqChannel.SendMessageAsync(":white_check_mark: User is now unblocked.").Wait()
+ Else
+ reqChannel.SendMessageAsync(":white_check_mark: The specified user has not been blocked.").Wait()
+ End If
+ End If
End Function
' "moderated on/off" - Sets/unsets moderated mode.
@@ -278,13 +255,9 @@ Friend Class ManagerCommands
Return
End If
- Dim currentSet As Boolean
-
- SyncLock Instance.KnownGuilds
- Dim gi = Instance.KnownGuilds(reqChannel.Guild.Id)
- currentSet = gi.IsModerated
- gi.UpdateModeratedModeAsync(modSet).Wait()
- End SyncLock
+ Dim gi = Instance.GuildCache(reqChannel.Guild.Id)
+ Dim currentSet = gi.IsModerated
+ gi.UpdateModeratedMode(modSet)
If currentSet = modSet Then
Await reqChannel.SendMessageAsync($":white_check_mark: Moderated mode is already {parameter}.")
@@ -307,9 +280,7 @@ Friend Class ManagerCommands
clear = True
End If
- SyncLock Instance.KnownGuilds
- Instance.KnownGuilds(reqChannel.Guild.Id).UpdateAnnounceMessageAsync(newmsg, plural).Wait()
- End SyncLock
+ Instance.GuildCache(reqChannel.Guild.Id).UpdateAnnounceMessage(newmsg, plural)
Const report = ":white_check_mark: The {0} birthday announcement message has been {1}."
Await reqChannel.SendMessageAsync(String.Format(report, If(plural, "plural", "singular"), If(clear, "reset", "updated")))
End Function
@@ -318,9 +289,7 @@ Friend Class ManagerCommands
' Execute command as another user
Private Async Function CmdOverride(param As String(), reqChannel As SocketTextChannel, reqUser As SocketGuildUser) As Task
' Moderators only. As with config, silently drop if this check fails.
- SyncLock Instance.KnownGuilds
- If Not Instance.KnownGuilds(reqUser.Guild.Id).IsUserModerator(reqUser) Then Return
- End SyncLock
+ If Not Instance.GuildCache(reqUser.Guild.Id).IsUserModerator(reqUser) Then Return
If param.Length <> 3 Then
Await reqChannel.SendMessageAsync(GenericError)
diff --git a/BirthdayBot/UserInterface/UserCommands.vb b/BirthdayBot/UserInterface/UserCommands.vb
index 25e7c2f..fb104b4 100644
--- a/BirthdayBot/UserInterface/UserCommands.vb
+++ b/BirthdayBot/UserInterface/UserCommands.vb
@@ -104,11 +104,9 @@ Class UserCommands
' Parsing successful. Update user information.
Dim known As Boolean ' Extra detail: Bot's response changes if the user was previously unknown.
Try
- SyncLock Instance.KnownGuilds
- Dim user = Instance.KnownGuilds(reqChannel.Guild.Id).GetUser(reqUser.Id)
- known = user.IsKnown
- user.UpdateAsync(bmonth, bday, btz, BotConfig.DatabaseSettings).Wait()
- End SyncLock
+ Dim user = Instance.GuildCache(reqChannel.Guild.Id).GetUser(reqUser.Id)
+ known = user.IsKnown
+ Await user.UpdateAsync(bmonth, bday, btz, BotConfig.DatabaseSettings)
Catch ex As Exception
Log("Error", ex.ToString())
reqChannel.SendMessageAsync(":x: An unknown error occurred. The bot owner has been notified.").Wait()
@@ -128,21 +126,20 @@ Class UserCommands
End If
Dim btz As String = Nothing
- SyncLock Instance.KnownGuilds
- Dim user = Instance.KnownGuilds(reqChannel.Guild.Id).GetUser(reqUser.Id)
- If Not user.IsKnown Then
- reqChannel.SendMessageAsync(":x: Can't set your time zone if your birth date isn't registered.").Wait()
- Return
- End If
+ Dim user = Instance.GuildCache(reqChannel.Guild.Id).GetUser(reqUser.Id)
+ If Not user.IsKnown Then
+ Await reqChannel.SendMessageAsync(":x: Can't set your time zone if your birth date isn't registered.")
+ Return
+ End If
+
+ Try
+ btz = ParseTimeZone(param(1))
+ Catch ex As Exception
+ reqChannel.SendMessageAsync(ex.Message).Wait()
+ Return
+ End Try
+ Await user.UpdateAsync(user.BirthMonth, user.BirthDay, btz, BotConfig.DatabaseSettings)
- Try
- btz = ParseTimeZone(param(1))
- Catch ex As Exception
- reqChannel.SendMessageAsync(ex.Message).Wait()
- Return
- End Try
- user.UpdateAsync(user.BirthMonth, user.BirthDay, btz, BotConfig.DatabaseSettings).Wait()
- End SyncLock
Await reqChannel.SendMessageAsync($":white_check_mark: Your time zone has been updated to **{btz}**.")
End Function
@@ -155,13 +152,10 @@ Class UserCommands
' Extra detail: Send a notification if the user isn't actually known by the bot.
Dim known As Boolean
- SyncLock Instance.KnownGuilds
- Dim g = Instance.KnownGuilds(reqChannel.Guild.Id)
- known = g.GetUser(reqUser.Id).IsKnown
- If known Then
- g.DeleteUserAsync(reqUser.Id).Wait()
- End If
- End SyncLock
+ Dim g = Instance.GuildCache(reqChannel.Guild.Id)
+ known = g.GetUser(reqUser.Id).IsKnown
+ ' Delete database and cache entry
+ Await g.DeleteUserAsync(reqUser.Id)
If Not known Then
Await reqChannel.SendMessageAsync(":white_check_mark: I don't have your information. Nothing to remove.")
Else