diff --git a/Budet-cho-bot/Budet-cho-bot.csproj b/Budet-cho-bot/Budet-cho-bot.csproj
index c7bc99f..ce10f7f 100644
--- a/Budet-cho-bot/Budet-cho-bot.csproj
+++ b/Budet-cho-bot/Budet-cho-bot.csproj
@@ -20,4 +20,9 @@
+
+
+
+
+
diff --git a/Budet-cho-bot/Helpers/Utility.cs b/Budet-cho-bot/Helpers/Utility.cs
new file mode 100644
index 0000000..32ff826
--- /dev/null
+++ b/Budet-cho-bot/Helpers/Utility.cs
@@ -0,0 +1,58 @@
+using Budet_cho_bot.Models;
+using Newtonsoft.Json.Linq;
+using System.Linq;
+
+namespace Budet_cho_bot.Helpers;
+
+public static class Utility
+{
+ public static DateTime ParseDate(string message)
+ {
+ if (TimeSpan.TryParse(message, out var parsedTime) == false)
+ {
+ throw new ArgumentException("Хуйня твоё время");
+ }
+
+ var today = DateTime.Today; //returns xx/xx/xxxx 00:00:00, so adding time span would set correct daate
+ var date = today + parsedTime;
+ return date;
+ }
+
+ public static TimeSpan DeserializeTime(string token)
+ {
+ return Newtonsoft.Json.JsonConvert.DeserializeObject(token);
+ }
+
+ public static string PackTimetableIntoString(CronRecord[] timetable)
+ {
+ return string.Join(';', timetable.Select(x =>
+ {
+ var unixRunTime = x.LastRun.ToUniversalTime().ToUnixTimeSeconds();
+ var secondsPeriod = (int)(x.Period.TotalSeconds);
+ return $"{unixRunTime}:{secondsPeriod}:{x.IsOneShot}";
+ }));
+ }
+
+ public static CronRecord[] UnpackTimetableFromString(string timetable)
+ {
+ if(timetable == null)
+ {
+ return new CronRecord[0];
+ }
+
+ return timetable.Split(';').Select(x =>
+ {
+ var record = x.Split(':'); //crude but whatever
+ var lastRun = DateTimeOffset.FromUnixTimeSeconds(long.Parse(record[0]));
+ var period = TimeSpan.FromSeconds(long.Parse(record[1]));
+ bool oneShot = bool.Parse(record[2]);
+
+ return new CronRecord()
+ {
+ LastRun = lastRun,
+ Period = period,
+ IsOneShot = oneShot
+ };
+ }).ToArray();
+ }
+}
\ No newline at end of file
diff --git a/Budet-cho-bot/Models/CronRecord.cs b/Budet-cho-bot/Models/CronRecord.cs
new file mode 100644
index 0000000..8292fd1
--- /dev/null
+++ b/Budet-cho-bot/Models/CronRecord.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Budet_cho_bot.Models
+{
+ public class CronRecord
+ {
+ public DateTimeOffset LastRun { set; get; }
+ public TimeSpan Period { set; get; }
+ public bool IsOneShot { set; get; }
+ }
+}
diff --git a/Budet-cho-bot/Modules/ExampleModule.cs b/Budet-cho-bot/Modules/ExampleModule.cs
deleted file mode 100644
index 70bad4b..0000000
--- a/Budet-cho-bot/Modules/ExampleModule.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-using Discord.Commands;
-using Discord.WebSocket;
-using System;
-using System.Threading.Tasks;
-using Discord;
-
-namespace Discord_Bot
-{
- public class ExampleModule : ModuleBase
- {
- // .say hello world -> hello world
- [Command("say")]
- [Summary("Echoes a message.")]
- public async Task SayAsync([Remainder] [Summary("The text to echo")] string echo)
- {
- RemoveLastUserMessage();
- await ReplyAsync(echo);
- }
- private async void RemoveLastUserMessage()
- {
- var channel = Context.Channel as SocketTextChannel;
- var items = await channel.GetMessagesAsync(1).FlattenAsync();
- await channel.DeleteMessagesAsync(items);
- }
-
- [Command("hello")] // Command name.
- [Summary("Say hello to the bot.")] // Command summary.
- public async Task Hello()
- => await ReplyAsync($"Hello there, **{Context.User.Username}**!");
-
- [Command("pick")]
- [Alias("choose")] // Aliases that will also trigger the command.
- [Summary("Pick something.")]
- public async Task Pick([Remainder]string message = "")
- {
- string[] options = message.Split(new string[] { " or " }, StringSplitOptions.RemoveEmptyEntries);
- string selection = options[new Random().Next(options.Length)];
-
- // ReplyAsync() is a shortcut for Context.Channel.SendMessageAsync()
- await ReplyAsync($"I choose **{selection}**");
- }
-
- [Command("cookie")]
- [Summary("Give someone a cookie.")]
- public async Task Cookie(SocketGuildUser user)
- {
- if (Context.Message.Author.Id == user.Id)
- await ReplyAsync($"{Context.User.Mention} doesn't have anyone to share a cookie with... :(");
- else
- await ReplyAsync($"{Context.User.Mention} shared a cookie with **{user.Username}** :cookie:");
- }
-
- [Command("amiadmin")]
- [Summary("Check your administrator status")]
- public async Task AmIAdmin()
- {
- if ((Context.User as SocketGuildUser).GuildPermissions.Administrator)
- await ReplyAsync($"Yes, **{Context.User.Username}**, you're an admin!");
- else
- await ReplyAsync($"No, **{Context.User.Username}**, you're **not** an admin!");
- }
-
- [Command("kick")]
- [Summary("Kick a user from the server.")]
- [RequireBotPermission(GuildPermission.KickMembers)]
- [RequireUserPermission(GuildPermission.KickMembers)]
- public async Task Kick(SocketGuildUser targetUser, [Remainder]string reason = "No reason provided.")
- {
- await targetUser.KickAsync(reason);
- await ReplyAsync($"**{targetUser}** has been kicked. Bye bye :wave:");
- }
-
- [Command("ban")]
- [Summary("Ban a user from the server")]
- [RequireUserPermission(GuildPermission.BanMembers)]
- [RequireBotPermission(GuildPermission.BanMembers)]
- public async Task Ban(SocketGuildUser targetUser, [Remainder]string reason = "No reason provided.")
- {
- await Context.Guild.AddBanAsync(targetUser.Id, 0, reason);
- await ReplyAsync($"**{targetUser}** has been banned. Bye bye :wave:");
- }
-
- [Command("unban")]
- [Summary("Unban a user from the server")]
- [RequireBotPermission(GuildPermission.BanMembers)]
- [RequireUserPermission(GuildPermission.BanMembers)]
- public async Task Unban(ulong targetUser)
- {
- await Context.Guild.RemoveBanAsync(targetUser);
- await Context.Channel.SendMessageAsync($"The user has been unbanned :clap:");
- }
-
- [Command("purge")]
- [Summary("Bulk deletes messages in chat")]
- [RequireBotPermission(GuildPermission.ManageMessages)]
- [RequireUserPermission(GuildPermission.ManageMessages)]
- public async Task Purge(int delNumber)
- {
- var channel = Context.Channel as SocketTextChannel;
- var items = await channel.GetMessagesAsync(delNumber + 1).FlattenAsync();
- await channel.DeleteMessagesAsync(items);
- }
-
- [Command("reloadconfig")]
- [Summary("Reloads the config and applies changes")]
- [RequireOwner] // Require the bot owner to execute the command successfully.
- public async Task ReloadConfig()
- {
- await Functions.SetBotStatusAsync(Context.Client);
- await ReplyAsync("Reloaded!");
- }
-
- [Command("ping")]
- [Summary("Show current latency.")]
- public async Task Ping()
- => await ReplyAsync($"Latency: {Context.Client.Latency} ms");
-
- [Command("avatar")]
- [Alias("getavatar")]
- [Summary("Get a user's avatar.")]
- public async Task GetAvatar([Remainder]SocketGuildUser user = null)
- => await ReplyAsync($":frame_photo: **{(user ?? Context.User as SocketGuildUser).Username}**'s avatar\n{Functions.GetAvatarUrl(user)}");
-
-
- [Command("info")]
- [Alias("server", "serverinfo")]
- [Summary("Show server information.")]
- [RequireBotPermission(GuildPermission.EmbedLinks)] // Require the bot the have the 'Embed Links' permissions to execute this command.
- public async Task ServerEmbed()
- {
- double botPercentage = Math.Round(Context.Guild.Users.Count(x => x.IsBot) / Context.Guild.MemberCount * 100d, 2);
-
- EmbedBuilder embed = new EmbedBuilder()
- .WithColor(0, 225, 225)
- .WithDescription(
- $"🏷️\n**Guild name:** {Context.Guild.Name}\n" +
- $"**Guild ID:** {Context.Guild.Id}\n" +
- $"**Created at:** {Context.Guild.CreatedAt:dd/M/yyyy}\n" +
- $"**Owner:** {Context.Guild.Owner}\n\n" +
- $"💬\n" +
- $"**Users:** {Context.Guild.MemberCount - Context.Guild.Users.Count(x => x.IsBot)}\n" +
- $"**Bots:** {Context.Guild.Users.Count(x => x.IsBot)} [ {botPercentage}% ]\n" +
- $"**Channels:** {Context.Guild.Channels.Count}\n" +
- $"**Roles:** {Context.Guild.Roles.Count}\n" +
- $"**Emotes: ** {Context.Guild.Emotes.Count}\n\n" +
- $"🌎 **Region:** {Context.Guild.VoiceRegionId}\n\n" +
- $"🔒 **Security level:** {Context.Guild.VerificationLevel}")
- .WithImageUrl(Context.Guild.IconUrl);
-
- await ReplyAsync($":information_source: Server info for **{Context.Guild.Name}**", embed: embed.Build());
- }
-
- [Command("role")]
- [Alias("roleinfo")]
- [Summary("Show information about a role.")]
- public async Task RoleInfo([Remainder]SocketRole role)
- {
- // Just in case someone tries to be funny.
- if (role.Id == Context.Guild.EveryoneRole.Id)
- return;
-
- await ReplyAsync(
- $":flower_playing_cards: **{role.Name}** information```ini" +
- $"\n[Members] {role.Members.Count()}" +
- $"\n[Role ID] {role.Id}" +
- $"\n[Hoisted status] {role.IsHoisted}" +
- $"\n[Created at] {role.CreatedAt:dd/M/yyyy}" +
- $"\n[Hierarchy position] {role.Position}" +
- $"\n[Color Hex] {role.Color}```");
- }
-
- // Please don't remove this command. I will appreciate it a lot <3
- [Command("source")]
- [Alias("sourcecode", "src")]
- [Summary("Link the source code used for this bot.")]
- public async Task Source()
- => await ReplyAsync($":heart: **{Context.Client.CurrentUser}** is based on this source code:\nhttps://github.com/VACEfron/Discord-Bot-Csharp");
- }
-}
diff --git a/Budet-cho-bot/Modules/ReminderModule.cs b/Budet-cho-bot/Modules/ReminderModule.cs
index 9a8298e..7ab6e30 100644
--- a/Budet-cho-bot/Modules/ReminderModule.cs
+++ b/Budet-cho-bot/Modules/ReminderModule.cs
@@ -1,76 +1,69 @@
-using Discord.Commands;
+using Budet_cho_bot.Helpers;
+using Budet_cho_bot.Models;
+using Budet_cho_bot.Services;
+using Discord.Commands;
using Discord.Commands.Builders;
using Newtonsoft.Json.Linq;
+using System.Text;
namespace Discord_Bot
{
public class ReminderModule : ModuleBase
{
- private const long DAY_PERIOD = 24 * 60 * 60 * 1000; // 10 * 1000; //
- private Timer reminderTimer;
+ private ReminderService _reminderService = new ReminderService();
protected override void OnModuleBuilding(CommandService commandService, ModuleBuilder builder)
{
base.OnModuleBuilding(commandService, builder);
Console.WriteLine($"{DateTime.Now.TimeOfDay:hh\\:mm\\:ss} | hello world ");
- ReloadTimers();
}
- [Command("remindertime")]
- private async Task SetReminderTime([Remainder]string message = "")
+ [Command("remind")]
+ public async Task CreateTask(string users, DateTime startsAt, string? repeat)
{
- SaveToConfig("reminderTime", Utility.ParseMessage(message));
- ReloadTimers();
- await ReplyAsync($"Заебись");
+ bool oneShot = repeat == null;
+ var now = DateTime.Now;
+ TimeSpan rep;
+ TimeSpan.TryParse(repeat, out rep);
+
+ var record = new CronRecord()
+ {
+ Period = oneShot ? startsAt - now : rep,
+ LastRun = oneShot ? now : startsAt,
+ IsOneShot = oneShot
+ };
+ var created = await _reminderService.CreateTask(record);
+ await ReplyAsync($"Заебись: {created}");
}
[Command("sequence")]
- private async Task SetSequence([Remainder]string message = "")
+ private async Task SetSequence(string message = "")
{
- SaveToConfig("sequence", message);
+ //_reminderService.SaveToConfig("sequence", message);
await ReplyAsync($"Заебись");
}
[Command("users")]
private async Task Users([Remainder]string message = "")
{
- SaveToConfig("users", message);
+ //_reminderService.SaveToConfig("users", message);
await ReplyAsync($"Заебись");
}
-
- private void ReloadTimers()
+
+ [Command("list")]
+ private async Task List()
{
- var time = Functions.GetConfigItem("reminderTime");
- if (time.Type == JTokenType.Boolean)
- return;
-
- var nextReminder = Utility.ParseTime(time.ToString());
- var now = DateTime.Now;
-
- var span = (nextReminder - now).TotalMilliseconds;
- if (span < 0)
+ var cron = await _reminderService.GetTasks();
+ var sb = new StringBuilder();
+ sb.AppendLine("Last Run | Period | Is one shot");
+ sb.AppendLine("-------------------------------");
+ foreach (var cr in cron)
{
- // skip to next day
- nextReminder = nextReminder.AddDays(1);
- span = (nextReminder - now).TotalMilliseconds;
+ sb.AppendLine($"{cr.LastRun.ToString("o")} | {cr.Period.ToString("c")} | {cr.IsOneShot}");
}
-
- reminderTimer = new Timer(SendReminder, "sd", (long)span, DAY_PERIOD);
- }
+ sb.AppendLine("-------------------------------");
- private async void SendReminder(object? state)
- {
- //check sequence
-
- var users = Functions.GetConfigItem("users").ToString();
- await ReplyAsync($"{users}\nБудет чо?");
- }
-
- private void SaveToConfig(string key, string data)
- {
- var config = Functions.GetConfig();
- config[key] = data;
- Functions.SaveConfig(config);
+ await ReplyAsync(sb.ToString());
}
}
}
\ No newline at end of file
diff --git a/Budet-cho-bot/Repositories/CronRepository.cs b/Budet-cho-bot/Repositories/CronRepository.cs
new file mode 100644
index 0000000..bfc71d9
--- /dev/null
+++ b/Budet-cho-bot/Repositories/CronRepository.cs
@@ -0,0 +1,33 @@
+using Budet_cho_bot.Helpers;
+using Discord_Bot;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Budet_cho_bot.Repositories
+{
+ public class CronRepository
+ {
+ public async Task SetCronTask(string taskType, string task)
+ {
+ var config = Functions.GetConfig();
+ config[taskType] = task;
+ Functions.SaveConfig(config);
+
+ return 1;
+ }
+
+ public async Task GetCronTask(string taskType)
+ {
+ var config = Functions.GetConfig();
+ if (config.TryGetValue(taskType, out var tasks))
+ {
+ return tasks.ToString();
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Budet-cho-bot/Services/ReminderService.cs b/Budet-cho-bot/Services/ReminderService.cs
new file mode 100644
index 0000000..01d10bb
--- /dev/null
+++ b/Budet-cho-bot/Services/ReminderService.cs
@@ -0,0 +1,44 @@
+using Budet_cho_bot.Helpers;
+using Budet_cho_bot.Models;
+using Budet_cho_bot.Repositories;
+using Discord;
+using Discord_Bot;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Budet_cho_bot.Services
+{
+ internal class ReminderService
+ {
+ private readonly CronRepository _cronRepository = new CronRepository();
+ private const long DAY_PERIOD = 24 * 60 * 60 * 1000; // 10 * 1000; //
+ private Timer reminderTimer;
+
+
+ public async void SendReminder(object? state)
+ {
+ var users = Functions.GetConfigItem("users").ToString();
+ //await ReplyAsync($"{users}\nБудет чо?");
+ }
+
+ public async Task CreateTask(CronRecord record)
+ {
+ var cron = await _cronRepository.GetCronTask("reminder");
+ var cronUnpacked = Utility.UnpackTimetableFromString(cron);
+
+ var result = await _cronRepository.SetCronTask("reminder", Utility.PackTimetableIntoString(cronUnpacked.Append(record).ToArray()));
+ return result;
+ }
+
+ public async Task GetTasks()
+ {
+ var cron = await _cronRepository.GetCronTask("reminder");
+ var cronUnpacked = Utility.UnpackTimetableFromString(cron);
+ return cronUnpacked;
+ }
+ }
+}
diff --git a/Budet-cho-bot/Utility.cs b/Budet-cho-bot/Utility.cs
deleted file mode 100644
index f039f46..0000000
--- a/Budet-cho-bot/Utility.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using Newtonsoft.Json.Linq;
-
-namespace Discord_Bot;
-
-public static class Utility
-{
- public static string ParseMessage(string message)
- {
- var time = message.Split(":");
- if (time.Length != 2)
- {
- throw new ArgumentException("Время неправильное. Хуйня твоё время");
- return null;
- }
-
- var now = DateTime.Now;
- var date = new DateTime(now.Year, now.Month, now.Day, int.Parse(time[0]), int.Parse(time[1]), 0);
- return Newtonsoft.Json.JsonConvert.SerializeObject(date);
- }
-
- public static DateTime ParseTime(string token)
- {
- return Newtonsoft.Json.JsonConvert.DeserializeObject(token);
- }
-}
\ No newline at end of file