Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
374804f
Merge SimplyJPK's TipService.cs
hariedo Apr 23, 2025
3cc02e4
Merge SimplyJPK's Tip.cs
hariedo Apr 23, 2025
46cd8c7
Merge SimplyJPK's Program.cs
hariedo Apr 23, 2025
755f89e
Merge SimplyJPK's TipModule.cs
hariedo Apr 23, 2025
cac112f
Merge branch 'Unity-Developer-Community:master' into feat/tips-service
hariedo Apr 23, 2025
b668896
Merge pull request #2 from hariedo/feat/tips-service
hariedo Apr 23, 2025
29f9bda
Merge SimplyJPK's Tip Service Settings.cs
hariedo Apr 23, 2025
ef1d813
Merge pull request #3 from hariedo/feat/tips-service
hariedo Apr 24, 2025
39e7639
Update TipModule.cs
hariedo Apr 24, 2025
75794f5
Error checking / validation in TipService.cs
hariedo Apr 24, 2025
2412d9d
Update Tip.cs
hariedo Apr 24, 2025
a48f51e
Update TipService.cs
hariedo Apr 24, 2025
896f159
Update Tip.cs
hariedo Apr 24, 2025
96122cd
Pseudo-database methods for TipService.cs
hariedo Apr 24, 2025
2b7034f
Syntax and cleanup in TipService.cs
hariedo Apr 24, 2025
f8400f4
Update TipModule.cs
hariedo Apr 24, 2025
839d173
Change TipService RemoveTip to async
hariedo Apr 24, 2025
74f64c5
Merge branch 'master' into feat/tips-service
hariedo Apr 25, 2025
d378087
Merge pull request #4 from hariedo/feat/tips-service
hariedo Apr 25, 2025
a854264
Fix TipModule.cs Alias
hariedo Apr 25, 2025
29e45ee
Cleanup TipModule.cs, kick build
hariedo Apr 25, 2025
725f695
Fixes to TipService.cs
hariedo Apr 25, 2025
d4c0121
Update TipModule.cs
hariedo Apr 25, 2025
9aec4e9
Update TipModule.cs
hariedo Apr 25, 2025
a5c544b
Update TipService.cs
hariedo Apr 25, 2025
080afef
Update TipModule.cs
hariedo Apr 25, 2025
befad98
Rewrite TipService.cs GetTips search
hariedo Apr 25, 2025
5c40533
rerun checks
hariedo Apr 25, 2025
64f7b2b
Typo in TipService.cs
hariedo Apr 25, 2025
4e372bf
ContainsKey in TipService.cs
hariedo Apr 25, 2025
6a5f79b
Add RemoveTip and startup logging to TipService.cs
hariedo Apr 25, 2025
10c5141
Update TipService.cs
hariedo Apr 25, 2025
7399b86
Initialize TipService.cs relative to ServerRootPath
hariedo Apr 25, 2025
48359d3
Update TipModule.cs path
hariedo Apr 25, 2025
c9a0873
Add GetTipPath to TipService.cs
hariedo Apr 25, 2025
957aac6
Update TipModule.cs to use GetTipPath
hariedo Apr 25, 2025
3254c9d
More TipService.cs RemoveTip updates
hariedo Apr 25, 2025
36244dd
Support ReadOnly ops in TipService.cs
hariedo Apr 25, 2025
07a2961
Fix TipService.cs string syntax
hariedo Apr 25, 2025
8612fbc
Update TipService.cs RemoveTip
hariedo Apr 25, 2025
fefdab6
GetTips in TipService.cs more exclusive
hariedo Apr 25, 2025
ed613b2
Fix TipService.cs
hariedo Apr 25, 2025
071b4e6
Count in TipService.cs GetTips
hariedo Apr 25, 2025
0840e46
TipService.cs GetAllTips
hariedo Apr 25, 2025
9b829df
TipModule.cs ListTips
hariedo Apr 25, 2025
f859158
Fix TipModule.cs
hariedo Apr 25, 2025
8d758af
TipService.cs GetAllTips
hariedo Apr 25, 2025
4c0ea2c
Update TipModule.cs ListTips
hariedo Apr 25, 2025
d07b22d
Update TipService.cs
hariedo Apr 25, 2025
8abe72d
Update TipModule.cs DumpTips chunking
hariedo Apr 25, 2025
56301bf
Update TipModule.cs
hariedo Apr 25, 2025
6ea4bf0
Update TipModule.cs chunking
hariedo Apr 25, 2025
413dc07
Update TipModule.cs chunk fix
hariedo Apr 25, 2025
859117e
Update TipModule.cs
hariedo Apr 25, 2025
3f5142d
Update TipModule.cs chunking
hariedo Apr 25, 2025
879c192
Update TipService.cs ReplaceTip
hariedo Apr 25, 2025
348463c
Update TipModule.cs show tip id
hariedo Apr 25, 2025
86ab632
Update TipModule.cs
hariedo Apr 25, 2025
571d9f4
Update TipModule.cs
hariedo Apr 25, 2025
bec5b2b
Update TipModule.cs
hariedo Apr 25, 2025
87516d3
Update TipModule.cs
hariedo Apr 25, 2025
042418f
Lint TipService.cs
hariedo Apr 30, 2025
40206bb
Lint TipService.cs
hariedo Apr 30, 2025
f105231
Lint TipService.cs
hariedo Apr 30, 2025
7d5616c
Lint TipService.cs
hariedo Apr 30, 2025
1203a31
Update TipModule.cs
hariedo May 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions DiscordBot/Modules/TipModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
using System.IO;
using Discord.Commands;
using DiscordBot.Attributes;
using DiscordBot.Services;
using DiscordBot.Services.Tips;
using DiscordBot.Services.Tips.Components;
using DiscordBot.Settings;

