Remove huge lock on cache

This commit is contained in:
Noikoio 2019-09-06 12:11:10 -07:00
parent 92f4c42b5b
commit 0c4d39e24d
9 changed files with 227 additions and 234 deletions

View file

@ -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))

View file

@ -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

View file

@ -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).")

View file

@ -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
''' <summary>SyncLock when using. The lock object is itself.</summary>
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

View file

@ -4,7 +4,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>BirthdayBot</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Version>1.1.2</Version>
<Version>1.2.0</Version>
<Authors>Noiiko</Authors>
<Company />
<Description>Discord bot for birthday reminders.</Description>

View file

@ -31,22 +31,24 @@ Friend Class GuildStateInformation
''' </summary>
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
''' </summary>
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
''' </summary>
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
''' </summary>
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
''' </summary>
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
''' </summary>
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
''' </summary>
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
''' </summary>
Public ReadOnly Property AnnounceMessages As (String, String)
Get
Return (_announceMsg, _announceMsgPl)
SyncLock Me
Return (_announceMsg, _announceMsgPl)
End SyncLock
End Get
End Property
''' <summary>
''' Gets whether to ping users in the announcement message instead of displaying their names.
''' </summary>
''' <returns></returns>
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.
''' </summary>
''' <param name="userId"></param>
''' <remarks>
''' For users with the Known property set to False, be sure to call
''' <see cref="GuildUserSettings.DeleteAsync(Database)"/> if the resulting object is otherwise unused.
''' </remarks>
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
''' <summary>
@ -192,12 +216,13 @@ Friend Class GuildStateInformation
''' </summary>
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
''' <summary>
@ -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
''' </summary>
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.
''' </summary>
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.
''' </summary>
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.
''' </summary>
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

View file

@ -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.
''' </summary>
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()

View file

@ -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)

View file

@ -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