Make corresponding changes from VB-based project

This commit is contained in:
Noi 2020-05-19 19:06:02 -07:00
parent 0b6f2c45a4
commit 0d93936bc8
6 changed files with 100 additions and 48 deletions

View file

@ -1,5 +1,7 @@
using BirthdayBot.Data; using BirthdayBot.Data;
using NpgsqlTypes;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace BirthdayBot.BackgroundServices namespace BirthdayBot.BackgroundServices
@ -13,33 +15,73 @@ namespace BirthdayBot.BackgroundServices
public override async Task OnTick() public override async Task OnTick()
{ {
using var db = await BotInstance.Config.DatabaseSettings.OpenConnectionAsync(); // Build a list of all values to update
var updateList = new Dictionary<ulong, List<ulong>>();
// Update only for all guilds the bot has cached foreach (var gi in BotInstance.GuildCache)
using (var c = db.CreateCommand())
{ {
c.CommandText = $"update {GuildStateInformation.BackingTable} set last_seen = now() " var existingUsers = new List<ulong>();
+ "where guild_id = @Gid"; updateList[gi.Key] = existingUsers;
var updateGuild = c.Parameters.Add("@Gid", NpgsqlTypes.NpgsqlDbType.Bigint);
c.Prepare();
var list = new List<ulong>(BotInstance.GuildCache.Keys); var guild = BotInstance.DiscordClient.GetGuild(gi.Key);
foreach (var id in list) if (guild == null) continue; // Have cache without being in guild. Unlikely, but...
{
updateGuild.Value = (long)id; // Get IDs of cached users which are currently in the guild
c.ExecuteNonQuery(); var cachedUserIds = from cu in gi.Value.Users select cu.UserId;
} var guildUserIds = from gu in guild.Users select gu.Id;
var existingCachedIds = cachedUserIds.Intersect(guildUserIds);
} }
// Delete all old values - expecte referencing tables to have 'on delete cascade' using (var db = await BotInstance.Config.DatabaseSettings.OpenConnectionAsync())
using (var t = db.BeginTransaction())
{ {
using (var c = db.CreateCommand()) // Prepare to update a lot of last-seen values
var cUpdateGuild = db.CreateCommand();
cUpdateGuild.CommandText = $"update {GuildStateInformation.BackingTable} set last_seen = now() "
+ "where guild_id = @Gid";
var pUpdateG = cUpdateGuild.Parameters.Add("@Gid", NpgsqlDbType.Bigint);
cUpdateGuild.Prepare();
var cUpdateGuildUser = db.CreateCommand();
cUpdateGuildUser.CommandText = $"update {GuildUserSettings.BackingTable} set last_seen = now() "
+ "where guild_id = @Gid and user_id = @Uid";
var pUpdateGU_g = cUpdateGuildUser.Parameters.Add("@Gid", NpgsqlDbType.Bigint);
var pUpdateGU_u = cUpdateGuild.Parameters.Add("@Uid", NpgsqlDbType.Bigint);
cUpdateGuildUser.Prepare();
// Do actual updates
foreach (var item in updateList)
{ {
// Delete data for guilds not seen in 2 weeks var guild = item.Key;
c.CommandText = $"delete from {GuildUserSettings.BackingTable} where (now() - interval '14 days') > last_seen"; var userlist = item.Value;
var r = c.ExecuteNonQuery();
if (r != 0) Log($"Removed {r} stale guild(s)."); pUpdateG.Value = (long)guild;
cUpdateGuild.ExecuteNonQuery();
pUpdateGU_g.Value = (long)guild;
foreach (var userid in userlist)
{
pUpdateGU_u.Value = (long)userid;
cUpdateGuildUser.ExecuteNonQuery();
}
}
// Delete all old values - expects referencing tables to have 'on delete cascade'
using (var t = db.BeginTransaction())
{
using (var c = db.CreateCommand())
{
// Delete data for guilds not seen in 4 weeks
c.CommandText = $"delete from {GuildStateInformation.BackingTable} where (now() - interval '28 days') > last_seen";
var r = c.ExecuteNonQuery();
if (r != 0) Log($"Removed {r} stale guild(s).");
}
using (var c = db.CreateCommand())
{
// Delete data for users not seen in 8 weeks
c.CommandText = $"delete from {GuildUserSettings.BackingTable} where (now() - interval '56 days') > last_seen";
var r = c.ExecuteNonQuery();
if (r != 0) Log($"Removed {r} stale user(s).");
}
t.Commit();
} }
} }
} }

View file

@ -131,6 +131,7 @@ namespace BirthdayBot.Data
+ "birth_month integer not null, " + "birth_month integer not null, "
+ "birth_day integer not null, " + "birth_day integer not null, "
+ "time_zone text null, " + "time_zone text null, "
+ "last_seen timestamptz not null default NOW(), "
+ "PRIMARY KEY (guild_id, user_id)" + "PRIMARY KEY (guild_id, user_id)"
+ ")"; + ")";
c.ExecuteNonQuery(); c.ExecuteNonQuery();

View file

