diff --git a/.sqlx/query-0402e16b1ec89a96d893d43f6b40500ccbde3c619116a702c87954df49898e23.json b/.sqlx/query-0402e16b1ec89a96d893d43f6b40500ccbde3c619116a702c87954df49898e23.json new file mode 100644 index 0000000..cd33d89 --- /dev/null +++ b/.sqlx/query-0402e16b1ec89a96d893d43f6b40500ccbde3c619116a702c87954df49898e23.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "DELETE FROM patreon_link WHERE user_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "0402e16b1ec89a96d893d43f6b40500ccbde3c619116a702c87954df49898e23" +} diff --git a/.sqlx/query-09f6269e5df3acc01e8e2660532b5fcab21c0cd4fd126b580176d24578932d7e.json b/.sqlx/query-09f6269e5df3acc01e8e2660532b5fcab21c0cd4fd126b580176d24578932d7e.json deleted file mode 100644 index 1178361..0000000 --- a/.sqlx/query-09f6269e5df3acc01e8e2660532b5fcab21c0cd4fd126b580176d24578932d7e.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n UPDATE reminders SET `status` = 'deleted' WHERE FIND_IN_SET(id, ?)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 1 - }, - "nullable": [] - }, - "hash": "09f6269e5df3acc01e8e2660532b5fcab21c0cd4fd126b580176d24578932d7e" -} diff --git a/.sqlx/query-19bc60a2ff67ce6e169985a76405af51d7d16d4d7b84d1c239de5af79da93268.json b/.sqlx/query-19bc60a2ff67ce6e169985a76405af51d7d16d4d7b84d1c239de5af79da93268.json new file mode 100644 index 0000000..35473b9 --- /dev/null +++ b/.sqlx/query-19bc60a2ff67ce6e169985a76405af51d7d16d4d7b84d1c239de5af79da93268.json @@ -0,0 +1,24 @@ +{ + "db_name": "MySQL", + "query": "\n SELECT IFNULL(timezone, 'UTC') AS timezone\n FROM users\n WHERE timezone IS NOT NULL\n GROUP BY timezone\n ORDER BY COUNT(timezone) DESC\n LIMIT 21\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "timezone", + "type_info": { + "type": "VarString", + "flags": "NOT_NULL", + "max_size": 128 + } + } + ], + "parameters": { + "Right": 0 + }, + "nullable": [ + false + ] + }, + "hash": "19bc60a2ff67ce6e169985a76405af51d7d16d4d7b84d1c239de5af79da93268" +} diff --git a/.sqlx/query-2d780695fe98347ea4ab2cb745462f0a9c55cf913c71d4d822b91958f4f8a729.json b/.sqlx/query-2d780695fe98347ea4ab2cb745462f0a9c55cf913c71d4d822b91958f4f8a729.json new file mode 100644 index 0000000..59cfed6 --- /dev/null +++ b/.sqlx/query-2d780695fe98347ea4ab2cb745462f0a9c55cf913c71d4d822b91958f4f8a729.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "\n DELETE FROM reminders\n WHERE `utc_time` < NOW() - INTERVAL ? DAY\n AND status != 'pending'\n ORDER BY `utc_time`\n LIMIT 1000\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "2d780695fe98347ea4ab2cb745462f0a9c55cf913c71d4d822b91958f4f8a729" +} diff --git a/.sqlx/query-2db489e076c93a5a2baf2dd48eb3278d68296aea93097a642e2bbb5112d51fe8.json b/.sqlx/query-2db489e076c93a5a2baf2dd48eb3278d68296aea93097a642e2bbb5112d51fe8.json deleted file mode 100644 index 6822d7a..0000000 --- a/.sqlx/query-2db489e076c93a5a2baf2dd48eb3278d68296aea93097a642e2bbb5112d51fe8.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n UPDATE reminders\n INNER JOIN `channels`\n ON `channels`.id = reminders.channel_id\n SET reminders.`utc_time` = reminders.`utc_time` + ?\n WHERE channels.`channel` = ?\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "2db489e076c93a5a2baf2dd48eb3278d68296aea93097a642e2bbb5112d51fe8" -} diff --git a/.sqlx/query-3695f95cea95c075b2b3becdf1b5d75bf1ccace3b9a176086faa4ad76c0a0fbd.json b/.sqlx/query-3695f95cea95c075b2b3becdf1b5d75bf1ccace3b9a176086faa4ad76c0a0fbd.json deleted file mode 100644 index 9f3b099..0000000 --- a/.sqlx/query-3695f95cea95c075b2b3becdf1b5d75bf1ccace3b9a176086faa4ad76c0a0fbd.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n SELECT\n reminders.id,\n reminders.uid,\n channels.channel,\n reminders.utc_time,\n reminders.interval_seconds,\n reminders.interval_days,\n reminders.interval_months,\n reminders.expires,\n reminders.enabled,\n reminders.content,\n reminders.embed_description,\n reminders.set_by\n FROM\n reminders\n LEFT JOIN\n channels\n ON\n channels.id = reminders.channel_id\n WHERE\n `status` = 'pending' AND\n FIND_IN_SET(channels.channel, ?)\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "id", - "type_info": { - "type": "Long", - "flags": "NOT_NULL | PRIMARY_KEY | UNSIGNED | AUTO_INCREMENT", - "max_size": 10 - } - }, - { - "ordinal": 1, - "name": "uid", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", - "max_size": 256 - } - }, - { - "ordinal": 2, - "name": "channel", - "type_info": { - "type": "LongLong", - "flags": "UNIQUE_KEY | UNSIGNED | NO_DEFAULT_VALUE", - "max_size": 20 - } - }, - { - "ordinal": 3, - "name": "utc_time", - "type_info": { - "type": "Datetime", - "flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE", - "max_size": 19 - } - }, - { - "ordinal": 4, - "name": "interval_seconds", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 5, - "name": "interval_days", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 6, - "name": "interval_months", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 7, - "name": "expires", - "type_info": { - "type": "Datetime", - "flags": "BINARY", - "max_size": 19 - } - }, - { - "ordinal": 8, - "name": "enabled", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 9, - "name": "content", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 10, - "name": "embed_description", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 11, - "name": "set_by", - "type_info": { - "type": "LongLong", - "flags": "MULTIPLE_KEY | UNSIGNED", - "max_size": 20 - } - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - false, - false, - true, - false, - true, - true, - true, - true, - false, - false, - false, - true - ] - }, - "hash": "3695f95cea95c075b2b3becdf1b5d75bf1ccace3b9a176086faa4ad76c0a0fbd" -} diff --git a/.sqlx/query-65496ff85dd92b5aaf12519628afdc16ca7d70131744c9c53880dc56b92991d9.json b/.sqlx/query-65496ff85dd92b5aaf12519628afdc16ca7d70131744c9c53880dc56b92991d9.json deleted file mode 100644 index 0ea513e..0000000 --- a/.sqlx/query-65496ff85dd92b5aaf12519628afdc16ca7d70131744c9c53880dc56b92991d9.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n UPDATE reminders\n INNER JOIN `channels`\n ON `channels`.id = reminders.channel_id\n SET reminders.`utc_time` = DATE_ADD(reminders.`utc_time`, INTERVAL ? SECOND)\n WHERE FIND_IN_SET(channels.`channel`, ?)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 2 - }, - "nullable": [] - }, - "hash": "65496ff85dd92b5aaf12519628afdc16ca7d70131744c9c53880dc56b92991d9" -} diff --git a/.sqlx/query-6e00a27fa770d1aa8cac48cd8878e712ef536c67eeb4fb9a4a801459ada35715.json b/.sqlx/query-6e00a27fa770d1aa8cac48cd8878e712ef536c67eeb4fb9a4a801459ada35715.json deleted file mode 100644 index e75066b..0000000 --- a/.sqlx/query-6e00a27fa770d1aa8cac48cd8878e712ef536c67eeb4fb9a4a801459ada35715.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n DELETE FROM todos WHERE FIND_IN_SET(id, ?)\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 1 - }, - "nullable": [] - }, - "hash": "6e00a27fa770d1aa8cac48cd8878e712ef536c67eeb4fb9a4a801459ada35715" -} diff --git a/.sqlx/query-92cdd6af01e398b22112ffe88b9ff63d9cc61faaf0dee9eda974efbc8bf84173.json b/.sqlx/query-92cdd6af01e398b22112ffe88b9ff63d9cc61faaf0dee9eda974efbc8bf84173.json new file mode 100644 index 0000000..bc7a3be --- /dev/null +++ b/.sqlx/query-92cdd6af01e398b22112ffe88b9ff63d9cc61faaf0dee9eda974efbc8bf84173.json @@ -0,0 +1,24 @@ +{ + "db_name": "MySQL", + "query": "SELECT user_id FROM patreon_link WHERE guild_id = ?", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "user_id", + "type_info": { + "type": "LongLong", + "flags": "NOT_NULL | PRIMARY_KEY | MULTIPLE_KEY | UNSIGNED | NO_DEFAULT_VALUE", + "max_size": 20 + } + } + ], + "parameters": { + "Right": 1 + }, + "nullable": [ + false + ] + }, + "hash": "92cdd6af01e398b22112ffe88b9ff63d9cc61faaf0dee9eda974efbc8bf84173" +} diff --git a/.sqlx/query-93897198be27266cd9de90063ee67594cf65c1216c9b9787fc96cd8ffcc1cdef.json b/.sqlx/query-93897198be27266cd9de90063ee67594cf65c1216c9b9787fc96cd8ffcc1cdef.json new file mode 100644 index 0000000..ac19e75 --- /dev/null +++ b/.sqlx/query-93897198be27266cd9de90063ee67594cf65c1216c9b9787fc96cd8ffcc1cdef.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "\n DELETE FROM reminders\n WHERE `utc_time` < NOW() - INTERVAL ? DAY\n ORDER BY `utc_time`\n LIMIT 1000\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 1 + }, + "nullable": [] + }, + "hash": "93897198be27266cd9de90063ee67594cf65c1216c9b9787fc96cd8ffcc1cdef" +} diff --git a/.sqlx/query-9b871f08d294555453696808185c6d29d4753619fbee6295a053cefaa9dcc0ae.json b/.sqlx/query-9b871f08d294555453696808185c6d29d4753619fbee6295a053cefaa9dcc0ae.json new file mode 100644 index 0000000..68be7be --- /dev/null +++ b/.sqlx/query-9b871f08d294555453696808185c6d29d4753619fbee6295a053cefaa9dcc0ae.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "\n UPDATE reminders\n INNER JOIN `channels`\n ON `channels`.id = reminders.channel_id\n SET reminders.`utc_time` = reminders.`utc_time` + ?\n WHERE channels.`channel` = ?\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 2 + }, + "nullable": [] + }, + "hash": "9b871f08d294555453696808185c6d29d4753619fbee6295a053cefaa9dcc0ae" +} diff --git a/.sqlx/query-a647934dc5485cfbf430c77b71f7b181f888b0961d5274621e5e1dd76417080e.json b/.sqlx/query-a647934dc5485cfbf430c77b71f7b181f888b0961d5274621e5e1dd76417080e.json new file mode 100644 index 0000000..9926b23 --- /dev/null +++ b/.sqlx/query-a647934dc5485cfbf430c77b71f7b181f888b0961d5274621e5e1dd76417080e.json @@ -0,0 +1,12 @@ +{ + "db_name": "MySQL", + "query": "INSERT INTO patreon_link (user_id, guild_id, linked_at) VALUES (?, ?, NOW())\n ON DUPLICATE KEY UPDATE guild_id = ?", + "describe": { + "columns": [], + "parameters": { + "Right": 3 + }, + "nullable": [] + }, + "hash": "a647934dc5485cfbf430c77b71f7b181f888b0961d5274621e5e1dd76417080e" +} diff --git a/.sqlx/query-af5bf4c6b30ffd316ecebc2dd53554e41f0d4f40cad63736930d20cb18159b38.json b/.sqlx/query-af5bf4c6b30ffd316ecebc2dd53554e41f0d4f40cad63736930d20cb18159b38.json deleted file mode 100644 index 751667e..0000000 --- a/.sqlx/query-af5bf4c6b30ffd316ecebc2dd53554e41f0d4f40cad63736930d20cb18159b38.json +++ /dev/null @@ -1,264 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n SELECT\n reminders.attachment_name,\n reminders.avatar,\n channels.channel,\n reminders.content,\n reminders.embed_author,\n reminders.embed_author_url,\n reminders.embed_color,\n reminders.embed_description,\n reminders.embed_footer,\n reminders.embed_footer_url,\n reminders.embed_image_url,\n reminders.embed_thumbnail_url,\n reminders.embed_title,\n IFNULL(reminders.embed_fields, '[]') AS embed_fields,\n reminders.enabled,\n reminders.expires,\n reminders.interval_seconds,\n reminders.interval_days,\n reminders.interval_months,\n reminders.name,\n reminders.restartable,\n reminders.tts,\n reminders.uid,\n reminders.username,\n reminders.utc_time\n FROM reminders\n INNER JOIN channels ON channels.id = reminders.channel_id\n WHERE `status` = 'pending' AND FIND_IN_SET(channels.channel, ?)", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "attachment_name", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 1040 - } - }, - { - "ordinal": 1, - "name": "avatar", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 2, - "name": "channel", - "type_info": { - "type": "LongLong", - "flags": "NOT_NULL | UNIQUE_KEY | UNSIGNED | NO_DEFAULT_VALUE", - "max_size": 20 - } - }, - { - "ordinal": 3, - "name": "content", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 4, - "name": "embed_author", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 1024 - } - }, - { - "ordinal": 5, - "name": "embed_author_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 6, - "name": "embed_color", - "type_info": { - "type": "Long", - "flags": "NOT_NULL | UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 7, - "name": "embed_description", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 8, - "name": "embed_footer", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 9, - "name": "embed_footer_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 10, - "name": "embed_image_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 11, - "name": "embed_thumbnail_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 12, - "name": "embed_title", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 1024 - } - }, - { - "ordinal": 13, - "name": "embed_fields", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL | BINARY", - "max_size": 4294967292 - } - }, - { - "ordinal": 14, - "name": "enabled", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 15, - "name": "expires", - "type_info": { - "type": "Datetime", - "flags": "BINARY", - "max_size": 19 - } - }, - { - "ordinal": 16, - "name": "interval_seconds", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 17, - "name": "interval_days", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 18, - "name": "interval_months", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 19, - "name": "name", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 400 - } - }, - { - "ordinal": 20, - "name": "restartable", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 21, - "name": "tts", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 22, - "name": "uid", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL | UNIQUE_KEY | NO_DEFAULT_VALUE", - "max_size": 256 - } - }, - { - "ordinal": 23, - "name": "username", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 128 - } - }, - { - "ordinal": 24, - "name": "utc_time", - "type_info": { - "type": "Datetime", - "flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE", - "max_size": 19 - } - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - true, - true, - false, - false, - false, - true, - false, - false, - false, - true, - true, - true, - false, - false, - false, - true, - true, - true, - true, - false, - false, - false, - false, - true, - false - ] - }, - "hash": "af5bf4c6b30ffd316ecebc2dd53554e41f0d4f40cad63736930d20cb18159b38" -} diff --git a/.sqlx/query-bbdd4bd7ebffb97efab8ba7e829159e104615260929341ec0e961b4d5cd6ca0c.json b/.sqlx/query-bbdd4bd7ebffb97efab8ba7e829159e104615260929341ec0e961b4d5cd6ca0c.json deleted file mode 100644 index 42d789b..0000000 --- a/.sqlx/query-bbdd4bd7ebffb97efab8ba7e829159e104615260929341ec0e961b4d5cd6ca0c.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "db_name": "MySQL", - "query": "\n SELECT IFNULL(timezone, 'UTC') AS timezone\n FROM users\n WHERE timezone IS NOT NULL\n GROUP BY timezone\n ORDER BY COUNT(timezone) DESC\n LIMIT 21\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "timezone", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 128 - } - } - ], - "parameters": { - "Right": 0 - }, - "nullable": [ - false - ] - }, - "hash": "bbdd4bd7ebffb97efab8ba7e829159e104615260929341ec0e961b4d5cd6ca0c" -} diff --git a/.sqlx/query-d60ea641070dbd882cd53878fa109d08bd3f65e0da8c263e78fe0b200228bc2b.json b/.sqlx/query-d2921961627fef0e12892dbbcd4b891e58c0e52c20897aab3d95365774c01bda.json similarity index 94% rename from .sqlx/query-d60ea641070dbd882cd53878fa109d08bd3f65e0da8c263e78fe0b200228bc2b.json rename to .sqlx/query-d2921961627fef0e12892dbbcd4b891e58c0e52c20897aab3d95365774c01bda.json index 02bc22c..e479b4d 100644 --- a/.sqlx/query-d60ea641070dbd882cd53878fa109d08bd3f65e0da8c263e78fe0b200228bc2b.json +++ b/.sqlx/query-d2921961627fef0e12892dbbcd4b891e58c0e52c20897aab3d95365774c01bda.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "\n SELECT\n reminders.id,\n reminders.uid,\n channels.channel,\n reminders.utc_time,\n reminders.interval_seconds,\n reminders.interval_days,\n reminders.interval_months,\n reminders.expires,\n reminders.enabled,\n reminders.content,\n reminders.embed_description,\n reminders.set_by\n FROM\n reminders\n INNER JOIN\n channels\n ON\n reminders.channel_id = channels.id\n WHERE\n `status` = 'pending' AND\n channels.channel = ? AND\n FIND_IN_SET(reminders.enabled, ?)\n ORDER BY\n reminders.utc_time\n ", + "query": "\n SELECT\n reminders.id,\n reminders.uid,\n channels.channel,\n reminders.utc_time,\n reminders.interval_seconds,\n reminders.interval_days,\n reminders.interval_months,\n reminders.expires,\n reminders.enabled,\n reminders.content,\n reminders.embed_description,\n reminders.set_by\n FROM\n reminders\n INNER JOIN\n channels\n ON\n reminders.channel_id = channels.id\n WHERE\n `status` = 'pending' AND\n channels.channel = ? AND\n reminders.enabled >= ?\n ORDER BY\n reminders.utc_time\n ", "describe": { "columns": [ { @@ -130,5 +130,5 @@ true ] }, - "hash": "d60ea641070dbd882cd53878fa109d08bd3f65e0da8c263e78fe0b200228bc2b" + "hash": "d2921961627fef0e12892dbbcd4b891e58c0e52c20897aab3d95365774c01bda" } diff --git a/.sqlx/query-db69def9391283efb9bf915223d7d6b2d169203b7dc45481a509137f7590d9a6.json b/.sqlx/query-db69def9391283efb9bf915223d7d6b2d169203b7dc45481a509137f7590d9a6.json deleted file mode 100644 index 46716c3..0000000 --- a/.sqlx/query-db69def9391283efb9bf915223d7d6b2d169203b7dc45481a509137f7590d9a6.json +++ /dev/null @@ -1,264 +0,0 @@ -{ - "db_name": "MySQL", - "query": "SELECT\n reminders.attachment,\n reminders.attachment_name,\n reminders.avatar,\n CONCAT('#', channels.channel) AS channel,\n reminders.content,\n reminders.embed_author,\n reminders.embed_author_url,\n reminders.embed_color,\n reminders.embed_description,\n reminders.embed_footer,\n reminders.embed_footer_url,\n reminders.embed_image_url,\n reminders.embed_thumbnail_url,\n reminders.embed_title,\n reminders.embed_fields,\n reminders.enabled,\n reminders.expires,\n reminders.interval_seconds,\n reminders.interval_days,\n reminders.interval_months,\n reminders.name,\n reminders.restartable,\n reminders.tts,\n reminders.username,\n reminders.utc_time\n FROM reminders\n LEFT JOIN channels ON channels.id = reminders.channel_id\n WHERE FIND_IN_SET(channels.channel, ?) AND status = 'pending'", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "attachment", - "type_info": { - "type": "Blob", - "flags": "BLOB | BINARY", - "max_size": 16777215 - } - }, - { - "ordinal": 1, - "name": "attachment_name", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 1040 - } - }, - { - "ordinal": 2, - "name": "avatar", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 3, - "name": "channel", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 84 - } - }, - { - "ordinal": 4, - "name": "content", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 5, - "name": "embed_author", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 1024 - } - }, - { - "ordinal": 6, - "name": "embed_author_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 7, - "name": "embed_color", - "type_info": { - "type": "Long", - "flags": "NOT_NULL | UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 8, - "name": "embed_description", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 9, - "name": "embed_footer", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 8192 - } - }, - { - "ordinal": 10, - "name": "embed_footer_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 11, - "name": "embed_image_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 12, - "name": "embed_thumbnail_url", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 2048 - } - }, - { - "ordinal": 13, - "name": "embed_title", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 1024 - } - }, - { - "ordinal": 14, - "name": "embed_fields", - "type_info": { - "type": "Json", - "flags": "BLOB | BINARY", - "max_size": 4294967295 - } - }, - { - "ordinal": 15, - "name": "enabled", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 16, - "name": "expires", - "type_info": { - "type": "Datetime", - "flags": "BINARY", - "max_size": 19 - } - }, - { - "ordinal": 17, - "name": "interval_seconds", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 18, - "name": "interval_days", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 19, - "name": "interval_months", - "type_info": { - "type": "Long", - "flags": "UNSIGNED", - "max_size": 10 - } - }, - { - "ordinal": 20, - "name": "name", - "type_info": { - "type": "VarString", - "flags": "NOT_NULL", - "max_size": 400 - } - }, - { - "ordinal": 21, - "name": "restartable", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 22, - "name": "tts", - "type_info": { - "type": "Tiny", - "flags": "NOT_NULL", - "max_size": 1 - } - }, - { - "ordinal": 23, - "name": "username", - "type_info": { - "type": "VarString", - "flags": "", - "max_size": 128 - } - }, - { - "ordinal": 24, - "name": "utc_time", - "type_info": { - "type": "Datetime", - "flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE", - "max_size": 19 - } - } - ], - "parameters": { - "Right": 1 - }, - "nullable": [ - true, - true, - true, - true, - false, - false, - true, - false, - false, - false, - true, - true, - true, - false, - true, - false, - true, - true, - true, - true, - false, - false, - false, - true, - false - ] - }, - "hash": "db69def9391283efb9bf915223d7d6b2d169203b7dc45481a509137f7590d9a6" -} diff --git a/Containerfile.run b/Containerfile.run index 3d957d5..6b8b7a4 100644 --- a/Containerfile.run +++ b/Containerfile.run @@ -34,4 +34,5 @@ COPY ./dp.py ./ RUN cargo install --path . +EXPOSE 18920 CMD ["reminder-rs"] diff --git a/README.md b/README.md index 6944347..61fe92d 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,78 @@ # reminder-rs + Reminder Bot for Discord. ## How do I use it? -I offer a hosted version of the bot. You can invite it with: **https://invite.reminder-bot.com**. The catch is that repeating + +I offer a hosted version of the bot. You can invite it with: **https://invite.reminder-bot.com**. +The catch is that repeating reminders are paid on the hosted version of the bot. Keep reading if you want to host it yourself. -You'll need rustc and cargo for compilation. To run, you'll need Python 3 still (due to no suitable replacement for dateparser in Rust) +You'll need rustc and cargo for compilation. To run, you'll need Python 3 still (due to no suitable +replacement for dateparser in Rust) ### Build APT package Recommended method. -By default, this builds targeting Ubuntu 20.04. Modify the Containerfile if you wish to target a different platform. These instructions are written using `podman`, but `docker` should work too. +By default, this builds targeting Ubuntu 20.04. Modify the Containerfile if you wish to target a +different platform. These instructions are written using `podman`, but `docker` should work too. 1. Install container software: `sudo apt install podman`. -2. Install database server: `sudo apt install mysql-server-8.0`. Create a database called `reminders` +2. Install database server: `sudo apt install mysql-server-8.0`. Create a database called + `reminders` 3. Install SQLx CLI: `cargo install sqlx-cli` 4. From the source code directory, execute `sqlx migrate run` 5. Build container image: `podman build -t reminder-rs .` -6. Build with podman: `podman run --rm --network=host -v "$PWD":/mnt -w /mnt -e "DATABASE_URL=mysql://user@localhost/reminders" reminder-rs cargo deb` - +6. Build with podman: + `podman run --rm --network=host -v "$PWD":/mnt -w /mnt -e "DATABASE_URL=mysql://user@localhost/reminders" reminder-rs cargo deb` ### Compiling for other target -1. Install requirements: -`sudo apt install gcc gcc-multilib cmake libssl-dev build-essential python3-dateparser` +1. Install requirements: + `sudo apt install gcc gcc-multilib cmake libssl-dev build-essential python3-dateparser` 2. Install rustup from https://rustup.rs 3. Install the nightly toolchain: `rustup toolchain default nightly` -4. Install database server: `sudo apt install mysql-server-8.0`. Create a database called `reminders`. +4. Install database server: `sudo apt install mysql-server-8.0`. Create a database called + `reminders`. 5. Install `sqlx-cli`: `cargo install sqlx-cli`. 6. Run migrations: `sqlx migrate run`. 7. Set environment variables: - * `DATABASE_URL` - the URL of your MySQL database (`mysql://user[:password]@domain/database`) + * `DATABASE_URL` - the URL of your MySQL database (`mysql://user[:password]@domain/database`) 8. Build: `cargo build --release` - ### Configuring -Reminder Bot reads a number of environment variables. Some are essential, and others have hardcoded fallbacks. Environment variables can be loaded from a .env file in the working directory. +Reminder Bot reads a number of environment variables. Some are essential, and others have hardcoded +fallbacks. Environment variables can be loaded from a .env file in the working directory. __Required Variables__ + * `DATABASE_URL` - the URL of your MySQL database (`mysql://user[:password]@domain/database`) * `DISCORD_TOKEN` - your application's bot user's authorization token __Other Variables__ + * `MIN_INTERVAL` - default `600`, defines the shortest interval the bot should accept * `LOCAL_TIMEZONE` - default `UTC`, necessary for calculations in the natural language processor -* `SUBSCRIPTION_ROLES` - default `None`, accepts a list of Discord role IDs that are given to subscribed users -* `CNC_GUILD` - default `None`, accepts a single Discord guild ID for the server that the subscription roles belong to -* `PYTHON_LOCATION` - default `/usr/bin/python3`. Can be changed if your Python executable is located somewhere else -* `THEME_COLOR` - default `8fb677`. Specifies the hex value of the color to use on info message embeds +* `SUBSCRIPTION_ROLES` - default `None`, accepts a list of Discord role IDs that are given to + subscribed users +* `CNC_GUILD` - default `None`, accepts a single Discord guild ID for the server that the + subscription roles belong to +* `PYTHON_LOCATION` - default `/usr/bin/python3`. Can be changed if your Python executable is + located somewhere else +* `THEME_COLOR` - default `8fb677`. Specifies the hex value of the color to use on info message + embeds + +## Running with Docker + +A `compose.yml` file is provided to aid in running the bot agnostically using docker. + +* Populate a `.env` file as in `conf/default.env` +* Add the additional variable `ROCKET_SECRET_KEY` with a key generated from + `head -c64 /dev/urandom | base64` +* Run `docker compose up` + +Please note that this is _not_ production-ready when run via compose. We do not offer a way for +backing up of your data, or a way to run the dashboard securely via HTTPS, which is required for +OAuth. diff --git a/compose.yaml b/compose.yaml index f276b1b..4df1c1b 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,21 +1,43 @@ -version: '3.3' - services: - bot: - build: ./Containerfile.run - image: reminder-rs-run - restart: always - expose: - - '80' database: image: mysql:8.0 restart: always + command: --log-bin-trust-function-creators=1 environment: - MYSQL_DATABASE: 'reminders' - MYSQL_USER: 'reminder-bot' - ports: - - '3306:3306' - expose: - - '3306' + MYSQL_ROOT_PASSWORD: root + MYSQL_DATABASE: reminders + MYSQL_USER: reminder-bot + MYSQL_PASSWORD: password volumes: - reminders:/var/lib/mysql + + bot: + build: + context: . + dockerfile: Containerfile.run + image: reminder-rs-run + restart: always + depends_on: + - database + env_file: + - .env + environment: + DATABASE_URL: "mysql://reminder-bot:password@database/reminders" + DISCORD_TOKEN: + PATREON_GUILD_ID: + PATREON_ROLE_ID: + LOCAL_TIMEZONE: + MIN_INTERVAL: + ROCKET_SECRET_KEY: + ROCKET_ADDRESS: "0.0.0.0" + ROCKET_PORT: "18920" + REMIND_INTERVAL: + OAUTH2_DISCORD_CALLBACK: + OAUTH2_CLIENT_ID: + OAUTH2_CLIENT_SECRET: + + ports: + - "18920:18920" + +volumes: + reminders: