Add rudimentary custom announcement feature

There is some room for improvement. Namely, custom placement of the
birthday list.
Moderator help message was edited to fit the 1024 character constraint.
This commit is contained in:
Noikoio 2019-05-13 23:27:26 -07:00
parent 2206c3a399
commit 272f289fb6
5 changed files with 83 additions and 38 deletions

View file

@ -97,11 +97,13 @@ Class BackgroundWorker
Dim users As IEnumerable(Of GuildUserSettings) Dim users As IEnumerable(Of GuildUserSettings)
Dim role As SocketRole = Nothing Dim role As SocketRole = Nothing
Dim channel As SocketTextChannel = Nothing Dim channel As SocketTextChannel = Nothing
Dim announceMsg As String
SyncLock _bot.KnownGuilds SyncLock _bot.KnownGuilds
If Not _bot.KnownGuilds.ContainsKey(guild.Id) Then Return 0 If Not _bot.KnownGuilds.ContainsKey(guild.Id) Then Return 0
Dim gs = _bot.KnownGuilds(guild.Id) Dim gs = _bot.KnownGuilds(guild.Id)
tz = gs.TimeZone tz = gs.TimeZone
users = gs.Users users = gs.Users
announceMsg = gs.AnnounceMessage
If gs.AnnounceChannelId.HasValue Then channel = guild.GetTextChannel(gs.AnnounceChannelId.Value) If gs.AnnounceChannelId.HasValue Then channel = guild.GetTextChannel(gs.AnnounceChannelId.Value)
If gs.RoleId.HasValue Then role = guild.GetRole(gs.RoleId.Value) If gs.RoleId.HasValue Then role = guild.GetRole(gs.RoleId.Value)
@ -133,7 +135,7 @@ Class BackgroundWorker
End Try End Try
If announceNames.Count <> 0 Then If announceNames.Count <> 0 Then
' Send out announcement message ' Send out announcement message
Await BirthdayAnnounceAsync(guild, channel, announceNames) Await BirthdayAnnounceAsync(announceMsg, channel, announceNames)
End If End If
Return announceNames.Count Return announceNames.Count
@ -225,36 +227,39 @@ Class BackgroundWorker
''' Makes (or attempts to make) an announcement in the specified channel that includes all users ''' Makes (or attempts to make) an announcement in the specified channel that includes all users
''' who have just had their birthday role added. ''' who have just had their birthday role added.
''' </summary> ''' </summary>
Private Async Function BirthdayAnnounceAsync(g As SocketGuild, c As SocketTextChannel, names As IEnumerable(Of SocketGuildUser)) As Task Private Async Function BirthdayAnnounceAsync(ByVal announceMsg As String,
c As SocketTextChannel,
names As IEnumerable(Of SocketGuildUser)) As Task
Const DefaultAnnounce = "Please wish a happy birthday to our esteemed member(s):"
If c Is Nothing Then Return If c Is Nothing Then Return
' TODO streamline this whole thing once a customizable message is implemented. ' TODO streamline this whole thing once a customizable message is implemented.
' Plan: "{custommessage}\n{namedisplay}" ' Plan: "{custommessage}\n{namedisplay}"
Dim result As String Dim result As String
If names.Count = 1 Then If announceMsg Is Nothing Then
' Single birthday. No need for tricks. announceMsg = DefaultAnnounce
Dim name = BirthdayAnnounceFormatName(names(0))
result = $"Please wish a happy birthday to our esteemed member, **{name}**."
Else
' Build sorted name list
Dim namestrings As New List(Of String)
For Each item In names
namestrings.Add(BirthdayAnnounceFormatName(item))
Next
namestrings.Sort(StringComparer.OrdinalIgnoreCase)
Dim namedisplay As New StringBuilder()
Dim first = True
For Each item In namestrings
If Not first Then
namedisplay.Append(", ")
End If
first = False
namedisplay.Append(item)
Next
result = $"Please wish a happy birthday to our esteemed members: {namedisplay.ToString()}."
End If End If
announceMsg = announceMsg.TrimEnd()
' Build sorted name list
Dim namestrings As New List(Of String)
For Each item In names
namestrings.Add(BirthdayAnnounceFormatName(item))
Next
namestrings.Sort(StringComparer.OrdinalIgnoreCase)
Dim namedisplay As New StringBuilder()
Dim first = True
For Each item In namestrings
If Not first Then
namedisplay.Append(", ")
End If
first = False
namedisplay.Append(item)
Next
result = announceMsg + " " + namedisplay.ToString()
Try Try
Await c.SendMessageAsync(result) Await c.SendMessageAsync(result)

View file