// ReSharper disable all UnusedMember.Local
namespace DiscordBot.Modules;

public class TipModule : ModuleBase
{
#region Dependency Injection

public CommandHandlingService CommandHandlingService { get; set; }
public BotSettings Settings { get; set; }
public TipService TipService { get; set; }

#endregion

[Command("Tip")]
[Summary("Find and provide pre-authored tips (images or text) by their keywords.")]
/* for now */ [RequireModerator] /* maybe Helper too */
public async Task Tip(string keywords)
{
var tips = TipService.GetTips(keywords);
if (tips.Count == 0)
{
await ReplyAsync("No tips for the keywords provided were found.");
return;
}

var isAnyTextTips = tips.Any(tip => !string.IsNullOrEmpty(tip.Content));
var builder = new EmbedBuilder();
if (isAnyTextTips)
{
// Loop through tips in order, have dot point list of the .Content property in an embed
builder
.WithTitle("Tip List")
.WithDescription("Here are the tips for your keywords:");
foreach (var tip in tips)
{
builder.AddField(tip.Keywords.Count == 1 ? tip.Keywords[0] : "Multiple Keywords", tip.Content);
}
}

var attachments = tips
.Where(tip => tip.ImagePaths != null && tip.ImagePaths.Any())
.SelectMany(tip => tip.ImagePaths)
.Select(imagePath => new FileAttachment(TipService.GetTipPath(imagePath)))
.ToList();

if (attachments.Count > 0)
{
if (isAnyTextTips)
{
await Context.Channel.SendFilesAsync(attachments, embed: builder.Build());
}
else
{
await Context.Channel.SendFilesAsync(attachments);
}
}
else
{
await ReplyAsync(embed: builder.Build());
}

var ids = string.Join(" ", tips.Select(t => t.Id.ToString()).ToArray());
await ReplyAsync($"-# Tip ID {ids}");
await Context.Message.DeleteAsync();
}

[Command("AddTip")]
[Summary("Add a tip to the database.")]
[RequireModerator]
public async Task AddTip(string keywords, string content = "")
{
await TipService.AddTip(Context.Message, keywords, content);
}

[Command("RemoveTip")]
[Summary("Remove a tip from the database.")]
[RequireModerator]
public async Task RemoveTip(ulong tipId)
{
Tip tip = TipService.GetTip(tipId);
if (tip == null)
{
await Context.Channel.SendMessageAsync("No such tip found to be removed.");
return;
}

await TipService.RemoveTip(Context.Message, tip);
}

[Command("ReplaceTip")]
[Summary("Replace image content of an existing tip in the database.")]
[RequireModerator]
public async Task ReplaceTip(ulong tipId, string content = "")
{
Tip tip = TipService.GetTip(tipId);
if (tip == null)
{
await Context.Channel.SendMessageAsync("No such tip found to be replaced.");
return;
}

await TipService.ReplaceTip(Context.Message, tip, content);
}

[Command("DumpTips")]
[Summary("For debugging, view the tip index.")]
[RequireModerator]
public async Task DumpTipDatabase()
{
string json = TipService.DumpTipDatabase();
string prefix = "Tip database index as JSON:\n";
int chunkSize = 1800;
int chunkTime = 2000;
while (!string.IsNullOrEmpty(json))
{
string chunk = json;
if (json.Length > chunkSize)
{
chunk = json.Substring(0, chunkSize);
json = json.Substring(chunkSize);
}
else
{
json = string.Empty;
}
await Context.Channel.SendMessageAsync(
$"{prefix}```\n{chunk}\n```");
prefix = string.Empty;
if (!string.IsNullOrEmpty(json))
await Task.Delay(chunkTime);
}
}

[Command("ListTips")]
[Summary("List available tips by their keywords.")]
[RequireModerator]
public async Task ListTips()
{
List<Tip> tips = TipService.GetAllTips().OrderBy(t => t.Id).ToList();
int chunkCount = 10;
int chunkTime = 2000;
bool first = true;

while (tips.Count > 0)
{
var builder = new EmbedBuilder();
if (first)
{
builder
.WithTitle("List of Tips")
.WithDescription("Tips available for the following keywords:");
first = false;
}

int chunk = 0;
while (tips.Count > 0 && chunk < chunkCount)
{
string keywords = string.Join("`, `", tips[0].Keywords.OrderBy(k => k));
string images = String.Concat(
Enumerable.Repeat(" :frame_photo:",
tips[0].ImagePaths.Count).ToArray());
builder.AddField($"ID: {tips[0].Id} {images}", $"`{keywords}`");
tips.RemoveAt(0);
chunk++;
}

await ReplyAsync(embed: builder.Build());
if (tips.Count > 0)
await Task.Delay(chunkTime);
}
}

#region CommandList
[Command("TipHelp")]
[Alias("TipsHelp")]
[Summary("Shows available tip database commands.")]
public async Task TipHelp()
{
// NOTE: skips the RequireModerator commands, so nearly an empty list
foreach (var message in CommandHandlingService.GetCommandListMessages("TipModule", true, true, false))
{
await ReplyAsync(message);
}
}
#endregion

}
4 changes: 3 additions & 1 deletion DiscordBot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Discord.WebSocket;
using DiscordBot.Service;
using DiscordBot.Services;
using DiscordBot.Services.Tips;
using DiscordBot.Settings;
using DiscordBot.Utils;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -104,6 +105,7 @@ private IServiceProvider ConfigureServices() =>
.AddSingleton<ReminderService>()
.AddSingleton<WeatherService>()
.AddSingleton<AirportService>()
.AddSingleton<TipService>()
.AddSingleton<CannedResponseService>()
.AddSingleton<UserExtendedService>()
.BuildServiceProvider();
Expand All @@ -114,4 +116,4 @@ private static void DeserializeSettings()
_rules = SerializeUtil.DeserializeFile<Rules>(@"Settings/Rules.json");
_userSettings = SerializeUtil.DeserializeFile<UserSettings>(@"Settings/UserSettings.json");
}
}
}
11 changes: 11 additions & 0 deletions DiscordBot/Services/Tips/Components/Tip.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Discord;

namespace DiscordBot.Services.Tips.Components;

public class Tip: IEntity<ulong>
{
public ulong Id { get; set; }
public string Content { get; set; }
public List<string> Keywords { get; set; }
public List<string> ImagePaths { get; set; }
}
Loading
Loading