List CSV output; show warning message on disconnect

This commit is contained in:
Noikoio 2019-07-14 00:29:35 -07:00
parent fe5bdb53f9
commit f3e70f8459
4 changed files with 97 additions and 25 deletions

View file

@ -15,6 +15,12 @@ Class Heartbeat
Log($"Tick {tick:00000} - Bot uptime: {BotUptime()}")
End If
If (BotInstance.DiscordClient.ConnectionState = Discord.ConnectionState.Disconnected) Then
Log("Client is disconnected! Restart the app if this persists.")
' The library alone cannot be restarted as it is in an unknown state. It was not designed to be restarted.
' This is the part where we'd signal something to restart us if we were fancy.
End If
Return Task.CompletedTask
End Function
End Class

View file

@ -1,16 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<RootNamespace>BirthdayBot</RootNamespace>
<TargetFramework>netcoreapp2.0</TargetFramework>
<Version>1.1.0</Version>
<AssemblyVersion>1.1.0.0</AssemblyVersion>
<Version>1.1.1</Version>
<Authors>Noiiko</Authors>
<Company />
<Description>Discord bot for birthday reminders.</Description>
<StartupObject>Sub Main</StartupObject>
<OptionStrict>On</OptionStrict>
<ApplicationManifest>My Project\app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">

View file

@ -53,7 +53,7 @@ Friend Class HelpInfoCommands
$"{cpfx}config`" + vbLf +
$" » Edit bot configuration. See `{CommandPrefix}help-config`." + vbLf +
$"{cpfx}list`" + vbLf +
$" » Exports all known birthdays to file." + vbLf +
$" » Exports all birthdays to file. Accepts `csv` as a parameter." + vbLf +
$"{cpfx}override (user ping or ID) (command w/ parameters)`" + vbLf +
" » Perform certain commands on behalf of another user."
}

View file

@ -28,31 +28,37 @@ Class ListingCommands
SyncLock Instance.KnownGuilds
reqMod = Instance.KnownGuilds(reqChannel.Guild.Id).IsUserModerator(reqUser)
End SyncLock
If Not reqMod Then
Await reqChannel.SendMessageAsync(":x: Only bot moderators may use this command.")
Return
End If
Dim bdlist = Await BuildList(reqChannel.Guild, False)
Dim useCsv = False
' Check for CSV option
If param.Length = 2 Then
If (param(1).ToLower() = "csv") Then
useCsv = True
Else
Await reqChannel.SendMessageAsync(":x: That is not available as an export format.")
Return
End If
ElseIf param.Length > 2 Then
Await reqChannel.SendMessageAsync(GenericError)
Return
End If
Dim filepath = Path.GetTempPath() + "birthdaybot-" + reqChannel.Guild.Id.ToString() + ".txt"
Using f = File.CreateText(filepath)
f.WriteLine("Birthdays in " + reqChannel.Guild.Name)
f.WriteLine()
For Each item In bdlist
Dim user = reqChannel.Guild.GetUser(item.UserId)
If user Is Nothing Then Continue For ' User disappeared in the instant between getting list and processing
f.Write($"● {MonthNames(item.BirthMonth)}-{item.BirthDay.ToString("00")}: ")
f.Write(item.UserId)
f.Write(" " + user.Username + "#" + user.Discriminator)
If user.Nickname IsNot Nothing Then
f.Write(" - Nickname: " + user.Nickname)
End If
f.WriteLine()
Next
Await f.FlushAsync()
End Using
Dim bdlist = Await LoadList(reqChannel.Guild, False)
Dim filepath = Path.GetTempPath() + "birthdaybot-" + reqChannel.Guild.Id.ToString()
Dim fileoutput As String
If useCsv Then
fileoutput = ListExportCsv(reqChannel, bdlist)
filepath += ".csv"
Else
fileoutput = ListExportNormal(reqChannel, bdlist)
filepath += ".txt"
End If
Await File.WriteAllTextAsync(filepath, fileoutput, Encoding.UTF8)
Try
Await reqChannel.SendFileAsync(filepath, $"Exported {bdlist.Count} birthdays to file.")
@ -73,7 +79,7 @@ Class ListingCommands
Dim search = DateIndex(now.Month, now.Day) - 4 ' begin search 4 days prior to current date UTC
If search <= 0 Then search = 366 - Math.Abs(search)
Dim query = Await BuildList(reqChannel.Guild, True)
Dim query = Await LoadList(reqChannel.Guild, True)
If query.Count = 0 Then
Await reqChannel.SendMessageAsync("There are currently no recent or upcoming birthdays.")
Return
@ -119,7 +125,7 @@ Class ListingCommands
''' Fetches all guild birthdays and places them into an easily usable structure.
''' Users currently not in the guild are not included in the result.
''' </summary>
Private Async Function BuildList(guild As SocketGuild, escapeFormat As Boolean) As Task(Of List(Of ListItem))
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
@ -155,6 +161,66 @@ Class ListingCommands
End Using
End Function
Private Function ListExportNormal(channel As SocketGuildChannel, list As IEnumerable(Of ListItem)) As String
'Output: "● Mon-dd: (user ID) Username [ - Nickname: (nickname)]"
Dim result As New StringBuilder()
With result
.AppendLine("Birthdays in " + channel.Guild.Name)
.AppendLine()
For Each item In list
Dim user = channel.Guild.GetUser(item.UserId)
If user Is Nothing Then Continue For ' User disappeared in the instant between getting list and processing
.Append($"● {MonthNames(item.BirthMonth)}-{item.BirthDay.ToString("00")}: ")
.Append(item.UserId)
.Append(" " + user.Username + "#" + user.Discriminator)
If user.Nickname IsNot Nothing Then
.Append(" - Nickname: " + user.Nickname)
End If
.AppendLine()
Next
End With
Return result.ToString()
End Function
Private Function ListExportCsv(channel As SocketGuildChannel, list As IEnumerable(Of ListItem)) As String
' Output: User ID, Username, Nickname, Month-Day, Month, Day
Dim result As New StringBuilder()
With result
' Conforming to RFC 4180
' With header.
result.Append("UserID,Username,Nickname,MonthDayDisp,Month,Day")
result.Append(vbCrLf) ' crlf is specified by the standard
For Each item In list
Dim user = channel.Guild.GetUser(item.UserId)
If user Is Nothing Then Continue For ' User disappeared in the instant between getting list and processing
.Append(item.UserId)
.Append(",")
.Append(CsvEscape(user.Username + "#" + user.Discriminator))
.Append(",")
If user.Nickname IsNot Nothing Then .Append(user.Nickname)
.Append(",")
.Append($"{MonthNames(item.BirthMonth)}-{item.BirthDay.ToString("00")}")
.Append(",")
.Append(item.BirthMonth)
.Append(",")
.Append(item.BirthDay)
.Append(vbCrLf)
Next
End With
Return result.ToString()
End Function
Private Function CsvEscape(input As String) As String
Dim result As New StringBuilder
result.Append("""")
For Each ch In input
If ch = """"c Then result.Append(""""c)
result.Append(ch)
Next
result.Append("""")
Return result.ToString()
End Function
Private Function DateIndex(month As Integer, day As Integer) As Integer
DateIndex = 0
' Add month offset