Compare commits
	
		
			11 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2d1668a63a | ||
| 
						 | 
					6f7d0f67b3 | ||
| 
						 | 
					bfc2d71ca0 | ||
| 
						 | 
					8eb46f1f23 | ||
| 
						 | 
					c4087bf569 | ||
| 
						 | 
					f25cfed8d7 | ||
| 
						 | 
					d2a8bd1982 | ||
| 
						 | 
					437ee6b446 | ||
| 
						 | 
					7d43aa5918 | ||
| 
						 | 
					8bad95510d | ||
| 
						 | 
					d7a0b727fb | 
							
								
								
									
										340
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										340
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -115,7 +115,7 @@ dependencies = [
 | 
				
			|||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "pin-project-lite",
 | 
					 "pin-project-lite",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-rustls 0.23.3",
 | 
					 "tokio-rustls 0.23.4",
 | 
				
			||||||
 "tungstenite",
 | 
					 "tungstenite",
 | 
				
			||||||
 "webpki-roots 0.22.3",
 | 
					 "webpki-roots 0.22.3",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -202,15 +202,6 @@ dependencies = [
 | 
				
			|||||||
 "generic-array 0.12.4",
 | 
					 "generic-array 0.12.4",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "block-buffer"
 | 
					 | 
				
			||||||
version = "0.9.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "generic-array 0.14.5",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "block-buffer"
 | 
					name = "block-buffer"
 | 
				
			||||||
version = "0.10.2"
 | 
					version = "0.10.2"
 | 
				
			||||||
@@ -354,7 +345,7 @@ dependencies = [
 | 
				
			|||||||
 "hmac",
 | 
					 "hmac",
 | 
				
			||||||
 "percent-encoding",
 | 
					 "percent-encoding",
 | 
				
			||||||
 "rand 0.8.5",
 | 
					 "rand 0.8.5",
 | 
				
			||||||
 "sha2 0.10.2",
 | 
					 "sha2",
 | 
				
			||||||
 "subtle",
 | 
					 "subtle",
 | 
				
			||||||
 "time 0.3.9",
 | 
					 "time 0.3.9",
 | 
				
			||||||
 "version_check",
 | 
					 "version_check",
 | 
				
			||||||
@@ -495,13 +486,13 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "dashmap"
 | 
					name = "dashmap"
 | 
				
			||||||
version = "5.2.0"
 | 
					version = "5.3.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c"
 | 
					checksum = "391b56fbd302e585b7a9494fb70e40949567b1cf9003a8e4a6041a1687c26573"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 "cfg-if 1.0.0",
 | 
				
			||||||
 "num_cpus",
 | 
					 "hashbrown 0.12.1",
 | 
				
			||||||
 "parking_lot 0.12.0",
 | 
					 "lock_api",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -575,15 +566,6 @@ dependencies = [
 | 
				
			|||||||
 "generic-array 0.12.4",
 | 
					 "generic-array 0.12.4",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "digest"
 | 
					 | 
				
			||||||
version = "0.9.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "generic-array 0.14.5",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "digest"
 | 
					name = "digest"
 | 
				
			||||||
version = "0.10.3"
 | 
					version = "0.10.3"
 | 
				
			||||||
@@ -941,7 +923,7 @@ dependencies = [
 | 
				
			|||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
 "slab",
 | 
					 "slab",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-util 0.7.1",
 | 
					 "tokio-util 0.7.2",
 | 
				
			||||||
 "tracing",
 | 
					 "tracing",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -954,13 +936,19 @@ dependencies = [
 | 
				
			|||||||
 "ahash",
 | 
					 "ahash",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "hashbrown"
 | 
				
			||||||
 | 
					version = "0.12.1"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "hashlink"
 | 
					name = "hashlink"
 | 
				
			||||||
version = "0.7.0"
 | 
					version = "0.7.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
 | 
					checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "hashbrown",
 | 
					 "hashbrown 0.11.2",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1007,9 +995,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "http"
 | 
					name = "http"
 | 
				
			||||||
version = "0.2.6"
 | 
					version = "0.2.7"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
 | 
					checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "fnv",
 | 
					 "fnv",
 | 
				
			||||||
@@ -1029,9 +1017,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "httparse"
 | 
					name = "httparse"
 | 
				
			||||||
version = "1.7.0"
 | 
					version = "1.7.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "6330e8a36bd8c859f3fa6d9382911fbb7147ec39807f63b923933a247240b9ba"
 | 
					checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "httpdate"
 | 
					name = "httpdate"
 | 
				
			||||||
@@ -1083,9 +1071,9 @@ checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac"
 | 
				
			|||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "http",
 | 
					 "http",
 | 
				
			||||||
 "hyper",
 | 
					 "hyper",
 | 
				
			||||||
 "rustls 0.20.4",
 | 
					 "rustls 0.20.5",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-rustls 0.23.3",
 | 
					 "tokio-rustls 0.23.4",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1143,7 +1131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
 | 
					checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "autocfg",
 | 
					 "autocfg",
 | 
				
			||||||
 "hashbrown",
 | 
					 "hashbrown 0.11.2",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1254,9 +1242,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "libc"
 | 
					name = "libc"
 | 
				
			||||||
version = "0.2.124"
 | 
					version = "0.2.125"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
 | 
					checksum = "5916d2ae698f6de9bfb891ad7a8d65c09d232dc58cc4ac433c7da3b2fd84bc2b"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "libm"
 | 
					name = "libm"
 | 
				
			||||||
@@ -1276,18 +1264,18 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "log"
 | 
					name = "log"
 | 
				
			||||||
version = "0.4.16"
 | 
					version = "0.4.17"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8"
 | 
					checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 "cfg-if 1.0.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "loom"
 | 
					name = "loom"
 | 
				
			||||||
version = "0.5.4"
 | 
					version = "0.5.5"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "edc5c7d328e32cc4954e8e01193d7f0ef5ab257b5090b70a964e099a36034309"
 | 
					checksum = "85eb735cf3c8ebac6cc3655c5da2f4a088b6a19133aa482471a21ba0eb5d83ab"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 "cfg-if 1.0.0",
 | 
				
			||||||
 "generator",
 | 
					 "generator",
 | 
				
			||||||
@@ -1321,9 +1309,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "memchr"
 | 
					name = "memchr"
 | 
				
			||||||
version = "2.4.1"
 | 
					version = "2.5.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
 | 
					checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "mime"
 | 
					name = "mime"
 | 
				
			||||||
@@ -1369,7 +1357,7 @@ dependencies = [
 | 
				
			|||||||
 "kernel32-sys",
 | 
					 "kernel32-sys",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "miow 0.2.2",
 | 
					 "miow",
 | 
				
			||||||
 "net2",
 | 
					 "net2",
 | 
				
			||||||
 "slab",
 | 
					 "slab",
 | 
				
			||||||
 "winapi 0.2.8",
 | 
					 "winapi 0.2.8",
 | 
				
			||||||
@@ -1377,16 +1365,14 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "mio"
 | 
					name = "mio"
 | 
				
			||||||
version = "0.8.2"
 | 
					version = "0.8.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
 | 
					checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "miow 0.3.7",
 | 
					 | 
				
			||||||
 "ntapi",
 | 
					 | 
				
			||||||
 "wasi 0.11.0+wasi-snapshot-preview1",
 | 
					 "wasi 0.11.0+wasi-snapshot-preview1",
 | 
				
			||||||
 "winapi 0.3.9",
 | 
					 "windows-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1413,15 +1399,6 @@ dependencies = [
 | 
				
			|||||||
 "ws2_32-sys",
 | 
					 "ws2_32-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "miow"
 | 
					 | 
				
			||||||
version = "0.3.7"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "winapi 0.3.9",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "multer"
 | 
					name = "multer"
 | 
				
			||||||
version = "2.0.2"
 | 
					version = "2.0.2"
 | 
				
			||||||
@@ -1438,7 +1415,7 @@ dependencies = [
 | 
				
			|||||||
 "mime",
 | 
					 "mime",
 | 
				
			||||||
 "spin 0.9.3",
 | 
					 "spin 0.9.3",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-util 0.6.9",
 | 
					 "tokio-util 0.6.10",
 | 
				
			||||||
 "version_check",
 | 
					 "version_check",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1508,15 +1485,6 @@ dependencies = [
 | 
				
			|||||||
 "winapi 0.3.9",
 | 
					 "winapi 0.3.9",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "ntapi"
 | 
					 | 
				
			||||||
version = "0.3.7"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "winapi 0.3.9",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-bigint"
 | 
					name = "num-bigint"
 | 
				
			||||||
version = "0.3.3"
 | 
					version = "0.3.3"
 | 
				
			||||||
@@ -1547,9 +1515,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-integer"
 | 
					name = "num-integer"
 | 
				
			||||||
version = "0.1.44"
 | 
					version = "0.1.45"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
 | 
					checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "autocfg",
 | 
					 "autocfg",
 | 
				
			||||||
 "num-traits",
 | 
					 "num-traits",
 | 
				
			||||||
@@ -1557,9 +1525,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-iter"
 | 
					name = "num-iter"
 | 
				
			||||||
version = "0.1.42"
 | 
					version = "0.1.43"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
 | 
					checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "autocfg",
 | 
					 "autocfg",
 | 
				
			||||||
 "num-integer",
 | 
					 "num-integer",
 | 
				
			||||||
@@ -1568,9 +1536,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num-traits"
 | 
					name = "num-traits"
 | 
				
			||||||
version = "0.2.14"
 | 
					version = "0.2.15"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
 | 
					checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "autocfg",
 | 
					 "autocfg",
 | 
				
			||||||
 "libm",
 | 
					 "libm",
 | 
				
			||||||
@@ -1588,18 +1556,18 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "num_threads"
 | 
					name = "num_threads"
 | 
				
			||||||
version = "0.1.5"
 | 
					version = "0.1.6"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "aba1801fb138d8e85e11d0fc70baf4fe1cdfffda7c6cd34a854905df588e5ed0"
 | 
					checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "oauth2"
 | 
					name = "oauth2"
 | 
				
			||||||
version = "4.1.0"
 | 
					version = "4.2.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "80e47cfc4c0a1a519d9a025ebfbac3a2439d1b5cdf397d72dcb79b11d9920dab"
 | 
					checksum = "c3bd7d544f02ae0fa9e06137962703d043870d7ad6e6d44786d6a5f20679b2c9"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "base64",
 | 
					 "base64",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
@@ -1610,7 +1578,7 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "serde_path_to_error",
 | 
					 "serde_path_to_error",
 | 
				
			||||||
 "sha2 0.9.9",
 | 
					 "sha2",
 | 
				
			||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
 "url",
 | 
					 "url",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -1635,18 +1603,30 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "openssl"
 | 
					name = "openssl"
 | 
				
			||||||
version = "0.10.38"
 | 
					version = "0.10.40"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
 | 
					checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bitflags",
 | 
					 "bitflags",
 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 "cfg-if 1.0.0",
 | 
				
			||||||
 "foreign-types",
 | 
					 "foreign-types",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 | 
					 "openssl-macros",
 | 
				
			||||||
 "openssl-sys",
 | 
					 "openssl-sys",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "openssl-macros"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "proc-macro2",
 | 
				
			||||||
 | 
					 "quote",
 | 
				
			||||||
 | 
					 "syn",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "openssl-probe"
 | 
					name = "openssl-probe"
 | 
				
			||||||
version = "0.1.5"
 | 
					version = "0.1.5"
 | 
				
			||||||
@@ -1655,9 +1635,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "openssl-sys"
 | 
					name = "openssl-sys"
 | 
				
			||||||
version = "0.9.72"
 | 
					version = "0.9.73"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
 | 
					checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "autocfg",
 | 
					 "autocfg",
 | 
				
			||||||
 "cc",
 | 
					 "cc",
 | 
				
			||||||
@@ -1693,7 +1673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			|||||||
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
 | 
					checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "lock_api",
 | 
					 "lock_api",
 | 
				
			||||||
 "parking_lot_core 0.9.2",
 | 
					 "parking_lot_core 0.9.3",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
@@ -1712,9 +1692,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "parking_lot_core"
 | 
					name = "parking_lot_core"
 | 
				
			||||||
version = "0.9.2"
 | 
					version = "0.9.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "995f667a6c822200b0433ac218e05582f0e2efa1b922a3fd2fbaadc5f87bab37"
 | 
					checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 "cfg-if 1.0.0",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
@@ -1860,9 +1840,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pin-project-lite"
 | 
					name = "pin-project-lite"
 | 
				
			||||||
version = "0.2.8"
 | 
					version = "0.2.9"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
 | 
					checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "pin-utils"
 | 
					name = "pin-utils"
 | 
				
			||||||
@@ -1900,9 +1880,9 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "poise"
 | 
					name = "poise"
 | 
				
			||||||
version = "0.2.0"
 | 
					version = "0.2.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "3c2eb79ba8241eb65b549e778e22a242ea30f5829f7487f10d8d95cfff9a4729"
 | 
					checksum = "046256f9b3bcca8aaed17c412c0e11ccfb8273d2dfea08716e2eb81931465cd4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "async-trait",
 | 
					 "async-trait",
 | 
				
			||||||
 "derivative",
 | 
					 "derivative",
 | 
				
			||||||
@@ -1918,9 +1898,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "poise_macros"
 | 
					name = "poise_macros"
 | 
				
			||||||
version = "0.2.0"
 | 
					version = "0.2.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "15b786b4bdc58345204469420c306d8c638e465b4b1ecad7e27bf9c8a45096cf"
 | 
					checksum = "94d99712c7e3cef666f344ccf5c5c729939331096d16c35eba3275028191a1af"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "darling",
 | 
					 "darling",
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
@@ -1966,9 +1946,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "proc-macro2"
 | 
					name = "proc-macro2"
 | 
				
			||||||
version = "1.0.37"
 | 
					version = "1.0.38"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
 | 
					checksum = "9027b48e9d4c9175fa2218adf3557f91c1137021739951d4932f5f8268ac48aa"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "unicode-xid",
 | 
					 "unicode-xid",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -2077,18 +2057,18 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "ref-cast"
 | 
					name = "ref-cast"
 | 
				
			||||||
version = "1.0.6"
 | 
					version = "1.0.7"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "300f2a835d808734ee295d45007adacb9ebb29dd3ae2424acfa17930cae541da"
 | 
					checksum = "685d58625b6c2b83e4cc88a27c4bf65adb7b6b16dbdc413e515c9405b47432ab"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "ref-cast-impl",
 | 
					 "ref-cast-impl",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "ref-cast-impl"
 | 
					name = "ref-cast-impl"
 | 
				
			||||||
version = "1.0.6"
 | 
					version = "1.0.7"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "4c38e3aecd2b21cb3959637b883bb3714bc7e43f0268b9a29d3743ee3e55cdd2"
 | 
					checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -2123,7 +2103,7 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "reminder_rs"
 | 
					name = "reminder_rs"
 | 
				
			||||||
version = "1.6.0-beta3"
 | 
					version = "1.6.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "base64",
 | 
					 "base64",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
@@ -2144,7 +2124,6 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "serde_repr",
 | 
					 "serde_repr",
 | 
				
			||||||
 "sqlx",
 | 
					 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2203,15 +2182,15 @@ dependencies = [
 | 
				
			|||||||
 "native-tls",
 | 
					 "native-tls",
 | 
				
			||||||
 "percent-encoding",
 | 
					 "percent-encoding",
 | 
				
			||||||
 "pin-project-lite",
 | 
					 "pin-project-lite",
 | 
				
			||||||
 "rustls 0.20.4",
 | 
					 "rustls 0.20.5",
 | 
				
			||||||
 "rustls-pemfile",
 | 
					 "rustls-pemfile 0.3.0",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "serde_urlencoded",
 | 
					 "serde_urlencoded",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-native-tls",
 | 
					 "tokio-native-tls",
 | 
				
			||||||
 "tokio-rustls 0.23.3",
 | 
					 "tokio-rustls 0.23.4",
 | 
				
			||||||
 "tokio-util 0.6.9",
 | 
					 "tokio-util 0.6.10",
 | 
				
			||||||
 "url",
 | 
					 "url",
 | 
				
			||||||
 "wasm-bindgen",
 | 
					 "wasm-bindgen",
 | 
				
			||||||
 "wasm-bindgen-futures",
 | 
					 "wasm-bindgen-futures",
 | 
				
			||||||
@@ -2259,8 +2238,8 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rocket"
 | 
					name = "rocket"
 | 
				
			||||||
version = "0.5.0-rc.1"
 | 
					version = "0.5.0-rc.2"
 | 
				
			||||||
source = "git+https://github.com/SergioBenitez/Rocket?branch=master#49d138de14074d40fb9223467434a5626782f51a"
 | 
					source = "git+https://github.com/SergioBenitez/Rocket?branch=master#bf2bd0e9ede12dc227326d069cd84fc98dddf2e4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "async-stream",
 | 
					 "async-stream",
 | 
				
			||||||
 "async-trait",
 | 
					 "async-trait",
 | 
				
			||||||
@@ -2289,7 +2268,7 @@ dependencies = [
 | 
				
			|||||||
 "time 0.3.9",
 | 
					 "time 0.3.9",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-stream",
 | 
					 "tokio-stream",
 | 
				
			||||||
 "tokio-util 0.7.1",
 | 
					 "tokio-util 0.7.2",
 | 
				
			||||||
 "ubyte",
 | 
					 "ubyte",
 | 
				
			||||||
 "version_check",
 | 
					 "version_check",
 | 
				
			||||||
 "yansi",
 | 
					 "yansi",
 | 
				
			||||||
@@ -2297,8 +2276,8 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rocket_codegen"
 | 
					name = "rocket_codegen"
 | 
				
			||||||
version = "0.5.0-rc.1"
 | 
					version = "0.5.0-rc.2"
 | 
				
			||||||
source = "git+https://github.com/SergioBenitez/Rocket?branch=master#49d138de14074d40fb9223467434a5626782f51a"
 | 
					source = "git+https://github.com/SergioBenitez/Rocket?branch=master#bf2bd0e9ede12dc227326d069cd84fc98dddf2e4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "devise",
 | 
					 "devise",
 | 
				
			||||||
 "glob",
 | 
					 "glob",
 | 
				
			||||||
@@ -2312,8 +2291,8 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rocket_dyn_templates"
 | 
					name = "rocket_dyn_templates"
 | 
				
			||||||
version = "0.1.0-rc.1"
 | 
					version = "0.1.0-rc.2"
 | 
				
			||||||
source = "git+https://github.com/SergioBenitez/Rocket?branch=master#49d138de14074d40fb9223467434a5626782f51a"
 | 
					source = "git+https://github.com/SergioBenitez/Rocket?branch=master#bf2bd0e9ede12dc227326d069cd84fc98dddf2e4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "glob",
 | 
					 "glob",
 | 
				
			||||||
 "normpath",
 | 
					 "normpath",
 | 
				
			||||||
@@ -2324,11 +2303,12 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rocket_http"
 | 
					name = "rocket_http"
 | 
				
			||||||
version = "0.5.0-rc.1"
 | 
					version = "0.5.0-rc.2"
 | 
				
			||||||
source = "git+https://github.com/SergioBenitez/Rocket?branch=master#49d138de14074d40fb9223467434a5626782f51a"
 | 
					source = "git+https://github.com/SergioBenitez/Rocket?branch=master#bf2bd0e9ede12dc227326d069cd84fc98dddf2e4"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "cookie",
 | 
					 "cookie",
 | 
				
			||||||
 "either",
 | 
					 "either",
 | 
				
			||||||
 | 
					 "futures",
 | 
				
			||||||
 "http",
 | 
					 "http",
 | 
				
			||||||
 "hyper",
 | 
					 "hyper",
 | 
				
			||||||
 "indexmap",
 | 
					 "indexmap",
 | 
				
			||||||
@@ -2338,15 +2318,15 @@ dependencies = [
 | 
				
			|||||||
 "percent-encoding",
 | 
					 "percent-encoding",
 | 
				
			||||||
 "pin-project-lite",
 | 
					 "pin-project-lite",
 | 
				
			||||||
 "ref-cast",
 | 
					 "ref-cast",
 | 
				
			||||||
 "rustls 0.20.4",
 | 
					 "rustls 0.20.5",
 | 
				
			||||||
 "rustls-pemfile",
 | 
					 "rustls-pemfile 1.0.0",
 | 
				
			||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "smallvec",
 | 
					 "smallvec",
 | 
				
			||||||
 "stable-pattern",
 | 
					 "stable-pattern",
 | 
				
			||||||
 "state",
 | 
					 "state",
 | 
				
			||||||
 "time 0.3.9",
 | 
					 "time 0.3.9",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "tokio-rustls 0.23.3",
 | 
					 "tokio-rustls 0.23.4",
 | 
				
			||||||
 "uncased",
 | 
					 "uncased",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2385,9 +2365,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rustls"
 | 
					name = "rustls"
 | 
				
			||||||
version = "0.20.4"
 | 
					version = "0.20.5"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
 | 
					checksum = "a024a432ae760ab3bff924ad91ce1cfa52cb57ed16e1ef32d0d249cfee1a6c13"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "ring",
 | 
					 "ring",
 | 
				
			||||||
@@ -2404,6 +2384,15 @@ dependencies = [
 | 
				
			|||||||
 "base64",
 | 
					 "base64",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "rustls-pemfile"
 | 
				
			||||||
 | 
					version = "1.0.0"
 | 
				
			||||||
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
 | 
					checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
 | 
				
			||||||
 | 
					dependencies = [
 | 
				
			||||||
 | 
					 "base64",
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "rustversion"
 | 
					name = "rustversion"
 | 
				
			||||||
version = "1.0.6"
 | 
					version = "1.0.6"
 | 
				
			||||||
@@ -2492,9 +2481,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde"
 | 
					name = "serde"
 | 
				
			||||||
version = "1.0.136"
 | 
					version = "1.0.137"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
 | 
					checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "serde_derive",
 | 
					 "serde_derive",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -2511,9 +2500,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde_derive"
 | 
					name = "serde_derive"
 | 
				
			||||||
version = "1.0.136"
 | 
					version = "1.0.137"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
 | 
					checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -2522,9 +2511,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde_json"
 | 
					name = "serde_json"
 | 
				
			||||||
version = "1.0.79"
 | 
					version = "1.0.81"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
 | 
					checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "itoa",
 | 
					 "itoa",
 | 
				
			||||||
 "ryu",
 | 
					 "ryu",
 | 
				
			||||||
@@ -2542,9 +2531,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "serde_repr"
 | 
					name = "serde_repr"
 | 
				
			||||||
version = "0.1.7"
 | 
					version = "0.1.8"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5"
 | 
					checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -2617,19 +2606,6 @@ dependencies = [
 | 
				
			|||||||
 "digest 0.10.3",
 | 
					 "digest 0.10.3",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "sha2"
 | 
					 | 
				
			||||||
version = "0.9.9"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "block-buffer 0.9.0",
 | 
					 | 
				
			||||||
 "cfg-if 1.0.0",
 | 
					 | 
				
			||||||
 "cpufeatures",
 | 
					 | 
				
			||||||
 "digest 0.9.0",
 | 
					 | 
				
			||||||
 "opaque-debug 0.3.0",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "sha2"
 | 
					name = "sha2"
 | 
				
			||||||
version = "0.10.2"
 | 
					version = "0.10.2"
 | 
				
			||||||
@@ -2779,7 +2755,7 @@ dependencies = [
 | 
				
			|||||||
 "serde",
 | 
					 "serde",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "sha-1 0.10.0",
 | 
					 "sha-1 0.10.0",
 | 
				
			||||||
 "sha2 0.10.2",
 | 
					 "sha2",
 | 
				
			||||||
 "smallvec",
 | 
					 "smallvec",
 | 
				
			||||||
 "sqlformat",
 | 
					 "sqlformat",
 | 
				
			||||||
 "sqlx-rt",
 | 
					 "sqlx-rt",
 | 
				
			||||||
@@ -2804,7 +2780,7 @@ dependencies = [
 | 
				
			|||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "serde_json",
 | 
					 "serde_json",
 | 
				
			||||||
 "sha2 0.10.2",
 | 
					 "sha2",
 | 
				
			||||||
 "sqlx-core",
 | 
					 "sqlx-core",
 | 
				
			||||||
 "sqlx-rt",
 | 
					 "sqlx-rt",
 | 
				
			||||||
 "syn",
 | 
					 "syn",
 | 
				
			||||||
@@ -2833,9 +2809,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "state"
 | 
					name = "state"
 | 
				
			||||||
version = "0.5.2"
 | 
					version = "0.5.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "87cf4f5369e6d3044b5e365c9690f451516ac8f0954084622b49ea3fde2f6de5"
 | 
					checksum = "dbe866e1e51e8260c9eed836a042a5e7f6726bb2b411dffeaa712e19c388f23b"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "loom",
 | 
					 "loom",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -2864,9 +2840,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "syn"
 | 
					name = "syn"
 | 
				
			||||||
version = "1.0.91"
 | 
					version = "1.0.94"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "b683b2b825c8eef438b77c36a06dc262294da3d5a5813fac20da149241dcd44d"
 | 
					checksum = "a07e33e919ebcd69113d5be0e4d70c5707004ff45188910106854f38b960df4a"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -2920,18 +2896,18 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "thiserror"
 | 
					name = "thiserror"
 | 
				
			||||||
version = "1.0.30"
 | 
					version = "1.0.31"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
 | 
					checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "thiserror-impl",
 | 
					 "thiserror-impl",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "thiserror-impl"
 | 
					name = "thiserror-impl"
 | 
				
			||||||
version = "1.0.30"
 | 
					version = "1.0.31"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
 | 
					checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -2978,9 +2954,9 @@ checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tinyvec"
 | 
					name = "tinyvec"
 | 
				
			||||||
version = "1.5.1"
 | 
					version = "1.6.0"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2"
 | 
					checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "tinyvec_macros",
 | 
					 "tinyvec_macros",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -2993,14 +2969,14 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tokio"
 | 
					name = "tokio"
 | 
				
			||||||
version = "1.17.0"
 | 
					version = "1.18.2"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
 | 
					checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "libc",
 | 
					 "libc",
 | 
				
			||||||
 "memchr",
 | 
					 "memchr",
 | 
				
			||||||
 "mio 0.8.2",
 | 
					 "mio 0.8.3",
 | 
				
			||||||
 "num_cpus",
 | 
					 "num_cpus",
 | 
				
			||||||
 "once_cell",
 | 
					 "once_cell",
 | 
				
			||||||
 "parking_lot 0.12.0",
 | 
					 "parking_lot 0.12.0",
 | 
				
			||||||
@@ -3045,11 +3021,11 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tokio-rustls"
 | 
					name = "tokio-rustls"
 | 
				
			||||||
version = "0.23.3"
 | 
					version = "0.23.4"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e"
 | 
					checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "rustls 0.20.4",
 | 
					 "rustls 0.20.5",
 | 
				
			||||||
 "tokio",
 | 
					 "tokio",
 | 
				
			||||||
 "webpki 0.22.0",
 | 
					 "webpki 0.22.0",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
@@ -3067,9 +3043,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tokio-util"
 | 
					name = "tokio-util"
 | 
				
			||||||
version = "0.6.9"
 | 
					version = "0.6.10"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
 | 
					checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "futures-core",
 | 
					 "futures-core",
 | 
				
			||||||
@@ -3081,9 +3057,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tokio-util"
 | 
					name = "tokio-util"
 | 
				
			||||||
version = "0.7.1"
 | 
					version = "0.7.2"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "0edfdeb067411dba2044da6d1cb2df793dd35add7888d73c16e3381ded401764"
 | 
					checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "bytes",
 | 
					 "bytes",
 | 
				
			||||||
 "futures-core",
 | 
					 "futures-core",
 | 
				
			||||||
@@ -3123,9 +3099,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tracing-attributes"
 | 
					name = "tracing-attributes"
 | 
				
			||||||
version = "0.1.20"
 | 
					version = "0.1.21"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
 | 
					checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
@@ -3144,9 +3120,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "tracing-log"
 | 
					name = "tracing-log"
 | 
				
			||||||
version = "0.1.2"
 | 
					version = "0.1.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "a6923477a48e41c1951f1999ef8bb5a3023eb723ceadafe78ffb65dc366761e3"
 | 
					checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "lazy_static",
 | 
					 "lazy_static",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
@@ -3190,7 +3166,7 @@ dependencies = [
 | 
				
			|||||||
 "httparse",
 | 
					 "httparse",
 | 
				
			||||||
 "log",
 | 
					 "log",
 | 
				
			||||||
 "rand 0.8.5",
 | 
					 "rand 0.8.5",
 | 
				
			||||||
 "rustls 0.20.4",
 | 
					 "rustls 0.20.5",
 | 
				
			||||||
 "sha-1 0.10.0",
 | 
					 "sha-1 0.10.0",
 | 
				
			||||||
 "thiserror",
 | 
					 "thiserror",
 | 
				
			||||||
 "url",
 | 
					 "url",
 | 
				
			||||||
@@ -3296,9 +3272,9 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode-bidi"
 | 
					name = "unicode-bidi"
 | 
				
			||||||
version = "0.3.7"
 | 
					version = "0.3.8"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
 | 
					checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode-normalization"
 | 
					name = "unicode-normalization"
 | 
				
			||||||
@@ -3317,9 +3293,9 @@ checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode-xid"
 | 
					name = "unicode-xid"
 | 
				
			||||||
version = "0.2.2"
 | 
					version = "0.2.3"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 | 
					checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "unicode_categories"
 | 
					name = "unicode_categories"
 | 
				
			||||||
@@ -3578,9 +3554,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows-sys"
 | 
					name = "windows-sys"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "5acdd78cb4ba54c0045ac14f62d8f94a03d10047904ae2a40afa1e99d8f70825"
 | 
					checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "windows_aarch64_msvc",
 | 
					 "windows_aarch64_msvc",
 | 
				
			||||||
 "windows_i686_gnu",
 | 
					 "windows_i686_gnu",
 | 
				
			||||||
@@ -3591,33 +3567,33 @@ dependencies = [
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows_aarch64_msvc"
 | 
					name = "windows_aarch64_msvc"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d"
 | 
					checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows_i686_gnu"
 | 
					name = "windows_i686_gnu"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed"
 | 
					checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows_i686_msvc"
 | 
					name = "windows_i686_msvc"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956"
 | 
					checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows_x86_64_gnu"
 | 
					name = "windows_x86_64_gnu"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4"
 | 
					checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "windows_x86_64_msvc"
 | 
					name = "windows_x86_64_msvc"
 | 
				
			||||||
version = "0.34.0"
 | 
					version = "0.36.1"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9"
 | 
					checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "winreg"
 | 
					name = "winreg"
 | 
				
			||||||
@@ -3646,6 +3622,6 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "zeroize"
 | 
					name = "zeroize"
 | 
				
			||||||
version = "1.5.4"
 | 
					version = "1.5.5"
 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
				
			||||||
checksum = "7eb5728b8afd3f280a869ce1d4c554ffaed35f45c231fc41bfbd0381bef50317"
 | 
					checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,9 @@
 | 
				
			|||||||
[package]
 | 
					[package]
 | 
				
			||||||
name = "reminder_rs"
 | 
					name = "reminder_rs"
 | 
				
			||||||
version = "1.6.0-beta3"
 | 
					version = "1.6.0"
 | 
				
			||||||
authors = ["jellywx <judesouthworth@pm.me>"]
 | 
					authors = ["jellywx <judesouthworth@pm.me>"]
 | 
				
			||||||
edition = "2018"
 | 
					edition = "2018"
 | 
				
			||||||
 | 
					workspaces = [".", "postman", "web", "entity", "migration"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
poise = "0.2"
 | 
					poise = "0.2"
 | 
				
			||||||
@@ -22,7 +23,6 @@ serde_repr = "0.1"
 | 
				
			|||||||
rmp-serde = "0.15"
 | 
					rmp-serde = "0.15"
 | 
				
			||||||
rand = "0.7"
 | 
					rand = "0.7"
 | 
				
			||||||
levenshtein = "1.0"
 | 
					levenshtein = "1.0"
 | 
				
			||||||
sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "macros", "mysql", "bigdecimal", "chrono"]}
 | 
					 | 
				
			||||||
base64 = "0.13.0"
 | 
					base64 = "0.13.0"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies.postman]
 | 
					[dependencies.postman]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							@@ -2,13 +2,20 @@
 | 
				
			|||||||
Reminder Bot for Discord.
 | 
					Reminder Bot for Discord.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## How do I use it?
 | 
					## How do I use it?
 | 
				
			||||||
We 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.
 | 
					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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Compiling
 | 
					### Compiling
 | 
				
			||||||
Reminder Bot can be built by running `cargo build --release` in the top level directory. It is necessary to create a folder called 'assets' containing an image file with its name specified in the environment as `WEBHOOK_AVATAR`, of dimensions 128x128px to be used as the webhook avatar.
 | 
					Install build requirements: 
 | 
				
			||||||
 | 
					`sudo apt install gcc gcc-multilib cmake libssl-dev build-essential`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install Rust from https://rustup.rs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Reminder Bot can then be built by running `cargo build --release` in the top level directory. It is necessary to create a 
 | 
				
			||||||
 | 
					folder called 'assets' containing an image file with its name specified in the environment as `WEBHOOK_AVATAR`, of 
 | 
				
			||||||
 | 
					dimensions 128x128px to be used as the webhook avatar.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### Compilation environment variables
 | 
					#### Compilation environment variables
 | 
				
			||||||
These environment variables must be provided when compiling the bot
 | 
					These environment variables must be provided when compiling the bot
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,233 +0,0 @@
 | 
				
			|||||||
CREATE DATABASE IF NOT EXISTS reminders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SET FOREIGN_KEY_CHECKS=0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
USE reminders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.guilds (
 | 
					 | 
				
			||||||
    id INT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
 | 
					 | 
				
			||||||
    guild BIGINT UNSIGNED UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(100),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    prefix VARCHAR(5) DEFAULT '$' NOT NULL,
 | 
					 | 
				
			||||||
    timezone VARCHAR(32) DEFAULT 'UTC' NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    default_channel_id INT UNSIGNED,
 | 
					 | 
				
			||||||
    default_username VARCHAR(32) DEFAULT 'Reminder' NOT NULL,
 | 
					 | 
				
			||||||
    default_avatar VARCHAR(512) DEFAULT 'https://raw.githubusercontent.com/reminder-bot/logos/master/Remind_Me_Bot_Logo_PPic.jpg' NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (default_channel_id) REFERENCES reminders.channels(id) ON DELETE SET NULL
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.channels (
 | 
					 | 
				
			||||||
    id INT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
 | 
					 | 
				
			||||||
    channel BIGINT UNSIGNED UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(100),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    nudge SMALLINT NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
    blacklisted BOOL NOT NULL DEFAULT FALSE,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    webhook_id BIGINT UNSIGNED UNIQUE,
 | 
					 | 
				
			||||||
    webhook_token TEXT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    paused BOOL NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
    paused_until TIMESTAMP,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guild_id INT UNSIGNED,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild_id) REFERENCES reminders.guilds(id) ON DELETE CASCADE
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.users (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
    user BIGINT UNSIGNED UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(37) NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    dm_channel INT UNSIGNED UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    language VARCHAR(2) DEFAULT 'EN' NOT NULL,
 | 
					 | 
				
			||||||
    timezone VARCHAR(32) DEFAULT 'UTC' NOT NULL,
 | 
					 | 
				
			||||||
    meridian_time BOOLEAN DEFAULT 0 NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    allowed_dm BOOLEAN DEFAULT 1 NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    patreon BOOLEAN NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (dm_channel) REFERENCES reminders.channels(id) ON DELETE RESTRICT
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.roles (
 | 
					 | 
				
			||||||
    id INT UNSIGNED UNIQUE NOT NULL AUTO_INCREMENT,
 | 
					 | 
				
			||||||
    role BIGINT UNSIGNED UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(100),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guild_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild_id) REFERENCES reminders.guilds(id) ON DELETE CASCADE
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.embeds (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    title VARCHAR(256) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
    description VARCHAR(2048) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    image_url VARCHAR(512),
 | 
					 | 
				
			||||||
    thumbnail_url VARCHAR(512),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    footer VARCHAR(2048) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
    footer_icon VARCHAR(512),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    color MEDIUMINT UNSIGNED NOT NULL DEFAULT 0x0,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.embed_fields (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    title VARCHAR(256) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
    value VARCHAR(1024) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
    inline BOOL NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
    embed_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (embed_id) REFERENCES reminders.embeds(id) ON DELETE CASCADE
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.messages (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    content VARCHAR(2048) NOT NULL DEFAULT '',
 | 
					 | 
				
			||||||
    tts BOOL NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
    embed_id INT UNSIGNED,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    attachment MEDIUMBLOB,
 | 
					 | 
				
			||||||
    attachment_name VARCHAR(260),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (embed_id) REFERENCES reminders.embeds(id) ON DELETE SET NULL
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.reminders (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
    uid VARCHAR(64) UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(24) NOT NULL DEFAULT 'Reminder',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    message_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
    channel_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    `time` INT UNSIGNED DEFAULT 0 NOT NULL,
 | 
					 | 
				
			||||||
    `interval` INT UNSIGNED DEFAULT NULL,
 | 
					 | 
				
			||||||
    expires TIMESTAMP DEFAULT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    enabled BOOLEAN DEFAULT 1 NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    avatar VARCHAR(512),
 | 
					 | 
				
			||||||
    username VARCHAR(32),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    method ENUM('remind', 'natural', 'dashboard', 'todo', 'countdown'),
 | 
					 | 
				
			||||||
    set_at TIMESTAMP DEFAULT NOW(),
 | 
					 | 
				
			||||||
    set_by INT UNSIGNED,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (message_id) REFERENCES reminders.messages(id) ON DELETE RESTRICT,
 | 
					 | 
				
			||||||
    FOREIGN KEY (channel_id) REFERENCES reminders.channels(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    FOREIGN KEY (set_by) REFERENCES reminders.users(id) ON DELETE SET NULL
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TRIGGER message_cleanup AFTER DELETE ON reminders.reminders
 | 
					 | 
				
			||||||
FOR EACH ROW
 | 
					 | 
				
			||||||
    DELETE FROM reminders.messages WHERE id = OLD.message_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TRIGGER embed_cleanup AFTER DELETE ON reminders.messages
 | 
					 | 
				
			||||||
FOR EACH ROW
 | 
					 | 
				
			||||||
    DELETE FROM reminders.embeds WHERE id = OLD.embed_id;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.todos (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
    user_id INT UNSIGNED,
 | 
					 | 
				
			||||||
    guild_id INT UNSIGNED,
 | 
					 | 
				
			||||||
    channel_id INT UNSIGNED,
 | 
					 | 
				
			||||||
    value VARCHAR(2000) NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (user_id) REFERENCES reminders.users(id) ON DELETE SET NULL,
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild_id) REFERENCES reminders.guilds(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    FOREIGN KEY (channel_id) REFERENCES reminders.channels(id) ON DELETE SET NULL
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.command_restrictions (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    role_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
    command ENUM('todos', 'natural', 'remind', 'interval', 'timer', 'del', 'look', 'alias', 'countdown') NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (role_id) REFERENCES reminders.roles(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    UNIQUE KEY (`role_id`, `command`)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.timers (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
    start_time TIMESTAMP NOT NULL DEFAULT NOW(),
 | 
					 | 
				
			||||||
    name VARCHAR(32) NOT NULL,
 | 
					 | 
				
			||||||
    owner BIGINT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.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 reminders.guilds(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    FOREIGN KEY (user_id) REFERENCES reminders.users(id) ON DELETE SET NULL,
 | 
					 | 
				
			||||||
    FOREIGN KEY (reminder_id) REFERENCES reminders.reminders(id) ON DELETE SET NULL
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.command_aliases (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT UNIQUE NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    guild_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
    name VARCHAR(12) NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    command VARCHAR(2048) NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild_id) REFERENCES reminders.guilds(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    UNIQUE KEY (`guild_id`, `name`)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminders.guild_users (
 | 
					 | 
				
			||||||
    guild INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
    user INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    can_access BOOL NOT NULL DEFAULT 0,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild) REFERENCES reminders.guilds(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    FOREIGN KEY (user) REFERENCES reminders.users(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    UNIQUE KEY (guild, user)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE EVENT reminders.event_cleanup
 | 
					 | 
				
			||||||
ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 DAY
 | 
					 | 
				
			||||||
ON COMPLETION PRESERVE
 | 
					 | 
				
			||||||
DO DELETE FROM reminders.events WHERE `time` < DATE_SUB(NOW(), INTERVAL 5 DAY);
 | 
					 | 
				
			||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -1,13 +0,0 @@
 | 
				
			|||||||
USE reminders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE macro (
 | 
					 | 
				
			||||||
    id INT UNSIGNED AUTO_INCREMENT,
 | 
					 | 
				
			||||||
    guild_id INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    name VARCHAR(100) NOT NULL,
 | 
					 | 
				
			||||||
    description VARCHAR(100),
 | 
					 | 
				
			||||||
    commands TEXT NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    FOREIGN KEY (guild_id) REFERENCES guilds(id) ON DELETE CASCADE,
 | 
					 | 
				
			||||||
    PRIMARY KEY (id)
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
@@ -1,4 +0,0 @@
 | 
				
			|||||||
USE reminders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ALTER TABLE reminders.reminders RENAME COLUMN `interval` TO `interval_seconds`;
 | 
					 | 
				
			||||||
ALTER TABLE reminders.reminders ADD COLUMN `interval_months` INT UNSIGNED DEFAULT NULL;
 | 
					 | 
				
			||||||
@@ -1,34 +0,0 @@
 | 
				
			|||||||
USE reminders;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
CREATE TABLE reminder_template (
 | 
					 | 
				
			||||||
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    `name` VARCHAR(24) NOT NULL DEFAULT 'Reminder',
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    `guild_id` INT UNSIGNED NOT NULL,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    `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,
 | 
					 | 
				
			||||||
    `embed_fields` JSON,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY (id),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    FOREIGN KEY (`guild_id`) REFERENCES guilds (`id`) ON DELETE CASCADE
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
ALTER TABLE reminders ADD COLUMN embed_fields JSON;
 | 
					 | 
				
			||||||
							
								
								
									
										7
									
								
								models/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								models/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					# This file is automatically @generated by Cargo.
 | 
				
			||||||
 | 
					# It is not intended for manual editing.
 | 
				
			||||||
 | 
					version = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[[package]]
 | 
				
			||||||
 | 
					name = "models"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
							
								
								
									
										8
									
								
								models/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								models/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "models"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
							
								
								
									
										8
									
								
								models/entity/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								models/entity/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "entity"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					chrono-tz = "^0.6"
 | 
				
			||||||
 | 
					sea-orm = { version = "^0.8", features = ["sqlx-postgres", "runtime-tokio-native-tls", "macros"] }
 | 
				
			||||||
							
								
								
									
										60
									
								
								models/entity/src/channel.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								models/entity/src/channel.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "channel")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key, auto_increment = false)]
 | 
				
			||||||
 | 
					    pub id: i64,
 | 
				
			||||||
 | 
					    pub guild_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub nudge: i32,
 | 
				
			||||||
 | 
					    pub webhook_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub webhook_token: Option<String>,
 | 
				
			||||||
 | 
					    pub paused: bool,
 | 
				
			||||||
 | 
					    pub paused_until: Option<DateTimeUtc>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::GuildId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::user::Entity")]
 | 
				
			||||||
 | 
					    User,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::reminder::Entity")]
 | 
				
			||||||
 | 
					    Reminder,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::todo::Entity")]
 | 
				
			||||||
 | 
					    Todo,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::guild::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Guild.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::user::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::User.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::reminder::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Reminder.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::todo::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Todo.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										34
									
								
								models/entity/src/command_macro.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								models/entity/src/command_macro.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "command_macro")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key)]
 | 
				
			||||||
 | 
					    pub id: i32,
 | 
				
			||||||
 | 
					    pub guild_id: i64,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub description: Option<String>,
 | 
				
			||||||
 | 
					    pub commands: Option<Json>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::GuildId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::guild::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Guild.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										48
									
								
								models/entity/src/guild.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								models/entity/src/guild.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "guild")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key, auto_increment = false)]
 | 
				
			||||||
 | 
					    pub id: i64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::reminder_template::Entity")]
 | 
				
			||||||
 | 
					    ReminderTemplate,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::channel::Entity")]
 | 
				
			||||||
 | 
					    Channel,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::todo::Entity")]
 | 
				
			||||||
 | 
					    Todo,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::command_macro::Entity")]
 | 
				
			||||||
 | 
					    CommandMacro,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::reminder_template::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::ReminderTemplate.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::channel::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Channel.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::todo::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Todo.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::command_macro::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::CommandMacro.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										1
									
								
								models/entity/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								models/entity/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										14
									
								
								models/entity/src/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								models/entity/src/mod.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod prelude;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod channel;
 | 
				
			||||||
 | 
					pub mod command_macro;
 | 
				
			||||||
 | 
					pub mod guild;
 | 
				
			||||||
 | 
					pub mod reminder;
 | 
				
			||||||
 | 
					pub mod reminder_template;
 | 
				
			||||||
 | 
					pub mod sea_orm_active_enums;
 | 
				
			||||||
 | 
					pub mod seaql_migrations;
 | 
				
			||||||
 | 
					pub mod timer;
 | 
				
			||||||
 | 
					pub mod todo;
 | 
				
			||||||
 | 
					pub mod user;
 | 
				
			||||||
							
								
								
									
										8
									
								
								models/entity/src/prelude.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								models/entity/src/prelude.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub use super::{
 | 
				
			||||||
 | 
					    channel::Entity as Channel, command_macro::Entity as CommandMacro, guild::Entity as Guild,
 | 
				
			||||||
 | 
					    reminder::Entity as Reminder, reminder_template::Entity as ReminderTemplate,
 | 
				
			||||||
 | 
					    seaql_migrations::Entity as SeaqlMigrations, timer::Entity as Timer, todo::Entity as Todo,
 | 
				
			||||||
 | 
					    user::Entity as User,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										73
									
								
								models/entity/src/reminder.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								models/entity/src/reminder.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::sea_orm_active_enums::Timezone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "reminder")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key)]
 | 
				
			||||||
 | 
					    pub id: i32,
 | 
				
			||||||
 | 
					    pub uid: String,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub channel_id: i64,
 | 
				
			||||||
 | 
					    pub utc_time: DateTimeUtc,
 | 
				
			||||||
 | 
					    pub timezone: Timezone,
 | 
				
			||||||
 | 
					    pub interval_seconds: Option<i32>,
 | 
				
			||||||
 | 
					    pub interval_months: Option<i32>,
 | 
				
			||||||
 | 
					    pub enabled: bool,
 | 
				
			||||||
 | 
					    pub expires: Option<DateTimeUtc>,
 | 
				
			||||||
 | 
					    pub username: Option<String>,
 | 
				
			||||||
 | 
					    pub avatar: Option<String>,
 | 
				
			||||||
 | 
					    pub content: Option<String>,
 | 
				
			||||||
 | 
					    pub tts: bool,
 | 
				
			||||||
 | 
					    pub attachment: Option<Vec<u8>>,
 | 
				
			||||||
 | 
					    pub attachment_name: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_title: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_description: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_image_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_thumbnail_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_footer: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_footer_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_author: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_author_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_color: Option<i32>,
 | 
				
			||||||
 | 
					    pub embed_fields: Option<Json>,
 | 
				
			||||||
 | 
					    pub set_at: DateTimeUtc,
 | 
				
			||||||
 | 
					    pub set_by: i64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::channel::Entity",
 | 
				
			||||||
 | 
					        from = "Column::ChannelId",
 | 
				
			||||||
 | 
					        to = "super::channel::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Channel,
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::user::Entity",
 | 
				
			||||||
 | 
					        from = "Column::SetBy",
 | 
				
			||||||
 | 
					        to = "super::user::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    User,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::channel::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Channel.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::user::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::User.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										48
									
								
								models/entity/src/reminder_template.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								models/entity/src/reminder_template.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "reminder_template")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key)]
 | 
				
			||||||
 | 
					    pub id: i32,
 | 
				
			||||||
 | 
					    pub guild_id: i64,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub username: Option<String>,
 | 
				
			||||||
 | 
					    pub avatar: Option<String>,
 | 
				
			||||||
 | 
					    pub content: Option<String>,
 | 
				
			||||||
 | 
					    pub tts: bool,
 | 
				
			||||||
 | 
					    pub attachment: Option<Vec<u8>>,
 | 
				
			||||||
 | 
					    pub attachment_name: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_title: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_description: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_image_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_thumbnail_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_footer: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_footer_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_author: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_author_url: Option<String>,
 | 
				
			||||||
 | 
					    pub embed_color: Option<i32>,
 | 
				
			||||||
 | 
					    pub embed_fields: Option<Json>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::GuildId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::guild::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Guild.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										1196
									
								
								models/entity/src/sea_orm_active_enums.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1196
									
								
								models/entity/src/sea_orm_active_enums.rs
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								models/entity/src/seaql_migrations.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								models/entity/src/seaql_migrations.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "seaql_migrations")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key, auto_increment = false)]
 | 
				
			||||||
 | 
					    pub version: String,
 | 
				
			||||||
 | 
					    pub applied_at: i64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter)]
 | 
				
			||||||
 | 
					pub enum Relation {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl RelationTrait for Relation {
 | 
				
			||||||
 | 
					    fn def(&self) -> RelationDef {
 | 
				
			||||||
 | 
					        panic!("No RelationDef")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										36
									
								
								models/entity/src/timer.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								models/entity/src/timer.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "timer")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key)]
 | 
				
			||||||
 | 
					    pub id: i32,
 | 
				
			||||||
 | 
					    pub start_time: DateTimeUtc,
 | 
				
			||||||
 | 
					    pub name: String,
 | 
				
			||||||
 | 
					    pub user_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub guild_id: Option<i64>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::GuildId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild2,
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::UserId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild1,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										62
									
								
								models/entity/src/todo.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								models/entity/src/todo.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "todo")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key)]
 | 
				
			||||||
 | 
					    pub id: i32,
 | 
				
			||||||
 | 
					    pub user_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub guild_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub channel_id: Option<i64>,
 | 
				
			||||||
 | 
					    pub value: String,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::channel::Entity",
 | 
				
			||||||
 | 
					        from = "Column::ChannelId",
 | 
				
			||||||
 | 
					        to = "super::channel::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Channel,
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::guild::Entity",
 | 
				
			||||||
 | 
					        from = "Column::GuildId",
 | 
				
			||||||
 | 
					        to = "super::guild::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Guild,
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::user::Entity",
 | 
				
			||||||
 | 
					        from = "Column::UserId",
 | 
				
			||||||
 | 
					        to = "super::user::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    User,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::channel::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Channel.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::guild::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Guild.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::user::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::User.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										50
									
								
								models/entity/src/user.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								models/entity/src/user.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,50 @@
 | 
				
			|||||||
 | 
					//! SeaORM Entity. Generated by sea-orm-codegen 0.8.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use sea_orm::entity::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::sea_orm_active_enums::Timezone;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
 | 
				
			||||||
 | 
					#[sea_orm(table_name = "user")]
 | 
				
			||||||
 | 
					pub struct Model {
 | 
				
			||||||
 | 
					    #[sea_orm(primary_key, auto_increment = false)]
 | 
				
			||||||
 | 
					    pub id: i64,
 | 
				
			||||||
 | 
					    pub dm_channel: i64,
 | 
				
			||||||
 | 
					    pub timezone: Timezone,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 | 
				
			||||||
 | 
					pub enum Relation {
 | 
				
			||||||
 | 
					    #[sea_orm(
 | 
				
			||||||
 | 
					        belongs_to = "super::channel::Entity",
 | 
				
			||||||
 | 
					        from = "Column::DmChannel",
 | 
				
			||||||
 | 
					        to = "super::channel::Column::Id",
 | 
				
			||||||
 | 
					        on_update = "NoAction",
 | 
				
			||||||
 | 
					        on_delete = "Cascade"
 | 
				
			||||||
 | 
					    )]
 | 
				
			||||||
 | 
					    Channel,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::reminder::Entity")]
 | 
				
			||||||
 | 
					    Reminder,
 | 
				
			||||||
 | 
					    #[sea_orm(has_many = "super::todo::Entity")]
 | 
				
			||||||
 | 
					    Todo,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::channel::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Channel.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::reminder::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Reminder.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Related<super::todo::Entity> for Entity {
 | 
				
			||||||
 | 
					    fn to() -> RelationDef {
 | 
				
			||||||
 | 
					        Relation::Todo.def()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl ActiveModelBehavior for ActiveModel {}
 | 
				
			||||||
							
								
								
									
										2400
									
								
								models/migration/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2400
									
								
								models/migration/Cargo.lock
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										16
									
								
								models/migration/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								models/migration/Cargo.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					[package]
 | 
				
			||||||
 | 
					name = "migration"
 | 
				
			||||||
 | 
					version = "0.1.0"
 | 
				
			||||||
 | 
					edition = "2021"
 | 
				
			||||||
 | 
					publish = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[lib]
 | 
				
			||||||
 | 
					name = "migration"
 | 
				
			||||||
 | 
					path = "src/lib.rs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies]
 | 
				
			||||||
 | 
					entity = { path = "../entity" }
 | 
				
			||||||
 | 
					chrono-tz = "^0.6"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dependencies.sea-orm-migration]
 | 
				
			||||||
 | 
					version = "^0.8.0"
 | 
				
			||||||
							
								
								
									
										37
									
								
								models/migration/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								models/migration/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					# Running Migrator CLI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Apply all pending migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- up
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Apply first 10 pending migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- up -n 10
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Rollback last applied migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- down
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Rollback last 10 applied migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- down -n 10
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Drop all tables from the database, then reapply all migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- fresh
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Rollback all applied migrations, then reapply all migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- refresh
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Rollback all applied migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- reset
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					- Check the status of all migrations
 | 
				
			||||||
 | 
					    ```sh
 | 
				
			||||||
 | 
					    cargo run -- status
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
							
								
								
									
										12
									
								
								models/migration/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								models/migration/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					pub use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod m20220101_000001_create_table;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Migrator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigratorTrait for Migrator {
 | 
				
			||||||
 | 
					    fn migrations() -> Vec<Box<dyn MigrationTrait>> {
 | 
				
			||||||
 | 
					        vec![Box::new(m20220101_000001_create_table::Migration)]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										553
									
								
								models/migration/src/m20220101_000001_create_table.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										553
									
								
								models/migration/src/m20220101_000001_create_table.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,553 @@
 | 
				
			|||||||
 | 
					use chrono_tz::{Tz, TZ_VARIANTS};
 | 
				
			||||||
 | 
					use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::extension::postgres::Type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Migration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl MigrationName for Migration {
 | 
				
			||||||
 | 
					    fn name(&self) -> &str {
 | 
				
			||||||
 | 
					        "m20220101_000001_create_table"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum Guild {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum Channel {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    GuildId,
 | 
				
			||||||
 | 
					    Nudge,
 | 
				
			||||||
 | 
					    WebhookId,
 | 
				
			||||||
 | 
					    WebhookToken,
 | 
				
			||||||
 | 
					    Paused,
 | 
				
			||||||
 | 
					    PausedUntil,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum User {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    DmChannel,
 | 
				
			||||||
 | 
					    Timezone,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum Reminder {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    Uid,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    ChannelId,
 | 
				
			||||||
 | 
					    UtcTime,
 | 
				
			||||||
 | 
					    Timezone,
 | 
				
			||||||
 | 
					    IntervalSeconds,
 | 
				
			||||||
 | 
					    IntervalMonths,
 | 
				
			||||||
 | 
					    Enabled,
 | 
				
			||||||
 | 
					    Expires,
 | 
				
			||||||
 | 
					    Username,
 | 
				
			||||||
 | 
					    Avatar,
 | 
				
			||||||
 | 
					    Content,
 | 
				
			||||||
 | 
					    Tts,
 | 
				
			||||||
 | 
					    Attachment,
 | 
				
			||||||
 | 
					    AttachmentName,
 | 
				
			||||||
 | 
					    EmbedTitle,
 | 
				
			||||||
 | 
					    EmbedDescription,
 | 
				
			||||||
 | 
					    EmbedImageUrl,
 | 
				
			||||||
 | 
					    EmbedThumbnailUrl,
 | 
				
			||||||
 | 
					    EmbedFooter,
 | 
				
			||||||
 | 
					    EmbedFooterUrl,
 | 
				
			||||||
 | 
					    EmbedAuthor,
 | 
				
			||||||
 | 
					    EmbedAuthorUrl,
 | 
				
			||||||
 | 
					    EmbedColor,
 | 
				
			||||||
 | 
					    EmbedFields,
 | 
				
			||||||
 | 
					    SetAt,
 | 
				
			||||||
 | 
					    SetBy,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum ReminderTemplate {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    GuildId,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    Username,
 | 
				
			||||||
 | 
					    Avatar,
 | 
				
			||||||
 | 
					    Content,
 | 
				
			||||||
 | 
					    Tts,
 | 
				
			||||||
 | 
					    Attachment,
 | 
				
			||||||
 | 
					    AttachmentName,
 | 
				
			||||||
 | 
					    EmbedTitle,
 | 
				
			||||||
 | 
					    EmbedDescription,
 | 
				
			||||||
 | 
					    EmbedImageUrl,
 | 
				
			||||||
 | 
					    EmbedThumbnailUrl,
 | 
				
			||||||
 | 
					    EmbedFooter,
 | 
				
			||||||
 | 
					    EmbedFooterUrl,
 | 
				
			||||||
 | 
					    EmbedAuthor,
 | 
				
			||||||
 | 
					    EmbedAuthorUrl,
 | 
				
			||||||
 | 
					    EmbedColor,
 | 
				
			||||||
 | 
					    EmbedFields,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum Timer {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    StartTime,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    UserId,
 | 
				
			||||||
 | 
					    GuildId,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum Todo {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    UserId,
 | 
				
			||||||
 | 
					    GuildId,
 | 
				
			||||||
 | 
					    ChannelId,
 | 
				
			||||||
 | 
					    Value,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Iden)]
 | 
				
			||||||
 | 
					pub enum CommandMacro {
 | 
				
			||||||
 | 
					    Table,
 | 
				
			||||||
 | 
					    Id,
 | 
				
			||||||
 | 
					    GuildId,
 | 
				
			||||||
 | 
					    Name,
 | 
				
			||||||
 | 
					    Description,
 | 
				
			||||||
 | 
					    Commands,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub enum Timezone {
 | 
				
			||||||
 | 
					    Type,
 | 
				
			||||||
 | 
					    Tz(Tz),
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Iden for Timezone {
 | 
				
			||||||
 | 
					    fn unquoted(&self, s: &mut dyn Write) {
 | 
				
			||||||
 | 
					        write!(
 | 
				
			||||||
 | 
					            s,
 | 
				
			||||||
 | 
					            "{}",
 | 
				
			||||||
 | 
					            match self {
 | 
				
			||||||
 | 
					                Self::Type => "timezone".to_string(),
 | 
				
			||||||
 | 
					                Self::Tz(tz) => tz.to_string(),
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .unwrap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_trait::async_trait]
 | 
				
			||||||
 | 
					impl MigrationTrait for Migration {
 | 
				
			||||||
 | 
					    async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_type(
 | 
				
			||||||
 | 
					                Type::create()
 | 
				
			||||||
 | 
					                    .as_enum(Timezone::Type)
 | 
				
			||||||
 | 
					                    .values(TZ_VARIANTS.iter().map(|tz| Timezone::Tz(tz.to_owned())))
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Guild::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Guild::Id).big_integer().not_null().primary_key())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Channel::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::Id).big_integer().not_null().primary_key())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::GuildId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::Nudge).integer().not_null().default(0))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::WebhookId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::WebhookToken).string())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::Paused).boolean().not_null().default(false))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Channel::PausedUntil).date_time())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_channel_guild")
 | 
				
			||||||
 | 
					                    .from(Channel::Table, Channel::GuildId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(User::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::Id).big_integer().not_null().primary_key())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(User::DmChannel).big_integer().not_null())
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(User::Timezone)
 | 
				
			||||||
 | 
					                            .custom(Timezone::Type)
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .default("UTC"),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_user_channel")
 | 
				
			||||||
 | 
					                    .from(User::Table, User::DmChannel)
 | 
				
			||||||
 | 
					                    .to(Channel::Table, Channel::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Reminder::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(Reminder::Id)
 | 
				
			||||||
 | 
					                            .integer()
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .auto_increment()
 | 
				
			||||||
 | 
					                            .primary_key(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Uid).string().char_len(64).not_null())
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(Reminder::Name)
 | 
				
			||||||
 | 
					                            .string()
 | 
				
			||||||
 | 
					                            .char_len(24)
 | 
				
			||||||
 | 
					                            .default("Reminder")
 | 
				
			||||||
 | 
					                            .not_null(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::ChannelId).big_integer().not_null())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::UtcTime).date_time().not_null())
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(Reminder::Timezone)
 | 
				
			||||||
 | 
					                            .custom(Timezone::Type)
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .default("UTC"),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::IntervalSeconds).integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::IntervalMonths).integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Enabled).boolean().not_null().default(false))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Expires).date_time())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Username).string_len(32))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Avatar).string_len(512))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Content).string_len(2000))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Tts).boolean().not_null().default(false))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::Attachment).binary_len(8 * 1024 * 1024))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::AttachmentName).string_len(260))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedTitle).string_len(256))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedDescription).string_len(4096))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedImageUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedThumbnailUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedFooter).string_len(2048))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedFooterUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedAuthor).string_len(256))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedAuthorUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedColor).integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::EmbedFields).json())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::SetAt).date_time().not_null().default("NOW()"))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Reminder::SetBy).big_integer().not_null())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_reminder_channel")
 | 
				
			||||||
 | 
					                    .from(Reminder::Table, Reminder::ChannelId)
 | 
				
			||||||
 | 
					                    .to(Channel::Table, Channel::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_reminder_user")
 | 
				
			||||||
 | 
					                    .from(Reminder::Table, Reminder::SetBy)
 | 
				
			||||||
 | 
					                    .to(User::Table, User::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(ReminderTemplate::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(ReminderTemplate::Id)
 | 
				
			||||||
 | 
					                            .integer()
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .auto_increment()
 | 
				
			||||||
 | 
					                            .primary_key(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::GuildId).big_integer().not_null())
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(ReminderTemplate::Name)
 | 
				
			||||||
 | 
					                            .string()
 | 
				
			||||||
 | 
					                            .char_len(24)
 | 
				
			||||||
 | 
					                            .default("Reminder")
 | 
				
			||||||
 | 
					                            .not_null(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::Username).string_len(32))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::Avatar).string_len(512))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::Content).string_len(2000))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::Tts).boolean().not_null().default(false))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::Attachment).binary_len(8 * 1024 * 1024))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::AttachmentName).string_len(260))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedTitle).string_len(256))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedDescription).string_len(4096))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedImageUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedThumbnailUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedFooter).string_len(2048))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedFooterUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedAuthor).string_len(256))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedAuthorUrl).string_len(500))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedColor).integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(ReminderTemplate::EmbedFields).json())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_reminder_template_guild")
 | 
				
			||||||
 | 
					                    .from(ReminderTemplate::Table, ReminderTemplate::GuildId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Timer::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(Timer::Id)
 | 
				
			||||||
 | 
					                            .integer()
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .auto_increment()
 | 
				
			||||||
 | 
					                            .primary_key(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Timer::StartTime).date_time().not_null().default("NOW()"))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Timer::Name).string_len(32).not_null().default("Timer"))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Timer::UserId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Timer::GuildId).big_integer())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_timer_user")
 | 
				
			||||||
 | 
					                    .from(Timer::Table, Timer::UserId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_timer_guild")
 | 
				
			||||||
 | 
					                    .from(Timer::Table, Timer::GuildId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(Todo::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(Todo::Id)
 | 
				
			||||||
 | 
					                            .integer()
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .auto_increment()
 | 
				
			||||||
 | 
					                            .primary_key(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Todo::UserId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Todo::GuildId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Todo::ChannelId).big_integer())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(Todo::Value).string_len(2000).not_null())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_todo_user")
 | 
				
			||||||
 | 
					                    .from(Todo::Table, Todo::UserId)
 | 
				
			||||||
 | 
					                    .to(User::Table, User::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_todo_guild")
 | 
				
			||||||
 | 
					                    .from(Todo::Table, Todo::GuildId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_todo_channel")
 | 
				
			||||||
 | 
					                    .from(Todo::Table, Todo::ChannelId)
 | 
				
			||||||
 | 
					                    .to(Channel::Table, Channel::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_table(
 | 
				
			||||||
 | 
					                Table::create()
 | 
				
			||||||
 | 
					                    .table(CommandMacro::Table)
 | 
				
			||||||
 | 
					                    .if_not_exists()
 | 
				
			||||||
 | 
					                    .col(
 | 
				
			||||||
 | 
					                        ColumnDef::new(CommandMacro::Id)
 | 
				
			||||||
 | 
					                            .integer()
 | 
				
			||||||
 | 
					                            .not_null()
 | 
				
			||||||
 | 
					                            .auto_increment()
 | 
				
			||||||
 | 
					                            .primary_key(),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(CommandMacro::GuildId).big_integer().not_null())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(CommandMacro::Name).string_len(100).not_null())
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(CommandMacro::Description).string_len(100))
 | 
				
			||||||
 | 
					                    .col(ColumnDef::new(CommandMacro::Commands).json())
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .create_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::create()
 | 
				
			||||||
 | 
					                    .name("fk_command_macro_guild")
 | 
				
			||||||
 | 
					                    .from(CommandMacro::Table, CommandMacro::GuildId)
 | 
				
			||||||
 | 
					                    .to(Guild::Table, Guild::Id)
 | 
				
			||||||
 | 
					                    .on_delete(ForeignKeyAction::Cascade)
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Channel::Table).name("fk_channel_guild").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(User::Table).name("fk_user_channel").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Reminder::Table).name("fk_reminder_channel").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Reminder::Table).name("fk_reminder_user").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop()
 | 
				
			||||||
 | 
					                    .table(ReminderTemplate::Table)
 | 
				
			||||||
 | 
					                    .name("fk_reminder_template_guild")
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Timer::Table).name("fk_timer_user").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Timer::Table).name("fk_timer_guild").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(ForeignKey::drop().table(Todo::Table).name("fk_todo_user").to_owned())
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Todo::Table).name("fk_todo_guild").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop().table(Todo::Table).name("fk_todo_channel").to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					        manager
 | 
				
			||||||
 | 
					            .drop_foreign_key(
 | 
				
			||||||
 | 
					                ForeignKey::drop()
 | 
				
			||||||
 | 
					                    .table(CommandMacro::Table)
 | 
				
			||||||
 | 
					                    .name("fk_command_macro_guild")
 | 
				
			||||||
 | 
					                    .to_owned(),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(Guild::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(Channel::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(User::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(Reminder::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(ReminderTemplate::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(Timer::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(Todo::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					        manager.drop_table(Table::drop().table(CommandMacro::Table).to_owned()).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        manager.drop_type(Type::drop().name(Timezone::Type).to_owned()).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								models/migration/src/main.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								models/migration/src/main.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					use sea_orm_migration::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[async_std::main]
 | 
				
			||||||
 | 
					async fn main() {
 | 
				
			||||||
 | 
					    cli::run_cli(migration::Migrator).await;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										1
									
								
								models/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								models/src/lib.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@@ -7,7 +7,7 @@ use regex::{Captures, Regex};
 | 
				
			|||||||
use serde::Deserialize;
 | 
					use serde::Deserialize;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    builder::CreateEmbed,
 | 
					    builder::CreateEmbed,
 | 
				
			||||||
    http::{CacheHttp, Http, StatusCode},
 | 
					    http::{CacheHttp, Http, HttpError, StatusCode},
 | 
				
			||||||
    model::{
 | 
					    model::{
 | 
				
			||||||
        channel::{Channel, Embed as SerenityEmbed},
 | 
					        channel::{Channel, Embed as SerenityEmbed},
 | 
				
			||||||
        id::ChannelId,
 | 
					        id::ChannelId,
 | 
				
			||||||
@@ -58,10 +58,10 @@ fn fmt_displacement(format: &str, seconds: u64) -> String {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub fn substitute(string: &str) -> String {
 | 
					pub fn substitute(string: &str) -> String {
 | 
				
			||||||
    let new = TIMEFROM_REGEX.replace(string, |caps: &Captures| {
 | 
					    let new = TIMEFROM_REGEX.replace(string, |caps: &Captures| {
 | 
				
			||||||
        let final_time = caps.name("time").unwrap().as_str();
 | 
					        let final_time = caps.name("time").map(|m| m.as_str().parse::<i64>().ok()).flatten();
 | 
				
			||||||
        let format = caps.name("format").unwrap().as_str();
 | 
					        let format = caps.name("format").map(|m| m.as_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if let Ok(final_time) = final_time.parse::<i64>() {
 | 
					        if let (Some(final_time), Some(format)) = (final_time, format) {
 | 
				
			||||||
            let dt = NaiveDateTime::from_timestamp(final_time, 0);
 | 
					            let dt = NaiveDateTime::from_timestamp(final_time, 0);
 | 
				
			||||||
            let now = Utc::now().naive_utc();
 | 
					            let now = Utc::now().naive_utc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -81,13 +81,11 @@ pub fn substitute(string: &str) -> String {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    TIMENOW_REGEX
 | 
					    TIMENOW_REGEX
 | 
				
			||||||
        .replace(&new, |caps: &Captures| {
 | 
					        .replace(&new, |caps: &Captures| {
 | 
				
			||||||
            let timezone = caps.name("timezone").unwrap().as_str();
 | 
					            let timezone = caps.name("timezone").map(|m| m.as_str().parse::<Tz>().ok()).flatten();
 | 
				
			||||||
 | 
					            let format = caps.name("format").map(|m| m.as_str());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            println!("{}", timezone);
 | 
					            if let (Some(timezone), Some(format)) = (timezone, format) {
 | 
				
			||||||
 | 
					                let now = Utc::now().with_timezone(&timezone);
 | 
				
			||||||
            if let Ok(tz) = timezone.parse::<Tz>() {
 | 
					 | 
				
			||||||
                let format = caps.name("format").unwrap().as_str();
 | 
					 | 
				
			||||||
                let now = Utc::now().with_timezone(&tz);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                now.format(format).to_string()
 | 
					                now.format(format).to_string()
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@@ -122,7 +120,7 @@ impl Embed {
 | 
				
			|||||||
        pool: impl Executor<'_, Database = Database> + Copy,
 | 
					        pool: impl Executor<'_, Database = Database> + Copy,
 | 
				
			||||||
        id: u32,
 | 
					        id: u32,
 | 
				
			||||||
    ) -> Option<Self> {
 | 
					    ) -> Option<Self> {
 | 
				
			||||||
        let mut embed = sqlx::query_as!(
 | 
					        match sqlx::query_as!(
 | 
				
			||||||
            Self,
 | 
					            Self,
 | 
				
			||||||
            r#"
 | 
					            r#"
 | 
				
			||||||
            SELECT
 | 
					            SELECT
 | 
				
			||||||
@@ -142,8 +140,8 @@ impl Embed {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
        .fetch_one(pool)
 | 
					        .fetch_one(pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .unwrap();
 | 
					        {
 | 
				
			||||||
 | 
					            Ok(mut embed) => {
 | 
				
			||||||
                embed.title = substitute(&embed.title);
 | 
					                embed.title = substitute(&embed.title);
 | 
				
			||||||
                embed.description = substitute(&embed.description);
 | 
					                embed.description = substitute(&embed.description);
 | 
				
			||||||
                embed.footer = substitute(&embed.footer);
 | 
					                embed.footer = substitute(&embed.footer);
 | 
				
			||||||
@@ -160,6 +158,14 @@ impl Embed {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                warn!("Error loading embed from reminder: {:?}", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                None
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn has_content(&self) -> bool {
 | 
					    pub fn has_content(&self) -> bool {
 | 
				
			||||||
        if self.title.is_empty()
 | 
					        if self.title.is_empty()
 | 
				
			||||||
            && self.description.is_empty()
 | 
					            && self.description.is_empty()
 | 
				
			||||||
@@ -251,9 +257,9 @@ pub struct Reminder {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
impl Reminder {
 | 
					impl Reminder {
 | 
				
			||||||
    pub async fn fetch_reminders(pool: impl Executor<'_, Database = Database> + Copy) -> Vec<Self> {
 | 
					    pub async fn fetch_reminders(pool: impl Executor<'_, Database = Database> + Copy) -> Vec<Self> {
 | 
				
			||||||
        sqlx::query_as_unchecked!(
 | 
					        match sqlx::query_as_unchecked!(
 | 
				
			||||||
            Reminder,
 | 
					            Reminder,
 | 
				
			||||||
            "
 | 
					            r#"
 | 
				
			||||||
SELECT
 | 
					SELECT
 | 
				
			||||||
    reminders.`id` AS id,
 | 
					    reminders.`id` AS id,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -261,9 +267,9 @@ SELECT
 | 
				
			|||||||
    channels.`webhook_id` AS webhook_id,
 | 
					    channels.`webhook_id` AS webhook_id,
 | 
				
			||||||
    channels.`webhook_token` AS webhook_token,
 | 
					    channels.`webhook_token` AS webhook_token,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    channels.`paused` AS channel_paused,
 | 
					    channels.`paused` AS 'channel_paused',
 | 
				
			||||||
    channels.`paused_until` AS channel_paused_until,
 | 
					    channels.`paused_until` AS 'channel_paused_until',
 | 
				
			||||||
    reminders.`enabled` AS enabled,
 | 
					    reminders.`enabled` AS 'enabled',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    reminders.`tts` AS tts,
 | 
					    reminders.`tts` AS tts,
 | 
				
			||||||
    reminders.`pin` AS pin,
 | 
					    reminders.`pin` AS pin,
 | 
				
			||||||
@@ -274,7 +280,7 @@ SELECT
 | 
				
			|||||||
    reminders.`utc_time` AS 'utc_time',
 | 
					    reminders.`utc_time` AS 'utc_time',
 | 
				
			||||||
    reminders.`timezone` AS timezone,
 | 
					    reminders.`timezone` AS timezone,
 | 
				
			||||||
    reminders.`restartable` AS restartable,
 | 
					    reminders.`restartable` AS restartable,
 | 
				
			||||||
    reminders.`expires` AS expires,
 | 
					    reminders.`expires` AS 'expires',
 | 
				
			||||||
    reminders.`interval_seconds` AS 'interval_seconds',
 | 
					    reminders.`interval_seconds` AS 'interval_seconds',
 | 
				
			||||||
    reminders.`interval_months` AS 'interval_months',
 | 
					    reminders.`interval_months` AS 'interval_months',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -288,18 +294,27 @@ ON
 | 
				
			|||||||
    reminders.channel_id = channels.id
 | 
					    reminders.channel_id = channels.id
 | 
				
			||||||
WHERE
 | 
					WHERE
 | 
				
			||||||
    reminders.`utc_time` < NOW()
 | 
					    reminders.`utc_time` < NOW()
 | 
				
			||||||
            ",
 | 
					LIMIT 25
 | 
				
			||||||
 | 
					            "#,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .fetch_all(pool)
 | 
					        .fetch_all(pool)
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .unwrap()
 | 
					        {
 | 
				
			||||||
 | 
					            Ok(reminders) => reminders
 | 
				
			||||||
                .into_iter()
 | 
					                .into_iter()
 | 
				
			||||||
                .map(|mut rem| {
 | 
					                .map(|mut rem| {
 | 
				
			||||||
                    rem.content = substitute(&rem.content);
 | 
					                    rem.content = substitute(&rem.content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    rem
 | 
					                    rem
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
        .collect::<Vec<Self>>()
 | 
					                .collect::<Vec<Self>>(),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Err(e) => {
 | 
				
			||||||
 | 
					                warn!("Could not fetch reminders: {:?}", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                vec![]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn reset_webhook(&self, pool: impl Executor<'_, Database = Database> + Copy) {
 | 
					    async fn reset_webhook(&self, pool: impl Executor<'_, Database = Database> + Copy) {
 | 
				
			||||||
@@ -319,7 +334,7 @@ UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?
 | 
				
			|||||||
            let mut updated_reminder_time = self.utc_time;
 | 
					            let mut updated_reminder_time = self.utc_time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let Some(interval) = self.interval_months {
 | 
					            if let Some(interval) = self.interval_months {
 | 
				
			||||||
                let row = sqlx::query!(
 | 
					                match sqlx::query!(
 | 
				
			||||||
                    // use the second date_add to force return value to datetime
 | 
					                    // use the second date_add to force return value to datetime
 | 
				
			||||||
                    "SELECT DATE_ADD(DATE_ADD(?, INTERVAL ? MONTH), INTERVAL 0 SECOND) AS new_time",
 | 
					                    "SELECT DATE_ADD(DATE_ADD(?, INTERVAL ? MONTH), INTERVAL 0 SECOND) AS new_time",
 | 
				
			||||||
                    updated_reminder_time,
 | 
					                    updated_reminder_time,
 | 
				
			||||||
@@ -327,9 +342,25 @@ UPDATE channels SET webhook_id = NULL, webhook_token = NULL WHERE channel = ?
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
                .fetch_one(pool)
 | 
					                .fetch_one(pool)
 | 
				
			||||||
                .await
 | 
					                .await
 | 
				
			||||||
                .unwrap();
 | 
					                {
 | 
				
			||||||
 | 
					                    Ok(row) => match row.new_time {
 | 
				
			||||||
 | 
					                        Some(datetime) => {
 | 
				
			||||||
 | 
					                            updated_reminder_time = datetime;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        None => {
 | 
				
			||||||
 | 
					                            warn!("Could not update interval by months: got NULL");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                updated_reminder_time = row.new_time.unwrap();
 | 
					                            updated_reminder_time += Duration::days(30);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Err(e) => {
 | 
				
			||||||
 | 
					                        warn!("Could not update interval by months: {:?}", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // naively fallback to adding 30 days
 | 
				
			||||||
 | 
					                        updated_reminder_time += Duration::days(30);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if let Some(interval) = self.interval_seconds {
 | 
					            if let Some(interval) = self.interval_seconds {
 | 
				
			||||||
@@ -538,12 +569,17 @@ UPDATE `channels` SET paused = 0, paused_until = NULL WHERE `channel` = ?
 | 
				
			|||||||
                error!("Error sending {:?}: {:?}", self, e);
 | 
					                error!("Error sending {:?}: {:?}", self, e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if let Error::Http(error) = e {
 | 
					                if let Error::Http(error) = e {
 | 
				
			||||||
                    if error.status_code() == Some(StatusCode::from_u16(404).unwrap()) {
 | 
					                    if error.status_code() == Some(StatusCode::NOT_FOUND) {
 | 
				
			||||||
                        error!("Seeing channel is deleted. Removing reminder");
 | 
					                        warn!("Seeing channel is deleted. Removing reminder");
 | 
				
			||||||
 | 
					                        self.force_delete(pool).await;
 | 
				
			||||||
 | 
					                    } else if let HttpError::UnsuccessfulRequest(error) = *error {
 | 
				
			||||||
 | 
					                        if error.error.code == 50007 {
 | 
				
			||||||
 | 
					                            warn!("User cannot receive DMs");
 | 
				
			||||||
                            self.force_delete(pool).await;
 | 
					                            self.force_delete(pool).await;
 | 
				
			||||||
                        } else {
 | 
					                        } else {
 | 
				
			||||||
                            self.refresh(pool).await;
 | 
					                            self.refresh(pool).await;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    self.refresh(pool).await;
 | 
					                    self.refresh(pool).await;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ pub async fn info(ctx: Context<'_>) -> Result<(), Error> {
 | 
				
			|||||||
        .send(|m| {
 | 
					        .send(|m| {
 | 
				
			||||||
            m.ephemeral(true).embed(|e| {
 | 
					            m.ephemeral(true).embed(|e| {
 | 
				
			||||||
                e.title("Info")
 | 
					                e.title("Info")
 | 
				
			||||||
                    .description(format!(
 | 
					                    .description(
 | 
				
			||||||
                        "Help: `/help`
 | 
					                        "Help: `/help`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**Welcome to Reminder Bot!**
 | 
					**Welcome to Reminder Bot!**
 | 
				
			||||||
@@ -81,7 +81,7 @@ Find me on https://discord.jellywx.com and on https://github.com/JellyWX :)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Invite the bot: https://invite.reminder-bot.com/
 | 
					Invite the bot: https://invite.reminder-bot.com/
 | 
				
			||||||
Use our dashboard: https://reminder-bot.com/",
 | 
					Use our dashboard: https://reminder-bot.com/",
 | 
				
			||||||
                    ))
 | 
					                    )
 | 
				
			||||||
                    .footer(footer)
 | 
					                    .footer(footer)
 | 
				
			||||||
                    .color(*THEME_COLOR)
 | 
					                    .color(*THEME_COLOR)
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					use std::collections::hash_map::Entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use chrono::offset::Utc;
 | 
					use chrono::offset::Utc;
 | 
				
			||||||
use chrono_tz::{Tz, TZ_VARIANTS};
 | 
					use chrono_tz::{Tz, TZ_VARIANTS};
 | 
				
			||||||
use levenshtein::levenshtein;
 | 
					use levenshtein::levenshtein;
 | 
				
			||||||
@@ -52,7 +54,7 @@ pub async fn timezone(
 | 
				
			|||||||
                            .description(format!(
 | 
					                            .description(format!(
 | 
				
			||||||
                                "Timezone has been set to **{}**. Your current time should be `{}`",
 | 
					                                "Timezone has been set to **{}**. Your current time should be `{}`",
 | 
				
			||||||
                                timezone,
 | 
					                                timezone,
 | 
				
			||||||
                                now.format("%H:%M").to_string()
 | 
					                                now.format("%H:%M")
 | 
				
			||||||
                            ))
 | 
					                            ))
 | 
				
			||||||
                            .color(*THEME_COLOR)
 | 
					                            .color(*THEME_COLOR)
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
@@ -75,10 +77,7 @@ pub async fn timezone(
 | 
				
			|||||||
                let fields = filtered_tz.iter().map(|tz| {
 | 
					                let fields = filtered_tz.iter().map(|tz| {
 | 
				
			||||||
                    (
 | 
					                    (
 | 
				
			||||||
                        tz.to_string(),
 | 
					                        tz.to_string(),
 | 
				
			||||||
                        format!(
 | 
					                        format!("🕗 `{}`", Utc::now().with_timezone(tz).format("%H:%M")),
 | 
				
			||||||
                            "🕗 `{}`",
 | 
					 | 
				
			||||||
                            Utc::now().with_timezone(tz).format("%H:%M").to_string()
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        true,
 | 
					                        true,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
@@ -98,11 +97,7 @@ pub async fn timezone(
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        let popular_timezones_iter = ctx.data().popular_timezones.iter().map(|t| {
 | 
					        let popular_timezones_iter = ctx.data().popular_timezones.iter().map(|t| {
 | 
				
			||||||
            (
 | 
					            (t.to_string(), format!("🕗 `{}`", Utc::now().with_timezone(t).format("%H:%M")), true)
 | 
				
			||||||
                t.to_string(),
 | 
					 | 
				
			||||||
                format!("🕗 `{}`", Utc::now().with_timezone(t).format("%H:%M").to_string()),
 | 
					 | 
				
			||||||
                true,
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ctx.send(|m| {
 | 
					        ctx.send(|m| {
 | 
				
			||||||
@@ -142,7 +137,7 @@ WHERE
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    .fetch_all(&ctx.data().database)
 | 
					    .fetch_all(&ctx.data().database)
 | 
				
			||||||
    .await
 | 
					    .await
 | 
				
			||||||
    .unwrap_or(vec![])
 | 
					    .unwrap_or_default()
 | 
				
			||||||
    .iter()
 | 
					    .iter()
 | 
				
			||||||
    .map(|s| s.name.clone())
 | 
					    .map(|s| s.name.clone())
 | 
				
			||||||
    .collect()
 | 
					    .collect()
 | 
				
			||||||
@@ -200,14 +195,11 @@ Please select a unique name for your macro.",
 | 
				
			|||||||
        let okay = {
 | 
					        let okay = {
 | 
				
			||||||
            let mut lock = ctx.data().recording_macros.write().await;
 | 
					            let mut lock = ctx.data().recording_macros.write().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if lock.contains_key(&(guild_id, ctx.author().id)) {
 | 
					            if let Entry::Vacant(e) = lock.entry((guild_id, ctx.author().id)) {
 | 
				
			||||||
                false
 | 
					                e.insert(CommandMacro { guild_id, name, description, commands: vec![] });
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                lock.insert(
 | 
					 | 
				
			||||||
                    (guild_id, ctx.author().id),
 | 
					 | 
				
			||||||
                    CommandMacro { guild_id, name, description, commands: vec![] },
 | 
					 | 
				
			||||||
                );
 | 
					 | 
				
			||||||
                true
 | 
					                true
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,13 +9,14 @@ use chrono_tz::Tz;
 | 
				
			|||||||
use num_integer::Integer;
 | 
					use num_integer::Integer;
 | 
				
			||||||
use poise::{
 | 
					use poise::{
 | 
				
			||||||
    serenity::{builder::CreateEmbed, model::channel::Channel},
 | 
					    serenity::{builder::CreateEmbed, model::channel::Channel},
 | 
				
			||||||
 | 
					    serenity_prelude::{ButtonStyle, ReactionType},
 | 
				
			||||||
    CreateReply,
 | 
					    CreateReply,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    component_models::{
 | 
					    component_models::{
 | 
				
			||||||
        pager::{DelPager, LookPager, Pager},
 | 
					        pager::{DelPager, LookPager, Pager},
 | 
				
			||||||
        ComponentDataModel, DelSelector,
 | 
					        ComponentDataModel, DelSelector, UndoReminder,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    consts::{
 | 
					    consts::{
 | 
				
			||||||
        EMBED_DESCRIPTION_MAX_LENGTH, HOUR, MINUTE, REGEX_CHANNEL_USER, SELECT_MAX_ENTRIES,
 | 
					        EMBED_DESCRIPTION_MAX_LENGTH, HOUR, MINUTE, REGEX_CHANNEL_USER, SELECT_MAX_ENTRIES,
 | 
				
			||||||
@@ -500,8 +501,7 @@ pub async fn start_timer(
 | 
				
			|||||||
    if count >= 25 {
 | 
					    if count >= 25 {
 | 
				
			||||||
        ctx.say("You already have 25 timers. Please delete some timers before creating a new one")
 | 
					        ctx.say("You already have 25 timers. Please delete some timers before creating a new one")
 | 
				
			||||||
            .await?;
 | 
					            .await?;
 | 
				
			||||||
    } else {
 | 
					    } else if name.len() <= 32 {
 | 
				
			||||||
        if name.len() <= 32 {
 | 
					 | 
				
			||||||
        Timer::create(&name, owner, &ctx.data().database).await;
 | 
					        Timer::create(&name, owner, &ctx.data().database).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ctx.say("Created a new timer").await?;
 | 
					        ctx.say("Created a new timer").await?;
 | 
				
			||||||
@@ -512,7 +512,6 @@ pub async fn start_timer(
 | 
				
			|||||||
        ))
 | 
					        ))
 | 
				
			||||||
        .await?;
 | 
					        .await?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -589,8 +588,7 @@ pub async fn remind(
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let scopes = {
 | 
					            let scopes = {
 | 
				
			||||||
                let list =
 | 
					                let list = channels.map(|arg| parse_mention_list(&arg)).unwrap_or_default();
 | 
				
			||||||
                    channels.map(|arg| parse_mention_list(&arg.to_string())).unwrap_or_default();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if list.is_empty() {
 | 
					                if list.is_empty() {
 | 
				
			||||||
                    if ctx.guild_id().is_some() {
 | 
					                    if ctx.guild_id().is_some() {
 | 
				
			||||||
@@ -610,7 +608,7 @@ pub async fn remind(
 | 
				
			|||||||
                {
 | 
					                {
 | 
				
			||||||
                    (
 | 
					                    (
 | 
				
			||||||
                        parse_duration(repeat)
 | 
					                        parse_duration(repeat)
 | 
				
			||||||
                            .or_else(|_| parse_duration(&format!("1 {}", repeat.to_string())))
 | 
					                            .or_else(|_| parse_duration(&format!("1 {}", repeat)))
 | 
				
			||||||
                            .ok(),
 | 
					                            .ok(),
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            if let Some(arg) = &expires {
 | 
					                            if let Some(arg) = &expires {
 | 
				
			||||||
@@ -653,8 +651,39 @@ pub async fn remind(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                let (errors, successes) = builder.build().await;
 | 
					                let (errors, successes) = builder.build().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                let embed = create_response(successes, errors, time);
 | 
					                let embed = create_response(&successes, &errors, time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if successes.len() == 1 {
 | 
				
			||||||
 | 
					                    let reminder = successes.iter().next().map(|(r, _)| r.id).unwrap();
 | 
				
			||||||
 | 
					                    let undo_button = ComponentDataModel::UndoReminder(UndoReminder {
 | 
				
			||||||
 | 
					                        user_id: ctx.author().id,
 | 
				
			||||||
 | 
					                        reminder_id: reminder,
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    ctx.send(|m| {
 | 
				
			||||||
 | 
					                        m.embed(|c| {
 | 
				
			||||||
 | 
					                            *c = embed;
 | 
				
			||||||
 | 
					                            c
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .components(|c| {
 | 
				
			||||||
 | 
					                            c.create_action_row(|r| {
 | 
				
			||||||
 | 
					                                r.create_button(|b| {
 | 
				
			||||||
 | 
					                                    b.emoji(ReactionType::Unicode("🔕".to_string()))
 | 
				
			||||||
 | 
					                                        .label("Cancel")
 | 
				
			||||||
 | 
					                                        .style(ButtonStyle::Danger)
 | 
				
			||||||
 | 
					                                        .custom_id(undo_button.to_custom_id())
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                                .create_button(|b| {
 | 
				
			||||||
 | 
					                                    b.emoji(ReactionType::Unicode("📝".to_string()))
 | 
				
			||||||
 | 
					                                        .label("Edit")
 | 
				
			||||||
 | 
					                                        .style(ButtonStyle::Link)
 | 
				
			||||||
 | 
					                                        .url("https://reminder-bot.com/dashboard")
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                    .await?;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
                    ctx.send(|m| {
 | 
					                    ctx.send(|m| {
 | 
				
			||||||
                        m.embed(|c| {
 | 
					                        m.embed(|c| {
 | 
				
			||||||
                            *c = embed;
 | 
					                            *c = embed;
 | 
				
			||||||
@@ -664,6 +693,7 @@ pub async fn remind(
 | 
				
			|||||||
                    .await?;
 | 
					                    .await?;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        None => {
 | 
					        None => {
 | 
				
			||||||
            ctx.say("Time could not be processed").await?;
 | 
					            ctx.say("Time could not be processed").await?;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -673,8 +703,8 @@ pub async fn remind(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn create_response(
 | 
					fn create_response(
 | 
				
			||||||
    successes: HashSet<ReminderScope>,
 | 
					    successes: &HashSet<(Reminder, ReminderScope)>,
 | 
				
			||||||
    errors: HashSet<ReminderError>,
 | 
					    errors: &HashSet<ReminderError>,
 | 
				
			||||||
    time: i64,
 | 
					    time: i64,
 | 
				
			||||||
) -> CreateEmbed {
 | 
					) -> CreateEmbed {
 | 
				
			||||||
    let success_part = match successes.len() {
 | 
					    let success_part = match successes.len() {
 | 
				
			||||||
@@ -682,7 +712,8 @@ fn create_response(
 | 
				
			|||||||
        n => format!(
 | 
					        n => format!(
 | 
				
			||||||
            "Reminder{s} for {locations} set for <t:{offset}:R>",
 | 
					            "Reminder{s} for {locations} set for <t:{offset}:R>",
 | 
				
			||||||
            s = if n > 1 { "s" } else { "" },
 | 
					            s = if n > 1 { "s" } else { "" },
 | 
				
			||||||
            locations = successes.iter().map(|l| l.mention()).collect::<Vec<String>>().join(", "),
 | 
					            locations =
 | 
				
			||||||
 | 
					                successes.iter().map(|(_, l)| l.mention()).collect::<Vec<String>>().join(", "),
 | 
				
			||||||
            offset = time
 | 
					            offset = time
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -336,7 +336,7 @@ pub fn show_todo_page(
 | 
				
			|||||||
                                opt.create_option(|o| {
 | 
					                                opt.create_option(|o| {
 | 
				
			||||||
                                    o.label(format!("Mark {} complete", count + first_num))
 | 
					                                    o.label(format!("Mark {} complete", count + first_num))
 | 
				
			||||||
                                        .value(id)
 | 
					                                        .value(id)
 | 
				
			||||||
                                        .description(disp.split_once(" ").unwrap_or(("", "")).1)
 | 
					                                        .description(disp.split_once(' ').unwrap_or(("", "")).1)
 | 
				
			||||||
                                });
 | 
					                                });
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,14 +3,20 @@ pub(crate) mod pager;
 | 
				
			|||||||
use std::io::Cursor;
 | 
					use std::io::Cursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use chrono_tz::Tz;
 | 
					use chrono_tz::Tz;
 | 
				
			||||||
use poise::serenity::{
 | 
					use log::warn;
 | 
				
			||||||
 | 
					use poise::{
 | 
				
			||||||
 | 
					    serenity::{
 | 
				
			||||||
        builder::CreateEmbed,
 | 
					        builder::CreateEmbed,
 | 
				
			||||||
        client::Context,
 | 
					        client::Context,
 | 
				
			||||||
        model::{
 | 
					        model::{
 | 
				
			||||||
            channel::Channel,
 | 
					            channel::Channel,
 | 
				
			||||||
        interactions::{message_component::MessageComponentInteraction, InteractionResponseType},
 | 
					            interactions::{
 | 
				
			||||||
 | 
					                message_component::MessageComponentInteraction, InteractionResponseType,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            prelude::InteractionApplicationCommandCallbackDataFlags,
 | 
					            prelude::InteractionApplicationCommandCallbackDataFlags,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    serenity_prelude as serenity,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use rmp_serde::Serializer;
 | 
					use rmp_serde::Serializer;
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
@@ -38,6 +44,7 @@ pub enum ComponentDataModel {
 | 
				
			|||||||
    DelSelector(DelSelector),
 | 
					    DelSelector(DelSelector),
 | 
				
			||||||
    TodoSelector(TodoSelector),
 | 
					    TodoSelector(TodoSelector),
 | 
				
			||||||
    MacroPager(MacroPager),
 | 
					    MacroPager(MacroPager),
 | 
				
			||||||
 | 
					    UndoReminder(UndoReminder),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ComponentDataModel {
 | 
					impl ComponentDataModel {
 | 
				
			||||||
@@ -334,6 +341,70 @@ WHERE guilds.guild = ?",
 | 
				
			|||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .await;
 | 
					                    .await;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            ComponentDataModel::UndoReminder(undo_reminder) => {
 | 
				
			||||||
 | 
					                if component.user.id == undo_reminder.user_id {
 | 
				
			||||||
 | 
					                    let reminder =
 | 
				
			||||||
 | 
					                        Reminder::from_id(&data.database, undo_reminder.reminder_id).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if let Some(reminder) = reminder {
 | 
				
			||||||
 | 
					                        match reminder.delete(&data.database).await {
 | 
				
			||||||
 | 
					                            Ok(()) => {
 | 
				
			||||||
 | 
					                                let _ = component
 | 
				
			||||||
 | 
					                                    .create_interaction_response(&ctx, |f| {
 | 
				
			||||||
 | 
					                                        f.kind(InteractionResponseType::UpdateMessage)
 | 
				
			||||||
 | 
					                                            .interaction_response_data(|d| {
 | 
				
			||||||
 | 
					                                                d.embed(|e| {
 | 
				
			||||||
 | 
					                                                    e.title("Reminder Canceled")
 | 
				
			||||||
 | 
					                                                        .description(
 | 
				
			||||||
 | 
					                                                            "This reminder has been canceled.",
 | 
				
			||||||
 | 
					                                                        )
 | 
				
			||||||
 | 
					                                                        .color(*THEME_COLOR)
 | 
				
			||||||
 | 
					                                                })
 | 
				
			||||||
 | 
					                                                .components(|c| c)
 | 
				
			||||||
 | 
					                                            })
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                                    .await;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            Err(e) => {
 | 
				
			||||||
 | 
					                                warn!("Error canceling reminder: {:?}", e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                                let _ = component
 | 
				
			||||||
 | 
					                                    .create_interaction_response(&ctx, |f| {
 | 
				
			||||||
 | 
					                                        f.kind(InteractionResponseType::ChannelMessageWithSource)
 | 
				
			||||||
 | 
					                                            .interaction_response_data(|d| {
 | 
				
			||||||
 | 
					                                                d.content(
 | 
				
			||||||
 | 
					                                                    "The reminder could not be canceled: it may have already been deleted. Check `/del`!")
 | 
				
			||||||
 | 
					                                                    .ephemeral(true)
 | 
				
			||||||
 | 
					                                            })
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                                    .await;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        let _ = component
 | 
				
			||||||
 | 
					                            .create_interaction_response(&ctx, |f| {
 | 
				
			||||||
 | 
					                                f.kind(InteractionResponseType::ChannelMessageWithSource)
 | 
				
			||||||
 | 
					                                    .interaction_response_data(|d| {
 | 
				
			||||||
 | 
					                                        d.content(
 | 
				
			||||||
 | 
					                                            "The reminder could not be canceled: it may have already been deleted. Check `/del`!")
 | 
				
			||||||
 | 
					                                            .ephemeral(true)
 | 
				
			||||||
 | 
					                                    })
 | 
				
			||||||
 | 
					                            })
 | 
				
			||||||
 | 
					                            .await;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    let _ = component
 | 
				
			||||||
 | 
					                        .create_interaction_response(&ctx, |f| {
 | 
				
			||||||
 | 
					                            f.kind(InteractionResponseType::ChannelMessageWithSource)
 | 
				
			||||||
 | 
					                                .interaction_response_data(|d| {
 | 
				
			||||||
 | 
					                                    d.content(
 | 
				
			||||||
 | 
					                                        "Only the user who performed the command can use this button.")
 | 
				
			||||||
 | 
					                                        .ephemeral(true)
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                        .await;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -351,3 +422,9 @@ pub struct TodoSelector {
 | 
				
			|||||||
    pub channel_id: Option<u64>,
 | 
					    pub channel_id: Option<u64>,
 | 
				
			||||||
    pub guild_id: Option<u64>,
 | 
					    pub guild_id: Option<u64>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct UndoReminder {
 | 
				
			||||||
 | 
					    pub user_id: serenity::UserId,
 | 
				
			||||||
 | 
					    pub reminder_id: u32,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,15 +36,11 @@ lazy_static! {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
    pub static ref CNC_GUILD: Option<u64> =
 | 
					    pub static ref CNC_GUILD: Option<u64> =
 | 
				
			||||||
        env::var("CNC_GUILD").map(|var| var.parse::<u64>().ok()).ok().flatten();
 | 
					        env::var("CNC_GUILD").map(|var| var.parse::<u64>().ok()).ok().flatten();
 | 
				
			||||||
    pub static ref MIN_INTERVAL: i64 = env::var("MIN_INTERVAL")
 | 
					    pub static ref MIN_INTERVAL: i64 =
 | 
				
			||||||
        .ok()
 | 
					        env::var("MIN_INTERVAL").ok().and_then(|inner| inner.parse::<i64>().ok()).unwrap_or(600);
 | 
				
			||||||
        .map(|inner| inner.parse::<i64>().ok())
 | 
					 | 
				
			||||||
        .flatten()
 | 
					 | 
				
			||||||
        .unwrap_or(600);
 | 
					 | 
				
			||||||
    pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
 | 
					    pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
 | 
				
			||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
        .map(|inner| inner.parse::<i64>().ok())
 | 
					        .and_then(|inner| inner.parse::<i64>().ok())
 | 
				
			||||||
        .flatten()
 | 
					 | 
				
			||||||
        .unwrap_or(60 * 60 * 24 * 365 * 50);
 | 
					        .unwrap_or(60 * 60 * 24 * 365 * 50);
 | 
				
			||||||
    pub static ref LOCAL_TIMEZONE: String =
 | 
					    pub static ref LOCAL_TIMEZONE: String =
 | 
				
			||||||
        env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
 | 
					        env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,9 @@ pub async fn listener(
 | 
				
			|||||||
    data: &Data,
 | 
					    data: &Data,
 | 
				
			||||||
) -> Result<(), Error> {
 | 
					) -> Result<(), Error> {
 | 
				
			||||||
    match event {
 | 
					    match event {
 | 
				
			||||||
 | 
					        poise::Event::Ready { .. } => {
 | 
				
			||||||
 | 
					            ctx.set_activity(serenity::Activity::watching("for /remind")).await;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        poise::Event::CacheReady { .. } => {
 | 
					        poise::Event::CacheReady { .. } => {
 | 
				
			||||||
            info!("Cache Ready! Preparing extra processes");
 | 
					            info!("Cache Ready! Preparing extra processes");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -39,7 +42,7 @@ pub async fn listener(
 | 
				
			|||||||
                        };
 | 
					                        };
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    warn!("Not running postman")
 | 
					                    warn!("Not running postman");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if !run_settings.contains("web") {
 | 
					                if !run_settings.contains("web") {
 | 
				
			||||||
@@ -47,7 +50,7 @@ pub async fn listener(
 | 
				
			|||||||
                        reminder_web::initialize(kill_tx, ctx2, pool2).await.unwrap();
 | 
					                        reminder_web::initialize(kill_tx, ctx2, pool2).await.unwrap();
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    warn!("Not running web")
 | 
					                    warn!("Not running web");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                data.is_loop_running.swap(true, Ordering::Relaxed);
 | 
					                data.is_loop_running.swap(true, Ordering::Relaxed);
 | 
				
			||||||
@@ -111,14 +114,13 @@ pub async fn listener(
 | 
				
			|||||||
                .execute(&data.database)
 | 
					                .execute(&data.database)
 | 
				
			||||||
                .await;
 | 
					                .await;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        poise::Event::InteractionCreate { interaction } => match interaction {
 | 
					        poise::Event::InteractionCreate { interaction } => {
 | 
				
			||||||
            Interaction::MessageComponent(component) => {
 | 
					            if let Interaction::MessageComponent(component) = interaction {
 | 
				
			||||||
                let component_model = ComponentDataModel::from_custom_id(&component.data.custom_id);
 | 
					                let component_model = ComponentDataModel::from_custom_id(&component.data.custom_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                component_model.act(ctx, data, component).await;
 | 
					                component_model.act(ctx, data, component).await;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            _ => {}
 | 
					        }
 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        _ => {}
 | 
					        _ => {}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								src/hooks.rs
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/hooks.rs
									
									
									
									
									
								
							@@ -30,19 +30,13 @@ async fn macro_check(ctx: Context<'_>) -> bool {
 | 
				
			|||||||
                            .await;
 | 
					                            .await;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    false
 | 
					                    return false;
 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    true
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                true
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            true
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        true
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async fn check_self_permissions(ctx: Context<'_>) -> bool {
 | 
					async fn check_self_permissions(ctx: Context<'_>) -> bool {
 | 
				
			||||||
@@ -56,14 +50,13 @@ async fn check_self_permissions(ctx: Context<'_>) -> bool {
 | 
				
			|||||||
        let (view_channel, send_messages, embed_links) = ctx
 | 
					        let (view_channel, send_messages, embed_links) = ctx
 | 
				
			||||||
            .channel_id()
 | 
					            .channel_id()
 | 
				
			||||||
            .to_channel_cached(&ctx.discord())
 | 
					            .to_channel_cached(&ctx.discord())
 | 
				
			||||||
            .map(|c| {
 | 
					            .and_then(|c| {
 | 
				
			||||||
                if let Channel::Guild(channel) = c {
 | 
					                if let Channel::Guild(channel) = c {
 | 
				
			||||||
                    channel.permissions_for_user(&ctx.discord(), user_id).ok()
 | 
					                    channel.permissions_for_user(&ctx.discord(), user_id).ok()
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    None
 | 
					                    None
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            .flatten()
 | 
					 | 
				
			||||||
            .map_or((false, false, false), |p| {
 | 
					            .map_or((false, false, false), |p| {
 | 
				
			||||||
                (p.view_channel(), p.send_messages(), p.embed_links())
 | 
					                (p.view_channel(), p.send_messages(), p.embed_links())
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -75,7 +75,7 @@ impl fmt::Display for Error {
 | 
				
			|||||||
        match self {
 | 
					        match self {
 | 
				
			||||||
            Error::InvalidCharacter(offset) => write!(f, "invalid character at {}", offset),
 | 
					            Error::InvalidCharacter(offset) => write!(f, "invalid character at {}", offset),
 | 
				
			||||||
            Error::NumberExpected(offset) => write!(f, "expected number at {}", offset),
 | 
					            Error::NumberExpected(offset) => write!(f, "expected number at {}", offset),
 | 
				
			||||||
            Error::UnknownUnit { unit, value, .. } if &unit == &"" => {
 | 
					            Error::UnknownUnit { unit, value, .. } if unit.is_empty() => {
 | 
				
			||||||
                write!(f, "time unit needed, for example {0}sec or {0}ms", value,)
 | 
					                write!(f, "time unit needed, for example {0}sec or {0}ms", value,)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Error::UnknownUnit { unit, .. } => {
 | 
					            Error::UnknownUnit { unit, .. } => {
 | 
				
			||||||
@@ -162,11 +162,11 @@ impl<'a> Parser<'a> {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        let mut nsec = self.current.2 + nsec;
 | 
					        let mut nsec = self.current.2 + nsec;
 | 
				
			||||||
        if nsec > 1_000_000_000 {
 | 
					        if nsec > 1_000_000_000 {
 | 
				
			||||||
            sec = sec + nsec / 1_000_000_000;
 | 
					            sec += nsec / 1_000_000_000;
 | 
				
			||||||
            nsec %= 1_000_000_000;
 | 
					            nsec %= 1_000_000_000;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        sec = self.current.1 + sec;
 | 
					        sec += self.current.1;
 | 
				
			||||||
        month = self.current.0 + month;
 | 
					        month += self.current.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.current = (month, sec, nsec);
 | 
					        self.current = (month, sec, nsec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
#![feature(int_roundings)]
 | 
					#![feature(int_roundings)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[macro_use]
 | 
					#[macro_use]
 | 
				
			||||||
extern crate lazy_static;
 | 
					extern crate lazy_static;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,7 +24,7 @@ use std::{
 | 
				
			|||||||
use chrono_tz::Tz;
 | 
					use chrono_tz::Tz;
 | 
				
			||||||
use dotenv::dotenv;
 | 
					use dotenv::dotenv;
 | 
				
			||||||
use poise::serenity::model::{
 | 
					use poise::serenity::model::{
 | 
				
			||||||
    gateway::{Activity, GatewayIntents},
 | 
					    gateway::GatewayIntents,
 | 
				
			||||||
    id::{GuildId, UserId},
 | 
					    id::{GuildId, UserId},
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use sqlx::{MySql, Pool};
 | 
					use sqlx::{MySql, Pool};
 | 
				
			||||||
@@ -52,7 +53,7 @@ pub struct Data {
 | 
				
			|||||||
    broadcast: Sender<()>,
 | 
					    broadcast: Sender<()>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl std::fmt::Debug for Data {
 | 
					impl Debug for Data {
 | 
				
			||||||
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        write!(f, "Data {{ .. }}")
 | 
					        write!(f, "Data {{ .. }}")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -171,8 +172,6 @@ async fn _main(tx: Sender<()>) -> Result<(), Box<dyn StdError + Send + Sync>> {
 | 
				
			|||||||
        .token(discord_token)
 | 
					        .token(discord_token)
 | 
				
			||||||
        .user_data_setup(move |ctx, _bot, framework| {
 | 
					        .user_data_setup(move |ctx, _bot, framework| {
 | 
				
			||||||
            Box::pin(async move {
 | 
					            Box::pin(async move {
 | 
				
			||||||
                ctx.set_activity(Activity::watching("for /remind")).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                register_application_commands(
 | 
					                register_application_commands(
 | 
				
			||||||
                    ctx,
 | 
					                    ctx,
 | 
				
			||||||
                    framework,
 | 
					                    framework,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,11 +5,11 @@ use serde::{Deserialize, Serialize};
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use crate::{Context, Data, Error};
 | 
					use crate::{Context, Data, Error};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn default_none<U, E>() -> Option<
 | 
					type Func<U, E> = for<'a> fn(
 | 
				
			||||||
    for<'a> fn(
 | 
					 | 
				
			||||||
    poise::ApplicationContext<'a, U, E>,
 | 
					    poise::ApplicationContext<'a, U, E>,
 | 
				
			||||||
    ) -> poise::BoxFuture<'a, Result<(), poise::FrameworkError<'a, U, E>>>,
 | 
					) -> poise::BoxFuture<'a, Result<(), poise::FrameworkError<'a, U, E>>>;
 | 
				
			||||||
> {
 | 
					
 | 
				
			||||||
 | 
					fn default_none<U, E>() -> Option<Func<U, E>> {
 | 
				
			||||||
    None
 | 
					    None
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -17,11 +17,7 @@ fn default_none<U, E>() -> Option<
 | 
				
			|||||||
pub struct RecordedCommand<U, E> {
 | 
					pub struct RecordedCommand<U, E> {
 | 
				
			||||||
    #[serde(skip)]
 | 
					    #[serde(skip)]
 | 
				
			||||||
    #[serde(default = "default_none::<U, E>")]
 | 
					    #[serde(default = "default_none::<U, E>")]
 | 
				
			||||||
    pub action: Option<
 | 
					    pub action: Option<Func<U, E>>,
 | 
				
			||||||
        for<'a> fn(
 | 
					 | 
				
			||||||
            poise::ApplicationContext<'a, U, E>,
 | 
					 | 
				
			||||||
        ) -> poise::BoxFuture<'a, Result<(), poise::FrameworkError<'a, U, E>>>,
 | 
					 | 
				
			||||||
    >,
 | 
					 | 
				
			||||||
    pub command_name: String,
 | 
					    pub command_name: String,
 | 
				
			||||||
    pub options: Vec<ApplicationCommandInteractionDataOption>,
 | 
					    pub options: Vec<ApplicationCommandInteractionDataOption>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -59,7 +55,7 @@ SELECT * FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND
 | 
				
			|||||||
            .iter()
 | 
					            .iter()
 | 
				
			||||||
            .find(|c| c.identifying_name == recorded_command.command_name);
 | 
					            .find(|c| c.identifying_name == recorded_command.command_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        recorded_command.action = command.map(|c| c.slash_action).flatten().clone();
 | 
					        recorded_command.action = command.map(|c| c.slash_action).flatten();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let command_macro = CommandMacro {
 | 
					    let command_macro = CommandMacro {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,7 +126,7 @@ INSERT INTO reminders (
 | 
				
			|||||||
                    .await
 | 
					                    .await
 | 
				
			||||||
                    .unwrap();
 | 
					                    .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    Ok(Reminder::from_uid(&self.pool, self.uid).await.unwrap())
 | 
					                    Ok(Reminder::from_uid(&self.pool, &self.uid).await.unwrap())
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -207,7 +207,7 @@ impl<'a> MultiReminderBuilder<'a> {
 | 
				
			|||||||
        self.scopes = scopes;
 | 
					        self.scopes = scopes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn build(self) -> (HashSet<ReminderError>, HashSet<ReminderScope>) {
 | 
					    pub async fn build(self) -> (HashSet<ReminderError>, HashSet<(Reminder, ReminderScope)>) {
 | 
				
			||||||
        let mut errors = HashSet::new();
 | 
					        let mut errors = HashSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut ok_locs = HashSet::new();
 | 
					        let mut ok_locs = HashSet::new();
 | 
				
			||||||
@@ -309,8 +309,8 @@ impl<'a> MultiReminderBuilder<'a> {
 | 
				
			|||||||
                        };
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        match builder.build().await {
 | 
					                        match builder.build().await {
 | 
				
			||||||
                            Ok(_) => {
 | 
					                            Ok(r) => {
 | 
				
			||||||
                                ok_locs.insert(scope);
 | 
					                                ok_locs.insert((r, scope));
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            Err(e) => {
 | 
					                            Err(e) => {
 | 
				
			||||||
                                errors.insert(e);
 | 
					                                errors.insert(e);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@ pub mod errors;
 | 
				
			|||||||
mod helper;
 | 
					mod helper;
 | 
				
			||||||
pub mod look_flags;
 | 
					pub mod look_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::hash::{Hash, Hasher};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use chrono::{NaiveDateTime, TimeZone};
 | 
					use chrono::{NaiveDateTime, TimeZone};
 | 
				
			||||||
use chrono_tz::Tz;
 | 
					use chrono_tz::Tz;
 | 
				
			||||||
use poise::{
 | 
					use poise::{
 | 
				
			||||||
@@ -32,11 +34,22 @@ pub struct Reminder {
 | 
				
			|||||||
    pub set_by: Option<u64>,
 | 
					    pub set_by: Option<u64>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Hash for Reminder {
 | 
				
			||||||
 | 
					    fn hash<H: Hasher>(&self, state: &mut H) {
 | 
				
			||||||
 | 
					        self.uid.hash(state);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl PartialEq<Self> for Reminder {
 | 
				
			||||||
 | 
					    fn eq(&self, other: &Self) -> bool {
 | 
				
			||||||
 | 
					        self.uid == other.uid
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Eq for Reminder {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Reminder {
 | 
					impl Reminder {
 | 
				
			||||||
    pub async fn from_uid(
 | 
					    pub async fn from_uid(pool: impl Executor<'_, Database = Database>, uid: &str) -> Option<Self> {
 | 
				
			||||||
        pool: impl Executor<'_, Database = Database>,
 | 
					 | 
				
			||||||
        uid: String,
 | 
					 | 
				
			||||||
    ) -> Option<Self> {
 | 
					 | 
				
			||||||
        sqlx::query_as_unchecked!(
 | 
					        sqlx::query_as_unchecked!(
 | 
				
			||||||
            Self,
 | 
					            Self,
 | 
				
			||||||
            "
 | 
					            "
 | 
				
			||||||
@@ -72,6 +85,42 @@ WHERE
 | 
				
			|||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn from_id(pool: impl Executor<'_, Database = Database>, id: u32) -> Option<Self> {
 | 
				
			||||||
 | 
					        sqlx::query_as_unchecked!(
 | 
				
			||||||
 | 
					            Self,
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					SELECT
 | 
				
			||||||
 | 
					    reminders.id,
 | 
				
			||||||
 | 
					    reminders.uid,
 | 
				
			||||||
 | 
					    channels.channel,
 | 
				
			||||||
 | 
					    reminders.utc_time,
 | 
				
			||||||
 | 
					    reminders.interval_seconds,
 | 
				
			||||||
 | 
					    reminders.interval_months,
 | 
				
			||||||
 | 
					    reminders.expires,
 | 
				
			||||||
 | 
					    reminders.enabled,
 | 
				
			||||||
 | 
					    reminders.content,
 | 
				
			||||||
 | 
					    reminders.embed_description,
 | 
				
			||||||
 | 
					    users.user AS set_by
 | 
				
			||||||
 | 
					FROM
 | 
				
			||||||
 | 
					    reminders
 | 
				
			||||||
 | 
					INNER JOIN
 | 
				
			||||||
 | 
					    channels
 | 
				
			||||||
 | 
					ON
 | 
				
			||||||
 | 
					    reminders.channel_id = channels.id
 | 
				
			||||||
 | 
					LEFT JOIN
 | 
				
			||||||
 | 
					    users
 | 
				
			||||||
 | 
					ON
 | 
				
			||||||
 | 
					    reminders.set_by = users.id
 | 
				
			||||||
 | 
					WHERE
 | 
				
			||||||
 | 
					    reminders.id = ?
 | 
				
			||||||
 | 
					            ",
 | 
				
			||||||
 | 
					            id
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        .fetch_one(pool)
 | 
				
			||||||
 | 
					        .await
 | 
				
			||||||
 | 
					        .ok()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn from_channel<C: Into<ChannelId>>(
 | 
					    pub async fn from_channel<C: Into<ChannelId>>(
 | 
				
			||||||
        pool: impl Executor<'_, Database = Database>,
 | 
					        pool: impl Executor<'_, Database = Database>,
 | 
				
			||||||
        channel_id: C,
 | 
					        channel_id: C,
 | 
				
			||||||
@@ -240,6 +289,13 @@ WHERE
 | 
				
			|||||||
        .unwrap()
 | 
					        .unwrap()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub async fn delete(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        db: impl Executor<'_, Database = Database>,
 | 
				
			||||||
 | 
					    ) -> Result<(), sqlx::Error> {
 | 
				
			||||||
 | 
					        sqlx::query!("DELETE FROM reminders WHERE uid = ?", self.uid).execute(db).await.map(|_| ())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn display_content(&self) -> &str {
 | 
					    pub fn display_content(&self) -> &str {
 | 
				
			||||||
        if self.content.is_empty() {
 | 
					        if self.content.is_empty() {
 | 
				
			||||||
            &self.embed_description
 | 
					            &self.embed_description
 | 
				
			||||||
@@ -254,10 +310,7 @@ WHERE
 | 
				
			|||||||
            count + 1,
 | 
					            count + 1,
 | 
				
			||||||
            self.display_content(),
 | 
					            self.display_content(),
 | 
				
			||||||
            self.channel,
 | 
					            self.channel,
 | 
				
			||||||
            timezone
 | 
					            timezone.timestamp(self.utc_time.timestamp(), 0).format("%Y-%m-%d %H:%M:%S")
 | 
				
			||||||
                .timestamp(self.utc_time.timestamp(), 0)
 | 
					 | 
				
			||||||
                .format("%Y-%m-%d %H:%M:%S")
 | 
					 | 
				
			||||||
                .to_string()
 | 
					 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,7 @@ INSERT IGNORE INTO channels (channel) VALUES (?)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                sqlx::query!(
 | 
					                sqlx::query!(
 | 
				
			||||||
                    "
 | 
					                    "
 | 
				
			||||||
INSERT INTO users (user, dm_channel, timezone) VALUES (?, (SELECT id FROM channels WHERE channel = ?), ?)
 | 
					INSERT INTO users (name, user, dm_channel, timezone) VALUES ('', ?, (SELECT id FROM channels WHERE channel = ?), ?)
 | 
				
			||||||
                    ",
 | 
					                    ",
 | 
				
			||||||
                    user_id.0,
 | 
					                    user_id.0,
 | 
				
			||||||
                    dm_channel.id.0,
 | 
					                    dm_channel.id.0,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,14 +211,12 @@ pub async fn natural_parser(time: &str, timezone: &str) -> Option<i64> {
 | 
				
			|||||||
        .output()
 | 
					        .output()
 | 
				
			||||||
        .await
 | 
					        .await
 | 
				
			||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
        .map(|inner| {
 | 
					        .and_then(|inner| {
 | 
				
			||||||
            if inner.status.success() {
 | 
					            if inner.status.success() {
 | 
				
			||||||
                Some(from_utf8(&*inner.stdout).unwrap().parse::<i64>().unwrap())
 | 
					                Some(from_utf8(&*inner.stdout).unwrap().parse::<i64>().unwrap())
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                None
 | 
					                None
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .flatten()
 | 
					        .and_then(|inner| if inner < 0 { None } else { Some(inner) })
 | 
				
			||||||
        .map(|inner| if inner < 0 { None } else { Some(inner) })
 | 
					 | 
				
			||||||
        .flatten()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,6 +126,9 @@ pub async fn initialize(
 | 
				
			|||||||
                routes::help_timers,
 | 
					                routes::help_timers,
 | 
				
			||||||
                routes::help_todo_lists,
 | 
					                routes::help_todo_lists,
 | 
				
			||||||
                routes::help_macros,
 | 
					                routes::help_macros,
 | 
				
			||||||
 | 
					                routes::help_intervals,
 | 
				
			||||||
 | 
					                routes::help_dashboard,
 | 
				
			||||||
 | 
					                routes::help_iemanager,
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .mount("/login", routes![routes::login::discord_login, routes::login::discord_callback])
 | 
					        .mount("/login", routes![routes::login::discord_login, routes::login::discord_callback])
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -420,12 +420,11 @@ pub async fn create_reminder(
 | 
				
			|||||||
         interval_seconds,
 | 
					         interval_seconds,
 | 
				
			||||||
         interval_months,
 | 
					         interval_months,
 | 
				
			||||||
         name,
 | 
					         name,
 | 
				
			||||||
         pin,
 | 
					 | 
				
			||||||
         restartable,
 | 
					         restartable,
 | 
				
			||||||
         tts,
 | 
					         tts,
 | 
				
			||||||
         username,
 | 
					         username,
 | 
				
			||||||
         `utc_time`
 | 
					         `utc_time`
 | 
				
			||||||
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
 | 
					        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
 | 
				
			||||||
        new_uid,
 | 
					        new_uid,
 | 
				
			||||||
        attachment_data,
 | 
					        attachment_data,
 | 
				
			||||||
        reminder.attachment_name,
 | 
					        reminder.attachment_name,
 | 
				
			||||||
@@ -447,7 +446,6 @@ pub async fn create_reminder(
 | 
				
			|||||||
        reminder.interval_seconds,
 | 
					        reminder.interval_seconds,
 | 
				
			||||||
        reminder.interval_months,
 | 
					        reminder.interval_months,
 | 
				
			||||||
        name,
 | 
					        name,
 | 
				
			||||||
        reminder.pin,
 | 
					 | 
				
			||||||
        reminder.restartable,
 | 
					        reminder.restartable,
 | 
				
			||||||
        reminder.tts,
 | 
					        reminder.tts,
 | 
				
			||||||
        reminder.username,
 | 
					        reminder.username,
 | 
				
			||||||
@@ -479,7 +477,6 @@ pub async fn create_reminder(
 | 
				
			|||||||
             reminders.interval_seconds,
 | 
					             reminders.interval_seconds,
 | 
				
			||||||
             reminders.interval_months,
 | 
					             reminders.interval_months,
 | 
				
			||||||
             reminders.name,
 | 
					             reminders.name,
 | 
				
			||||||
             reminders.pin,
 | 
					 | 
				
			||||||
             reminders.restartable,
 | 
					             reminders.restartable,
 | 
				
			||||||
             reminders.tts,
 | 
					             reminders.tts,
 | 
				
			||||||
             reminders.uid,
 | 
					             reminders.uid,
 | 
				
			||||||
@@ -543,7 +540,6 @@ pub async fn get_reminders(id: u64, ctx: &State<Context>, pool: &State<Pool<MySq
 | 
				
			|||||||
                 reminders.interval_seconds,
 | 
					                 reminders.interval_seconds,
 | 
				
			||||||
                 reminders.interval_months,
 | 
					                 reminders.interval_months,
 | 
				
			||||||
                 reminders.name,
 | 
					                 reminders.name,
 | 
				
			||||||
                 reminders.pin,
 | 
					 | 
				
			||||||
                 reminders.restartable,
 | 
					                 reminders.restartable,
 | 
				
			||||||
                 reminders.tts,
 | 
					                 reminders.tts,
 | 
				
			||||||
                 reminders.uid,
 | 
					                 reminders.uid,
 | 
				
			||||||
@@ -600,7 +596,6 @@ pub async fn edit_reminder(
 | 
				
			|||||||
        interval_seconds,
 | 
					        interval_seconds,
 | 
				
			||||||
        interval_months,
 | 
					        interval_months,
 | 
				
			||||||
        name,
 | 
					        name,
 | 
				
			||||||
        pin,
 | 
					 | 
				
			||||||
        restartable,
 | 
					        restartable,
 | 
				
			||||||
        tts,
 | 
					        tts,
 | 
				
			||||||
        username,
 | 
					        username,
 | 
				
			||||||
@@ -687,7 +682,6 @@ pub async fn edit_reminder(
 | 
				
			|||||||
         reminders.interval_seconds,
 | 
					         reminders.interval_seconds,
 | 
				
			||||||
         reminders.interval_months,
 | 
					         reminders.interval_months,
 | 
				
			||||||
         reminders.name,
 | 
					         reminders.name,
 | 
				
			||||||
         reminders.pin,
 | 
					 | 
				
			||||||
         reminders.restartable,
 | 
					         reminders.restartable,
 | 
				
			||||||
         reminders.tts,
 | 
					         reminders.tts,
 | 
				
			||||||
         reminders.uid,
 | 
					         reminders.uid,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,7 +97,6 @@ pub struct Reminder {
 | 
				
			|||||||
    interval_months: Option<u32>,
 | 
					    interval_months: Option<u32>,
 | 
				
			||||||
    #[serde(default = "name_default")]
 | 
					    #[serde(default = "name_default")]
 | 
				
			||||||
    name: String,
 | 
					    name: String,
 | 
				
			||||||
    pin: bool,
 | 
					 | 
				
			||||||
    restartable: bool,
 | 
					    restartable: bool,
 | 
				
			||||||
    tts: bool,
 | 
					    tts: bool,
 | 
				
			||||||
    #[serde(default)]
 | 
					    #[serde(default)]
 | 
				
			||||||
@@ -151,8 +150,6 @@ pub struct PatchReminder {
 | 
				
			|||||||
    #[serde(default)]
 | 
					    #[serde(default)]
 | 
				
			||||||
    name: Unset<String>,
 | 
					    name: Unset<String>,
 | 
				
			||||||
    #[serde(default)]
 | 
					    #[serde(default)]
 | 
				
			||||||
    pin: Unset<bool>,
 | 
					 | 
				
			||||||
    #[serde(default)]
 | 
					 | 
				
			||||||
    restartable: Unset<bool>,
 | 
					    restartable: Unset<bool>,
 | 
				
			||||||
    #[serde(default)]
 | 
					    #[serde(default)]
 | 
				
			||||||
    tts: Unset<bool>,
 | 
					    tts: Unset<bool>,
 | 
				
			||||||
@@ -213,8 +210,8 @@ mod base64s {
 | 
				
			|||||||
    where
 | 
					    where
 | 
				
			||||||
        D: Deserializer<'de>,
 | 
					        D: Deserializer<'de>,
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let string = String::deserialize(deserializer)?;
 | 
					        let string = Option::<String>::deserialize(deserializer)?;
 | 
				
			||||||
        Some(base64::decode(string).map_err(de::Error::custom)).transpose()
 | 
					        Some(string.map(|b| base64::decode(b).map_err(de::Error::custom))).flatten().transpose()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,3 +86,21 @@ pub async fn help_macros() -> Template {
 | 
				
			|||||||
    let map: HashMap<&str, String> = HashMap::new();
 | 
					    let map: HashMap<&str, String> = HashMap::new();
 | 
				
			||||||
    Template::render("support/macros", &map)
 | 
					    Template::render("support/macros", &map)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[get("/intervals")]
 | 
				
			||||||
 | 
					pub async fn help_intervals() -> Template {
 | 
				
			||||||
 | 
					    let map: HashMap<&str, String> = HashMap::new();
 | 
				
			||||||
 | 
					    Template::render("support/intervals", &map)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[get("/dashboard")]
 | 
				
			||||||
 | 
					pub async fn help_dashboard() -> Template {
 | 
				
			||||||
 | 
					    let map: HashMap<&str, String> = HashMap::new();
 | 
				
			||||||
 | 
					    Template::render("support/dashboard", &map)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[get("/iemanager")]
 | 
				
			||||||
 | 
					pub async fn help_iemanager() -> Template {
 | 
				
			||||||
 | 
					    let map: HashMap<&str, String> = HashMap::new();
 | 
				
			||||||
 | 
					    Template::render("support/iemanager", &map)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -288,6 +288,10 @@ textarea, input {
 | 
				
			|||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					input.default-width {
 | 
				
			||||||
 | 
					    width: initial;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.message-input:placeholder-shown {
 | 
					.message-input:placeholder-shown {
 | 
				
			||||||
    border-top: none;
 | 
					    border-top: none;
 | 
				
			||||||
    border-left: none;
 | 
					    border-left: none;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								web/static/img/support/delete_reminder/cancel-1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/static/img/support/delete_reminder/cancel-1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 17 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/static/img/support/delete_reminder/cancel-2.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/static/img/support/delete_reminder/cancel-2.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 14 KiB  | 
@@ -14,10 +14,19 @@ const $deleteTemplateBtn = document.querySelector("button#delete-template");
 | 
				
			|||||||
const $templateSelect = document.querySelector("select#templateSelect");
 | 
					const $templateSelect = document.querySelector("select#templateSelect");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let channels = [];
 | 
					let channels = [];
 | 
				
			||||||
 | 
					let guildNames = {};
 | 
				
			||||||
let roles = [];
 | 
					let roles = [];
 | 
				
			||||||
let templates = {};
 | 
					let templates = {};
 | 
				
			||||||
 | 
					let mentions = new Tribute({
 | 
				
			||||||
 | 
					    values: [],
 | 
				
			||||||
 | 
					    allowSpaces: true,
 | 
				
			||||||
 | 
					    selectTemplate: (item) => {
 | 
				
			||||||
 | 
					        return `<@&${item.original.value}>`;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let globalPatreon = false;
 | 
					let globalPatreon = false;
 | 
				
			||||||
 | 
					let guildPatreon = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function guildId() {
 | 
					function guildId() {
 | 
				
			||||||
    return document.querySelector(".guildList a.is-active").dataset["guild"];
 | 
					    return document.querySelector(".guildList a.is-active").dataset["guild"];
 | 
				
			||||||
@@ -31,18 +40,6 @@ function intToColor(i) {
 | 
				
			|||||||
    return `#${i.toString(16).padStart(6, "0")}`;
 | 
					    return `#${i.toString(16).padStart(6, "0")}`;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function resize_textareas() {
 | 
					 | 
				
			||||||
    document.querySelectorAll("textarea.autoresize").forEach((element) => {
 | 
					 | 
				
			||||||
        element.style.height = "";
 | 
					 | 
				
			||||||
        element.style.height = element.scrollHeight + 3 + "px";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        element.addEventListener("input", () => {
 | 
					 | 
				
			||||||
            element.style.height = "";
 | 
					 | 
				
			||||||
            element.style.height = element.scrollHeight + 3 + "px";
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function switch_pane(selector) {
 | 
					function switch_pane(selector) {
 | 
				
			||||||
    document.querySelectorAll("aside a").forEach((el) => {
 | 
					    document.querySelectorAll("aside a").forEach((el) => {
 | 
				
			||||||
        el.classList.remove("is-active");
 | 
					        el.classList.remove("is-active");
 | 
				
			||||||
@@ -52,8 +49,6 @@ function switch_pane(selector) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    document.getElementById(selector).classList.remove("is-hidden");
 | 
					    document.getElementById(selector).classList.remove("is-hidden");
 | 
				
			||||||
 | 
					 | 
				
			||||||
    resize_textareas();
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function update_select(sel) {
 | 
					function update_select(sel) {
 | 
				
			||||||
@@ -78,6 +73,18 @@ function reset_guild_pane() {
 | 
				
			|||||||
        .forEach((opt) => opt.remove());
 | 
					        .forEach((opt) => opt.remove());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function fetch_patreon(guild_id) {
 | 
				
			||||||
 | 
					    fetch(`/dashboard/api/guild/${guild_id}/patreon`)
 | 
				
			||||||
 | 
					        .then((response) => response.json())
 | 
				
			||||||
 | 
					        .then((data) => {
 | 
				
			||||||
 | 
					            if (data.error) {
 | 
				
			||||||
 | 
					                show_error(data.error);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return data.patreon;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function fetch_roles(guild_id) {
 | 
					function fetch_roles(guild_id) {
 | 
				
			||||||
    fetch(`/dashboard/api/guild/${guild_id}/roles`)
 | 
					    fetch(`/dashboard/api/guild/${guild_id}/roles`)
 | 
				
			||||||
        .then((response) => response.json())
 | 
					        .then((response) => response.json())
 | 
				
			||||||
@@ -85,7 +92,16 @@ function fetch_roles(guild_id) {
 | 
				
			|||||||
            if (data.error) {
 | 
					            if (data.error) {
 | 
				
			||||||
                show_error(data.error);
 | 
					                show_error(data.error);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                roles = data;
 | 
					                let values = Array.from(
 | 
				
			||||||
 | 
					                    data.map((role) => {
 | 
				
			||||||
 | 
					                        return {
 | 
				
			||||||
 | 
					                            key: role.name,
 | 
				
			||||||
 | 
					                            value: role.id,
 | 
				
			||||||
 | 
					                        };
 | 
				
			||||||
 | 
					                    })
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                mentions.collection[0].values = values;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -158,6 +174,8 @@ async function fetch_reminders(guild_id) {
 | 
				
			|||||||
                    newFrame.querySelector(".reminderContent").dataset["uid"] =
 | 
					                    newFrame.querySelector(".reminderContent").dataset["uid"] =
 | 
				
			||||||
                        reminder["uid"];
 | 
					                        reminder["uid"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    mentions.attach(newFrame.querySelector("textarea"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    deserialize_reminder(reminder, newFrame, "load");
 | 
					                    deserialize_reminder(reminder, newFrame, "load");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    $reminderBox.appendChild(newFrame);
 | 
					                    $reminderBox.appendChild(newFrame);
 | 
				
			||||||
@@ -299,7 +317,6 @@ async function serialize_reminder(node, mode) {
 | 
				
			|||||||
        interval_seconds: mode !== "template" ? interval.seconds : null,
 | 
					        interval_seconds: mode !== "template" ? interval.seconds : null,
 | 
				
			||||||
        interval_months: mode !== "template" ? interval.months : null,
 | 
					        interval_months: mode !== "template" ? interval.months : null,
 | 
				
			||||||
        name: node.querySelector('input[name="name"]').value,
 | 
					        name: node.querySelector('input[name="name"]').value,
 | 
				
			||||||
        pin: node.querySelector('input[name="pin"]').checked,
 | 
					 | 
				
			||||||
        tts: node.querySelector('input[name="tts"]').checked,
 | 
					        tts: node.querySelector('input[name="tts"]').checked,
 | 
				
			||||||
        username: node.querySelector('input[name="username"]').value,
 | 
					        username: node.querySelector('input[name="username"]').value,
 | 
				
			||||||
        utc_time: utc_time,
 | 
					        utc_time: utc_time,
 | 
				
			||||||
@@ -370,6 +387,10 @@ function deserialize_reminder(reminder, frame, mode) {
 | 
				
			|||||||
document.addEventListener("guildSwitched", async (e) => {
 | 
					document.addEventListener("guildSwitched", async (e) => {
 | 
				
			||||||
    $loader.classList.remove("is-hidden");
 | 
					    $loader.classList.remove("is-hidden");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    document
 | 
				
			||||||
 | 
					        .querySelectorAll(".patreon-only")
 | 
				
			||||||
 | 
					        .forEach((el) => el.classList.add("is-locked"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let $anchor = document.querySelector(
 | 
					    let $anchor = document.querySelector(
 | 
				
			||||||
        `.switch-pane[data-guild="${e.detail.guild_id}"]`
 | 
					        `.switch-pane[data-guild="${e.detail.guild_id}"]`
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@@ -378,6 +399,12 @@ document.addEventListener("guildSwitched", async (e) => {
 | 
				
			|||||||
    reset_guild_pane();
 | 
					    reset_guild_pane();
 | 
				
			||||||
    $anchor.classList.add("is-active");
 | 
					    $anchor.classList.add("is-active");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (globalPatreon || (await fetch_patreon(e.detail.guild_id))) {
 | 
				
			||||||
 | 
					        document
 | 
				
			||||||
 | 
					            .querySelectorAll(".patreon-only")
 | 
				
			||||||
 | 
					            .forEach((el) => el.classList.remove("is-locked"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fetch_roles(e.detail.guild_id);
 | 
					    fetch_roles(e.detail.guild_id);
 | 
				
			||||||
    fetch_templates(e.detail.guild_id);
 | 
					    fetch_templates(e.detail.guild_id);
 | 
				
			||||||
    await fetch_channels(e.detail.guild_id);
 | 
					    await fetch_channels(e.detail.guild_id);
 | 
				
			||||||
@@ -392,8 +419,6 @@ document.addEventListener("guildSwitched", async (e) => {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    resize_textareas();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    $loader.classList.add("is-hidden");
 | 
					    $loader.classList.add("is-hidden");
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -531,6 +556,8 @@ document.querySelectorAll(".show-modal").forEach((element) => {
 | 
				
			|||||||
document.addEventListener("DOMContentLoaded", () => {
 | 
					document.addEventListener("DOMContentLoaded", () => {
 | 
				
			||||||
    $loader.classList.remove("is-hidden");
 | 
					    $loader.classList.remove("is-hidden");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mentions.attach(document.querySelectorAll("textarea"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    document.querySelectorAll(".navbar-burger").forEach((el) => {
 | 
					    document.querySelectorAll(".navbar-burger").forEach((el) => {
 | 
				
			||||||
        el.addEventListener("click", () => {
 | 
					        el.addEventListener("click", () => {
 | 
				
			||||||
            const target = el.dataset["target"];
 | 
					            const target = el.dataset["target"];
 | 
				
			||||||
@@ -569,6 +596,8 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
				
			|||||||
                const $template = document.getElementById("guildListEntry");
 | 
					                const $template = document.getElementById("guildListEntry");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                for (let guild of data) {
 | 
					                for (let guild of data) {
 | 
				
			||||||
 | 
					                    guildNames[guild.id] = guild.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    document.querySelectorAll(".guildList").forEach((element) => {
 | 
					                    document.querySelectorAll(".guildList").forEach((element) => {
 | 
				
			||||||
                        const $clone = $template.content.cloneNode(true);
 | 
					                        const $clone = $template.content.cloneNode(true);
 | 
				
			||||||
                        const $anchor = $clone.querySelector("a");
 | 
					                        const $anchor = $clone.querySelector("a");
 | 
				
			||||||
@@ -585,11 +614,7 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                        $anchor.addEventListener("click", async (e) => {
 | 
					                        $anchor.addEventListener("click", async (e) => {
 | 
				
			||||||
                            e.preventDefault();
 | 
					                            e.preventDefault();
 | 
				
			||||||
                            window.history.pushState(
 | 
					                            window.history.pushState({}, "", `/dashboard/${guild.id}`);
 | 
				
			||||||
                                {},
 | 
					 | 
				
			||||||
                                "",
 | 
					 | 
				
			||||||
                                `/dashboard/${guild.id}?name=${guild.name}`
 | 
					 | 
				
			||||||
                            );
 | 
					 | 
				
			||||||
                            const event = new CustomEvent("guildSwitched", {
 | 
					                            const event = new CustomEvent("guildSwitched", {
 | 
				
			||||||
                                detail: {
 | 
					                                detail: {
 | 
				
			||||||
                                    guild_name: guild.name,
 | 
					                                    guild_name: guild.name,
 | 
				
			||||||
@@ -607,8 +632,8 @@ document.addEventListener("DOMContentLoaded", () => {
 | 
				
			|||||||
                const matches = window.location.href.match(/dashboard\/(\d+)/);
 | 
					                const matches = window.location.href.match(/dashboard\/(\d+)/);
 | 
				
			||||||
                if (matches) {
 | 
					                if (matches) {
 | 
				
			||||||
                    let id = matches[1];
 | 
					                    let id = matches[1];
 | 
				
			||||||
                    let name =
 | 
					                    let name = guildNames[id];
 | 
				
			||||||
                        new URLSearchParams(window.location.search).get("name") || id;
 | 
					
 | 
				
			||||||
                    const event = new CustomEvent("guildSwitched", {
 | 
					                    const event = new CustomEvent("guildSwitched", {
 | 
				
			||||||
                        detail: {
 | 
					                        detail: {
 | 
				
			||||||
                            guild_name: name,
 | 
					                            guild_name: name,
 | 
				
			||||||
@@ -901,7 +926,6 @@ document.addEventListener("DOMNodeInserted", () => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    check_embed_fields();
 | 
					    check_embed_fields();
 | 
				
			||||||
    resize_textareas();
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
document.addEventListener("click", (ev) => {
 | 
					document.addEventListener("click", (ev) => {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,8 +27,10 @@
 | 
				
			|||||||
    <link rel="stylesheet" href="/static/css/font.css">
 | 
					    <link rel="stylesheet" href="/static/css/font.css">
 | 
				
			||||||
    <link rel="stylesheet" href="/static/css/style.css">
 | 
					    <link rel="stylesheet" href="/static/css/style.css">
 | 
				
			||||||
    <link rel="stylesheet" href="/static/css/dtsel.css">
 | 
					    <link rel="stylesheet" href="/static/css/dtsel.css">
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tributejs/5.1.3/tribute.css" integrity="sha512-GnwBnXd+ZGO9CdP343MUr0jCcJXCr++JVtQRnllexRW2IDq4Zvrh/McTQjooAKnSUbXZ7wamp7AQSweTnfMVoA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <script src="/static/js/luxon.min.js"></script>
 | 
					    <script src="/static/js/luxon.min.js"></script>
 | 
				
			||||||
 | 
					    <script src="https://cdnjs.cloudflare.com/ajax/libs/tributejs/5.1.3/tribute.min.js" integrity="sha512-KJYWC7RKz/Abtsu1QXd7VJ1IJua7P7GTpl3IKUqfa21Otg2opvRYmkui/CXBC6qeDYCNlQZ7c+7JfDXnKdILUA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
 | 
				
			||||||
</head>
 | 
					</head>
 | 
				
			||||||
<body>
 | 
					<body>
 | 
				
			||||||
<nav class="navbar is-spaced is-size-4 is-hidden-desktop dashboard-navbar" role="navigation"
 | 
					<nav class="navbar is-spaced is-size-4 is-hidden-desktop dashboard-navbar" role="navigation"
 | 
				
			||||||
@@ -173,6 +175,36 @@
 | 
				
			|||||||
            <button class="delete close-modal" aria-label="close"></button>
 | 
					            <button class="delete close-modal" aria-label="close"></button>
 | 
				
			||||||
        </header>
 | 
					        </header>
 | 
				
			||||||
        <section class="modal-card-body">
 | 
					        <section class="modal-card-body">
 | 
				
			||||||
 | 
					            <div class="control">
 | 
				
			||||||
 | 
					                <div class="field">
 | 
				
			||||||
 | 
					                    <input type="checkbox" class="default-width">
 | 
				
			||||||
 | 
					                    <label>Reminders</label>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="control">
 | 
				
			||||||
 | 
					                <div class="field">
 | 
				
			||||||
 | 
					                    <input type="checkbox" class="default-width">
 | 
				
			||||||
 | 
					                    <label>Todo Lists</label>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="control">
 | 
				
			||||||
 | 
					                <div class="field">
 | 
				
			||||||
 | 
					                    <input type="checkbox" class="default-width">
 | 
				
			||||||
 | 
					                    <label>Timers</label>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="control">
 | 
				
			||||||
 | 
					                <div class="field">
 | 
				
			||||||
 | 
					                    <input type="checkbox" class="default-width">
 | 
				
			||||||
 | 
					                    <label>Reminder templates</label>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="control">
 | 
				
			||||||
 | 
					                <div class="field">
 | 
				
			||||||
 | 
					                    <input type="checkbox" class="default-width">
 | 
				
			||||||
 | 
					                    <label>Macros</label>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
            <div class="has-text-centered">
 | 
					            <div class="has-text-centered">
 | 
				
			||||||
                <button class="button is-success is-outlined" id="import-data">Import Data</button>
 | 
					                <button class="button is-success is-outlined" id="import-data">Import Data</button>
 | 
				
			||||||
                <button class="button is-success" id="export-data">Export Data</button>
 | 
					                <button class="button is-success" id="export-data">Export Data</button>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -93,6 +93,65 @@
 | 
				
			|||||||
                </article>
 | 
					                </article>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="tile is-ancestor">
 | 
				
			||||||
 | 
					            <div class="tile is-parent">
 | 
				
			||||||
 | 
					                <article class="tile is-child notification">
 | 
				
			||||||
 | 
					                    <p class="title">Intervals</p>
 | 
				
			||||||
 | 
					                    <p class="subtitle">Learn about repeating reminders</p>
 | 
				
			||||||
 | 
					                    <div class="content has-text-centered">
 | 
				
			||||||
 | 
					                        <a class="button is-size-4 is-rounded is-light" href="/help/intervals">
 | 
				
			||||||
 | 
					                            <p class="is-size-4">
 | 
				
			||||||
 | 
					                                Read <span class="icon"><i class="fas fa-chevron-right"></i></span>
 | 
				
			||||||
 | 
					                            </p>
 | 
				
			||||||
 | 
					                        </a>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </article>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="tile is-parent">
 | 
				
			||||||
 | 
					                <article class="tile is-child notification">
 | 
				
			||||||
 | 
					                    <p class="title">Dashboard</p>
 | 
				
			||||||
 | 
					                    <p class="subtitle">Learn to use the interactive web dashboard</p>
 | 
				
			||||||
 | 
					                    <div class="content has-text-centered">
 | 
				
			||||||
 | 
					                        <a class="button is-size-4 is-rounded is-light" href="/help/dashboard">
 | 
				
			||||||
 | 
					                            <p class="is-size-4">
 | 
				
			||||||
 | 
					                                Read <span class="icon"><i class="fas fa-chevron-right"></i></span>
 | 
				
			||||||
 | 
					                            </p>
 | 
				
			||||||
 | 
					                        </a>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </article>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="tile is-parent is-vertical">
 | 
				
			||||||
 | 
					                <article class="tile is-child notification">
 | 
				
			||||||
 | 
					                    <p class="title">Import/Export</p>
 | 
				
			||||||
 | 
					                    <p class="subtitle">Learn how to import and export data from the dashboard</p>
 | 
				
			||||||
 | 
					                    <div class="content has-text-centered">
 | 
				
			||||||
 | 
					                        <a class="button is-size-4 is-rounded is-light" href="/help/iemanager">
 | 
				
			||||||
 | 
					                            <p class="is-size-4">
 | 
				
			||||||
 | 
					                                Read <span class="icon"><i class="fas fa-chevron-right"></i></span>
 | 
				
			||||||
 | 
					                            </p>
 | 
				
			||||||
 | 
					                        </a>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </article>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container has-text-centered">
 | 
				
			||||||
 | 
					                <p class="title">Need more help?</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    Feel free to come and ask us!
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="hero-foot has-text-centered">
 | 
				
			||||||
 | 
					            <a class="button is-size-6 is-rounded is-primary" href="https://discord.jellywx.com">
 | 
				
			||||||
 | 
					                <p class="is-size-6">
 | 
				
			||||||
 | 
					                    Join Discord <span class="icon"><i class="fas fa-chevron-right"></i></span>
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -158,9 +158,9 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="collapses">
 | 
					        <div class="collapses">
 | 
				
			||||||
            <div class="is-locked">
 | 
					            <div class="patreon-only">
 | 
				
			||||||
                <div class="field">
 | 
					                <div class="field">
 | 
				
			||||||
                    <label class="label">Interval <a class="foreground" href="/help/interval"><i class="fas fa-question-circle"></i></a></label>
 | 
					                    <label class="label">Interval <a class="foreground" href="/help/intervals"><i class="fas fa-question-circle"></i></a></label>
 | 
				
			||||||
                    <div class="control intervalSelector" style="min-width: 400px;" >
 | 
					                    <div class="control intervalSelector" style="min-width: 400px;" >
 | 
				
			||||||
                        <div class="input interval-group">
 | 
					                        <div class="input interval-group">
 | 
				
			||||||
                            <div class="interval-group-left">
 | 
					                            <div class="interval-group-left">
 | 
				
			||||||
@@ -206,11 +206,6 @@
 | 
				
			|||||||
                        <label class="label">Enable TTS <input type="checkbox" name="tts"></label>
 | 
					                        <label class="label">Enable TTS <input type="checkbox" name="tts"></label>
 | 
				
			||||||
                    </div>
 | 
					                    </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
                <div class="column has-text-centered">
 | 
					 | 
				
			||||||
                    <div class="is-boxed">
 | 
					 | 
				
			||||||
                        <label class="label">Pin Message <input type="checkbox" name="pin"></label>
 | 
					 | 
				
			||||||
                    </div>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
                <div class="column has-text-centered">
 | 
					                <div class="column has-text-centered">
 | 
				
			||||||
                    <div class="file is-small is-boxed">
 | 
					                    <div class="file is-small is-boxed">
 | 
				
			||||||
                        <label class="file-label">
 | 
					                        <label class="file-label">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										22
									
								
								web/templates/support/dashboard.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								web/templates/support/dashboard.html.tera
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					{% extends "base" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block init %}
 | 
				
			||||||
 | 
					    {% set title = "Support" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% set page_title = "Dashboard" %}
 | 
				
			||||||
 | 
					    {% set page_subtitle = "" %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Accessing the dashboard</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -33,6 +33,24 @@
 | 
				
			|||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Deleting reminders you've just created</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    If you made a mistake, you can quickly delete a reminder you made by pressing "Cancel"
 | 
				
			||||||
 | 
					                    <br>
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					                <figure>
 | 
				
			||||||
 | 
					                    <img src="/static/img/support/delete_reminder/cancel-1.png" alt="Cancel button">
 | 
				
			||||||
 | 
					                </figure>
 | 
				
			||||||
 | 
					                <figure>
 | 
				
			||||||
 | 
					                    <img src="/static/img/support/delete_reminder/cancel-2.png" alt="Reminder deleted">
 | 
				
			||||||
 | 
					                </figure>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <section class="hero is-small">
 | 
					    <section class="hero is-small">
 | 
				
			||||||
        <div class="hero-body">
 | 
					        <div class="hero-body">
 | 
				
			||||||
            <div class="container">
 | 
					            <div class="container">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								web/templates/support/iemanager.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								web/templates/support/iemanager.html.tera
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					{% extends "base" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block init %}
 | 
				
			||||||
 | 
					    {% set title = "Support" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% set page_title = "Import/Export" %}
 | 
				
			||||||
 | 
					    {% set page_subtitle = "" %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Export your data</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    You can create reminders with the <code>/remind</code> command.
 | 
				
			||||||
 | 
					                    <br>
 | 
				
			||||||
 | 
					                    Fill out the "time" and "content" fields. If you wish, press on "Optional" to view other options
 | 
				
			||||||
 | 
					                    for the reminder.
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
							
								
								
									
										70
									
								
								web/templates/support/intervals.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								web/templates/support/intervals.html.tera
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
				
			|||||||
 | 
					{% extends "base" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block init %}
 | 
				
			||||||
 | 
					    {% set title = "Support" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {% set page_title = "Intervals" %}
 | 
				
			||||||
 | 
					    {% set page_subtitle = "Interval reminders, or repeating reminders, are available to our Patreon supporters" %}
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% block content %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Fixed intervals</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    The main type of interval is the fixed interval. Fixed intervals are ideal for hourly, daily, or
 | 
				
			||||||
 | 
					                    reminders repeating at any other fixed amount of time.
 | 
				
			||||||
 | 
					                    <br>
 | 
				
			||||||
 | 
					                    You can create fixed interval reminders via the dashboard or via the <code>/remind</code> command.
 | 
				
			||||||
 | 
					                    When you have filled out the "time" and "content" on the command, press <kbd>tab</kbd>. Select the
 | 
				
			||||||
 | 
					                    "interval" option. Then, write the interval you wish to use: for example, "1 day" for daily (starting
 | 
				
			||||||
 | 
					                    at the time specified in "time").
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Daylight savings</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    If you live in a region that uses daylight savings (DST), then your interval reminders may become
 | 
				
			||||||
 | 
					                    offset by an hour due to clock changes.
 | 
				
			||||||
 | 
					                    <br>
 | 
				
			||||||
 | 
					                    Reminder Bot offers a quick solution to this via the <code>/offset</code> command. This command
 | 
				
			||||||
 | 
					                    moves all existing reminders on a server by a certain amount of time. You can use offset to move
 | 
				
			||||||
 | 
					                    your reminders forward or backward by an hour when daylight savings happens.
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Monthly/yearly intervals</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    Monthly or yearly intervals are configured the same as fixed intervals. Instead of a fixed time
 | 
				
			||||||
 | 
					                    interval, these reminders repeat on a certain day each month or each year. This makes them ideal
 | 
				
			||||||
 | 
					                    for marking certain dates.
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <section class="hero is-small">
 | 
				
			||||||
 | 
					        <div class="hero-body">
 | 
				
			||||||
 | 
					            <div class="container">
 | 
				
			||||||
 | 
					                <p class="title">Interval expiration</p>
 | 
				
			||||||
 | 
					                <p class="content">
 | 
				
			||||||
 | 
					                    An expiration time can also be specified, both via commands and dashboard, for repeating reminders.
 | 
				
			||||||
 | 
					                    This is optional, and if omitted, the reminder will repeat indefinitely.
 | 
				
			||||||
 | 
					                </p>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% endblock %}
 | 
				
			||||||
@@ -3,8 +3,8 @@
 | 
				
			|||||||
{% block init %}
 | 
					{% block init %}
 | 
				
			||||||
    {% set title = "Support" %}
 | 
					    {% set title = "Support" %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {% set page_title = "Timezone Help" %}
 | 
					    {% set page_title = "Timezones" %}
 | 
				
			||||||
    {% set page_subtitle = "Timezones are tricky. Read on for help" %}
 | 
					    {% set page_subtitle = "" %}
 | 
				
			||||||
    {% set show_invite = false %}
 | 
					    {% set show_invite = false %}
 | 
				
			||||||
{% endblock %}
 | 
					{% endblock %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,7 +31,7 @@
 | 
				
			|||||||
            <div class="container">
 | 
					            <div class="container">
 | 
				
			||||||
                <p class="title">Selecting your timezone automatically</p>
 | 
					                <p class="title">Selecting your timezone automatically</p>
 | 
				
			||||||
                <p class="content">
 | 
					                <p class="content">
 | 
				
			||||||
                    A new feature we offer is the ability to configure Reminder Bot's timezone from your browser. To do
 | 
					                    You can also configure Reminder Bot's timezone from your browser. To do
 | 
				
			||||||
                    this, go to our dashboard, press 'Timezone' in the bottom left (desktop) or at the bottom of the
 | 
					                    this, go to our dashboard, press 'Timezone' in the bottom left (desktop) or at the bottom of the
 | 
				
			||||||
                    navigation menu (mobile). Then, choose 'Set Bot Timezone' to set Reminder Bot to use your browser's
 | 
					                    navigation menu (mobile). Then, choose 'Set Bot Timezone' to set Reminder Bot to use your browser's
 | 
				
			||||||
                    timezone.
 | 
					                    timezone.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,8 +23,8 @@
 | 
				
			|||||||
                Reminder Bot or the Discord server.
 | 
					                Reminder Bot or the Discord server.
 | 
				
			||||||
                <br>
 | 
					                <br>
 | 
				
			||||||
                <br>
 | 
					                <br>
 | 
				
			||||||
                The Terms of Service may be updated at any time, and should be considered a guideline for appropriate
 | 
					                The Terms of Service may be updated at any time. Notice will be provided via the Discord server. You
 | 
				
			||||||
                behaviour.
 | 
					                should consider the Terms of Service to be a guideline for appropriate behaviour.
 | 
				
			||||||
            </p>
 | 
					            </p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
@@ -35,7 +35,8 @@
 | 
				
			|||||||
            <ul class="is-size-5 pl-6">
 | 
					            <ul class="is-size-5 pl-6">
 | 
				
			||||||
                <li>Reasonably disclose potential exploits or bugs to me by email or by Discord private message</li>
 | 
					                <li>Reasonably disclose potential exploits or bugs to me by email or by Discord private message</li>
 | 
				
			||||||
                <li>Do not use the bot to harass other Discord users</li>
 | 
					                <li>Do not use the bot to harass other Discord users</li>
 | 
				
			||||||
                <li>Do not use the bot to send more than 30 messages during a 60 second period</li>
 | 
					                <li>Do not use the bot to transmit malware or other illegal content</li>
 | 
				
			||||||
 | 
					                <li>Do not use the bot to send more than 15 messages during a 60 second period</li>
 | 
				
			||||||
            </ul>
 | 
					            </ul>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </section>
 | 
					    </section>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user