aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.pre-commit-config.yaml5
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--Pipfile4
-rw-r--r--Pipfile.lock245
-rwxr-xr-xREADME.md361
-rw-r--r--bot/constants.py6
-rw-r--r--bot/resources/valentines/date_ideas.json127
-rw-r--r--bot/seasons/valentines/savethedate.py41
8 files changed, 634 insertions, 157 deletions
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 00000000..1d75342a
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,5 @@
+repos:
+- repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v2.0.0
+ hooks:
+ - id: flake8 \ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 58513c03..4161715e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -34,7 +34,7 @@ All projects evolve over time, and this contribution guide is no different. This
## Supplemental Information
### Developer Environment
-Seasonalbot utilizes [Pipenv](https://pipenv.readthedocs.io/en/latest/) for installation and dependency management. For users unfamiliar with the Pipenv workflow, a [Pipenv Primer](https://github.com/python-discord/seasonalbot/wiki/Hacktoberbot-and-Pipenv) is provided in Seasonalbot's Wiki.
+Seasonalbot utilizes [Pipenv](https://pipenv.readthedocs.io/en/latest/) for installation and dependency management. For users unfamiliar with the Pipenv workflow, Pipenv's documentation provides a [Basic Usage](https://pipenv.readthedocs.io/en/latest/basics/) tutorial, along with some of the more advanced workflows.
### Logging levels
The project currently defines [`logging`](https://docs.python.org/3/library/logging.html) levels as follows:
diff --git a/Pipfile b/Pipfile
index 6ffc2136..90707d25 100644
--- a/Pipfile
+++ b/Pipfile
@@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi"
[packages]
-"discord-py" = {ref = "rewrite", git = "https://github.com/Rapptz/discord.py"}
+discord-py = {ref = "rewrite",git = "https://github.com/Rapptz/discord.py"}
arrow = "*"
beautifulsoup4 = "*"
aiodns = "*"
@@ -18,6 +18,7 @@ pytz = "*"
"flake8-tidy-imports" = "*"
"flake8-todo" = "*"
"flake8-string-format" = "*"
+pre-commit = "*"
[requires]
python_version = "3.7"
@@ -25,3 +26,4 @@ python_version = "3.7"
[scripts]
start = "python -m bot"
lint = "flake8 bot"
+precommit = "pre-commit install"
diff --git a/Pipfile.lock b/Pipfile.lock
index 1f693364..a318af42 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
- "sha256": "37690a44eef1762372759be11694f873af63f032de0264280ad1762d917c2b89"
+ "sha256": "56ef4499fef622c131943cc402884901581fa337ac602069e9e6e2d25096ff93"
},
"pipfile-spec": 6,
"requires": {
@@ -18,93 +18,95 @@
"default": {
"aiodns": {
"hashes": [
- "sha256:99d0652f2c02f73bfa646bf44af82705260a523014576647d7959e664830b26b",
- "sha256:d8677adc679ce8d0ef706c14d9c3d2f27a0e0cc11d59730cdbaf218ad52dd9ea"
+ "sha256:970688599fcb7d65334ec490a94a51afd634ae2de8a2138d21e2ffbbddc12718",
+ "sha256:d67e14b32176bcf3ff79b5d47c466011ce4adeadfa264f7949da1377332a0449"
],
"index": "pypi",
- "version": "==1.1.1"
+ "version": "==1.2.0"
},
"arrow": {
"hashes": [
- "sha256:a558d3b7b6ce7ffc74206a86c147052de23d3d4ef0e17c210dd478c53575c4cd"
+ "sha256:9cb4a910256ed536751cd5728673bfb53e6f0026e240466f90c2a92c0b79c895"
],
"index": "pypi",
- "version": "==0.12.1"
+ "version": "==0.13.0"
},
"beautifulsoup4": {
"hashes": [
- "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57",
- "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10",
- "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938"
+ "sha256:034740f6cb549b4e932ae1ab975581e6103ac8f942200a0e9759065984391858",
+ "sha256:945065979fb8529dd2f37dbb58f00b661bdbcbebf954f93b32fdf5263ef35348",
+ "sha256:ba6d5c59906a85ac23dadfe5c88deaf3e179ef565f4898671253e50a78680718"
],
"index": "pypi",
- "version": "==4.6.3"
+ "version": "==4.7.1"
},
"discord-py": {
"git": "https://github.com/Rapptz/discord.py",
- "ref": "66e5033785259400d340b8c00eaa8ad60fbbb82a"
+ "ref": "7f4c57dd5ad20b7fa10aea485f674a4bc24b9547"
},
"pillow": {
"hashes": [
- "sha256:00203f406818c3f45d47bb8fe7e67d3feddb8dcbbd45a289a1de7dd789226360",
- "sha256:0616f800f348664e694dddb0b0c88d26761dd5e9f34e1ed7b7a7d2da14b40cb7",
- "sha256:1f7908aab90c92ad85af9d2fec5fc79456a89b3adcc26314d2cde0e238bd789e",
- "sha256:2ea3517cd5779843de8a759c2349a3cd8d3893e03ab47053b66d5ec6f8bc4f93",
- "sha256:48a9f0538c91fc136b3a576bee0e7cd174773dc9920b310c21dcb5519722e82c",
- "sha256:5280ebc42641a1283b7b1f2c20e5b936692198b9dd9995527c18b794850be1a8",
- "sha256:5e34e4b5764af65551647f5cc67cf5198c1d05621781d5173b342e5e55bf023b",
- "sha256:63b120421ab85cad909792583f83b6ca3584610c2fe70751e23f606a3c2e87f0",
- "sha256:696b5e0109fe368d0057f484e2e91717b49a03f1e310f857f133a4acec9f91dd",
- "sha256:870ed021a42b1b02b5fe4a739ea735f671a84128c0a666c705db2cb9abd528eb",
- "sha256:916da1c19e4012d06a372127d7140dae894806fad67ef44330e5600d77833581",
- "sha256:9303a289fa0811e1c6abd9ddebfc770556d7c3311cb2b32eff72164ddc49bc64",
- "sha256:9577888ecc0ad7d06c3746afaba339c94d62b59da16f7a5d1cff9e491f23dace",
- "sha256:987e1c94a33c93d9b209315bfda9faa54b8edfce6438a1e93ae866ba20de5956",
- "sha256:99a3bbdbb844f4fb5d6dd59fac836a40749781c1fa63c563bc216c27aef63f60",
- "sha256:99db8dc3097ceafbcff9cb2bff384b974795edeb11d167d391a02c7bfeeb6e16",
- "sha256:a5a96cf49eb580756a44ecf12949e52f211e20bffbf5a95760ac14b1e499cd37",
- "sha256:aa6ca3eb56704cdc0d876fc6047ffd5ee960caad52452fbee0f99908a141a0ae",
- "sha256:aade5e66795c94e4a2b2624affeea8979648d1b0ae3fcee17e74e2c647fc4a8a",
- "sha256:b78905860336c1d292409e3df6ad39cc1f1c7f0964e66844bbc2ebfca434d073",
- "sha256:b92f521cdc4e4a3041cc343625b699f20b0b5f976793fb45681aac1efda565f8",
- "sha256:bfde84bbd6ae5f782206d454b67b7ee8f7f818c29b99fd02bf022fd33bab14cb",
- "sha256:c2b62d3df80e694c0e4a0ed47754c9480521e25642251b3ab1dff050a4e60409",
- "sha256:c5e2be6c263b64f6f7656e23e18a4a9980cffc671442795682e8c4e4f815dd9f",
- "sha256:c99aa3c63104e0818ec566f8ff3942fb7c7a8f35f9912cb63fd8e12318b214b2",
- "sha256:dae06620d3978da346375ebf88b9e2dd7d151335ba668c995aea9ed07af7add4",
- "sha256:db5499d0710823fa4fb88206050d46544e8f0e0136a9a5f5570b026584c8fd74",
- "sha256:f36baafd82119c4a114b9518202f2a983819101dcc14b26e43fc12cbefdce00e",
- "sha256:f52b79c8796d81391ab295b04e520bda6feed54d54931708872e8f9ae9db0ea1",
- "sha256:ff8cff01582fa1a7e533cb97f628531c4014af4b5f38e33cdcfe5eec29b6d888"
+ "sha256:051de330a06c99d6f84bcf582960487835bcae3fc99365185dc2d4f65a390c0e",
+ "sha256:0ae5289948c5e0a16574750021bd8be921c27d4e3527800dc9c2c1d2abc81bf7",
+ "sha256:0b1efce03619cdbf8bcc61cfae81fcda59249a469f31c6735ea59badd4a6f58a",
+ "sha256:163136e09bd1d6c6c6026b0a662976e86c58b932b964f255ff384ecc8c3cefa3",
+ "sha256:18e912a6ccddf28defa196bd2021fe33600cbe5da1aa2f2e2c6df15f720b73d1",
+ "sha256:24ec3dea52339a610d34401d2d53d0fb3c7fd08e34b20c95d2ad3973193591f1",
+ "sha256:267f8e4c0a1d7e36e97c6a604f5b03ef58e2b81c1becb4fccecddcb37e063cc7",
+ "sha256:3273a28734175feebbe4d0a4cde04d4ed20f620b9b506d26f44379d3c72304e1",
+ "sha256:4c678e23006798fc8b6f4cef2eaad267d53ff4c1779bd1af8725cc11b72a63f3",
+ "sha256:4d4bc2e6bb6861103ea4655d6b6f67af8e5336e7216e20fff3e18ffa95d7a055",
+ "sha256:505738076350a337c1740a31646e1de09a164c62c07db3b996abdc0f9d2e50cf",
+ "sha256:5233664eadfa342c639b9b9977190d64ad7aca4edc51a966394d7e08e7f38a9f",
+ "sha256:5d95cb9f6cced2628f3e4de7e795e98b2659dfcc7176ab4a01a8b48c2c2f488f",
+ "sha256:7eda4c737637af74bac4b23aa82ea6fbb19002552be85f0b89bc27e3a762d239",
+ "sha256:801ddaa69659b36abf4694fed5aa9f61d1ecf2daaa6c92541bbbbb775d97b9fe",
+ "sha256:825aa6d222ce2c2b90d34a0ea31914e141a85edefc07e17342f1d2fdf121c07c",
+ "sha256:9c215442ff8249d41ff58700e91ef61d74f47dfd431a50253e1a1ca9436b0697",
+ "sha256:a3d90022f2202bbb14da991f26ca7a30b7e4c62bf0f8bf9825603b22d7e87494",
+ "sha256:a631fd36a9823638fe700d9225f9698fb59d049c942d322d4c09544dc2115356",
+ "sha256:a6523a23a205be0fe664b6b8747a5c86d55da960d9586db039eec9f5c269c0e6",
+ "sha256:a756ecf9f4b9b3ed49a680a649af45a8767ad038de39e6c030919c2f443eb000",
+ "sha256:b117287a5bdc81f1bac891187275ec7e829e961b8032c9e5ff38b70fd036c78f",
+ "sha256:ba04f57d1715ca5ff74bb7f8a818bf929a204b3b3c2c2826d1e1cc3b1c13398c",
+ "sha256:cd878195166723f30865e05d87cbaf9421614501a4bd48792c5ed28f90fd36ca",
+ "sha256:cee815cc62d136e96cf76771b9d3eb58e0777ec18ea50de5cfcede8a7c429aa8",
+ "sha256:d1722b7aa4b40cf93ac3c80d3edd48bf93b9208241d166a14ad8e7a20ee1d4f3",
+ "sha256:d7c1c06246b05529f9984435fc4fa5a545ea26606e7f450bdbe00c153f5aeaad",
+ "sha256:e9c8066249c040efdda84793a2a669076f92a301ceabe69202446abb4c5c5ef9",
+ "sha256:f227d7e574d050ff3996049e086e1f18c7bd2d067ef24131e50a1d3fe5831fbc",
+ "sha256:fc9a12aad714af36cf3ad0275a96a733526571e52710319855628f476dcb144e"
],
"index": "pypi",
- "version": "==5.3.0"
+ "version": "==5.4.1"
},
"pycares": {
"hashes": [
- "sha256:0e81c971236bb0767354f1456e67ab6ae305f248565ce77cd413a311f9572bf5",
- "sha256:11c0ff3ccdb5a838cbd59a4e59df35d31355a80a61393bca786ca3b44569ba10",
- "sha256:170d62bd300999227e64da4fa85459728cc96e62e44780bbc86a915fdae01f78",
- "sha256:36f4c03df57c41a87eb3d642201684eb5a8bc194f4bafaa9f60ee6dc0aef8e40",
- "sha256:371ce688776da984c4105c8ca760cc60944b9b49ccf8335c71dc7669335e6173",
- "sha256:3a2234516f7db495083d8bba0ccdaabae587e62cfcd1b8154d5d0b09d3a48dfc",
- "sha256:3f288586592c697109b2b06e3988b7e17d9765887b5fc367010ee8500cbddc86",
- "sha256:40134cee03c8bbfbc644d4c0bc81796e12dd012a5257fb146c5a5417812ee5f7",
- "sha256:722f5d2c5f78d47b13b0112f6daff43ce4e08e8152319524d14f1f917cc5125e",
- "sha256:7b18fab0ed534a898552df91bc804bd62bb3a2646c11e054baca14d23663e1d6",
- "sha256:8a39d03bd99ea191f86b990ef67ecce878d6bf6518c5cde9173fb34fb36beb5e",
- "sha256:8ea263de8bf1a30b0d87150b4aa0e3203cf93bc1723ea3e7408a7d25e1299217",
- "sha256:943e2dc67ff45ab4c81d628c959837d01561d7e185080ab7a276b8ca67573fb5",
- "sha256:9d56a54c93e64b30c0d31f394d9890f175edec029cd846221728f99263cdee82",
- "sha256:b95b339c11d824f0bb789d31b91c8534916fcbdce248cccce216fa2630bb8a90",
- "sha256:bbfd9aba1e172cd2ab7b7142d49b28cf44d6451c4a66a870aff1dc3cb84849c7",
- "sha256:d8637bcc2f901aa61ec1d754abc862f9f145cb0346a0249360df4c159377018e",
- "sha256:e2446577eeea79d2179c9469d9d4ce3ab8a07d7985465c3cb91e7d74abc329b6",
- "sha256:e72fa163f37ae3b09f143cc6690a36f012d13e905d142e1beed4ec0e593ff657",
- "sha256:f32b7c63094749fbc0c1106c9a785666ec8afd49ecfe7002a30bb7c42e62b47c",
- "sha256:f50be4dd53f009cfb4b98c3c6b240e18ff9b17e3f1c320bd594bb83eddabfcb2"
- ],
- "version": "==2.3.0"
+ "sha256:080ae0f1b1b754be60b6ef31b9ab2915364c210eb1cb4d8e089357c89d7b9819",
+ "sha256:0eccb76dff0155ddf793a589c6270e1bdbf6975b2824d18d1d23db2075d7fc96",
+ "sha256:223a03d69e864a18d7bb2e0108bca5ba069ef91e5b048b953ed90ea9f50eb77f",
+ "sha256:289e49f98adfd7a2ae3656df26e1d62cf49a06bbc03ced63f243c22cd8919adf",
+ "sha256:292ac442a1d4ff27d41be748ec19f0c4ff47efebfb715064ba336564ea0f2071",
+ "sha256:34771095123da0e54597fe3c5585a28d3799945257e51b378a20778bf33573b6",
+ "sha256:34c8865f2d047be4c301ce90a916c7748be597e271c5c7932e8b9a6de85840f4",
+ "sha256:36af260b215f86ebfe4a5e4aea82fd6036168a5710cbf8aad77019ab52156dda",
+ "sha256:5e8e2a461717da40482b5fecf1119116234922d29660b3c3e01cbc5ba2cbf4bd",
+ "sha256:61e77bd75542c56dff49434fedbafb25604997bc57dc0ebf791a5732503cb1bb",
+ "sha256:691740c332f38a9035b4c6d1f0e6c8af239466ef2373a894d4393f0ea65c815d",
+ "sha256:6bc0e0fdcb4cdc4ca06aa0b07e6e3560d62b2af79ef0ea4589835fcd2059012b",
+ "sha256:96db5c93e2fe2e39f519efb7bb9d86aef56f5813fa0b032e47aba329fa925d57",
+ "sha256:af701b22c91b3e36f65ee9f4b1bc2fe4800c8ed486eb6ef203624acbe53d026d",
+ "sha256:b25bd21bba9c43d44320b719118c2ce35e4a78031f61d906caeb01316d49dafb",
+ "sha256:c42f68319f8ea2322ed81c31a86c4e60547e6e90f3ebef479a7a7540bddbf268",
+ "sha256:cc9a8d35af12bc5f484f3496f9cb3ab5bedfa4dcf3dfff953099453d88b659a7",
+ "sha256:dfee9d198ba6d6f29aa5bf510bfb2c28a60c3f308116f114c9fd311980d3e870",
+ "sha256:e1dd02e110a7a97582097ebba6713d9da28583b538c08e8a14bc82169c5d3e10",
+ "sha256:e48c586c80a139c6c7fb0298b944d1c40752cf839bc8584cc793e42a8971ba6c",
+ "sha256:f509762dec1a70eac32b86c098f37ac9c5d3d4a8a9098983328377c9e71543b2",
+ "sha256:f8e0d61733843844f9019c911d5676818d99c4cd2c54b91de58384c7d962862b",
+ "sha256:fe20280fed496deba60e0f6437b7672bdc83bf45e243bb546af47c60c85bcfbc"
+ ],
+ "version": "==2.4.0"
},
"python-dateutil": {
"hashes": [
@@ -115,21 +117,43 @@
},
"pytz": {
"hashes": [
- "sha256:31cb35c89bd7d333cd32c5f278fca91b523b0834369e757f4c5641ea252236ca",
- "sha256:8e0f8568c118d3077b46be7d654cc8167fa916092e28320cde048e54bfc9f1e6"
+ "sha256:32b0891edff07e28efe91284ed9c31e123d84bea3fd98e1f72be2508f43ef8d9",
+ "sha256:d5f05e487007e29e03409f9398d074e158d920d36eb82eaf66fb1136b0c5374c"
],
"index": "pypi",
- "version": "==2018.7"
+ "version": "==2018.9"
},
"six": {
"hashes": [
- "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
- "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "version": "==1.12.0"
+ },
+ "soupsieve": {
+ "hashes": [
+ "sha256:10687fc53eeb3518e01a0ac84d3d711da623d3298a3039459d3f649927c4a270",
+ "sha256:b23a0d7da0247200fe83c67c34de9d7599ad404106367313d8e65e04174d0b4b"
],
- "version": "==1.11.0"
+ "version": "==1.7.2"
+ },
+ "typing": {
+ "hashes": [
+ "sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d",
+ "sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4",
+ "sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"
+ ],
+ "version": "==3.6.6"
}
},
"develop": {
+ "aspy.yaml": {
+ "hashes": [
+ "sha256:04d26279513618f1024e1aba46471db870b3b33aef204c2d09bcf93bea9ba13f",
+ "sha256:0a77e23fafe7b242068ffc0252cee130d3e509040908fc678d9d1060e7494baa"
+ ],
+ "version": "==1.1.1"
+ },
"attrs": {
"hashes": [
"sha256:10cbf6e27dbce8c30807caf056c8eb50917e0eaafe86347671b57254006c3e69",
@@ -137,6 +161,13 @@
],
"version": "==18.2.0"
},
+ "cfgv": {
+ "hashes": [
+ "sha256:39d9055c47e3932908fe25abd5807e21dc002630db01c7a5f05738d027e2b706",
+ "sha256:41d22dd864c474f919ecb88900000d2410d640315f75bdb79b3abf9347089641"
+ ],
+ "version": "==1.4.0"
+ },
"flake8": {
"hashes": [
"sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670",
@@ -184,6 +215,20 @@
"index": "pypi",
"version": "==0.7"
},
+ "identify": {
+ "hashes": [
+ "sha256:0b2bb67c857b8048d979caeef4d20a3dfdb0337f154d16a8f9e31cd6e04ae554",
+ "sha256:113622f73da90a723e9baf764553f807051ad80c3a9e8a7edd15aa4309861f4d"
+ ],
+ "version": "==1.2.0"
+ },
+ "importlib-metadata": {
+ "hashes": [
+ "sha256:a17ce1a8c7bff1e8674cb12c992375d8d0800c9190177ecf0ad93e0097224095",
+ "sha256:b50191ead8c70adfa12495fba19ce6d75f2e0275c14c5a7beb653d6799b512bd"
+ ],
+ "version": "==0.8"
+ },
"mccabe": {
"hashes": [
"sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42",
@@ -191,6 +236,20 @@
],
"version": "==0.6.1"
},
+ "nodeenv": {
+ "hashes": [
+ "sha256:ad8259494cf1c9034539f6cced78a1da4840a4b157e23640bc4a0c0546b0cb7a"
+ ],
+ "version": "==1.3.3"
+ },
+ "pre-commit": {
+ "hashes": [
+ "sha256:2cb7a588fdc78e4ec4e624932765e65d285159f4b3425121106cbd9060e40e04",
+ "sha256:74ee5779a17ef540efdf9a832911fe9057b1bb57d5d0152eace6534a228a863b"
+ ],
+ "index": "pypi",
+ "version": "==1.14.2"
+ },
"pycodestyle": {
"hashes": [
"sha256:cbc619d09254895b0d12c2c691e237b2e91e9b2ecf5e84c26b35400f93dcfb83",
@@ -204,6 +263,50 @@
"sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae"
],
"version": "==2.0.0"
+ },
+ "pyyaml": {
+ "hashes": [
+ "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b",
+ "sha256:3ef3092145e9b70e3ddd2c7ad59bdd0252a94dfe3949721633e41344de00a6bf",
+ "sha256:40c71b8e076d0550b2e6380bada1f1cd1017b882f7e16f09a65be98e017f211a",
+ "sha256:558dd60b890ba8fd982e05941927a3911dc409a63dcb8b634feaa0cda69330d3",
+ "sha256:a7c28b45d9f99102fa092bb213aa12e0aaf9a6a1f5e395d36166639c1f96c3a1",
+ "sha256:aa7dd4a6a427aed7df6fb7f08a580d68d9b118d90310374716ae90b710280af1",
+ "sha256:bc558586e6045763782014934bfaf39d48b8ae85a2713117d16c39864085c613",
+ "sha256:d46d7982b62e0729ad0175a9bc7e10a566fc07b224d2c79fafb5e032727eaa04",
+ "sha256:d5eef459e30b09f5a098b9cea68bebfeb268697f78d647bd255a085371ac7f3f",
+ "sha256:e01d3203230e1786cd91ccfdc8f8454c8069c91bee3962ad93b87a4b2860f537",
+ "sha256:e170a9e6fcfd19021dd29845af83bb79236068bf5fd4df3327c1be18182b2531"
+ ],
+ "version": "==3.13"
+ },
+ "six": {
+ "hashes": [
+ "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
+ "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
+ ],
+ "version": "==1.12.0"
+ },
+ "toml": {
+ "hashes": [
+ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
+ "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
+ ],
+ "version": "==0.10.0"
+ },
+ "virtualenv": {
+ "hashes": [
+ "sha256:34b9ae3742abed2f95d3970acf4d80533261d6061b51160b197f84e5b4c98b4c",
+ "sha256:fa736831a7b18bd2bfeef746beb622a92509e9733d645952da136b0639cd40cd"
+ ],
+ "version": "==16.2.0"
+ },
+ "zipp": {
+ "hashes": [
+ "sha256:55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478",
+ "sha256:682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4"
+ ],
+ "version": "==0.3.3"
}
}
}
diff --git a/README.md b/README.md
index 6227a36d..877471ed 100755
--- a/README.md
+++ b/README.md
@@ -3,105 +3,298 @@
[![Build Status](https://dev.azure.com/python-discord/Python%20Discord/_apis/build/status/Seasonal%20Bot%20(Mainline))](https://dev.azure.com/python-discord/Python%20Discord/_build/latest?definitionId=3)
[![Discord](https://discordapp.com/api/guilds/267624335836053506/embed.png)](https://discord.gg/2B963hn)
-A community project initially started for [Hacktoberfest 2018](https://hacktoberfest.digitalocean.com). A Discord bot for the Python Discord community which changes with the seasons, and provides useful event features.
+A Discord bot for the Python Discord community which changes with the seasons, and provides useful event features.
You can find our community by going to https://discord.gg/python
## Motivations
-We know it can be difficult to get into the whole open source thing at first. To help out, we've decided to start a little community project during hacktober that you can all choose to contribute to if you're finding the event a little overwhelming, or if you're new to this whole thing and just want someone to hold your hand at first.
-This later evolved into a bot that will be running all through the year, providing season-appropriate functionality and issues that beginners can work on.
+We know it can be difficult to get into the whole open source thing at first. To help out, we started the HacktoberBot community project during [Hacktoberfest 2018](https://hacktoberfest.digitalocean.com) to help introduce and encourage members to participate in contributing to open source, providing a calmer and helpful environment for those who want to be part of it.
+
+This later evolved into a bot that runs all year, providing season-appropriate functionality and issues that beginners can work on.
## Getting started
-If you are new to this you will find it far easier using PyCharm:
+Please ensure you read the [contributing guidelines](CONTRIBUTING.md) in full.
+
+If you are new to this you may find it easier to use PyCharm. [What is PyCharm?](#what-is-pycharm)
+
+1. [Fork the Project](#fork-the-project)
+2. [Clone & Install Packages](#clone--install-packages)
+3. [Test Server](#test-server)
+4. [Bot Account](#bot-account)
+5. [Configuration](#configuration)
+6. [Working with Git](#working-with-git)
+7. [Pull Requests (PRs)](#pull-requests-prs)
+8. [Further Reading](#further-reading)
+
+### What is PyCharm?
+
+PyCharm is a Python IDE (integrated development environment) that is used to make python development quicker and easier.
+
+Our instruction include PyCharm specific steps for those who have it, so you're welcome to give it a go if you haven't tried it before.
-### With PyCharm
+You can download PyCharm for free [here](https://www.jetbrains.com/pycharm/).
-First things first, what is PyCharm?
-PyCharm is a Python IDE(integrated development environment) that is used to make python development quicker and easier overall.
-So now your going to need to download it [here](https://www.jetbrains.com/pycharm/).
+### Requirements
+
+- [Python 3.7](https://www.python.org/downloads/)
+- [Pipenv](https://pipenv.readthedocs.io/en/latest/install/#installing-pipenv)
+- Git
+ - [Windows Installer](https://git-scm.com/download/win)
+ - [MacOS Installer](https://sourceforge.net/projects/git-osx-installer/files/) or `brew install git`
+
+### Fork the Project
+
+To fork this project, press the Fork button at the top of the [repository page](https://github.com/python-discord/seasonalbot):
+
+![](https://i.imgur.com/gPfSW8j.png)
+
+In your new forked repository, copy the git url by clicking the green `clone or download` button and then the copy link button:
-#### 1. Fork
-Ok, now you have got PyCharm downloading you are going to want to fork this project and find its git URL. To fork scroll to the top of the page and press this button.
-![](https://i.imgur.com/Saf9pgJ.png)
-Then when you new forked repository loads you are going to want to get the Git Url by clicking the green `clone or download` button and then the copy link button as seen below:
![](https://i.imgur.com/o6kuQcZ.png)
-#### 2. Clone
-Now that you have done that you are going to want to load up Pycharm and you'll get something like this without the left sidebar:
-![](https://i.imgur.com/xiGERvR.png)
-You going to want to click Check Out from Version `Control->Git` and you'll get a popup like the one below:
-![](https://i.imgur.com/d4U6Iw7.png)
-Now paste your link in, test the connection and hit `clone`. You now have a copy of your repository to work with and it should setup your Pipenv automatically.
-#### 3. Bot
-Now we have setup our repository we need somewhere to test out bot.
-You'll need to make a new discord server:
-![](https://i.imgur.com/49gBlQI.png)
-We need to make the applicaiton for our bot... navigate over to [discordapp.com/developers](https://discordapp.com/developers) and hit new application
-![](https://i.imgur.com/UIeGPju.png)
-Now we have our discord application you'll want to name your bot as below:
-![](https://i.imgur.com/odTWSMV.png)
-To actually make the bot hit `Bot->Add Bot->Yes, do It!` as below:
-![](https://i.imgur.com/frAUbTZ.png)
-Copy that Token and put to somewhere for safe keeping.
-![](https://i.imgur.com/oEpIqND.png)
-Now to add that robot to out new discord server we need to generate an OAuth2 Url to do so navigate to the OAuth2 tab, Scroll to the OAUTH2 URL GENERATOR section, click the `Bot` checkbox in the scope section and finally hit the `administrator` checkbox in the newly formed Bot Permissions section.
-![](https://i.imgur.com/I2XzYPj.png)
-Copy and paste the link into your browser and follow the instructions to add the bot to your server - ensure it is the server you have just created.
-#### 4. Run Configurations
-Go back to PyCharm and you should have something a bit like below, Your going to want to hit the `Add Configuration` button in the top right.
-![](https://i.imgur.com/nLpDfQO.png)
-We are going to want to choose a python config as below:
-![](https://i.imgur.com/9FgCuP1.png)
-The first setting we need to change is script path as below (the start script may have changed from bot.py so be sure to click the right one
-![](https://i.imgur.com/napKLar.png)
-Now we need to add an enviroment variable - what this will do is allow us to set a value without it affact the main repository.
-To do this click the folder icon to the right of the text, then on the new window the plus icon. Now name the var `HACKTOBERBOT_TOKEN` and give the value the token we kept for safe keeping earilier.
-![](https://i.imgur.com/nZFWNaQ.png)
-Now hit apply on that window and your ready to get going!
-#### 5. Git in PyCharm
-As we work on our project we are going to want to make commits. Commits are effectively a list of changes you made to the pervious version. To make one first hit the green tick in the top right
-![](https://i.imgur.com/BCiisvN.png)
-1. Select the files you wish to commit
-2. Write a brief description of what your commit is
-3. See the actual changes you commit does here (you can also turn some of them off or on if you wish)
-4. Hit commit
-
-![](https://i.imgur.com/xA5ga4C.png)
-Now once you have made a few commits and are happy with your changes you are going to want to push them back to your fork.
-There are three ways of doing this.
-1. Using the VSC Menu `VSC->Git->Push`
-2. Using the VSC popup <code>alt-\`->Push</code>
-3. A shortcut: `ctrl+shift+K`
-
-You should get a menu like below:
-1. List of commits
-2. List of changed files
-3. Hit Push to send to fork!
-
-![](https://i.imgur.com/xA5ga4C.png)
-#### 6. Pull Requests (PR or PRs)
-Goto https://github.com/python-discord/seasonalbot/pulls and the green New Pull Request button!
+
+### Clone & Install Packages
+
+#### With PyCharm:
+
+Load up PyCharm and click `Check Out from Version Control` -> `Git`:
+
+![](https://i.imgur.com/ND7Z5rN.png)
+
+Test the URL with `Test` first and then click `Clone`.
+
+![](https://i.imgur.com/gJkwHA0.png)
+
+Note: PyCharm automatically detects the Pipfile in the project and sets up your packages for you.
+
+#### With console:
+
+Open a console at the directory you want your project to be in and use the git clone command to copy the project files from your fork repository:
+
+```bash
+git clone https://github.com/yourusername/seasonalbot.git
+```
+
+Change your console directory to be within the new project folder (should be named `seasonalbot` usually) and run the pipenv sync command to install and setup your environment.
+```bash
+cd seasonalbot
+pipenv sync --dev
+```
+
+### Test Server
+
+Create a test discord server if you haven't got one already:
+
+![](https://i.imgur.com/49gBlQIl.png)
+
+In your test server, ensure you have the following:
+ - `#announcements` channel
+ - `#dev-logs` channel
+ - `admins` role
+ - A channel to test your commands in.
+
+### Bot Account
+
+Go to the [Discord Developers Portal](https://discordapp.com/developers/applications/) and click the `New Application` button, enter the new bot name and click `Create`:
+
+![](https://i.imgur.com/q5wlDPs.png)
+
+In your new application, go to the `Bot` tab, click `Add Bot` and confirm `Yes, do it!`:
+
+![](https://i.imgur.com/PxlscgF.png)
+
+Change your bot's `Public Bot` setting off so only you can invite it, save, and then get your token with the `Copy` button:
+
+![](https://i.imgur.com/EM3NIiB.png)
+
+Save your token somewhere safe so we can put it in the project settings later.
+
+In the `General Information` tab, grab the Client ID:
+
+![](https://i.imgur.com/pG7Ix3n.png)
+
+Add the Client ID to the following invite url and visit it in your browser to invite the bot to your new test server:
+```
+https://discordapp.com/api/oauth2/authorize?client_id=CLIENT_ID_HERE&permissions=8&scope=bot
+```
+
+Optionally, you can generate your own invite url in the `OAuth` tab, after selecting `bot` as the Scope.
+
+### Configuration
+
+#### Environment Variables:
+
+Create a `.env` file in your project root and copy the following text into it:
+```
+SEASONALBOT_DEBUG=True
+SEASONALBOT_TOKEN=0
+SEASONALBOT_GUILD=0
+SEASONALBOT_ADMIN_ROLE_ID=0
+CHANNEL_ANNOUNCEMENTS=0
+CHANNEL_DEVLOG=0
+```
+
+Edit the variable values to match your own bot token that you put aside earlier, the ID of your Guild, the Announcements and Dev-logs channel IDs and the admin role ID. To get the role ID, you can make it mentionable, and send an escaped mention like `\@admin`:
+
+![](https://i.imgur.com/qANC8jA.png)
+
+Note: These are only the basic environment variables. Each season will likely have their own variables needing to set, so be sure to check out the respective seasonal setups that you're working on.
+
+#### PyCharm Project Config:
+
+Copy the contents of your `.env` file first.
+Click the `Add Configuration` button in the top right of the window.
+
+![](https://i.imgur.com/Qj2RDwU.png)
+
+In the Configuration Window do the following:
+1. Click the plus on the top left and select `Python`.
+2. Add `bot` to the `Script path` input box.
+5. Add `-m` to the `Interpreter options` input box.
+
+![](https://i.imgur.com/3Cs05fg.png)
+
+Click the folder icon for the `Environment variables` input box. In the new window, click the paste icon on the right side and click `OK`:
+
+![](https://i.imgur.com/ET6gC3e.png)
+
+Note: This should have your actual bot token and IDs as the values. If you copied the blank template from above and didn't update it, go back to do so first.
+
+Click `OK` to save and close the Configuration window.
+
+From now on, to run the bot you only need to click the `Run` button in the top right of PyCharm:
+
+![](https://i.imgur.com/YmqnLqC.png)
+
+#### In console:
+
+Since we have the `.env` file in the project root, anytime we run Pipenv and it'll automatically load the environment variables present within.
+
+To run the the bot, use:
+```bash
+pipenv run start
+```
+
+### Working with Git
+
+Working with git can be intimidating at first, so feel free to ask for any help in the server.
+
+For each push request you work on, you'll want to push your commits to a branch just for it in your repository. This keeps your `master` branch clean, so you can pull changes from the original repository without pulling the same commits you've already added to your fork.
+
+Once you finish a push request, you can delete your branch, and pull the changes from the original repository into your master branch. With the master branch updated, you can now create a new branch to work on something else.
+
+Note: You should never commit directly to the original repository's `master` branch. All additions to the `master` branch of the original repository **must** be put through a PR first.
+
+#### Precommit Hook
+
+Projects need to pass linting checks to be able to successfully build and pass as in push requests.
+Read [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
+
+To install the precommit hook, which checks your code before commits are submitted, do the following:
+```bash
+pipenv run precommit
+```
+
+#### In PyCharm
+
+The PyCharm interface has a set of Git actions on the top right section of your workspace:
+
+![](https://i.imgur.com/1LsyMx9.png)
+
+In order from left to right these are:
+- Update
+- Commit
+- History
+- Revert
+
+As we work on our project we are going to want to make commits. Commits are effectively a log of changes you made over time.
+
+Before making any commits, you should make the branch for the PR you're about to work on. At the bottom of the PyCharm workspace, you'll see the current git branch, which you can click to show a menu of actions. You can click `New Branch` to create a new one, and name it something short that references what the PR is to accomplish. Before making new branches, be sure you change to `master` and ensure it's up to date before creating a new branch.
+
+![](https://i.imgur.com/A9zV4lF.png)
+
+After making changes to the project files, you can commit by clicking the `Commit` button that's part of the git actions available on the top right of your workspace.
+
+The flow of making a commit is as follows:
+
+1. Select the files you wish to commit.
+2. Write a brief description of what your commit is.
+3. See the actual changes you commit does, and optionally tick/untick specific changes to only commit the changes you want.
+4. Click `Commit`.
+
+![](https://i.imgur.com/MvGQKT9.png)
+
+To create a new branch,
+
+Once you have made a few commits and are ready to push them to your fork repository, you can do any of the following:
+- Use the VSC Menu `VSC` -> `Git` -> `Push`
+- Use the VSC popup `alt-\ ` -> `Push`
+- Use the Push shortcut: `CTRL+SHIFT+K`
+
+You should see a window listing commits and changed files.
+Click `Push` when you're ready and it'll submit the commits to your forked repository.
+
+#### With console:
+
+When you create a commit, you will either want to add certain files for that commit, or apply all changes to every file.
+
+It's recommended to add only the files that you want to apply changes to before committing, rather than committing everything tracked. This brings more caution, and allows you to check first each file is relevant to the PR you're working on.
+
+To only add certain files, you will need to do that first before committing:
+```bash
+# create/use feature branch
+git checkout some_new_feature
+
+# stage a single file
+git add my_file.py
+
+# stage multiple files in one command
+git add file_one.py file_two.py file_three.py
+
+# stage all files in current directory
+git add .
+
+# remove a file from staging
+git rm --cached wrong_file.py
+
+# finally commit
+git commit -m "commit message here"
+```
+
+If you're absolutely sure that the tracked changes are all within scope of your PR, you can try using the commit all command.
+To commit all changes across all tracked files, just use the `-a` flag:
+```bash
+git commit -a -m "commit message here"
+```
+
+### Pull Requests (PRs)
+
+Go to the [Pull requests](https://github.com/python-discord/seasonalbot/pulls) and click the green New Pull Request button:
+
![](https://i.imgur.com/fB4a2wQ.png)
-Now you should hit `Compare across forks` then on the third dropdown select your fork (it will be `your username/seasonalbot`) then hit Create Pull request.
-1[](https://i.imgur.com/N2X9A9v.png)
-Now to tell other people what your PR does
-1. Title - be concise and informative
-2. Description - write what the PR changes as well as what issues it relates to
-3. Hit `Create pull request`
-![](https://i.imgur.com/OjKYdsL.png)
-#### 7. Wait & further reading
-At this point your PR will either be accepted or a maintainer might request some changes.
+Click `Compare across forks`.
+Change the `head fork` dropdown box to your fork (`your_username/seasonalbot`).
+Click `Create pull request`.
+
+![](https://i.imgur.com/N2X9A9v.png)
+
+In the PR details, put a concise and informative title.
+Write a description for the PR regarding the changes and any related issues.
+Ensure `Allow edits from maintainers.` has been ticked.
+Click `Create pull request`.
+
+![](https://i.imgur.com/yMJVMNj.png)
-You can now read up some more on [Git](https://try.github.io), [PyCharm](https://www.jetbrains.com/help/pycharm/quick-start-guide.html),
-or learn more about Python and Discord: [discord.py rewrite](https://discordpy.readthedocs.io/en/rewrite)
+A maintainer or other participants may comment or review your PR, and may suggest changes. Communicate in the PR ticket and try ensure you respond timely on any questions or feedback you might get to prevent a PR being marked stale.
+After a successful review by a maintainer, the PR may be merged successfully, and the new feature will deploy to the live bot within 10 minutes usually.
-### Without PyCharm
-The process above can be completed without PyCharm however it will be necessary to learn how to use Git, Pipenv and Environment variables.
+### Further Reading
-You can find tutorials for the above below:
-- Git: [try.github](http://try.github.io/)
-- Pipenv [Pipenv.readthedocs](https://pipenv.readthedocs.io)
-- Environment Variables: [youtube](https://youtu.be/bEroNNzqlF4?t=27)
+- [Git](https://try.github.io)
+- [PyCharm](https://www.jetbrains.com/help/pycharm/quick-start-guide.html)
+- [Pipenv](https://pipenv.readthedocs.io)
+- [discord.py rewrite](https://discordpy.readthedocs.io/en/rewrite)
+- [Environment Variables (youtube)](https://youtu.be/bEroNNzqlF4?t=27)
diff --git a/bot/constants.py b/bot/constants.py
index 4e09b448..ec8a1a4d 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -61,6 +61,7 @@ class Client(NamedTuple):
class Colours:
soft_red = 0xcd6d6d
soft_green = 0x68c290
+ bright_green = 0x01d277
dark_green = 0x1f8b4c
orange = 0xe67e22
pink = 0xcf84e0
@@ -72,6 +73,11 @@ class Emojis:
check = "\u2611"
+class Lovefest:
+ channel_id = int(environ.get("LOVEFEST_CHANNEL_ID", 542272993192050698))
+ role_id = int(environ.get("LOVEFEST_ROLE_ID", 542431903886606399))
+
+
class Hacktoberfest(NamedTuple):
channel_id = 498804484324196362
voice_id = 514420006474219521
diff --git a/bot/resources/valentines/date_ideas.json b/bot/resources/valentines/date_ideas.json
new file mode 100644
index 00000000..09d31067
--- /dev/null
+++ b/bot/resources/valentines/date_ideas.json
@@ -0,0 +1,127 @@
+{
+ "ideas": [
+ {
+ "name": "Chick flick marathon",
+ "description": "This is a very basic yet highly romantic way of spending the day with your partner. Take a few days to prepare the right playlist and create a romantic atmosphere at home. You can order out some food, open a bottle of wine and cuddle up in front of the TV."
+ },
+
+ {
+ "name": "Recreate your first date",
+ "description": "Rated pretty high on the “romantic gestures scale,” this is guaranteed to impress your significant other. It requires a good memory and a bit of work to make it just right, but it is well worth it. Walk down the same streets where you first kissed and have a couple of drinks in that old coffee shop where you had your first drinks together. Don’t be afraid to spend a bit extra and add a little romantic gift into the mix."
+ },
+ {
+ "name": "Cook for your loved one",
+ "description": "Start researching good recipes for a romantic dinner for two, get the right ingredients and prepare a couple of practice dinners to make sure you’ve got your technique and presentation down pat. Cooking for someone can be a big turn on and you can create some incredible meals without spending too much money. Take it up a notch by dressing classy, decorating your dining room and presenting your partner with a printed menu."
+ },
+ {
+ "name": "Organize your very own ancient Greek party",
+ "description": "Here’s another one of those creative date ideas for the stay-at-home couple. The ancient Greek private party can be a very fun and erotic experience. You can decorate by using big bowls full of grapes, spreading some white sheets all over the place, placing some plastic vines here and there, putting up a few posters depicting Greek parties and having plenty of wine lying around. Wear nothing but light sheets or costumes and channel some of that hot-blooded Greek spirit."
+ },
+ {
+ "name": "A romantic weekend getaway in the mountains",
+ "description": "For those looking for a change of scenery and an escape from the busy city, there is nothing better than a quiet, romantic weekend in the mountains. There are plenty of fun activities like skiing that will keep you active. You can have fun making a snowman or engaging in a snowball fight, and, of course, there is plenty of privacy and great room service waiting for you back at your room."
+ },
+ {
+ "name": "Fun day at the shooting range",
+ "description": "A bit unconventional but an incredibly fun and exciting date that will get your blood pumping and put a huge smile on your faces. Try out a number of guns and have a bit of a competition. Some outdoor ranges have fully automatic rifles, which are a blast to shoot."
+ },
+ {
+ "name": "Rent an expensive sports car for a day",
+ "description": "Don’t be afraid to live large from time to time—even if you can’t afford the glamorous lifestyle of the stars, you can most definitely play pretend for a day. Put on some classy clothes and drive around town in a rented sports car. The quick acceleration and high speed are sure to provide an exhilarating experience. "
+ },
+ {
+ "name": "Go on a shopping spree together",
+ "description": "Very few things can elicit such a huge dopamine rush as a good old shopping spree. Get some new sexy lingerie, pretty shoes, a nice shirt and tie, a couple of new video games or whatever else you need or want. This is a unique chance to bond, have fun and get some stuff that you’ve been waiting to buy for a while now."
+ },
+ {
+ "name": "Hit the clubs",
+ "description": "For all the party animals out there, one of the best date ideas is to go out drinking, dancing, and just generally enjoying the night life. Visit a few good clubs, then go to an after-party and keep that party spirit going for as long as you can."
+ },
+ {
+ "name": "Spend the day driving around the city and visiting new places",
+ "description": "This one is geared towards couples who have been together for a year or two and want to experience a few new things together. Visit a few cool coffee places on the other side of town, check out interesting restaurants you’ve never been to, and consider going to see a play or having fun at a comedy club on open mic night."
+ },
+ {
+ "name": "Wine and chocolates at sunset",
+ "description": "Pick out a romantic location, such as a camping spot on a hill overlooking the city or a balcony in a restaurant with a nice view, open a bottle of wine and a box of chocolates and wait for that perfect moment when the sky turns fiery red to embrace and share a passionate kiss."
+ },
+ {
+ "name": "Ice skating",
+ "description": "There is something incredibly fun about ice skating that brings people closer together and just keeps you laughing (maybe it’s all the falling and clinging to the other person for dear life). You can have some great fun and then move on to a more private location for some alone time."
+ },
+ {
+ "name": "Model clothes for each other",
+ "description": "This one goes well when combined with a shopping spree, but you can just get a bunch of your clothes—old and new—from the closet, set up a catwalk area and then try on different combinations. You can be stylish, funny, handsome and sexy. It’s a great after-dinner show and a good way to transition into a more intimate atmosphere."
+ },
+ {
+ "name": "Dance the night away",
+ "description": "If you and your significant other are relatively good dancers, or if you simply enjoy moving your body to the rhythm of the music, then a night at salsa club or similar venue is the perfect thing for you. Alternatively, you can set up dance floor at home, play your favorite music, have a few drinks and dance like there is no tomorrow."
+ },
+ {
+ "name": "Organize a nature walk",
+ "description": "Being outside has many health benefits, but what you are going for is the beautiful view, seclusion, and the thrill of engaging in some erotic behavior out in the open. You can rent a cottage far from the city, bring some food and drinks, and explore the wilderness. This is nice way to spice things up a bit and get away from the loud and busy city life."
+ },
+ {
+ "name": "Travel abroad",
+ "description": "This takes a bit of planning in advance and may be a bit costly, but if you can afford it, there are very few things that can match a trip to France, Italy, Egypt, Turkey, Greece, or a number of other excellent locations."
+ },
+ {
+ "name": "Go on a hot-air balloon ride",
+ "description": "These are very fun and romantic—you get an incredible view, get to experience the thrill of flying, and you’ve got enough room for a romantic dinner and some champagne. Just be sure to wear warm clothes, it can get pretty cold high up in the air."
+ },
+ {
+ "name": "A relaxing day at the spa",
+ "description": "Treat your body, mind and senses to a relaxing day at the spa. You and your partner will feel fresh, comfortable, relaxed, and sexy as hell—a perfect date for the more serious couples who don’t get to spend as much time with each other as they’d like."
+ },
+ {
+ "name": "Fun times at a karaoke bar",
+ "description": "A great choice for couples celebrating their first Valentine’s Day together—it’s fairly informal and inexpensive, yet incredibly fun and allows for deeper bonding. Once you have a few drinks in your system and come to terms with the fact that you are making a complete fool of yourself, you’ll have the time of your life!"
+ },
+ {
+ "name": "Horseback riding",
+ "description": "Horseback riding is incredibly fun, especially if you’ve never done it before. And what girl doesn’t dream of a prince coming to take her on an adventure on his noble steed? It evokes a sense of nobility and is a very good bonding experience."
+ },
+ {
+ "name": "Plan a fun date night with other couples",
+ "description": "Take a break and rent a cabin in the woods, go to a mountain resort, a couple’s retreat, or just organize a huge date night at someone’s place and hang out with other couples. This is a great option for couples who have spent at least one Valentine’s Day together and allows you to customize your experience to suit your needs. Also, you can always retire early and get some alone time with your partner if you so desire."
+ },
+ {
+ "name": "Go to a concert",
+ "description": "There are a whole bunch of things happening around Valentine’s Day, so go online and check out what’s happening near you. You’ll surely be able to find tickets for a cool concert or some type of festival with live music."
+ },
+ {
+ "name": "Fancy night on the town",
+ "description": "Buy some elegant new clothes, rent a limo for the night and go to a nice restaurant, followed by a jazz club or gallery exhibition. Walk tall, make a few sarcastic quips, and have a few laughs with your partner while letting your inner snob take charge for a few hours."
+ },
+ {
+ "name": "Live out a James Bond film at a casino",
+ "description": "A beautiful lady in a simple yet sensual, form-fitting, black dress, and a strong and handsome, if somewhat stern-looking man in a fine suit walk up to a roulette table with drinks in hand and place bets at random as they smile at each other seductively. This is a scenario most of us wish to play out, but rarely get a chance. It can be a bit costly, but this is one of the most incredibly adventurous and romantic date ideas."
+ },
+ {
+ "name": "Go bungee jumping",
+ "description": "People in long-term relationships often talk about things like keeping a relationship fun and exciting, doing new things together, trusting each other and using aphrodisiacs. Well, bungee jumping is a fun, exhilarating activity you can both enjoy; it requires trust and the adrenaline rush you get from it is better than any aphrodisiac out there. Just saying, give it a shot and you won’t regret it. "
+ },
+ {
+ "name": "Play some sports",
+ "description": "Some one-on-one basketball, a soccer match against another couple, a bit of tennis, or even something as simple as a table tennis tournament (make it fun by stripping off items of clothing when you lose a game). You can combine this with date idea #13 and paint team uniforms on each other and play in the nude."
+ },
+ {
+ "name": "Take skydiving lessons",
+ "description": "An adrenaline-filled date, skydiving is sure to get your heart racing like crazy and leave you with a goofy grin for the rest of the day. You can offset all the excitement by ending the day with a quiet dinner at home."
+ },
+ {
+ "name": "Go for some paintball",
+ "description": "Playing war games is an excellent way to get your body moving, focus on some of that hand-eye-coordination, and engage your brain in coming up with tactical solutions in the heat of the moment. It is also a great bonding experience, adrenaline-fueled fun, and role-playing all wrapped into one. And when you get back home, you can always act out the wounded soldier scenario."
+ },
+ {
+ "name": "Couples’ Yoga",
+ "description": "Getting up close, hot, and sweaty? Sounds like a Valentine’s Day movie to me. By signing up with your partner for a couples’ yoga class, you can sneak in a workout while getting some face-to-face time with your date.This type of yoga focuses on poses that can be done with a partner, such as back-to-back bends, assisted stretches, and face-to-face breathing exercises. By working out together, you strengthen your bond while stretching away the stress of the week. Finish the date off by heading to the juice bar for a smoothie, or indulging in healthy salads for two. Expect to spend around $35 per person, or approximately $50 to $60 per couple."
+ },
+ {
+ "name": "Volunteer Together",
+ "description": "Getting your hands dirty for a good cause might not be the first thing that pops into your mind when you think “romance,” but there’s something to be said for a date that gives you a glimpse of your partner’s charitable side. Consider volunteering at an animal rescue, where you might be able to play with pups or help a few lovebirds pick out their perfect pet. Or, sign up to visit the elderly at a care center, where you can be a completely different kind of Valentine for someone in need."
+ }
+ ]
+}
+
+
diff --git a/bot/seasons/valentines/savethedate.py b/bot/seasons/valentines/savethedate.py
new file mode 100644
index 00000000..a9bddd34
--- /dev/null
+++ b/bot/seasons/valentines/savethedate.py
@@ -0,0 +1,41 @@
+import logging
+import random
+from json import load
+from pathlib import Path
+
+import discord
+from discord.ext import commands
+
+from bot.constants import Colours
+
+log = logging.getLogger(__name__)
+
+HEART_EMOJIS = [":heart:", ":gift_heart:", ":revolving_hearts:", ":sparkling_heart:", ":two_hearts:"]
+
+
+class SaveTheDate:
+ """
+ A cog that gives random suggestion, for a valentines date !
+ """
+
+ def __init__(self, bot):
+ self.bot = bot
+
+ @commands.command()
+ async def savethedate(self, ctx):
+ with open(Path('bot', 'resources', 'valentines', 'date_ideas.json'), 'r', encoding="utf8") as f:
+ valentine_dates = load(f)
+ random_date = random.choice(valentine_dates['ideas'])
+ emoji_1 = random.choice(HEART_EMOJIS)
+ emoji_2 = random.choice(HEART_EMOJIS)
+ embed = discord.Embed(
+ title=f"{emoji_1}{random_date['name']}{emoji_2}",
+ description=f"{random_date['description']}",
+ colour=Colours.pink
+ )
+ await ctx.send(embed=embed)
+
+
+def setup(bot):
+ bot.add_cog(SaveTheDate(bot))
+ log.debug("Save the date cog loaded")