@ -4,8 +4,8 @@
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>BirthdayBot</RootNamespace> <RootNamespace>BirthdayBot</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework> <TargetFramework>netcoreapp2.0</TargetFramework>
<Version>0.6.1</Version> <Version>0.7.0</Version>
<AssemblyVersion>0.6.1.0</AssemblyVersion> <AssemblyVersion>0.7.0.0</AssemblyVersion>
<Authors>Noikoio</Authors> <Authors>Noikoio</Authors>
<Company /> <Company />
<Description>Discord bot for birthday reminders.</Description> <Description>Discord bot for birthday reminders.</Description>

View file

@ -16,6 +16,7 @@ Friend Class GuildSettings
Private _modRole As ULong? Private _modRole As ULong?
Private _tz As String Private _tz As String
Private _moderated As Boolean Private _moderated As Boolean
Private _announceMsg As String
Private _userCache As Dictionary(Of ULong, GuildUserSettings) Private _userCache As Dictionary(Of ULong, GuildUserSettings)
Private _roleWarning As Boolean Private _roleWarning As Boolean
@ -103,6 +104,15 @@ Friend Class GuildSettings
End Get End Get
End Property End Property
''' <summary>
''' Gets the guild-specific birthday announcement message.
''' </summary>
Public ReadOnly Property AnnounceMessage As String
Get
Return _announceMsg
End Get
End Property
' Called by LoadSettingsAsync. Double-check ordinals when changes are made. ' Called by LoadSettingsAsync. Double-check ordinals when changes are made.
Private Sub New(reader As DbDataReader, dbconfig As Database) Private Sub New(reader As DbDataReader, dbconfig As Database)
_db = dbconfig _db = dbconfig
@ -118,6 +128,7 @@ Friend Class GuildSettings
_tz = If(reader.IsDBNull(3), Nothing, reader.GetString(3)) _tz = If(reader.IsDBNull(3), Nothing, reader.GetString(3))
_moderated = reader.GetBoolean(4) _moderated = reader.GetBoolean(4)
If Not reader.IsDBNull(5) Then _modRole = CULng(reader.GetInt64(5)) If Not reader.IsDBNull(5) Then _modRole = CULng(reader.GetInt64(5))
_announceMsg = If(reader.IsDBNull(6), Nothing, reader.GetString(6))
' Get user information loaded up. ' Get user information loaded up.
Dim userresult = GuildUserSettings.GetGuildUsersAsync(dbconfig, GuildId) Dim userresult = GuildUserSettings.GetGuildUsersAsync(dbconfig, GuildId)
@ -253,6 +264,11 @@ Friend Class GuildSettings
Await UpdateDatabaseAsync() Await UpdateDatabaseAsync()
End Function End Function
Public Async Function UpdateAnnounceMessageAsync(message As String) As Task
_announceMsg = message
Await UpdateDatabaseAsync()
End Function
#Region "Database" #Region "Database"
Public Const BackingTable = "settings" Public Const BackingTable = "settings"
Public Const BackingTableBans = "banned_users" Public Const BackingTableBans = "banned_users"
@ -265,7 +281,8 @@ Friend Class GuildSettings
"channel_announce_id bigint null, " + "channel_announce_id bigint null, " +
"time_zone text null, " + "time_zone text null, " +
"moderated boolean not null default FALSE, " + "moderated boolean not null default FALSE, " +
"moderator_role bigint null" + "moderator_role bigint null, " +
"announce_message text null" +
")" ")"
c.ExecuteNonQuery() c.ExecuteNonQuery()
End Using End Using
@ -287,7 +304,7 @@ Friend Class GuildSettings
Using db = Await dbsettings.OpenConnectionAsync() Using db = Await dbsettings.OpenConnectionAsync()
Using c = db.CreateCommand() Using c = db.CreateCommand()
' Take note of ordinals for use in the constructor ' Take note of ordinals for use in the constructor
c.CommandText = "select guild_id, role_id, channel_announce_id, time_zone, moderated, moderator_role " + c.CommandText = "select guild_id, role_id, channel_announce_id, time_zone, moderated, moderator_role, announce_message " +
$"from {BackingTable} where guild_id = @Gid" $"from {BackingTable} where guild_id = @Gid"
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = guild c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = guild
c.Prepare() c.Prepare()
@ -322,7 +339,8 @@ Friend Class GuildSettings
"channel_announce_id = @ChannelId, " + "channel_announce_id = @ChannelId, " +
"time_zone = @TimeZone, " + "time_zone = @TimeZone, " +
"moderated = @Moderated, " + "moderated = @Moderated, " +
"moderator_role = @ModRole " + "moderator_role = @ModRole, " +
"announce_message = @AnnounceMsg " +
"where guild_id = @Gid" "where guild_id = @Gid"
c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = GuildId c.Parameters.Add("@Gid", NpgsqlDbType.Bigint).Value = GuildId
With c.Parameters.Add("@RoleId", NpgsqlDbType.Bigint) With c.Parameters.Add("@RoleId", NpgsqlDbType.Bigint)
@ -354,6 +372,13 @@ Friend Class GuildSettings
.Value = DBNull.Value .Value = DBNull.Value
End If End If
End With End With
With c.Parameters.Add("@AnnounceMsg", NpgsqlDbType.Text)
If AnnounceMessage IsNot Nothing Then
.Value = AnnounceMessage
Else
.Value = DBNull.Value
End If
End With
c.Prepare() c.Prepare()
Await c.ExecuteNonQueryAsync() Await c.ExecuteNonQueryAsync()
End Using End Using

View file

@ -47,21 +47,22 @@ Friend Class HelpInfoCommands
.Name = "Commands for server managers and bot moderators", .Name = "Commands for server managers and bot moderators",
.Value = .Value =
$"{mpfx}role (role name or ID)`" + vbLf + $"{mpfx}role (role name or ID)`" + vbLf +
" » Configures the role to apply to users having birthdays." + vbLf + " » Sets the role to apply to users having birthdays. **Required for bot function.**" + vbLf +
$"{mpfx}channel (channel name or ID)`" + vbLf + $"{mpfx}channel (channel name or ID)`" + vbLf +
" » Configures the channel to use for announcements. Leave blank to disable." + vbLf + " » Sets the channel to use for announcements. Leave blank to disable." + vbLf +
$"{mpfx}message (message)`" + vbLf +
" » Sets a custom announcement message. The names of those celebrating birthdays are appended to it." + vbLf +
$"{mpfx}modrole (role name or ID)`" + vbLf + $"{mpfx}modrole (role name or ID)`" + vbLf +
" » Sets the designated role for bot moderators. Moderators can access `bb.config` and `bb.override`." + vbLf + " » Sets the designated role for bot moderators, granting them access to `bb.config` and `bb.override`." + vbLf +
$"{mpfx}zone (time zone name)`" + vbLf + $"{mpfx}zone (time zone name)`" + vbLf +
" » Sets the default time zone for all dates that don't have their own zone set." + vbLf + " » Sets the default time zone for users without their own zone." + vbLf +
$" »» See `{CommandPrefix}help-tzdata`. Leave blank to set to UTC." + vbLf + $" »» See `{CommandPrefix}help-tzdata`. Leave blank to set to default." + vbLf +
$"{mpfx}block/unblock (user mention or ID)`" + vbLf + $"{mpfx}block/unblock (user mention or ID)`" + vbLf +
" » Prevents or allows usage of bot commands to the given user." + vbLf + " » Prevents or allows usage of bot commands to the given user." + vbLf +
$"{mpfx}moderated on/off`" + vbLf + $"{mpfx}moderated on/off`" + vbLf +
" » Prevents or allows usage of bot commands to all users excluding managers." + vbLf + " » Prevents or allows usage of bot commands to everyone excluding moderators." + vbLf +
$"{cpfx}override (user mention or ID) (command)`" + vbLf + $"{cpfx}override (user mention or ID) (command w/ parameters)`" + vbLf +
" » Performs a command on behalf of the given user." + vbLf + " » Performs certain commands on behalf of another given user."
" »» Command may be either `set`, `zone`, or `remove` plus appropriate parameters."
} }
Dim helpNoManager As New EmbedBuilder Dim helpNoManager As New EmbedBuilder

View file

@ -23,6 +23,7 @@ Friend Class ManagerCommands
{"role", AddressOf ScmdRole}, {"role", AddressOf ScmdRole},
{"channel", AddressOf ScmdChannel}, {"channel", AddressOf ScmdChannel},
{"modrole", AddressOf ScmdModRole}, {"modrole", AddressOf ScmdModRole},
{"message", AddressOf ScmdAnnounceMsg},
{"zone", AddressOf ScmdZone}, {"zone", AddressOf ScmdZone},
{"block", AddressOf ScmdBlock}, {"block", AddressOf ScmdBlock},
{"unblock", AddressOf ScmdBlock}, {"unblock", AddressOf ScmdBlock},
@ -260,6 +261,19 @@ Friend Class ManagerCommands
Await reqChannel.SendMessageAsync($":white_check_mark: Moderated mode has been turned {parameter}.") Await reqChannel.SendMessageAsync($":white_check_mark: Moderated mode has been turned {parameter}.")
End If End If
End Function End Function
' Sets/unsets custom announcement message.
Private Async Function ScmdAnnounceMsg(param As String(), reqChannel As SocketTextChannel) As Task
If param.Length <> 2 Then
Await reqChannel.SendMessageAsync(GenericError)
Return
End If
SyncLock Instance.KnownGuilds
Instance.KnownGuilds(reqChannel.Guild.Id).UpdateAnnounceMessageAsync(param(1)).Wait()
End SyncLock
Await reqChannel.SendMessageAsync(":white_check_mark: The birthday announcement message has been updated.")
End Function
#End Region #End Region
' Execute command as another user ' Execute command as another user