First try of actually working code
This commit is contained in:
parent
7479534a9f
commit
6885d6b6b9
BIN
DiscoBot/615631052047908870-calendar.db
Normal file
BIN
DiscoBot/615631052047908870-calendar.db
Normal file
Binary file not shown.
BIN
DiscoBot/615631052047908870-gsmeet.db
Normal file
BIN
DiscoBot/615631052047908870-gsmeet.db
Normal file
Binary file not shown.
BIN
DiscoBot/615631052047908870-gsmeet.db-shm
Normal file
BIN
DiscoBot/615631052047908870-gsmeet.db-shm
Normal file
Binary file not shown.
BIN
DiscoBot/615631052047908870-gsmeet.db-wal
Normal file
BIN
DiscoBot/615631052047908870-gsmeet.db-wal
Normal file
Binary file not shown.
BIN
DiscoBot/615631052047908870-rss.db
Normal file
BIN
DiscoBot/615631052047908870-rss.db
Normal file
Binary file not shown.
Binary file not shown.
BIN
DiscoBot/98293701175955456-gsmeet.db-shm
Normal file
BIN
DiscoBot/98293701175955456-gsmeet.db-shm
Normal file
Binary file not shown.
0
DiscoBot/98293701175955456-gsmeet.db-wal
Normal file
0
DiscoBot/98293701175955456-gsmeet.db-wal
Normal file
Binary file not shown.
@ -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<string, GSMeetingTimers> meetingTimers = new Dictionary<string, GSMeetingTimers>();
|
||||
|
||||
|
||||
|
||||
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<GSMeetUserNotification>();
|
||||
}
|
||||
if(f.NotifiedEvents == null)
|
||||
{
|
||||
f.NotifiedEvents = new List<GSMeetEventNotification>();
|
||||
}
|
||||
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<IList<object>> values)
|
||||
private GSMeeting ParseMeeting(SocketTextChannel c, IList<IList<object>> values)
|
||||
{
|
||||
var daterow = values[1];
|
||||
var time = TimeSpan.Parse((string)daterow[0]);
|
||||
var events = new List<DateTimeOffset>();
|
||||
var users = new List<GSMeetUser>();
|
||||
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<values.Count;++i)
|
||||
{
|
||||
var row = values[i];
|
||||
GSMeetUser u = new GSMeetUser();
|
||||
var u = new GSMeetingUser();
|
||||
u.DiscordTag = (string)row[0];
|
||||
try {
|
||||
u.User = guild.Users.Where(gu => (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);
|
||||
}
|
||||
users.Add(u);
|
||||
// Fill the empty columns that the api skipped
|
||||
while(u.Signups.Count < meeting.Dates.Count)
|
||||
{
|
||||
u.Signups.Add("");
|
||||
}
|
||||
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<List<GSMeeting>> ParseGSMeetSheet(GSSheet sheet, IList<IList<object>> 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<IList<object>>;
|
||||
var meetings = new List<GSMeeting>();
|
||||
for (var i=0;i<values.Count;++i)
|
||||
{
|
||||
|
||||
if(DateTimeOffset.UtcNow + new TimeSpan(4,0,0,0) > date && date > DateTimeOffset.UtcNow)
|
||||
var row = values[i] as List<object>;
|
||||
if(row.Count < 1)
|
||||
{
|
||||
await chan.SendMessageAsync("I should signup notify for " + date);
|
||||
foreach (var user in sheetData.Users)
|
||||
continue;
|
||||
}
|
||||
if((string)row[0] == "Raid")
|
||||
{
|
||||
if(meetStart == -1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
meetStart = i;
|
||||
} else
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
if (DateTimeOffset.UtcNow + new TimeSpan(2,0,0,0) > date)
|
||||
{
|
||||
await chan.SendMessageAsync("I should raid notify for " + date);
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Task CleanupNotifyDB(GSMeetSheetData sheetData)
|
||||
{
|
||||
for(var i=sheetData.Sheet.NotifiedEvents.Count-1;i>=0;i--)
|
||||
{
|
||||
var n = sheetData.Sheet.NotifiedEvents[i];
|
||||
if(DateTimeOffset.UtcNow > n.Date)
|
||||
{
|
||||
sheetData.Sheet.NotifiedEvents.Remove(n);
|
||||
gsmeetContext.Entry(n).State = EntityState.Deleted;
|
||||
}
|
||||
}
|
||||
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");
|
||||
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)
|
||||
{
|
||||
await c.SendMessageAsync("No values found.");
|
||||
Console.WriteLine("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);
|
||||
var meetings = await ParseGSMeetSheet(sheet, values);
|
||||
foreach(var meeting in meetings)
|
||||
{
|
||||
if(!sheet.Timers.ContainsKey(meeting.Id))
|
||||
{
|
||||
sheet.Timers.Add(meeting.Id, new GSMeetingTimers());
|
||||
|
||||
}
|
||||
sheet.Timers[meeting.Id].UpdateTimers(c, meeting);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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<GSMeetEventNotification> NotifiedEvents { get; set; }
|
||||
public List<GSMeetUserNotification> 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<string, GSMeetingTimers>();
|
||||
}
|
||||
public DBSheet Db { get; set; }
|
||||
public Dictionary<string, GSMeetingTimers> Timers { get; set; }
|
||||
}
|
||||
|
||||
public class GSMeetingUser
|
||||
{
|
||||
public GSMeetingUser()
|
||||
{
|
||||
this.Signups = new List<string>();
|
||||
}
|
||||
[ScaffoldColumn(false)]
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
[Key]
|
||||
public long Id { get; set; }
|
||||
public string DiscordTag { get; set; }
|
||||
public DateTimeOffset Date { get; set; }
|
||||
public SocketGuildUser User { get; set; }
|
||||
public string Name { get; set; }
|
||||
public List<string> Signups { get; set; }
|
||||
}
|
||||
|
||||
public class GSMeetSheetData
|
||||
public class GSMeeting
|
||||
{
|
||||
public GSMeetSheetData(DBSheet sheet)
|
||||
public GSMeeting()
|
||||
{
|
||||
this.Sheet = sheet;
|
||||
this.Users = new List<GSMeetingUser>();
|
||||
this.Dates = new List<DateTimeOffset>();
|
||||
}
|
||||
public DBSheet Sheet { get; set; }
|
||||
public List<GSMeetUser> Users { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<GSMeetingUser> Users { get; set; }
|
||||
public List<DateTimeOffset> Dates { get; set; }
|
||||
}
|
||||
|
||||
public class GSMeetUser
|
||||
{
|
||||
public GSMeetUser()
|
||||
{
|
||||
this.Signups = new Dictionary<DateTimeOffset, string>();
|
||||
}
|
||||
public string DiscordTag { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Dictionary<DateTimeOffset, string> Signups { get; set; }
|
||||
}
|
||||
}
|
||||
|
95
DiscoBot/gsmeet/GSMeetingTimers.cs
Normal file
95
DiscoBot/gsmeet/GSMeetingTimers.cs
Normal file
@ -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<TimeSpan> WarningTimes = new List<TimeSpan> {
|
||||
new TimeSpan(2, 0, 0, 0),
|
||||
new TimeSpan(1, 0, 0, 0) };
|
||||
private List<TimeSpan> UserTimes = new List<TimeSpan> {
|
||||
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<DateTimeOffset, GSEventTimers> events = new Dictionary<DateTimeOffset, GSEventTimers>();
|
||||
public GSMeetingTimers()
|
||||
{
|
||||
}
|
||||
public void UpdateTimers(SocketTextChannel chan, GSMeeting meeting)
|
||||
{
|
||||
for(var i=0;i<meeting.Dates.Count;++i)
|
||||
{
|
||||
var date = meeting.Dates[i];
|
||||
// Keep this so we can use it to pick from user.Signups later! (async)
|
||||
var idx = i;
|
||||
GSEventTimers evt;
|
||||
if(events.ContainsKey(date))
|
||||
{
|
||||
evt = events[date];
|
||||
} else
|
||||
{
|
||||
evt = new GSEventTimers();
|
||||
events.Add(date, evt);
|
||||
}
|
||||
|
||||
foreach(var t in evt.UserTimers)
|
||||
{
|
||||
t.Dispose();
|
||||
}
|
||||
|
||||
evt.UserTimers = new List<Timer>();
|
||||
|
||||
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<Timer>();
|
||||
this.WarningTimers = new List<Timer>();
|
||||
}
|
||||
public List<Timer> UserTimers { get; set; }
|
||||
public List<Timer> WarningTimers { get; set; }
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user