Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added Assets/datetimemessagehelp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
702 changes: 702 additions & 0 deletions Assets/datetimemessagehelp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion COMMANDS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# List of commands (74 total)
# List of commands (77 total)

## Main (7)
Stuff to do with the bot and other random stuff.
Expand Down Expand Up @@ -124,6 +124,15 @@ For having a bit of fun.
|`!wow games verbal-memory`|Try remember as many words as you can.|
|`!wow games verbal-memory-leaderboard [optional:PAGE]`|Shows the leaderboard for the counting game.|

## Events (3)
Create and organise events for you and your friends.

|Command|Summary|
|---|---|
|`!wow events new [optional:DESCRIPTION]`|Create a new event.|
|`!wow events delete`|Delete an upcoming event.|
|`!wow events set-announcements-channel [CHANNEL]`|Sets the channel that event notifications will be sent to.|

## Developer (10)
Boring stuff for developers.

Expand Down
9 changes: 8 additions & 1 deletion wow2.Bot/BotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using wow2.Bot.Data;
using wow2.Bot.Extensions;
using wow2.Bot.Modules;
using wow2.Bot.Modules.Events;
using wow2.Bot.Modules.Games.Counting;
using wow2.Bot.Modules.Games.VerbalMemory;
using wow2.Bot.Modules.Keywords;
Expand Down Expand Up @@ -207,7 +208,13 @@ public static async Task ReactionAddedAsync(Cacheable<IUserMessage, ulong> cache
{
if (!await ResponseMessage.ActOnReactionAddedAsync(reaction))
{
await QuestionMessage.ActOnReactionAsync(reaction);
if (!await QuestionMessage.ActOnReactionAsync(reaction))
{
if (!await DateTimeSelectorMessage.ActOnReactionAsync(reaction))
{
await EventMessage.ActOnReactionAddedAsync(reaction);
}
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions wow2.Bot/Data/GuildData.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Text.Json.Serialization;
using wow2.Bot.Modules.Events;
using wow2.Bot.Modules.Games;
using wow2.Bot.Modules.Keywords;
using wow2.Bot.Modules.Main;
Expand All @@ -26,6 +27,9 @@ public class GuildData
[JsonIgnore]
public List<QuestionMessage> QuestionMessages { get; set; } = new();

[JsonIgnore]
public List<DateTimeSelectorMessage> DateTimeSelectorMessages { get; set; } = new();

public MainModuleConfig Main { get; set; } = new();

public KeywordsModuleConfig Keywords { get; set; } = new();
Expand All @@ -41,5 +45,7 @@ public class GuildData
public YouTubeModuleConfig YouTube { get; set; } = new();

public TimersModuleConfig Timers { get; set; } = new();

public EventsModuleConfig Events { get; set; } = new();
}
}
9 changes: 9 additions & 0 deletions wow2.Bot/Modules/Dev/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Discord;
using Discord.Commands;
using wow2.Bot.Data;
using wow2.Bot.Modules.Events;
using wow2.Bot.Modules.Keywords;
using wow2.Bot.Modules.Main;
using wow2.Bot.Modules.Voice;
Expand Down Expand Up @@ -73,6 +74,14 @@ public static async Task QuestionMessageTest(SocketCommandContext context)
.SendAsync(context.Channel);
}

[Test("date-time-message")]
public static async Task DateTimeMessageTeset(SocketCommandContext context)
{
await new DateTimeSelectorMessage(
(d) => context.Channel.SendMessageAsync($"DateTime: {d}"))
.SendAsync(context.Channel);
}

[Test("aliases")]
public static async Task AliasesTest(SocketCommandContext context)
{
Expand Down
16 changes: 16 additions & 0 deletions wow2.Bot/Modules/Events/Event.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;

namespace wow2.Bot.Modules.Events
{
public class Event
{
public string Description { get; set; }

public DateTime ForDateTime { get; set; }

public string CreatedByMention { get; set; }

public List<string> AttendeeMentions { get; set; } = new();
}
}
95 changes: 95 additions & 0 deletions wow2.Bot/Modules/Events/EventMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using wow2.Bot.Data;
using wow2.Bot.Extensions;
using wow2.Bot.Verbose.Messages;

namespace wow2.Bot.Modules.Events
{
public class EventMessage : Message
{
public static readonly IEmote AttendEmote = new Emoji("👌");
public static readonly IEmote EditEmote = new Emoji("✏");

public EventMessage()
{
}

public EventMessage(Event @event)
{
Event = @event;
}

public Event Event { get; set; }

public static async Task<bool> ActOnReactionAddedAsync(SocketReaction reaction)
{
EventsModuleConfig config = DataManager.AllGuildData[reaction.Channel.GetGuild().Id].Events;
EventMessage message = config.EventMessages.Find(m => m.SentMessage.Id == reaction.MessageId);

if (message == null)
return false;

if (reaction.Emote.Name == AttendEmote.Name)
{
message.Event.AttendeeMentions.Add(reaction.User.Value.Mention);
await message.UpdateMessageAsync();
}
else if (reaction.Emote.Name == EditEmote.Name)
{
IUserMessage sentMessage = await new DateTimeSelectorMessage(
async d =>
{
message.Event.ForDateTime = d;
await message.UpdateMessageAsync();
},
"Select the new date and time for this event.")
.SendAsync(reaction.Channel);

await message.SentMessage.RemoveReactionAsync(EditEmote, reaction.User.Value);
}
else
{
return false;
}

return true;
}

public async override Task<IUserMessage> SendAsync(IMessageChannel channel)
{
await UpdateMessageAsync();

IUserMessage message = await base.SendAsync(channel);
List<EventMessage> eventMessages = DataManager.AllGuildData[message.GetGuild().Id].Events.EventMessages;

eventMessages.Truncate(30);
eventMessages.Add(this);

await message.AddReactionsAsync(
new IEmote[] { AttendEmote, EditEmote });

return message;
}

public async Task UpdateMessageAsync()
{
EmbedBuilder = new EmbedBuilder()
{
Title = $"📋 {Event.Description}",
Description = $"{Event.AttendeeMentions.Count} people are attending on `{Event.ForDateTime}`",
Footer = new EmbedFooterBuilder()
{
Text = $"Want to attend this event? React with {AttendEmote.Name}",
},
Color = Color.LightGrey,
};

if (SentMessage != null)
await SentMessage.ModifyAsync(m => m.Embed = Embed);
}
}
}
71 changes: 71 additions & 0 deletions wow2.Bot/Modules/Events/EventsModule.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.WebSocket;
using wow2.Bot.Data;
using wow2.Bot.Extensions;
using wow2.Bot.Verbose.Messages;

namespace wow2.Bot.Modules.Events
{
[Name("Events")]
[Group("events")]
[Alias("event")]
[Summary("Create and organise events for you and your friends.")]
public class EventsModule : Module
{
private EventsModuleConfig Config => DataManager.AllGuildData[Context.Guild.Id].Events;

[Command("new")]
[Alias("start", "create", "add")]
[Summary("Create a new event.")]
public async Task NewAsync([Remainder] string description = "untitled event")
{
if (Config.AnnouncementsChannelId == default)
{
throw new CommandReturnException(
Context,
$"You can do this be using `{Context.Guild.GetCommandPrefix()} events set-announcements-channel`",
"Set an announcements channel first");
}

await new DateTimeSelectorMessage(
async d =>
{
var @event = new Event()
{
Description = description,
ForDateTime = d,
CreatedByMention = Context.User.Mention,
};

Config.Events.Add(@event);
await new EventMessage(@event)
.SendAsync((IMessageChannel)BotService.Client.GetChannel(Config.AnnouncementsChannelId));
},
"Select a date and time for this event.")
.SendAsync(Context.Channel);
}

[Command("delete")]
[Alias("remove", "stop")]
[Summary("Delete an upcoming event.")]
public async Task DeleteAsync()
{
throw new NotImplementedException();
}

[Command("set-announcements-channel")]
[Alias("set-channel", "announcements-channel", "channel")]
[Summary("Sets the channel that event notifications will be sent to.")]
public async Task SetAnnouncementsChannelAsync(SocketTextChannel channel)
{
Config.AnnouncementsChannelId = channel.Id;
await DataManager.SaveGuildDataToFileAsync(Context.Guild.Id);

await new SuccessMessage($"You'll get notified about events in {channel.Mention}")
.SendAsync(Context.Channel);
}
}
}
13 changes: 13 additions & 0 deletions wow2.Bot/Modules/Events/EventsModuleConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.Collections.Generic;

namespace wow2.Bot.Modules.Events
{
public class EventsModuleConfig
{
public List<Event> Events { get; set; } = new();

public List<EventMessage> EventMessages { get; set; } = new();

public ulong AnnouncementsChannelId { get; set; }
}
}
101 changes: 101 additions & 0 deletions wow2.Bot/Verbose/Messages/DateTimeSelectorMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using wow2.Bot.Data;
using wow2.Bot.Extensions;

namespace wow2.Bot.Verbose.Messages
{
public class DateTimeSelectorMessage : Message
{
public const string ConfirmChar = "✅";

public static readonly IReadOnlyDictionary<IEmote, TimeSpan> DateTimeModifierEmotes = new Dictionary<IEmote, TimeSpan>()
{
{ new Emoji("⏫"), TimeSpan.FromDays(7) },
{ new Emoji("⏬"), TimeSpan.FromDays(-7) },
{ new Emoji("🔼"), TimeSpan.FromDays(1) },
{ new Emoji("🔽"), TimeSpan.FromDays(-1) },
{ new Emoji("⏩"), TimeSpan.FromHours(1) },
{ new Emoji("⏪"), TimeSpan.FromHours(-1) },
{ new Emoji("▶"), TimeSpan.FromMinutes(10) },
{ new Emoji("◀"), TimeSpan.FromMinutes(-10) },
};

public DateTimeSelectorMessage(Func<DateTime, Task> confirmFunc, string description = "Select a date and time.")
{
EmbedBuilder = new EmbedBuilder()
{
Description = "Give me a second to add reactions...",
Color = Color.LightGrey,
};
Description = description;
ConfirmFunc = confirmFunc;
}

public DateTime DateTime { get; set; } = DateTime.Now;

private string Description { get; }

private Func<DateTime, Task> ConfirmFunc { get; }

public static async Task<bool> ActOnReactionAsync(SocketReaction reaction)
{
GuildData guildData = DataManager.AllGuildData[reaction.Channel.GetGuild().Id];
DateTimeSelectorMessage message = guildData.DateTimeSelectorMessages.Find(m => m.SentMessage.Id == reaction.MessageId);

if (message == null)
return false;

if (reaction.Emote.Name == ConfirmChar)
{
guildData.DateTimeSelectorMessages.Remove(message);
await message.SentMessage.RemoveAllReactionsAsync();
await message.ConfirmFunc.Invoke(message.DateTime);
return true;
}
else if (DateTimeModifierEmotes.Any(p => p.Key.Name == reaction.Emote.Name))
{
await message.SentMessage.RemoveReactionAsync(reaction.Emote, reaction.User.Value);
message.DateTime += DateTimeModifierEmotes[reaction.Emote];
await message.UpdateMessageAsync();
return true;
}
else
{
return false;
}
}

public async override Task<IUserMessage> SendAsync(IMessageChannel channel)
{
IUserMessage message = await base.SendAsync(channel);
List<DateTimeSelectorMessage> dateTimeSelectorMessages = DataManager
.AllGuildData[message.GetGuild().Id].DateTimeSelectorMessages;

await message.AddReactionsAsync(
DateTimeModifierEmotes.Keys.Append(new Emoji(ConfirmChar)).ToArray());

dateTimeSelectorMessages.Truncate(12);
dateTimeSelectorMessages.Add(this);
await UpdateMessageAsync();

return message;
}

private async Task UpdateMessageAsync()
{
EmbedBuilder = new EmbedBuilder()
{
Description = $"{new Emoji($"<:wowquestion:{QuestionEmoteId}>")} {Description}\n`{DateTime}`",
ImageUrl = "https://github.com/rednir/wow2/blob/master/Assets/datetimemessagehelp.png",
Color = new Color(0x9b59b6),
};

await SentMessage?.ModifyAsync(m => m.Embed = Embed);
}
}
}