@ -1,18 +0,0 @@
## Recognize birthdays in your Discord community!
Birthday Bot is a simple, single-purpose bot. It will set a role on your users for the duration of their birthdays and, if desired, can announce a message in a channel of your choosing. Server owners can further specify a default time zone, with individual users also setting their own to ensure everyone's birthdays are recognized precisely on time.
#### Getting started
* Invite the bot. Be mindful that it requires role setting permissions.
* Create a dedicated birthday role to be used only by the bot. Ensure the new role is placed beneath the bot's own role.
* **Do not use an existing role!** This bot assumes exclusive control over it. Users that have the role but are not having a birthday *will* be removed from it!
* Instruct the bot to use the role: `bb.config role (role name)`
#### Other tips
* Set the birthday announcement channel: `bb.config channel (channel)`
* Set a default time zone: `bb.config zone (time zone)`
* Use the command `bb.help-tzdata` for information on how to specify time zones.
* Customize the announcement message: See `bb.help-message` for more information.
#### Note
Birthday information is not shared between servers. This is *by design*, as some people prefer to share their birthdays with select groups of people but keep it obscured from other communities.

View file

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2018-2019 Noi, a.k.a. Noiiko <noikoio1@gmail.com> Copyright (c) 2018-2020 Noi <noithecat@protonmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View file

@ -1,10 +1,35 @@
# Birthday Bot # Birthday Bot
Recognize birthdays in your Discord community!
* Info: https://discord.bots.gg/bots/470673087671566366 * Info: https://discord.bots.gg/bots/470673087671566366
* Invite: https://discordapp.com/oauth2/authorize?client_id=470673087671566366&scope=bot&permissions=268435456
This bot will automatically add a role to users during their birthdays. If desired, it will also announce birthdays in a channel of your choosing. Time zones are supported per-server and per-user to ensure that birthdays and events are recognized at appropriate times. ## Recognize birthdays in your Discord community!
For more information, see the `DiscordBots.md` file. Birthday Bot is a simple, single-purpose bot. It will set a role on your users for the duration of their birthdays and, if desired, can announce a message in a channel of your choosing. Server owners can further specify a default time zone, with individual users also setting their own to ensure everyone's birthdays are recognized precisely on time.
#### Getting started
This bot requires a small amount of initial set-up before it's ready for use. To quickly get started, ensure that you:
* Create a dedicated birthday role to be used only by the bot. Ensure the new role is placed beneath the bot's own role.
* **Do not use an existing role!** This bot assumes exclusive control over it. Users that have the role but are not having a birthday *will* be removed from it!
* Instruct the bot to use the role: `bb.config role (role name)`
At this point, you may also wish to do the following optional steps:
* Set the birthday announcement channel: `bb.config channel (channel)`
* Set a default time zone: `bb.config zone (time zone)`
* Use the command `bb.help-tzdata` for information on how to specify time zones.
* Customize the announcement message: See `bb.help-message` for more information.
#### Support the bot
Birthday Bot is and shall remain free. I have no plans to hide new or existing features behind pay-only, premium features. This is an independent hobby project and all costs associated with it come out of my pocket.
This bot has had a far greater response than I've ever expected, and at this point I find it difficult to pay for the server it runs on as its resource needs grow. I would greatly appreciate if you consider pitching in a little bit to cover my recurring costs by checking out my Patreon link: https://www.patreon.com/noibots.
#### Support, Privacy and Security
The support server for my bots can be accessed via the given link: https://discord.gg/JCRyFk7. Further information in setting up the bot can be found within it, as well as a small group of volunteers who are willing to answer questions.
This bot collects and stores only information necessary for its operation, including user, server, and role IDs. This data is not stored indefinitely, and is removed after some period of time depending on if the bot has been removed from a respective server or its users have been absent for a long enough time.
Information is not shared between servers. This is *by design*, for those preferring to share their birthdays with only certain communities instead of automatically sharing it to all of them. Users must enter their birthday information onto every server they share with the bot for the servers they wish for it to be known in.
Any questions and concerns regarding data and security may be sent to the bot author via the support server or GitHub.
#### Image credit
The icon used by this bot is from Flaticon, found at: https://www.flaticon.com/free-icon/birthday-cake_168532

View file

@ -164,9 +164,11 @@ namespace BirthdayBot.UserInterface
IconUrl = Discord.CurrentUser.GetAvatarUrl() IconUrl = Discord.CurrentUser.GetAvatarUrl()
}, },
// TODO this message needs an overhaul // TODO this message needs an overhaul
Description = "Suggestions and feedback are always welcome. Please refer to the listing on Discord Bots " Description = "For more information regarding support, data retention, privacy, and other details, please refer to: "
+ "(discord.bots.gg) for information on reaching my personal server. I may not be available often, but I am happy to " + "https://github.com/NoiTheCat/BirthdayBot/blob/master/Readme.md" + "\n\n"
+ "respond to feedback in due time." // TODO update this string + "This bot is provided for free, without any intention to add premium, pay-only features. "
+ "If you find this bot helpful, please consider contributing towards my operating costs "
+ "via Patreon: https://www.patreon.com/noibots."
}.AddField(new EmbedFieldBuilder() }.AddField(new EmbedFieldBuilder()
{ {
Name = "Statistics", Name = "Statistics",