database migration

This commit is contained in:
jude committed 2021-04-17 16:57:46 +01:00
1 parent 0a9624d12d
commit 4a64238ee4
5 files changed
+206 -116

No files matched your search

Generated
+1 -1
View File
@@ -1270,7 +1270,7 @@ dependencies = [
[[package]]
name = "reminder_rs"
version = "1.4.13"
version = "1.5.0"
dependencies = [
"Inflector",
"chrono",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "reminder_rs"
version = "1.4.13"
version = "1.5.0"
authors = ["jellywx <judesouthworth@pm.me>"]
edition = "2018"
+160
View File
@@ -0,0 +1,160 @@
USE reminders;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS reminders_new;
DROP TABLE IF EXISTS embed_fields_new;
# create new reminders table structure
CREATE TABLE reminders_new (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`uid` VARCHAR(64) NOT NULL UNIQUE,
`name` VARCHAR(24) NOT NULL DEFAULT 'Reminder',
`channel_id` INT UNSIGNED NOT NULL,
`utc_time` DATETIME NOT NULL,
`timezone` ENUM('Africa/Abidjan', 'Africa/Accra', 'Africa/Addis_Ababa', 'Africa/Algiers', 'Africa/Asmara', 'Africa/Asmera', 'Africa/Bamako', 'Africa/Bangui', 'Africa/Banjul', 'Africa/Bissau', 'Africa/Blantyre', 'Africa/Brazzaville', 'Africa/Bujumbura', 'Africa/Cairo', 'Africa/Casablanca', 'Africa/Ceuta', 'Africa/Conakry', 'Africa/Dakar', 'Africa/Dar_es_Salaam', 'Africa/Djibouti', 'Africa/Douala', 'Africa/El_Aaiun', 'Africa/Freetown', 'Africa/Gaborone', 'Africa/Harare', 'Africa/Johannesburg', 'Africa/Juba', 'Africa/Kampala', 'Africa/Khartoum', 'Africa/Kigali', 'Africa/Kinshasa', 'Africa/Lagos', 'Africa/Libreville', 'Africa/Lome', 'Africa/Luanda', 'Africa/Lubumbashi', 'Africa/Lusaka', 'Africa/Malabo', 'Africa/Maputo', 'Africa/Maseru', 'Africa/Mbabane', 'Africa/Mogadishu', 'Africa/Monrovia', 'Africa/Nairobi', 'Africa/Ndjamena', 'Africa/Niamey', 'Africa/Nouakchott', 'Africa/Ouagadougou', 'Africa/Porto-Novo', 'Africa/Sao_Tome', 'Africa/Timbuktu', 'Africa/Tripoli', 'Africa/Tunis', 'Africa/Windhoek', 'America/Adak', 'America/Anchorage', 'America/Anguilla', 'America/Antigua', 'America/Araguaina', 'America/Argentina/Buenos_Aires', 'America/Argentina/Catamarca', 'America/Argentina/ComodRivadavia', 'America/Argentina/Cordoba', 'America/Argentina/Jujuy', 'America/Argentina/La_Rioja', 'America/Argentina/Mendoza', 'America/Argentina/Rio_Gallegos', 'America/Argentina/Salta', 'America/Argentina/San_Juan', 'America/Argentina/San_Luis', 'America/Argentina/Tucuman', 'America/Argentina/Ushuaia', 'America/Aruba', 'America/Asuncion', 'America/Atikokan', 'America/Atka', 'America/Bahia', 'America/Bahia_Banderas', 'America/Barbados', 'America/Belem', 'America/Belize', 'America/Blanc-Sablon', 'America/Boa_Vista', 'America/Bogota', 'America/Boise', 'America/Buenos_Aires', 'America/Cambridge_Bay', 'America/Campo_Grande', 'America/Cancun', 'America/Caracas', 'America/Catamarca', 'America/Cayenne', 'America/Cayman', 'America/Chicago', 'America/Chihuahua', 'America/Coral_Harbour', 'America/Cordoba', 'America/Costa_Rica', 'America/Creston', 'America/Cuiaba', 'America/Curacao', 'America/Danmarkshavn', 'America/Dawson', 'America/Dawson_Creek', 'America/Denver', 'America/Detroit', 'America/Dominica', 'America/Edmonton', 'America/Eirunepe', 'America/El_Salvador', 'America/Ensenada', 'America/Fort_Nelson', 'America/Fort_Wayne', 'America/Fortaleza', 'America/Glace_Bay', 'America/Godthab', 'America/Goose_Bay', 'America/Grand_Turk', 'America/Grenada', 'America/Guadeloupe', 'America/Guatemala', 'America/Guayaquil', 'America/Guyana', 'America/Halifax', 'America/Havana', 'America/Hermosillo', 'America/Indiana/Indianapolis', 'America/Indiana/Knox', 'America/Indiana/Marengo', 'America/Indiana/Petersburg', 'America/Indiana/Tell_City', 'America/Indiana/Vevay', 'America/Indiana/Vincennes', 'America/Indiana/Winamac', 'America/Indianapolis', 'America/Inuvik', 'America/Iqaluit', 'America/Jamaica', 'America/Jujuy', 'America/Juneau', 'America/Kentucky/Louisville', 'America/Kentucky/Monticello', 'America/Knox_IN', 'America/Kralendijk', 'America/La_Paz', 'America/Lima', 'America/Los_Angeles', 'America/Louisville', 'America/Lower_Princes', 'America/Maceio', 'America/Managua', 'America/Manaus', 'America/Marigot', 'America/Martinique', 'America/Matamoros', 'America/Mazatlan', 'America/Mendoza', 'America/Menominee', 'America/Merida', 'America/Metlakatla', 'America/Mexico_City', 'America/Miquelon', 'America/Moncton', 'America/Monterrey', 'America/Montevideo', 'America/Montreal', 'America/Montserrat', 'America/Nassau', 'America/New_York', 'America/Nipigon', 'America/Nome', 'America/Noronha', 'America/North_Dakota/Beulah', 'America/North_Dakota/Center', 'America/North_Dakota/New_Salem', 'America/Ojinaga', 'America/Panama', 'America/Pangnirtung', 'America/Paramaribo', 'America/Phoenix', 'America/Port-au-Prince', 'America/Port_of_Spain', 'America/Porto_Acre', 'America/Porto_Velho', 'America/Puerto_Rico', 'America/Punta_Arenas', 'America/Rainy_River', 'America/Rankin_Inlet', 'America/Recife', 'America/Regina', 'America/Resolute', 'America/Rio_Branco', 'America/Rosario', 'America/Santa_Isabel', 'America/Santarem', 'America/Santiago', 'America/Santo_Domingo', 'America/Sao_Paulo', 'America/Scoresbysund', 'America/Shiprock', 'America/Sitka', 'America/St_Barthelemy', 'America/St_Johns', 'America/St_Kitts', 'America/St_Lucia', 'America/St_Thomas', 'America/St_Vincent', 'America/Swift_Current', 'America/Tegucigalpa', 'America/Thule', 'America/Thunder_Bay', 'America/Tijuana', 'America/Toronto', 'America/Tortola', 'America/Vancouver', 'America/Virgin', 'America/Whitehorse', 'America/Winnipeg', 'America/Yakutat', 'America/Yellowknife', 'Antarctica/Casey', 'Antarctica/Davis', 'Antarctica/DumontDUrville', 'Antarctica/Macquarie', 'Antarctica/Mawson', 'Antarctica/McMurdo', 'Antarctica/Palmer', 'Antarctica/Rothera', 'Antarctica/South_Pole', 'Antarctica/Syowa', 'Antarctica/Troll', 'Antarctica/Vostok', 'Arctic/Longyearbyen', 'Asia/Aden', 'Asia/Almaty', 'Asia/Amman', 'Asia/Anadyr', 'Line truncated
`interval` INT UNSIGNED,
`restartable` BOOL NOT NULL DEFAULT 0,
`enabled` BOOL NOT NULL DEFAULT 1,
`expires` DATETIME,
`username` VARCHAR(32) DEFAULT NULL,
`avatar` VARCHAR(512) DEFAULT NULL,
`content` VARCHAR(2048) NOT NULL DEFAULT '',
`tts` BOOL NOT NULL DEFAULT 0,
`attachment` MEDIUMBLOB,
`attachment_name` VARCHAR(260),
`embed_title` VARCHAR(256) NOT NULL DEFAULT '',
`embed_description` VARCHAR(2048) NOT NULL DEFAULT '',
`embed_image_url` VARCHAR(512),
`embed_thumbnail_url` VARCHAR(512),
`embed_footer` VARCHAR(2048) NOT NULL DEFAULT '',
`embed_footer_url` VARCHAR(512),
`embed_author` VARCHAR(256) NOT NULL DEFAULT '',
`embed_author_url` VARCHAR(512),
`embed_color` INT UNSIGNED NOT NULL DEFAULT 0x0,
`pin` BOOL NOT NULL DEFAULT 0,
`set_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`set_by` INT UNSIGNED DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (`channel_id`) REFERENCES channels (`id`) ON DELETE CASCADE,
FOREIGN KEY (`set_by`) REFERENCES users (`id`) ON DELETE SET NULL,
# disallow having a reminder as restartable if it has no interval
CONSTRAINT restartable_interval_mutex CHECK (`restartable` = 0 OR `interval` IS NULL),
# disallow disabling if interval is unspecified
CONSTRAINT interval_enabled_mutin CHECK (`enabled` = 1 OR `interval` IS NULL),
# disallow an expiry time if interval is unspecified
CONSTRAINT interval_expires_mutin CHECK (`expires` IS NULL OR `interval` IS NOT NULL)
);
# import data from other tables
INSERT INTO reminders_new (
uid,
name,
channel_id,
`utc_time`,
`interval`,
enabled,
expires,
username,
avatar,
content,
tts,
attachment,
attachment_name,
embed_title,
embed_description,
embed_image_url,
embed_thumbnail_url,
embed_footer,
embed_footer_url,
embed_color,
set_at,
set_by
) SELECT
reminders.uid,
reminders.name,
reminders.channel_id,
FROM_UNIXTIME(reminders.time),
reminders.`interval`,
reminders.enabled,
reminders.expires,
reminders.username,
reminders.avatar,
messages.content,
messages.tts,
messages.attachment,
messages.attachment_name,
IFNULL(embeds.title, ''),
IFNULL(embeds.description, ''),
embeds.image_url,
embeds.thumbnail_url,
IFNULL(embeds.footer, ''),
embeds.footer_icon,
IFNULL(embeds.color, 0),
reminders.set_at,
reminders.set_by
FROM reminders
INNER JOIN messages ON reminders.message_id = messages.id
LEFT JOIN embeds ON messages.embed_id = embeds.id;
CREATE TABLE embed_fields_new (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
title VARCHAR(256) NOT NULL,
value VARCHAR(1024) NOT NULL,
inline BOOL NOT NULL DEFAULT 0,
reminder_id INT UNSIGNED,
PRIMARY KEY (id),
FOREIGN KEY (reminder_id) REFERENCES reminders_new (id)
);
INSERT INTO embed_fields_new (
title,
value,
inline,
reminder_id
) SELECT
embed_fields.title,
embed_fields.value,
embed_fields.inline,
(SELECT id FROM reminders_new WHERE reminders_new.uid = reminders.uid)
FROM embed_fields
INNER JOIN embeds e on e.id = embed_fields.embed_id
INNER JOIN messages m on e.id = m.embed_id
INNER JOIN reminders on m.id = reminders.message_id;
DROP TABLE IF EXISTS events;
CREATE TABLE events (
id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
`time` TIMESTAMP NOT NULL DEFAULT NOW(),
event_name ENUM('edit', 'enable', 'disable', 'delete') NOT NULL,
bulk_count INT UNSIGNED,
guild_id INT UNSIGNED NOT NULL,
user_id INT UNSIGNED,
reminder_id INT UNSIGNED,
PRIMARY KEY (id),
FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
FOREIGN KEY (reminder_id) REFERENCES reminders_new(id) ON DELETE SET NULL
);
SET FOREIGN_KEY_CHECKS = 1;
+43 -113
View File
@@ -193,7 +193,7 @@ UPDATE reminders
INNER JOIN `channels`
ON `channels`.id = reminders.channel_id
SET
reminders.`time` = reminders.`time` + ?
reminders.`utc_time` = reminders.`utc_time` + ?
WHERE channels.guild_id = ?
",
displacement,
@@ -205,7 +205,7 @@ UPDATE reminders
} else {
sqlx::query!(
"
UPDATE reminders SET `time` = `time` + ? WHERE reminders.channel_id = ?
UPDATE reminders SET `utc_time` = `utc_time` + ? WHERE reminders.channel_id = ?
",
displacement,
user_data.dm_channel
@@ -345,11 +345,11 @@ impl LookFlags {
struct LookReminder {
id: u32,
time: u32,
time: NaiveDateTime,
interval: Option<u32>,
channel: u64,
content: String,
description: Option<String>,
description: String,
}
impl LookReminder {
@@ -357,7 +357,7 @@ impl LookReminder {
if self.content.len() > 0 {
self.content.clone()
} else {
self.description.clone().unwrap_or(String::from(""))
self.description.clone()
}
}
@@ -370,7 +370,7 @@ impl LookReminder {
) -> String {
let time_display = match flags.time_display {
TimeDisplayType::Absolute => timezone
.timestamp(self.time as i64, 0)
.from_utc_datetime(&self.time)
.format(meridian.fmt_str())
.to_string(),
@@ -380,7 +380,7 @@ impl LookReminder {
.unwrap()
.as_secs();
longhand_displacement((self.time as u64).checked_sub(now).unwrap_or(1))
longhand_displacement((self.time.timestamp() as u64).checked_sub(now).unwrap_or(1))
}
};
@@ -434,26 +434,18 @@ async fn look(ctx: &Context, msg: &Message, args: String) {
LookReminder,
"
SELECT
reminders.id, reminders.time, reminders.interval, channels.channel, messages.content, embeds.description
reminders.id, reminders.utc_time AS time, reminders.interval, channels.channel, reminders.content, reminders.embed_description AS description
FROM
reminders
INNER JOIN
channels
ON
reminders.channel_id = channels.id
INNER JOIN
messages
ON
messages.id = reminders.message_id
LEFT JOIN
embeds
ON
embeds.id = messages.embed_id
WHERE
channels.channel = ? AND
FIND_IN_SET(reminders.enabled, ?)
ORDER BY
reminders.time
reminders.utc_time
LIMIT
?
",
@@ -509,21 +501,13 @@ async fn delete(ctx: &Context, msg: &Message, _args: String) {
LookReminder,
"
SELECT
reminders.id, reminders.time, reminders.interval, channels.channel, messages.content, embeds.description
reminders.id, reminders.utc_time AS time, reminders.interval, channels.channel, reminders.content, reminders.embed_description AS description
FROM
reminders
LEFT OUTER JOIN
INNER JOIN
channels
ON
channels.id = reminders.channel_id
INNER JOIN
messages
ON
messages.id = reminders.message_id
LEFT JOIN
embeds
ON
embeds.id = messages.embed_id
WHERE
FIND_IN_SET(channels.channel, ?)
",
@@ -536,21 +520,13 @@ WHERE
LookReminder,
"
SELECT
reminders.id, reminders.time, reminders.interval, channels.channel, messages.content, embeds.description
reminders.id, reminders.utc_time AS time, reminders.interval, channels.channel, reminders.content, reminders.embed_description AS description
FROM
reminders
LEFT OUTER JOIN
INNER JOIN
channels
ON
channels.id = reminders.channel_id
INNER JOIN
messages
ON
messages.id = reminders.message_id
LEFT JOIN
embeds
ON
embeds.id = messages.embed_id
WHERE
channels.guild_id = (SELECT id FROM guilds WHERE guild = ?)
",
@@ -564,17 +540,9 @@ WHERE
LookReminder,
"
SELECT
reminders.id, reminders.time, reminders.interval, channels.channel, messages.content, embeds.description
reminders.id, reminders.utc_time AS time, reminders.interval, channels.channel, reminders.content, reminders.embed_description AS description
FROM
reminders
INNER JOIN
messages
ON
reminders.message_id = messages.id
LEFT JOIN
embeds
ON
embeds.id = messages.embed_id
INNER JOIN
channels
ON
@@ -593,7 +561,7 @@ WHERE
let enumerated_reminders = reminders.iter().enumerate().map(|(count, reminder)| {
reminder_ids.push(reminder.id);
let time = user_data.timezone().timestamp(reminder.time as i64, 0);
let time = user_data.timezone().timestamp(reminder.time.timestamp(), 0);
format!(
"**{}**: '{}' *<#{}>* at {}",
@@ -1047,70 +1015,41 @@ async fn countdown(ctx: &Context, msg: &Message, args: String) {
event_name, target_ts
);
sqlx::query!(
"
INSERT INTO embeds (title, description, color) VALUES (?, ?, ?)
",
event_name,
description,
*THEME_COLOR
)
.execute(&pool)
.await
.unwrap();
let embed_id = sqlx::query!(
"
SELECT id FROM embeds WHERE title = ? AND description = ?
",
event_name,
description
)
.fetch_one(&pool)
.await
.unwrap();
sqlx::query!(
"
INSERT INTO messages (embed_id) VALUES (?)
",
embed_id.id
)
.execute(&pool)
.await
.unwrap();
sqlx::query!(
"
INSERT INTO reminders (
`uid`,
`name`,
`message_id`,
`channel_id`,
`time`,
`utc_time`,
`interval`,
`method`,
`set_by`,
`expires`
`expires`,
`embed_title`,
`embed_description`,
`embed_color`,
`set_by`
) VALUES (
?,
'Countdown',
(SELECT id FROM messages WHERE embed_id = ?),
(SELECT id FROM channels WHERE channel = ?),
?,
?,
'countdown',
(SELECT id FROM users WHERE user = ?),
FROM_UNIXTIME(?)
FROM_UNIXTIME(?),
?,
?,
?,
(SELECT id FROM users WHERE user = ?)
)
",
generate_uid(),
embed_id.id,
msg.channel_id.as_u64(),
first_time,
interval,
target_ts,
event_name,
description,
*THEME_COLOR,
msg.author.id.as_u64(),
target_ts
)
.execute(&pool)
.await
@@ -1250,6 +1189,7 @@ async fn remind_command(ctx: &Context, msg: &Message, args: String, command: Rem
msg.guild_id,
&scope,
&time_parser,
timezone.to_string(),
expires_parser.as_ref().clone(),
interval,
&mut content,
@@ -1479,6 +1419,7 @@ async fn natural(ctx: &Context, msg: &Message, args: String) {
msg.guild_id,
&scope,
timestamp,
user_data.timezone.clone(),
expires,
interval.clone(),
&mut content,
@@ -1618,6 +1559,7 @@ async fn create_reminder<'a, U: Into<u64>, T: TryInto<i64>>(
guild_id: Option<GuildId>,
scope_id: &ReminderScope,
time_parser: T,
timezone: String,
expires_parser: Option<T>,
interval: Option<i64>,
content: &mut Content,
@@ -1698,37 +1640,25 @@ async fn create_reminder<'a, U: Into<u64>, T: TryInto<i64>>(
} else {
sqlx::query!(
"
INSERT INTO messages (content, tts, attachment, attachment_name) VALUES (?, ?, ?, ?)
INSERT INTO reminders (uid, content, tts, attachment, attachment_name, channel_id, `utc_time`, timezone, expires, `interval`, set_by) VALUES
(?, ?, ?, ?, ?, ?, FROM_UNIXTIME(?), ?, FROM_UNIXTIME(?), ?, (SELECT id FROM users WHERE user = ? LIMIT 1))
",
generate_uid(),
content.content,
content.tts,
content.attachment,
content.attachment_name,
db_channel_id,
time,
timezone,
expires,
interval,
user_id
)
.execute(&pool.clone())
.execute(pool)
.await
.unwrap();
sqlx::query!(
"
INSERT INTO reminders (uid, message_id, channel_id, time, expires, `interval`, method, set_by) VALUES
(?,
(SELECT id FROM messages WHERE content = ? ORDER BY id DESC LIMIT 1),
?, ?, FROM_UNIXTIME(?), ?, 'remind',
(SELECT id FROM users WHERE user = ? LIMIT 1))
",
generate_uid(),
content.content,
db_channel_id,
time as u32,
expires,
interval,
user_id
)
.execute(pool)
.await
.unwrap();
Ok(())
}
} else if time < 0 {
+1 -1
View File
@@ -32,7 +32,7 @@ enum ParseType {
}
pub struct TimeParser {
timezone: Tz,
pub timezone: Tz,
inverted: bool,
time_string: String,
parse_type: ParseType,