Browse Source

First try of actually working code

master
amki 5 years ago
parent
commit
6885d6b6b9
  1. BIN
      DiscoBot/615631052047908870-calendar.db
  2. BIN
      DiscoBot/615631052047908870-gsmeet.db
  3. BIN
      DiscoBot/615631052047908870-gsmeet.db-shm
  4. BIN
      DiscoBot/615631052047908870-gsmeet.db-wal
  5. BIN
      DiscoBot/615631052047908870-rss.db
  6. BIN
      DiscoBot/98293701175955456-gsmeet.db
  7. BIN
      DiscoBot/98293701175955456-gsmeet.db-shm
  8. 0
      DiscoBot/98293701175955456-gsmeet.db-wal
  9. BIN
      DiscoBot/98293701175955456-rss.db
  10. 209
      DiscoBot/gsmeet/GSMeet.cs
  11. 54
      DiscoBot/gsmeet/GSMeetContext.cs
  12. 95
      DiscoBot/gsmeet/GSMeetingTimers.cs

BIN
DiscoBot/615631052047908870-calendar.db

Binary file not shown.

BIN
DiscoBot/615631052047908870-gsmeet.db

Binary file not shown.

BIN
DiscoBot/615631052047908870-gsmeet.db-shm

Binary file not shown.

BIN
DiscoBot/615631052047908870-gsmeet.db-wal

Binary file not shown.

BIN
DiscoBot/615631052047908870-rss.db

Binary file not shown.

BIN
DiscoBot/98293701175955456-gsmeet.db

Binary file not shown.

BIN
DiscoBot/98293701175955456-gsmeet.db-shm

Binary file not shown.

0
DiscoBot/98293701175955456-gsmeet.db-wal

BIN
DiscoBot/98293701175955456-rss.db

Binary file not shown.

209
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<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);
}
// 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<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)
{
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;
}
}
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;
}
sheet.Timers.Add(meeting.Id, new GSMeetingTimers());
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.");
}
sheet.Timers[meeting.Id].UpdateTimers(c, meeting);
}
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;
}

54
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<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>();
}
[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<string, GSMeetingTimers> Timers { get; set; }
}
public class GSMeetSheetData
public class GSMeetingUser
{
public GSMeetSheetData(DBSheet sheet)
public GSMeetingUser()
{
this.Sheet = sheet;
this.Signups = new List<string>();
}
public DBSheet Sheet { get; set; }
public List<GSMeetUser> Users { get; set; }
public List<DateTimeOffset> Dates { get; set; }
public string DiscordTag { get; set; }
public SocketGuildUser User { get; set; }
public string Name { get; set; }
public List<string> Signups { get; set; }
}
public class GSMeetUser
public class GSMeeting
{
public GSMeetUser()
public GSMeeting()
{
this.Signups = new Dictionary<DateTimeOffset, string>();
this.Users = new List<GSMeetingUser>();
this.Dates = new List<DateTimeOffset>();
}
public string DiscordTag { get; set; }
public string Name { get; set; }
public Dictionary<DateTimeOffset, string> Signups { get; set; }
public string Id { get; set; }
public List<GSMeetingUser> Users { get; set; }
public List<DateTimeOffset> Dates { get; set; }
}
}

95
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<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…
Cancel
Save