From 6885d6b6b9d27dba82b1799dba6d9067f3dff28f Mon Sep 17 00:00:00 2001 From: amki Date: Thu, 17 Oct 2019 04:23:13 +0200 Subject: [PATCH] First try of actually working code --- DiscoBot/615631052047908870-calendar.db | Bin 0 -> 28672 bytes DiscoBot/615631052047908870-gsmeet.db | Bin 0 -> 32768 bytes DiscoBot/615631052047908870-gsmeet.db-shm | Bin 0 -> 32768 bytes DiscoBot/615631052047908870-gsmeet.db-wal | Bin 0 -> 4152 bytes DiscoBot/615631052047908870-rss.db | Bin 0 -> 12288 bytes DiscoBot/98293701175955456-gsmeet.db | Bin 32768 -> 32768 bytes DiscoBot/98293701175955456-gsmeet.db-shm | Bin 0 -> 32768 bytes DiscoBot/98293701175955456-gsmeet.db-wal | 0 DiscoBot/98293701175955456-rss.db | Bin 20480 -> 20480 bytes DiscoBot/gsmeet/GSMeet.cs | 209 +++++++++------------- DiscoBot/gsmeet/GSMeetContext.cs | 54 +++--- DiscoBot/gsmeet/GSMeetingTimers.cs | 95 ++++++++++ 12 files changed, 197 insertions(+), 161 deletions(-) create mode 100644 DiscoBot/615631052047908870-calendar.db create mode 100644 DiscoBot/615631052047908870-gsmeet.db create mode 100644 DiscoBot/615631052047908870-gsmeet.db-shm create mode 100644 DiscoBot/615631052047908870-gsmeet.db-wal create mode 100644 DiscoBot/615631052047908870-rss.db create mode 100644 DiscoBot/98293701175955456-gsmeet.db-shm create mode 100644 DiscoBot/98293701175955456-gsmeet.db-wal create mode 100644 DiscoBot/gsmeet/GSMeetingTimers.cs diff --git a/DiscoBot/615631052047908870-calendar.db b/DiscoBot/615631052047908870-calendar.db new file mode 100644 index 0000000000000000000000000000000000000000..79be17730cc25f848083b391dcf8c88ab779fa6e GIT binary patch literal 28672 zcmeI(U2D@&9LMpb+ZtA#iU_?uLjP!P=gUur94x2J3~4XpghdW~__gZ7J+U z_;P$Pz67s5>9X3BwxbH(ly9IkkLTg@`=@X&dh))}O_cb2Ip{};cx^qg3I*$}5SC>X z^vBVkyKO`7tlu5zZ+mKg(Qd(dvDeztSBslJt;f$E{doB6!OPNjeZYnQ0tg_000Iag z@E-++uZm9j!@fOicjJ!w=AE6_qMnL7(ZEYoznUcJe*8%pr@hYno19u8tDzL0UzcaX zUA8e-G=1UDZ_*Vz#ucyQR)$YEoN{y99=@43=JVQ@D2`Qc(w;Hc;=MzheRg(i;}PY% za4Vzwx>MfYw{M;&(Z`;e^lm85Kf95QDXhM0$a^5RNG zO=Glrq**i5<2_h3USk@@LE7p;Gmze)Kc35Mk%&MZ$Uyovd18{L`K48q7F}I7q^{RM zYCEqMZj~w{Z_O!hZ`(JgGciujYJG8Jy8V9)YKeIKsIQ|5<=JiQcbQ}*zc`V4luVw> zN@nuxWxucDWO1vLc~95fQc31tr~L7p6lY&7Gf4CL{aLmO#q#d1-5w`-ebv*;+4F04 z^;PNLv)tjDk!SAWPOR1U^pllg*LKn-N1M0RVU8yE!&5NYbaPk#vP{gLmZ+4hJLC1s zC4YR`Q3G8V)4681=r1(Ktm;w# literal 0 HcmV?d00001 diff --git a/DiscoBot/615631052047908870-gsmeet.db b/DiscoBot/615631052047908870-gsmeet.db new file mode 100644 index 0000000000000000000000000000000000000000..32fb450bd2afb144a83c48f29120e166d5042590 GIT binary patch literal 32768 zcmeI(%}?5390%|gmHNiq#gN4;dD2~Ef+=WJ^fH78(+CAiopLf29)(Oxlp~*;bG#Fl35X)|inrA2cHs_$p&Muf$ zVLiKJT~X;dIdAb!qWsFp?bL`A-q;ZDVjXe!rOQL$eTPT8`tVkUuNI%wKZm|gBY%$l zQ-;?!fd3NTPt&3lo|_YI8(uWrtniW}(5u}_8Bf?{?*)SF>4(KTse50SG_<0uX=z1Rwwb2tWV=5cp35mMG1# zSHaf>-Kld-rGi?0%8X?=NZJ+ZQwh%YONwd8_ZVUo{Fc4Jsgeycf|X$D3PJ|3S8#;5NX&~8(%Ol9KOA>F z9#?z=T>8wSkj1;!p(jH%-L5L`*URCyJoU%?yxEuSYFj_jFaHm##)Q57ET8A8#nWUU zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!Cvi3xu02LVy4P0t5&UAV7cs0RjXF5FkK+009C7 u2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNCfTLLd6(I+1O literal 0 HcmV?d00001 diff --git a/DiscoBot/615631052047908870-gsmeet.db-wal b/DiscoBot/615631052047908870-gsmeet.db-wal new file mode 100644 index 0000000000000000000000000000000000000000..e5fedceb128d34ea9923c86fe814a1df3968e760 GIT binary patch literal 4152 zcmXr7XKP~6eI&uaAiw|u6VGzZ`aj)vQQpT3OHPVAcmRc%fS3a&Ug-3&ar2>b_Pjtr zM*c|*Kr{+QLtr!nMnhmU1V%$(Gz3ONU^E0qLtr!nMnhmU1V%$(Gz91t0y&KAqN$>6 zvi?DdnJI?h#TPGO@5SGSf3MG%+x;u+#=C0071I BGZFv* literal 0 HcmV?d00001 diff --git a/DiscoBot/615631052047908870-rss.db b/DiscoBot/615631052047908870-rss.db new file mode 100644 index 0000000000000000000000000000000000000000..89307fb92bc126fe5fa833bc94fe5cc9853df5ad GIT binary patch literal 12288 zcmeI#O-sWt7zgk)iprqdZaWnodQupQcowWB%2@4c*MU2Y=pq|#9j={t6+fKEeI1Xc zqv?+GJpO?s&C8RQUr*^j2Gd;8>tZ>VIbE?P5oIx&~?$?l{h1Rwwb2tWV=5P$##AOHaf{6pYtWgWL1$NIj`z{}fB*y_ w009U<00Izz00bbguL8B=VtD`W>+i+AAOHafKmY;|fB*y_009U<00J9SPilUFoglj7x{#~?A8HNcpKn~j@ov!K9iuFcn@POoT!2XxlSPz8EdR zWvF0iVP$M!WymynLX7O>Pf;S95?BNnftm|Un8o?UfqHNAO%|`e%_mrrT3o`xEXoL? FnE*;2DzpFq diff --git a/DiscoBot/98293701175955456-gsmeet.db-shm b/DiscoBot/98293701175955456-gsmeet.db-shm new file mode 100644 index 0000000000000000000000000000000000000000..fe9ac2845eca6fe6da8a63cd096d9cf9e24ece10 GIT binary patch literal 32768 zcmeIuAr62r3Wae_4CtBEqsjITB(Y_;MxG*d9Nv@$TWGBlX1U>(G5Xrf?bWMyJvWn?zF z);gWf&_EZc#K_pn*u=`fX!0lPe2|cVrGlZEm5HU5sm0`co5wIyj6tTv+9q%tnkyI> zSs7SbnV3yJVH*eL8v^xP8JJEsw5#F*$r}PCtqdk_wF`zSH#E00F`X=Ie+Q=B%*x1Q S^Dq0GTug>$o3DClvjPCyh%@E@ delta 193 zcmZozz}T>Wae_1>&qNt#MxKocTdlYa3>6H`txOE949q4gSO+t$k=%DC+mDZ19M#ia|Hu4D?=bMnw)R*7;1{Kv6ZRG zPuRwR`DRu|mR2UllMU^vxFEIy)tgM-Y8MQawy-j=v@$iHENp)VYMiO1m4VUbU-mb- Nm<$XzU-i;v1pu6OG9dr} diff --git a/DiscoBot/gsmeet/GSMeet.cs b/DiscoBot/gsmeet/GSMeet.cs index 7ba2ed5..fedbfba 100644 --- a/DiscoBot/gsmeet/GSMeet.cs +++ b/DiscoBot/gsmeet/GSMeet.cs @@ -4,7 +4,9 @@ using System.Globalization; using System.IO; using System.Linq; using System.Net.WebSockets; +using System.Security.Cryptography; using System.ServiceModel.Syndication; +using System.Text; using System.Threading.Tasks; using System.Timers; using System.Xml; @@ -30,6 +32,8 @@ namespace DiscoBot.gsmeet private static readonly string ApplicationName = "DiscoBot"; private SheetsService service; + private Dictionary meetingTimers = new Dictionary(); + public GSMeet(SocketGuild guild) @@ -49,21 +53,11 @@ namespace DiscoBot.gsmeet ApplicationName = ApplicationName }); - gsmeetContext.GSheets.Include(s => s.NotifiedEvents).Load(); - gsmeetContext.GSheets.Include(s => s.NotifiedUsers).Load(); - foreach (var f in gsmeetContext.GSheets) { - if(f.NotifiedUsers == null) - { - f.NotifiedUsers = new List(); - } - if(f.NotifiedEvents == null) - { - f.NotifiedEvents = new List(); - } - InitializeSheet(f); - HandleSheetCheck(f); + var gssheet = new GSSheet(f); + InitializeSheet(gssheet); + HandleSheetCheck(gssheet); } Commands.Add("gsmeetadd", HandleGSMeetAddCommand); @@ -72,21 +66,21 @@ namespace DiscoBot.gsmeet Commands.Add("gsmeetdebug", HandleGSMeetDebugCommand); } - private Task InitializeSheet(DBSheet sheet) + private Task InitializeSheet(GSSheet sheet) { - Console.WriteLine("Found sheet " + sheet.Name); - Timer timer = new Timer(sheet.CheckInterval.TotalMilliseconds); + Console.WriteLine("Found sheet " + sheet.Db.Name); + Timer timer = new Timer(sheet.Db.CheckInterval.TotalMilliseconds); timer.AutoReset = true; timer.Elapsed += async (sender, e) => { await Task.Run(() => HandleSheetCheck(sheet)); }; timer.Start(); - timers.Add(sheet.Name, timer); + timers.Add(sheet.Db.Name, timer); return Task.CompletedTask; } - private Task DeinitializeSheets(DBSheet sheet) + private Task DeinitializeSheets(GSSheet sheet) { /* Timer t = timers[feed.Name]; @@ -96,125 +90,103 @@ namespace DiscoBot.gsmeet return Task.CompletedTask; } - private Task ParseGSMeetSheet(GSMeetSheetData sheetData, IList> values) + private GSMeeting ParseMeeting(SocketTextChannel c, IList> values) { - var daterow = values[1]; - var time = TimeSpan.Parse((string)daterow[0]); - var events = new List(); - var users = new List(); - for (int i = 2; i < daterow.Count; ++i) + var meeting = new GSMeeting(); + var dateRow = values[1]; + var time = TimeSpan.Parse((string)dateRow[0]); + var idString = ""; + for (int i = 2; i < dateRow.Count; ++i) { - var col = daterow[i]; + var col = dateRow[i]; var d = DateTimeOffset.Parse((string)col, null, DateTimeStyles.AssumeUniversal); - events.Add(d + time); + var dateTime = d + time; + idString += dateTime.ToString("o"); + meeting.Dates.Add(dateTime); } - for (int i = 2; i < values.Count; ++i) + for(int i=2;i (gu.Username + "#" + gu.DiscriminatorValue) == u.DiscordTag).Single(); + } catch(InvalidOperationException e) + { + // Too spammy, do something about it? Don't rely on u.User + //c.SendMessageAsync("Could not find User "+ u.DiscordTag+" in Discord, cannot mention."); + } u.Name = (string)row[1]; for (int j = 2; j < row.Count; ++j) { var str = (string)row[j]; - if(str != "") - u.Signups.Add(events[j - 2], str); + u.Signups.Add(str); + } + // Fill the empty columns that the api skipped + while(u.Signups.Count < meeting.Dates.Count) + { + u.Signups.Add(""); } - users.Add(u); + meeting.Users.Add(u); } - sheetData.Dates = events; - sheetData.Users = users; - return Task.CompletedTask; + var sha1 = new SHA1CryptoServiceProvider(); + var binHash = sha1.ComputeHash(Encoding.ASCII.GetBytes(idString)); + var hash = BitConverter.ToString(binHash).Replace("-", string.Empty); + meeting.Id = hash; + return meeting; } - private async Task SignupNotify(SocketTextChannel chan, GSMeetSheetData sheetData) + private async Task> ParseGSMeetSheet(GSSheet sheet, IList> values) { - foreach(var date in sheetData.Dates) + SocketTextChannel c = guild.Channels.Where(g => g.Id == sheet.Db.Channel).Single() as SocketTextChannel; + int meetStart = -1; + var val = values as List>; + var meetings = new List(); + for (var i=0;i date && date > DateTimeOffset.UtcNow) + var row = values[i] as List; + if(row.Count < 1) + { + continue; + } + if((string)row[0] == "Raid") { - await chan.SendMessageAsync("I should signup notify for " + date); - foreach (var user in sheetData.Users) + if(meetStart == -1) + { + meetStart = i; + } else { - if (!user.Signups.ContainsKey(date)) - { - bool doNotify = true; - foreach(var notification in sheetData.Sheet.NotifiedUsers) - { - if(notification.Date == date && notification.DiscordTag == user.DiscordTag) - { - Console.WriteLine("User already notified."); - doNotify = false; - break; - } - } - if (doNotify) - { - await chan.SendMessageAsync("Hey " + user.DiscordTag + " please sign up for our raid on " + date); - var n = new GSMeetUserNotification(user.DiscordTag, date); - sheetData.Sheet.NotifiedUsers.Add(n); - } - } + meetings.Add(ParseMeeting(c, val.GetRange(meetStart,(i-meetStart-2)))); + meetStart = i; } } } + // Last meeting starts with Raid, thus sets meetStart but no other meeting finishes it, so parse last rows as last meeting + meetings.Add(ParseMeeting(c, val.GetRange(meetStart, (values.Count - meetStart)))); + Console.WriteLine("I parsed " + meetings.Count + " meetings from the sheet."); + return meetings; } - private async Task RaidNotify(SocketTextChannel chan, GSMeetSheetData sheetData) + private async Task HandleSheetCheck(GSSheet sheet) { - foreach (var date in sheetData.Dates) + SocketTextChannel c = guild.Channels.Where(g => g.Id == sheet.Db.Channel).Single() as SocketTextChannel; + Console.WriteLine("Checking sheet " + sheet.Db.Id + " :3"); + var values = FetchRangeFromSheet(sheet.Db.Id, $"{sheet.Db.SheetName}!A:I"); + if (values == null || values.Count < 1) { - - if (DateTimeOffset.UtcNow + new TimeSpan(2,0,0,0) > date) - { - await chan.SendMessageAsync("I should raid notify for " + date); - // - } + Console.WriteLine("No values found."); } - } - - private Task CleanupNotifyDB(GSMeetSheetData sheetData) - { - for(var i=sheetData.Sheet.NotifiedEvents.Count-1;i>=0;i--) + var meetings = await ParseGSMeetSheet(sheet, values); + foreach(var meeting in meetings) { - var n = sheetData.Sheet.NotifiedEvents[i]; - if(DateTimeOffset.UtcNow > n.Date) + if(!sheet.Timers.ContainsKey(meeting.Id)) { - sheetData.Sheet.NotifiedEvents.Remove(n); - gsmeetContext.Entry(n).State = EntityState.Deleted; + sheet.Timers.Add(meeting.Id, new GSMeetingTimers()); + } + sheet.Timers[meeting.Id].UpdateTimers(c, meeting); } - for (var i = sheetData.Sheet.NotifiedUsers.Count - 1; i >= 0; i--) - { - var n = sheetData.Sheet.NotifiedUsers[i]; - if (DateTimeOffset.UtcNow > n.Date) - { - sheetData.Sheet.NotifiedUsers.Remove(n); - gsmeetContext.Entry(n).State = EntityState.Deleted; - } - } - gsmeetContext.SaveChanges(); - return Task.CompletedTask; - } - - - private async Task HandleSheetCheck(DBSheet sheet) - { - var sheetData = new GSMeetSheetData(sheet); - SocketTextChannel c = guild.Channels.Where(g => g.Id == sheet.Channel).Single() as SocketTextChannel; - await c.SendMessageAsync("Checking sheet " + sheet.Id + " :3"); - var values = FetchRangeFromSheet(sheet.Id, $"{sheet.SheetName}!A1:I10"); - if (values == null || values.Count < 1) - { - await c.SendMessageAsync("No values found."); - } - await ParseGSMeetSheet(sheetData, values); - await c.SendMessageAsync("Parsed sheet " + sheet.Id); - await SignupNotify(c, sheetData); - await RaidNotify(c, sheetData); - gsmeetContext.SaveChanges(); - CleanupNotifyDB(sheetData); + Console.WriteLine("Parsed sheet " + sheet.Db.Id); /* var str = ""; foreach (var row in values) @@ -249,7 +221,8 @@ namespace DiscoBot.gsmeet try { gsmeetContext.SaveChanges(); - InitializeSheet(sheet); + var gssheet = new GSSheet(sheet); + InitializeSheet(gssheet); msg.Channel.SendMessageAsync("Sheet " + sheet.Name + " with id " + sheet.Id + " saved."); } catch (InvalidOperationException) @@ -313,27 +286,7 @@ namespace DiscoBot.gsmeet private Task HandleGSMeetDebugCommand(SocketMessage msg, string[] parameters) { var gchan = msg.Channel as IGuildChannel; - string name = parameters[1]; - string sheetId = parameters[2]; - string sheetName = parameters[3]; - - var values = FetchRangeFromSheet(sheetId, $"{sheetName}!A1:I10"); - if(values == null || values.Count < 1) - { - msg.Channel.SendMessageAsync("No values found."); - return Task.CompletedTask; - } - var str = ""; - foreach(var row in values) - { - foreach(var col in row) - { - str += col + "| "; - } - str += "\n"; - } - msg.Channel.SendMessageAsync("Result: "+str); - + msg.Channel.SendMessageAsync("Username: "+msg.Author.Username+"#"+msg.Author.DiscriminatorValue); return Task.CompletedTask; } diff --git a/DiscoBot/gsmeet/GSMeetContext.cs b/DiscoBot/gsmeet/GSMeetContext.cs index 0ed1f2e..bd723e9 100644 --- a/DiscoBot/gsmeet/GSMeetContext.cs +++ b/DiscoBot/gsmeet/GSMeetContext.cs @@ -6,6 +6,7 @@ using System.Timers; using System.Linq; using System.Threading.Tasks; using System.ComponentModel.DataAnnotations.Schema; +using Discord.WebSocket; namespace DiscoBot.gsmeet { @@ -34,53 +35,40 @@ namespace DiscoBot.gsmeet public ulong Channel { get; set; } public TimeSpan CheckInterval { get; set; } public DateTimeOffset LastChecked { get; set; } - public List NotifiedEvents { get; set; } - public List NotifiedUsers { get; set; } } - public class GSMeetEventNotification + public class GSSheet { - [ScaffoldColumn(false)] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [Key] - public long Id { get; set; } - public DateTimeOffset Date { get; set; } - } - - public class GSMeetUserNotification - { - public GSMeetUserNotification(string discordTag, DateTimeOffset date) + public GSSheet(DBSheet db) { - this.DiscordTag = discordTag; - this.Date = date; + this.Db = db; + this.Timers = new Dictionary(); } - [ScaffoldColumn(false)] - [DatabaseGenerated(DatabaseGeneratedOption.Identity)] - [Key] - public long Id { get; set; } - public string DiscordTag { get; set; } - public DateTimeOffset Date { get; set; } + public DBSheet Db { get; set; } + public Dictionary Timers { get; set; } } - public class GSMeetSheetData + public class GSMeetingUser { - public GSMeetSheetData(DBSheet sheet) + public GSMeetingUser() { - this.Sheet = sheet; + this.Signups = new List(); } - public DBSheet Sheet { get; set; } - public List Users { get; set; } - public List Dates { get; set; } + public string DiscordTag { get; set; } + public SocketGuildUser User { get; set; } + public string Name { get; set; } + public List Signups { get; set; } } - public class GSMeetUser + public class GSMeeting { - public GSMeetUser() + public GSMeeting() { - this.Signups = new Dictionary(); + this.Users = new List(); + this.Dates = new List(); } - public string DiscordTag { get; set; } - public string Name { get; set; } - public Dictionary Signups { get; set; } + public string Id { get; set; } + public List Users { get; set; } + public List Dates { get; set; } } } diff --git a/DiscoBot/gsmeet/GSMeetingTimers.cs b/DiscoBot/gsmeet/GSMeetingTimers.cs new file mode 100644 index 0000000..2725b4c --- /dev/null +++ b/DiscoBot/gsmeet/GSMeetingTimers.cs @@ -0,0 +1,95 @@ +using Discord.WebSocket; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Timers; + +namespace DiscoBot.gsmeet +{ + public class GSMeetingTimers + { + private List WarningTimes = new List { + new TimeSpan(2, 0, 0, 0), + new TimeSpan(1, 0, 0, 0) }; + private List UserTimes = new List { + new TimeSpan(7, 0, 0, 0), + new TimeSpan(6, 0, 0, 0), + new TimeSpan(5, 0, 0, 0), + new TimeSpan(4, 0, 0, 0), + new TimeSpan(3, 0, 0, 0) }; + private Dictionary events = new Dictionary(); + public GSMeetingTimers() + { + } + public void UpdateTimers(SocketTextChannel chan, GSMeeting meeting) + { + for(var i=0;i(); + + foreach(var ts in UserTimes) + { + var when = date - ts; + if(when < DateTimeOffset.Now) + { + continue; + } + Console.WriteLine("Setting a timer for " + when + " for evt " + date); + var whents = when - DateTimeOffset.Now; + // Debug resolve timers after 30s + //Timer t = new Timer(new TimeSpan(0, 0, 30).TotalMilliseconds); + Timer t = new Timer(whents.TotalMilliseconds); + t.AutoReset = false; + var users = meeting.Users; + t.Elapsed += async (sender, e) => + { + foreach(var user in users) + { + if(user.Signups[idx] != "1" && user.Signups[idx] != "0" && user.Signups[idx] != "0.5") + { + if(user.User != null) { + await chan.SendMessageAsync("Hey " + user.User.Mention + " could you please sign up for our raid on " + date + "?"); + } else + { + await chan.SendMessageAsync("Hey " + user.Name + " could you please sign up for our raid on " + date + "?"); + } + } + } + }; + t.Start(); + evt.UserTimers.Add(t); + } + } + } + } + + public class GSEventTimers + { + public GSEventTimers() + { + this.UserTimers = new List(); + this.WarningTimers = new List(); + } + public List UserTimers { get; set; } + public List WarningTimers { get; set; } + } +}