From 203a4517651ac38a9da28b8808ec0326f46ef793 Mon Sep 17 00:00:00 2001 From: deepfates Date: Mon, 21 Feb 2022 13:31:36 -0700 Subject: [PATCH 1/8] persistent synonyms working --- Pipfile.lock | 513 +------------------------------------------------- synonymbot.py | 83 ++++++++ 2 files changed, 85 insertions(+), 511 deletions(-) create mode 100755 synonymbot.py diff --git a/Pipfile.lock b/Pipfile.lock index ae6d1f7e..c00be2e7 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "bf0eef9b2c01dc0078c2581ecb4652ce5acfd38978a5997dbfcd8c06c21e9727" + "sha256": "500e5c319674d72a813bad7de6f5dd9ad28984b2ec222a4d8c58ff081795451d" }, "pipfile-spec": 6, "requires": { @@ -16,520 +16,11 @@ ] }, "default": { - "aiodns": { - "hashes": [ - "sha256:2b19bc5f97e5c936638d28e665923c093d8af2bf3aa88d35c43417fa25d136a2", - "sha256:946bdfabe743fceeeb093c8a010f5d1645f708a241be849e17edfb0e49e08cd6" - ], - "version": "==3.0.0" - }, "aiohttp": { "extras": [ "speedups" ], - "hashes": [ - "sha256:173267050501e1537293df06723bc5e719990889e2820ba3932969983892e960", - "sha256:438f1f1555c02c50894604d94944cff188fe138b46467b7fa99fdceb51ab5842", - "sha256:90bed250d1435aef33a1f8c439c5056d5d25a44fe6caf33fcafafed805bad4dc", - "sha256:93c3b14747413f38f094a60e98f55e73831f0c9a23ae7faa3dc97d8963e13021", - "sha256:a6e70a38d883185b1921d8122759661c39ade54949770394412a9e713fec6fa7", - "sha256:b5036133c1ba77ed5a70208d2a021a90b76fdf8bf523ae33dae46d4f4380d86f", - "sha256:c138451a82cdbf65cddf952941d5c7a1a2cac8ce3bc618dee8d889e5251ec7a5", - "sha256:c94770383e49f9cc5912b926364ad022a6c8a5dbf5498933ca3a5713c6daf738", - "sha256:ea26536ae06df6dac021303a0df72c79e55512070e6a304ba93ad468a3a754dc" - ], - "index": "pypi", - "version": "==4.0.0a1" - }, - "aioprocessing": { - "hashes": [ - "sha256:00757aa3ae8d99a7e41079d7b5fcdcbb7794b1d454961e8c6601e3d4be63c03f", - "sha256:469dfb746e8c4e0c727ba135cfabf9e034c554f6a73c27f908bfe3625dd74b9e" - ], - "index": "pypi", - "version": "==2.0.0" - }, - "async-timeout": { - "hashes": [ - "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f", - "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3" - ], - "markers": "python_full_version >= '3.5.3'", - "version": "==3.0.1" - }, - "asyncpg": { - "hashes": [ - "sha256:0a61fb196ce4dae2f2fa26eb20a778db21bbee484d2e798cb3cc988de13bdd1b", - "sha256:18d49e2d93a7139a2fdbd113e320cc47075049997268a61bfbe0dde680c55471", - "sha256:191fe6341385b7fdea7dbdcf47fd6db3fd198827dcc1f2b228476d13c05a03c6", - "sha256:1a70783f6ffa34cc7dd2de20a873181414a34fd35a4a208a1f1a7f9f695e4ec4", - "sha256:2633331cbc8429030b4f20f712f8d0fbba57fa8555ee9b2f45f981b81328b256", - "sha256:2bc197fc4aca2fd24f60241057998124012469d2e414aed3f992579db0c88e3a", - "sha256:4327f691b1bdb222df27841938b3e04c14068166b3a97491bec2cb982f49f03e", - "sha256:43cde84e996a3afe75f325a68300093425c2f47d340c0fc8912765cf24a1c095", - "sha256:52fab7f1b2c29e187dd8781fce896249500cf055b63471ad66332e537e9b5f7e", - "sha256:56d88d7ef4341412cd9c68efba323a4519c916979ba91b95d4c08799d2ff0c09", - "sha256:5e4105f57ad1e8fbc8b1e535d8fcefa6ce6c71081228f08680c6dea24384ff0e", - "sha256:63f8e6a69733b285497c2855464a34de657f2cccd25aeaeeb5071872e9382540", - "sha256:649e2966d98cc48d0646d9a4e29abecd8b59d38d55c256d5c857f6b27b7407ac", - "sha256:6f8f5fc975246eda83da8031a14004b9197f510c41511018e7b1bedde6968e92", - "sha256:72a1e12ea0cf7c1e02794b697e3ca967b2360eaa2ce5d4bfdd8604ec2d6b774b", - "sha256:739bbd7f89a2b2f6bc44cb8bf967dab12c5bc714fcbe96e68d512be45ecdf962", - "sha256:863d36eba4a7caa853fd7d83fad5fd5306f050cc2fe6e54fbe10cdb30420e5e9", - "sha256:a738f1b2876f30d710d3dc1e7858160a0afe1603ba16bf5f391f5316eb0ed855", - "sha256:a84d30e6f850bac0876990bcd207362778e2208df0bee8be8da9f1558255e634", - "sha256:acb311722352152936e58a8ee3c5b8e791b24e84cd7d777c414ff05b3530ca68", - "sha256:beaecc52ad39614f6ca2e48c3ca15d56e24a2c15cbfdcb764a4320cc45f02fd5", - "sha256:bf5e3408a14a17d480f36ebaf0401a12ff6ae5457fdf45e4e2775c51cc9517d3", - "sha256:bf6dc9b55b9113f39eaa2057337ce3f9ef7de99a053b8a16360395ce588925cd", - "sha256:ddb4c3263a8d63dcde3d2c4ac1c25206bfeb31fa83bd70fd539e10f87739dee4", - "sha256:f55918ded7b85723a5eaeb34e86e7b9280d4474be67df853ab5a7fa0cc7c6bf2", - "sha256:fe471ccd915b739ca65e2e4dbd92a11b44a5b37f2e38f70827a1c147dafe0fa8" - ], - "index": "pypi", - "version": "==0.25.0" - }, - "attrs": { - "hashes": [ - "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4", - "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==21.4.0" - }, - "base58": { - "hashes": [ - "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2", - "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c" - ], - "index": "pypi", - "version": "==2.1.1" - }, - "brotli": { - "hashes": [ - "sha256:160c78292e98d21e73a4cc7f76a234390e516afcd982fa17e1422f7c6a9ce9c8", - "sha256:16d528a45c2e1909c2798f27f7bf0a3feec1dc9e50948e738b961618e38b6a7b", - "sha256:19598ecddd8a212aedb1ffa15763dd52a388518c4550e615aed88dc3753c0f0c", - "sha256:1c48472a6ba3b113452355b9af0a60da5c2ae60477f8feda8346f8fd48e3e87c", - "sha256:268fe94547ba25b58ebc724680609c8ee3e5a843202e9a381f6f9c5e8bdb5c70", - "sha256:269a5743a393c65db46a7bb982644c67ecba4b8d91b392403ad8a861ba6f495f", - "sha256:26d168aac4aaec9a4394221240e8a5436b5634adc3cd1cdf637f6645cecbf181", - "sha256:29d1d350178e5225397e28ea1b7aca3648fcbab546d20e7475805437bfb0a130", - "sha256:2aad0e0baa04517741c9bb5b07586c642302e5fb3e75319cb62087bd0995ab19", - "sha256:35a3edbe18e876e596553c4007a087f8bcfd538f19bc116917b3c7522fca0429", - "sha256:3b78a24b5fd13c03ee2b7b86290ed20efdc95da75a3557cc06811764d5ad1126", - "sha256:40d15c79f42e0a2c72892bf407979febd9cf91f36f495ffb333d1d04cebb34e4", - "sha256:44bb8ff420c1d19d91d79d8c3574b8954288bdff0273bf788954064d260d7ab0", - "sha256:4d1b810aa0ed773f81dceda2cc7b403d01057458730e309856356d4ef4188438", - "sha256:503fa6af7da9f4b5780bb7e4cbe0c639b010f12be85d02c99452825dd0feef3f", - "sha256:56d027eace784738457437df7331965473f2c0da2c70e1a1f6fdbae5402e0389", - "sha256:5913a1177fc36e30fcf6dc868ce23b0453952c78c04c266d3149b3d39e1410d6", - "sha256:5b6ef7d9f9c38292df3690fe3e302b5b530999fa90014853dcd0d6902fb59f26", - "sha256:5cb1e18167792d7d21e21365d7650b72d5081ed476123ff7b8cac7f45189c0c7", - "sha256:61a7ee1f13ab913897dac7da44a73c6d44d48a4adff42a5701e3239791c96e14", - "sha256:622a231b08899c864eb87e85f81c75e7b9ce05b001e59bbfbf43d4a71f5f32b2", - "sha256:68715970f16b6e92c574c30747c95cf8cf62804569647386ff032195dc89a430", - "sha256:6b2ae9f5f67f89aade1fab0f7fd8f2832501311c363a21579d02defa844d9296", - "sha256:6c772d6c0a79ac0f414a9f8947cc407e119b8598de7621f39cacadae3cf57d12", - "sha256:76ffebb907bec09ff511bb3acc077695e2c32bc2142819491579a695f77ffd4d", - "sha256:7cb81373984cc0e4682f31bc3d6be9026006d96eecd07ea49aafb06897746452", - "sha256:7ee83d3e3a024a9618e5be64648d6d11c37047ac48adff25f12fa4226cf23d1c", - "sha256:854c33dad5ba0fbd6ab69185fec8dab89e13cda6b7d191ba111987df74f38761", - "sha256:87fdccbb6bb589095f413b1e05734ba492c962b4a45a13ff3408fa44ffe6479b", - "sha256:88c63a1b55f352b02c6ffd24b15ead9fc0e8bf781dbe070213039324922a2eea", - "sha256:8a674ac10e0a87b683f4fa2b6fa41090edfd686a6524bd8dedbd6138b309175c", - "sha256:93130612b837103e15ac3f9cbacb4613f9e348b58b3aad53721d92e57f96d46a", - "sha256:9744a863b489c79a73aba014df554b0e7a0fc44ef3f8a0ef2a52919c7d155031", - "sha256:9749a124280a0ada4187a6cfd1ffd35c350fb3af79c706589d98e088c5044267", - "sha256:97f715cf371b16ac88b8c19da00029804e20e25f30d80203417255d239f228b5", - "sha256:9bf919756d25e4114ace16a8ce91eb340eb57a08e2c6950c3cebcbe3dff2a5e7", - "sha256:9d12cf2851759b8de8ca5fde36a59c08210a97ffca0eb94c532ce7b17c6a3d1d", - "sha256:a72661af47119a80d82fa583b554095308d6a4c356b2a554fdc2799bc19f2a43", - "sha256:afde17ae04d90fbe53afb628f7f2d4ca022797aa093e809de5c3cf276f61bbfa", - "sha256:b663f1e02de5d0573610756398e44c130add0eb9a3fc912a09665332942a2efb", - "sha256:c2415d9d082152460f2bd4e382a1e85aed233abc92db5a3880da2257dc7daf7b", - "sha256:c83aa123d56f2e060644427a882a36b3c12db93727ad7a7b9efd7d7f3e9cc2c4", - "sha256:cfc391f4429ee0a9370aa93d812a52e1fee0f37a81861f4fdd1f4fb28e8547c3", - "sha256:db844eb158a87ccab83e868a762ea8024ae27337fc7ddcbfcddd157f841fdfe7", - "sha256:defed7ea5f218a9f2336301e6fd379f55c655bea65ba2476346340a0ce6f74a1", - "sha256:e16eb9541f3dd1a3e92b89005e37b1257b157b7256df0e36bd7b33b50be73bcb", - "sha256:f909bbbc433048b499cb9db9e713b5d8d949e8c109a2a548502fb9aa8630f0b1" - ], - "version": "==1.0.9" - }, - "cchardet": { - "hashes": [ - "sha256:0b859069bbb9d27c78a2c9eb997e6f4b738db2d7039a03f8792b4058d61d1109", - "sha256:228d2533987c450f39acf7548f474dd6814c446e9d6bd228e8f1d9a2d210f10b", - "sha256:2309ff8fc652b0fc3c0cff5dbb172530c7abb92fe9ba2417c9c0bcf688463c1c", - "sha256:24974b3e40fee9e7557bb352be625c39ec6f50bc2053f44a3d1191db70b51675", - "sha256:273699c4e5cd75377776501b72a7b291a988c6eec259c29505094553ee505597", - "sha256:27a9ba87c9f99e0618e1d3081189b1217a7d110e5c5597b0b7b7c3fedd1c340a", - "sha256:302aa443ae2526755d412c9631136bdcd1374acd08e34f527447f06f3c2ddb98", - "sha256:45456c59ec349b29628a3c6bfb86d818ec3a6fbb7eb72de4ff3bd4713681c0e3", - "sha256:48ba829badef61441e08805cfa474ccd2774be2ff44b34898f5854168c596d4d", - "sha256:50ad671e8d6c886496db62c3bd68b8d55060688c655873aa4ce25ca6105409a1", - "sha256:54341e7e1ba9dc0add4c9d23b48d3a94e2733065c13920e85895f944596f6150", - "sha256:54d0b26fd0cd4099f08fb9c167600f3e83619abefeaa68ad823cc8ac1f7bcc0c", - "sha256:5a25f9577e9bebe1a085eec2d6fdd72b7a9dd680811bba652ea6090fb2ff472f", - "sha256:6b6397d8a32b976a333bdae060febd39ad5479817fabf489e5596a588ad05133", - "sha256:70eeae8aaf61192e9b247cf28969faef00578becd2602526ecd8ae7600d25e0e", - "sha256:80e6faae75ecb9be04a7b258dc4750d459529debb6b8dee024745b7b5a949a34", - "sha256:90086e5645f8a1801350f4cc6cb5d5bf12d3fa943811bb08667744ec1ecc9ccd", - "sha256:a39526c1c526843965cec589a6f6b7c2ab07e3e56dc09a7f77a2be6a6afa4636", - "sha256:b154effa12886e9c18555dfc41a110f601f08d69a71809c8d908be4b1ab7314f", - "sha256:b59ddc615883835e03c26f81d5fc3671fab2d32035c87f50862de0da7d7db535", - "sha256:bd7f262f41fd9caf5a5f09207a55861a67af6ad5c66612043ed0f81c58cdf376", - "sha256:c428b6336545053c2589f6caf24ea32276c6664cb86db817e03a94c60afa0eaf", - "sha256:c6f70139aaf47ffb94d89db603af849b82efdf756f187cdd3e566e30976c519f", - "sha256:c96aee9ebd1147400e608a3eff97c44f49811f8904e5a43069d55603ac4d8c97", - "sha256:ec3eb5a9c475208cf52423524dcaf713c394393e18902e861f983c38eeb77f18", - "sha256:eee4f5403dc3a37a1ca9ab87db32b48dc7e190ef84601068f45397144427cc5e", - "sha256:f16517f3697569822c6d09671217fdeab61dfebc7acb5068634d6b0728b86c0b", - "sha256:f86e0566cb61dc4397297696a4a1b30f6391b50bc52b4f073507a48466b6255a", - "sha256:fdac1e4366d0579fff056d1280b8dc6348be964fda8ebb627c0269e097ab37fa" - ], - "version": "==2.1.7" - }, - "cffi": { - "hashes": [ - "sha256:00c878c90cb53ccfaae6b8bc18ad05d2036553e6d9d1d9dbcf323bbe83854ca3", - "sha256:0104fb5ae2391d46a4cb082abdd5c69ea4eab79d8d44eaaf79f1b1fd806ee4c2", - "sha256:06c48159c1abed75c2e721b1715c379fa3200c7784271b3c46df01383b593636", - "sha256:0808014eb713677ec1292301ea4c81ad277b6cdf2fdd90fd540af98c0b101d20", - "sha256:10dffb601ccfb65262a27233ac273d552ddc4d8ae1bf93b21c94b8511bffe728", - "sha256:14cd121ea63ecdae71efa69c15c5543a4b5fbcd0bbe2aad864baca0063cecf27", - "sha256:17771976e82e9f94976180f76468546834d22a7cc404b17c22df2a2c81db0c66", - "sha256:181dee03b1170ff1969489acf1c26533710231c58f95534e3edac87fff06c443", - "sha256:23cfe892bd5dd8941608f93348c0737e369e51c100d03718f108bf1add7bd6d0", - "sha256:263cc3d821c4ab2213cbe8cd8b355a7f72a8324577dc865ef98487c1aeee2bc7", - "sha256:2756c88cbb94231c7a147402476be2c4df2f6078099a6f4a480d239a8817ae39", - "sha256:27c219baf94952ae9d50ec19651a687b826792055353d07648a5695413e0c605", - "sha256:2a23af14f408d53d5e6cd4e3d9a24ff9e05906ad574822a10563efcef137979a", - "sha256:31fb708d9d7c3f49a60f04cf5b119aeefe5644daba1cd2a0fe389b674fd1de37", - "sha256:3415c89f9204ee60cd09b235810be700e993e343a408693e80ce7f6a40108029", - "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139", - "sha256:3b96a311ac60a3f6be21d2572e46ce67f09abcf4d09344c49274eb9e0bf345fc", - "sha256:3f7d084648d77af029acb79a0ff49a0ad7e9d09057a9bf46596dac9514dc07df", - "sha256:41d45de54cd277a7878919867c0f08b0cf817605e4eb94093e7516505d3c8d14", - "sha256:4238e6dab5d6a8ba812de994bbb0a79bddbdf80994e4ce802b6f6f3142fcc880", - "sha256:45db3a33139e9c8f7c09234b5784a5e33d31fd6907800b316decad50af323ff2", - "sha256:45e8636704eacc432a206ac7345a5d3d2c62d95a507ec70d62f23cd91770482a", - "sha256:4958391dbd6249d7ad855b9ca88fae690783a6be9e86df65865058ed81fc860e", - "sha256:4a306fa632e8f0928956a41fa8e1d6243c71e7eb59ffbd165fc0b41e316b2474", - "sha256:57e9ac9ccc3101fac9d6014fba037473e4358ef4e89f8e181f8951a2c0162024", - "sha256:59888172256cac5629e60e72e86598027aca6bf01fa2465bdb676d37636573e8", - "sha256:5e069f72d497312b24fcc02073d70cb989045d1c91cbd53979366077959933e0", - "sha256:64d4ec9f448dfe041705426000cc13e34e6e5bb13736e9fd62e34a0b0c41566e", - "sha256:6dc2737a3674b3e344847c8686cf29e500584ccad76204efea14f451d4cc669a", - "sha256:74fdfdbfdc48d3f47148976f49fab3251e550a8720bebc99bf1483f5bfb5db3e", - "sha256:75e4024375654472cc27e91cbe9eaa08567f7fbdf822638be2814ce059f58032", - "sha256:786902fb9ba7433aae840e0ed609f45c7bcd4e225ebb9c753aa39725bb3e6ad6", - "sha256:8b6c2ea03845c9f501ed1313e78de148cd3f6cad741a75d43a29b43da27f2e1e", - "sha256:91d77d2a782be4274da750752bb1650a97bfd8f291022b379bb8e01c66b4e96b", - "sha256:91ec59c33514b7c7559a6acda53bbfe1b283949c34fe7440bcf917f96ac0723e", - "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954", - "sha256:a5263e363c27b653a90078143adb3d076c1a748ec9ecc78ea2fb916f9b861962", - "sha256:abb9a20a72ac4e0fdb50dae135ba5e77880518e742077ced47eb1499e29a443c", - "sha256:c2051981a968d7de9dd2d7b87bcb9c939c74a34626a6e2f8181455dd49ed69e4", - "sha256:c21c9e3896c23007803a875460fb786118f0cdd4434359577ea25eb556e34c55", - "sha256:c2502a1a03b6312837279c8c1bd3ebedf6c12c4228ddbad40912d671ccc8a962", - "sha256:d4d692a89c5cf08a8557fdeb329b82e7bf609aadfaed6c0d79f5a449a3c7c023", - "sha256:da5db4e883f1ce37f55c667e5c0de439df76ac4cb55964655906306918e7363c", - "sha256:e7022a66d9b55e93e1a845d8c9eba2a1bebd4966cd8bfc25d9cd07d515b33fa6", - "sha256:ef1f279350da2c586a69d32fc8733092fd32cc8ac95139a00377841f59a3f8d8", - "sha256:f54a64f8b0c8ff0b64d18aa76675262e1700f3995182267998c31ae974fbc382", - "sha256:f5c7150ad32ba43a07c4479f40241756145a1f03b43480e058cfd862bf5041c7", - "sha256:f6f824dc3bce0edab5f427efcfb1d63ee75b6fcb7282900ccaf925be84efb0fc", - "sha256:fd8a250edc26254fe5b33be00402e6d287f562b6a5b2152dec302fa15bb3e997", - "sha256:ffaa5c925128e29efbde7301d8ecaf35c8c60ffbcd6a1ffd3a552177c8e5e796" - ], - "version": "==1.15.0" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "idna": { - "hashes": [ - "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", - "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" - ], - "markers": "python_version >= '3.5'", - "version": "==3.3" - }, - "multidict": { - "hashes": [ - "sha256:1ece5a3369835c20ed57adadc663400b5525904e53bae59ec854a5d36b39b21a", - "sha256:275ca32383bc5d1894b6975bb4ca6a7ff16ab76fa622967625baeebcf8079000", - "sha256:3750f2205b800aac4bb03b5ae48025a64e474d2c6cc79547988ba1d4122a09e2", - "sha256:4538273208e7294b2659b1602490f4ed3ab1c8cf9dbdd817e0e9db8e64be2507", - "sha256:5141c13374e6b25fe6bf092052ab55c0c03d21bd66c94a0e3ae371d3e4d865a5", - "sha256:51a4d210404ac61d32dada00a50ea7ba412e6ea945bbe992e4d7a595276d2ec7", - "sha256:5cf311a0f5ef80fe73e4f4c0f0998ec08f954a6ec72b746f3c179e37de1d210d", - "sha256:6513728873f4326999429a8b00fc7ceddb2509b01d5fd3f3be7881a257b8d463", - "sha256:7388d2ef3c55a8ba80da62ecfafa06a1c097c18032a501ffd4cabbc52d7f2b19", - "sha256:9456e90649005ad40558f4cf51dbb842e32807df75146c6d940b6f5abb4a78f3", - "sha256:c026fe9a05130e44157b98fea3ab12969e5b60691a276150db9eda71710cd10b", - "sha256:d14842362ed4cf63751648e7672f7174c9818459d169231d03c56e84daf90b7c", - "sha256:e0d072ae0f2a179c375f67e3da300b47e1a83293c554450b29c900e50afaae87", - "sha256:f07acae137b71af3bb548bd8da720956a3bc9f9a0b87733e0899226a2317aeb7", - "sha256:fbb77a75e529021e7c4a8d4e823d88ef4d23674a202be4f5addffc72cbb91430", - "sha256:fcfbb44c59af3f8ea984de67ec7c306f618a3ec771c2843804069917a8f2e255", - "sha256:feed85993dbdb1dbc29102f50bca65bdc68f2c0c8d352468c25b54874f23c39d" - ], - "markers": "python_version >= '3.5'", - "version": "==4.7.6" - }, - "phonenumberslite": { - "hashes": [ - "sha256:153885eefec397058c8ce91fb987f55545b2cfa945f22a904584ddf162aa82b1", - "sha256:e6fe6cad1091f8928e34a98570cade4758f4cf4e70e9e32ff7eca517ce98e273" - ], - "index": "pypi", - "version": "==8.12.40" - }, - "prometheus-async": { - "hashes": [ - "sha256:227f516e5bf98a0dc602348381e182358f8b2ed24a8db05e8e34d9cf027bab83", - "sha256:3cc68d1f39e9bbf16dbd0b51103d87671b3cbd1d75a72cda472cd9a35cc9d0d2" - ], - "index": "pypi", - "version": "==19.2.0" - }, - "prometheus-client": { - "hashes": [ - "sha256:1b12ba48cee33b9b0b9de64a1047cbd3c5f2d0ab6ebcead7ddda613a750ec3c5", - "sha256:317453ebabff0a1b02df7f708efbab21e3489e7072b61cb6957230dd004a0af0" - ], - "index": "pypi", - "version": "==0.12.0" - }, - "protobuf": { - "hashes": [ - "sha256:038daf4fa38a7e818dd61f51f22588d61755160a98db087a046f80d66b855942", - "sha256:28ccea56d4dc38d35cd70c43c2da2f40ac0be0a355ef882242e8586c6d66666f", - "sha256:36d90676d6f426718463fe382ec6274909337ca6319d375eebd2044e6c6ac560", - "sha256:3cd0458870ea7d1c58e948ac8078f6ba8a7ecc44a57e03032ed066c5bb318089", - "sha256:5935c8ce02e3d89c7900140a8a42b35bc037ec07a6aeb61cc108be8d3c9438a6", - "sha256:615b426a177780ce381ecd212edc1e0f70db8557ed72560b82096bd36b01bc04", - "sha256:62a8e4baa9cb9e064eb62d1002eca820857ab2138440cb4b3ea4243830f94ca7", - "sha256:655264ed0d0efe47a523e2255fc1106a22f6faab7cc46cfe99b5bae085c2a13e", - "sha256:6e8ea9173403219239cdfd8d946ed101f2ab6ecc025b0fda0c6c713c35c9981d", - "sha256:71b0250b0cfb738442d60cab68abc166de43411f2a4f791d31378590bfb71bd7", - "sha256:74f33edeb4f3b7ed13d567881da8e5a92a72b36495d57d696c2ea1ae0cfee80c", - "sha256:77d2fadcf369b3f22859ab25bd12bb8e98fb11e05d9ff9b7cd45b711c719c002", - "sha256:8b30a7de128c46b5ecb343917d9fa737612a6e8280f440874e5cc2ba0d79b8f6", - "sha256:8e51561d72efd5bd5c91490af1f13e32bcba8dab4643761eb7de3ce18e64a853", - "sha256:a529e7df52204565bcd33738a7a5f288f3d2d37d86caa5d78c458fa5fabbd54d", - "sha256:b691d996c6d0984947c4cf8b7ae2fe372d99b32821d0584f0b90277aa36982d3", - "sha256:d80f80eb175bf5f1169139c2e0c5ada98b1c098e2b3c3736667f28cbbea39fc8", - "sha256:d83e1ef8cb74009bebee3e61cc84b1c9cd04935b72bca0cbc83217d140424995", - "sha256:d8919368410110633717c406ab5c97e8df5ce93020cfcf3012834f28b1fab1ea", - "sha256:db3532d9f7a6ebbe2392041350437953b6d7a792de10e629c1e4f5a6b1fe1ac6", - "sha256:e7b24c11df36ee8e0c085e5b0dc560289e4b58804746fb487287dda51410f1e2", - "sha256:e7e8d2c20921f8da0dea277dfefc6abac05903ceac8e72839b2da519db69206b", - "sha256:e813b1c9006b6399308e917ac5d298f345d95bb31f46f02b60cd92970a9afa17", - "sha256:fd390367fc211cc0ffcf3a9e149dfeca78fecc62adb911371db0cec5c8b7472d" - ], - "index": "pypi", - "version": "==3.19.1" - }, - "pycares": { - "hashes": [ - "sha256:03490be0e7b51a0c8073f877bec347eff31003f64f57d9518d419d9369452837", - "sha256:056330275dea42b7199494047a745e1d9785d39fb8c4cd469dca043532240b80", - "sha256:0aa897543a786daba74ec5e19638bd38b2b432d179a0e248eac1e62de5756207", - "sha256:112e1385c451069112d6b5ea1f9c378544f3c6b89882ff964e9a64be3336d7e4", - "sha256:27a6f09dbfb69bb79609724c0f90dfaa7c215876a7cd9f12d585574d1f922112", - "sha256:2b837315ed08c7df009b67725fe1f50489e99de9089f58ec1b243dc612f172aa", - "sha256:2f5f84fe9f83eab9cd68544b165b74ba6e3412d029cc9ab20098d9c332869fc5", - "sha256:40079ed58efa91747c50aac4edf8ecc7e570132ab57dc0a4030eb0d016a6cab8", - "sha256:439799be4b7576e907139a7f9b3c8a01b90d3e38af4af9cd1fc6c1ee9a42b9e6", - "sha256:4d5da840aa0d9b15fa51107f09270c563a348cb77b14ae9653d0bbdbe326fcc2", - "sha256:4e190471a015f8225fa38069617192e06122771cce2b169ac7a60bfdbd3d4ab2", - "sha256:5632f21d92cc0225ba5ff906e4e5dec415ef0b3df322c461d138190681cd5d89", - "sha256:569eef8597b5e02b1bc4644b9f272160304d8c9985357d7ecfcd054da97c0771", - "sha256:58a41a2baabcd95266db776c510d349d417919407f03510fc87ac7488730d913", - "sha256:6831e963a910b0a8cbdd2750ffcdf5f2bb0edb3f53ca69ff18484de2cc3807c4", - "sha256:71b99b9e041ae3356b859822c511f286f84c8889ec9ed1fbf6ac30fb4da13e4c", - "sha256:8319afe4838e09df267c421ca93da408f770b945ec6217dda72f1f6a493e37e4", - "sha256:8fd1ff17a26bb004f0f6bb902ba7dddd810059096ae0cc3b45e4f5be46315d19", - "sha256:a810d01c9a426ee8b0f36969c2aef5fb966712be9d7e466920beb328cd9cefa3", - "sha256:ad7b28e1b6bc68edd3d678373fa3af84e39d287090434f25055d21b4716b2fc6", - "sha256:b0e50ddc78252f2e2b6b5f2c73e5b2449dfb6bea7a5a0e21dfd1e2bcc9e17382", - "sha256:b266cec81dcea2c3efbbd3dda00af8d7eb0693ae9e47e8706518334b21f27d4a", - "sha256:c000942f5fc64e6e046aa61aa53b629b576ba11607d108909727c3c8f211a157", - "sha256:c6680f7fdc0f1163e8f6c2a11d11b9a0b524a61000d2a71f9ccd410f154fb171", - "sha256:c7eba3c8354b730a54d23237d0b6445a2f68570fa68d0848887da23a3f3b71f3", - "sha256:cbceaa9b2c416aa931627466d3240aecfc905c292c842252e3d77b8630072505", - "sha256:dc942692fca0e27081b7bb414bb971d34609c80df5e953f6d0c62ecc8019acd9", - "sha256:e1489aa25d14dbf7176110ead937c01176ed5a0ebefd3b092bbd6b202241814c", - "sha256:e5a060f5fa90ae245aa99a4a8ad13ec39c2340400de037c7e8d27b081e1a3c64", - "sha256:ec00f3594ee775665167b1a1630edceefb1b1283af9ac57480dba2fb6fd6c360", - "sha256:ed71dc4290d9c3353945965604ef1f6a4de631733e9819a7ebc747220b27e641" - ], - "version": "==4.1.2" - }, - "pycparser": { - "hashes": [ - "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", - "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" - ], - "version": "==2.21" - }, - "termcolor": { - "hashes": [ - "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b" - ], - "index": "pypi", - "version": "==1.1.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e", - "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b" - ], - "markers": "python_version >= '3.6'", - "version": "==4.0.1" - }, - "wrapt": { - "hashes": [ - "sha256:086218a72ec7d986a3eddb7707c8c4526d677c7b35e355875a0fe2918b059179", - "sha256:0877fe981fd76b183711d767500e6b3111378ed2043c145e21816ee589d91096", - "sha256:0a017a667d1f7411816e4bf214646d0ad5b1da2c1ea13dec6c162736ff25a374", - "sha256:0cb23d36ed03bf46b894cfec777eec754146d68429c30431c99ef28482b5c1df", - "sha256:1fea9cd438686e6682271d36f3481a9f3636195578bab9ca3382e2f5f01fc185", - "sha256:220a869982ea9023e163ba915077816ca439489de6d2c09089b219f4e11b6785", - "sha256:25b1b1d5df495d82be1c9d2fad408f7ce5ca8a38085e2da41bb63c914baadff7", - "sha256:2dded5496e8f1592ec27079b28b6ad2a1ef0b9296d270f77b8e4a3a796cf6909", - "sha256:2ebdde19cd3c8cdf8df3fc165bc7827334bc4e353465048b36f7deeae8ee0918", - "sha256:43e69ffe47e3609a6aec0fe723001c60c65305784d964f5007d5b4fb1bc6bf33", - "sha256:46f7f3af321a573fc0c3586612db4decb7eb37172af1bc6173d81f5b66c2e068", - "sha256:47f0a183743e7f71f29e4e21574ad3fa95676136f45b91afcf83f6a050914829", - "sha256:498e6217523111d07cd67e87a791f5e9ee769f9241fcf8a379696e25806965af", - "sha256:4b9c458732450ec42578b5642ac53e312092acf8c0bfce140ada5ca1ac556f79", - "sha256:51799ca950cfee9396a87f4a1240622ac38973b6df5ef7a41e7f0b98797099ce", - "sha256:5601f44a0f38fed36cc07db004f0eedeaadbdcec90e4e90509480e7e6060a5bc", - "sha256:5f223101f21cfd41deec8ce3889dc59f88a59b409db028c469c9b20cfeefbe36", - "sha256:610f5f83dd1e0ad40254c306f4764fcdc846641f120c3cf424ff57a19d5f7ade", - "sha256:6a03d9917aee887690aa3f1747ce634e610f6db6f6b332b35c2dd89412912bca", - "sha256:705e2af1f7be4707e49ced9153f8d72131090e52be9278b5dbb1498c749a1e32", - "sha256:766b32c762e07e26f50d8a3468e3b4228b3736c805018e4b0ec8cc01ecd88125", - "sha256:77416e6b17926d953b5c666a3cb718d5945df63ecf922af0ee576206d7033b5e", - "sha256:778fd096ee96890c10ce96187c76b3e99b2da44e08c9e24d5652f356873f6709", - "sha256:78dea98c81915bbf510eb6a3c9c24915e4660302937b9ae05a0947164248020f", - "sha256:7dd215e4e8514004c8d810a73e342c536547038fb130205ec4bba9f5de35d45b", - "sha256:7dde79d007cd6dfa65afe404766057c2409316135cb892be4b1c768e3f3a11cb", - "sha256:81bd7c90d28a4b2e1df135bfbd7c23aee3050078ca6441bead44c42483f9ebfb", - "sha256:85148f4225287b6a0665eef08a178c15097366d46b210574a658c1ff5b377489", - "sha256:865c0b50003616f05858b22174c40ffc27a38e67359fa1495605f96125f76640", - "sha256:87883690cae293541e08ba2da22cacaae0a092e0ed56bbba8d018cc486fbafbb", - "sha256:8aab36778fa9bba1a8f06a4919556f9f8c7b33102bd71b3ab307bb3fecb21851", - "sha256:8c73c1a2ec7c98d7eaded149f6d225a692caa1bd7b2401a14125446e9e90410d", - "sha256:936503cb0a6ed28dbfa87e8fcd0a56458822144e9d11a49ccee6d9a8adb2ac44", - "sha256:944b180f61f5e36c0634d3202ba8509b986b5fbaf57db3e94df11abee244ba13", - "sha256:96b81ae75591a795d8c90edc0bfaab44d3d41ffc1aae4d994c5aa21d9b8e19a2", - "sha256:981da26722bebb9247a0601e2922cedf8bb7a600e89c852d063313102de6f2cb", - "sha256:ae9de71eb60940e58207f8e71fe113c639da42adb02fb2bcbcaccc1ccecd092b", - "sha256:b73d4b78807bd299b38e4598b8e7bd34ed55d480160d2e7fdaabd9931afa65f9", - "sha256:d4a5f6146cfa5c7ba0134249665acd322a70d1ea61732723c7d3e8cc0fa80755", - "sha256:dd91006848eb55af2159375134d724032a2d1d13bcc6f81cd8d3ed9f2b8e846c", - "sha256:e05e60ff3b2b0342153be4d1b597bbcfd8330890056b9619f4ad6b8d5c96a81a", - "sha256:e6906d6f48437dfd80464f7d7af1740eadc572b9f7a4301e7dd3d65db285cacf", - "sha256:e92d0d4fa68ea0c02d39f1e2f9cb5bc4b4a71e8c442207433d8db47ee79d7aa3", - "sha256:e94b7d9deaa4cc7bac9198a58a7240aaf87fe56c6277ee25fa5b3aa1edebd229", - "sha256:ea3e746e29d4000cd98d572f3ee2a6050a4f784bb536f4ac1f035987fc1ed83e", - "sha256:ec7e20258ecc5174029a0f391e1b948bf2906cd64c198a9b8b281b811cbc04de", - "sha256:ec9465dd69d5657b5d2fa6133b3e1e989ae27d29471a672416fd729b429eb554", - "sha256:f122ccd12fdc69628786d0c947bdd9cb2733be8f800d88b5a37c57f1f1d73c10", - "sha256:f99c0489258086308aad4ae57da9e8ecf9e1f3f30fa35d5e170b4d4896554d80", - "sha256:f9c51d9af9abb899bd34ace878fbec8bf357b3194a10c4e8e0a25512826ef056", - "sha256:fd76c47f20984b43d93de9a82011bb6e5f8325df6c9ed4d8310029a55fa361ea" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.13.3" - }, - "yarl": { - "hashes": [ - "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac", - "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8", - "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e", - "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746", - "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98", - "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125", - "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d", - "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d", - "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986", - "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d", - "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec", - "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8", - "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee", - "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3", - "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1", - "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd", - "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b", - "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de", - "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0", - "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8", - "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6", - "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245", - "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23", - "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332", - "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1", - "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c", - "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4", - "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0", - "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8", - "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832", - "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58", - "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6", - "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1", - "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52", - "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92", - "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185", - "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d", - "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d", - "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b", - "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739", - "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05", - "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63", - "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d", - "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa", - "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913", - "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe", - "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b", - "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b", - "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656", - "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1", - "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4", - "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e", - "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63", - "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271", - "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed", - "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d", - "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda", - "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265", - "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f", - "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c", - "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba", - "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c", - "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b", - "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523", - "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a", - "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef", - "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95", - "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72", - "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794", - "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41", - "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576", - "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59" - ], - "markers": "python_version >= '3.6'", - "version": "==1.7.2" + "version": "*" } }, "develop": {} diff --git a/synonymbot.py b/synonymbot.py new file mode 100755 index 00000000..a5086018 --- /dev/null +++ b/synonymbot.py @@ -0,0 +1,83 @@ +#!/usr/bin/python3.9 +# Copyright (c) 2021 MobileCoin Inc. +# Copyright (c) 2021 The Forest Team + +import asyncio +from forest.core import Bot, Message, requires_admin, is_admin, run_bot +from forest.pdictng import aPersistDict + + +class SynonymBot(Bot): + + def __init__(self) -> None: + self.synonyms = aPersistDict("synonyms") + super().__init__() + + @requires_admin + async def do_build_synonyms(self, _) -> str: + for short_cmd in self.commands: + command = "do_" + short_cmd + method = None + if hasattr(self, command): + method = getattr(self, command) + if hasattr(super, command): + method = getattr(self, command) + if method is not None: + if hasattr(method, "syns"): + syns = getattr(method, "syns") + await self.synonyms.set(short_cmd, syns) + if syns := self.synonyms: + return(f'Built synonym list: {syns}') + + @requires_admin + async def do_clear_synonyms(self, _) -> str: + cmds = await self.synonyms.keys() + for cmd in cmds: + await self.synonyms.remove(cmd) + return('Synonym list cleared') + + async def do_list_synonyms(self, msg: Message) -> str: + valid_commands = self.commands if is_admin(msg) else self.visible_commands + if msg.arg1 in valid_commands: + syns = await self.synonyms.get(msg.arg1) + return f"Synonyms for {msg.arg1} are: {syns}" + else: + syns = self.synonyms.dict_ + valid_syns = {k:v for k, v in syns.items() if k in valid_commands} + return f"Synonym list: {valid_syns}" + + async def do_link(self, msg: Message) -> str: + valid_commands = self.commands if is_admin(msg) else self.visible_commands + if msg.arg1 in valid_commands: + if msg.arg2: + syns = await self.synonyms.get(msg.arg1) + if syns is None: + await self.synonyms.set(msg.arg1, [msg.arg2]) + else: + await self.synonyms.extend(msg.arg1, msg.arg2) + return f"Linked synonym {msg.arg2} to command {msg.arg1}" + else: + return f"Need a synonym to link to command '{msg.arg1}', try again" + return "Syntax for linking commands is 'link command synonym', try again" + + async def do_unlink(self, msg: Message) -> str: + valid_commands = self.commands if is_admin(msg) else self.visible_commands + if msg.arg1 in await self.synonyms.keys(): + syns = await self.synonyms.get(msg.arg1) + if msg.arg2 in syns: + await self.synonyms.remove_from(msg.arg1, msg.arg2) + return f"Unlinked synonym {msg.arg2} from command {msg.arg1}" + else: + return f"Need a synonym to unlink from command '{msg.arg1}'. Valid synonyms are {syns}" + return "Syntax for unlinking commands is 'unlink command synonym', try again" + + async def do_hello(self, _: Message) -> str: + return "Hello, world!" + do_hello.syns = ['hi', 'hey', 'whatup'] + + async def do_goodbye(self, _: Message) -> str: + return "Goodbye, cruel world!" + do_goodbye.syns = ['bye', 'goodby', 'later' ] + +if __name__ == "__main__": + run_bot(SynonymBot) From 9963557c61dc905e694ba98d79c31d6ff9f324fe Mon Sep 17 00:00:00 2001 From: deepfates Date: Mon, 21 Feb 2022 14:07:26 -0700 Subject: [PATCH 2/8] synonyms in match_command --- synonymbot.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/synonymbot.py b/synonymbot.py index a5086018..2544bd82 100755 --- a/synonymbot.py +++ b/synonymbot.py @@ -15,6 +15,10 @@ def __init__(self) -> None: @requires_admin async def do_build_synonyms(self, _) -> str: + """Build synonyms from in-code definitions. + + Run this command as admin when bot is first deployed. + """ for short_cmd in self.commands: command = "do_" + short_cmd method = None @@ -26,8 +30,7 @@ async def do_build_synonyms(self, _) -> str: if hasattr(method, "syns"): syns = getattr(method, "syns") await self.synonyms.set(short_cmd, syns) - if syns := self.synonyms: - return(f'Built synonym list: {syns}') + return(f'Built synonym list: {self.synonyms}') @requires_admin async def do_clear_synonyms(self, _) -> str: @@ -42,8 +45,7 @@ async def do_list_synonyms(self, msg: Message) -> str: syns = await self.synonyms.get(msg.arg1) return f"Synonyms for {msg.arg1} are: {syns}" else: - syns = self.synonyms.dict_ - valid_syns = {k:v for k, v in syns.items() if k in valid_commands} + valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_commands} return f"Synonym list: {valid_syns}" async def do_link(self, msg: Message) -> str: @@ -58,7 +60,7 @@ async def do_link(self, msg: Message) -> str: return f"Linked synonym {msg.arg2} to command {msg.arg1}" else: return f"Need a synonym to link to command '{msg.arg1}', try again" - return "Syntax for linking commands is 'link command synonym', try again" + return "Syntax for linking commands is 'link command synonym'. Synonyms must be a single word or snake_cased. Please try again" async def do_unlink(self, msg: Message) -> str: valid_commands = self.commands if is_admin(msg) else self.visible_commands @@ -71,6 +73,21 @@ async def do_unlink(self, msg: Message) -> str: return f"Need a synonym to unlink from command '{msg.arg1}'. Valid synonyms are {syns}" return "Syntax for unlinking commands is 'unlink command synonym', try again" + def match_command(self, msg: Message) -> str: + if not msg.arg0: + return "" + + valid_commands = self.commands if is_admin(msg) else self.visible_commands + valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_commands} + + if msg.arg0 in valid_commands: + return msg.arg0 + + for k, v in valid_syns.items(): + if msg.arg0 in v: + return k + return super().match_command(msg) + async def do_hello(self, _: Message) -> str: return "Hello, world!" do_hello.syns = ['hi', 'hey', 'whatup'] From 0b8d538180a364b63aab5c792ea95e9db43562ec Mon Sep 17 00:00:00 2001 From: deepfates Date: Mon, 21 Feb 2022 15:49:13 -0700 Subject: [PATCH 3/8] deal with edge cases for synonyms --- synonymbot.py | 99 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/synonymbot.py b/synonymbot.py index 2544bd82..e9fb51ec 100755 --- a/synonymbot.py +++ b/synonymbot.py @@ -2,8 +2,8 @@ # Copyright (c) 2021 MobileCoin Inc. # Copyright (c) 2021 The Forest Team -import asyncio -from forest.core import Bot, Message, requires_admin, is_admin, run_bot +from typing import Tuple +from forest.core import Bot, Message, Response, requires_admin, is_admin, run_bot from forest.pdictng import aPersistDict @@ -13,88 +13,127 @@ def __init__(self) -> None: self.synonyms = aPersistDict("synonyms") super().__init__() + def get_valid_syns(self, msg: Message) -> Tuple: + "Get commands and synonyms without leaking admin commands" + valid_cmds = self.commands if is_admin(msg) else self.visible_commands + valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_cmds} + return(valid_cmds, valid_syns) + @requires_admin async def do_build_synonyms(self, _) -> str: """Build synonyms from in-code definitions. Run this command as admin when bot is first deployed. """ - for short_cmd in self.commands: - command = "do_" + short_cmd + for cmd in self.commands: + command = "do_" + cmd method = None + # check for the command if hasattr(self, command): method = getattr(self, command) - if hasattr(super, command): - method = getattr(self, command) if method is not None: if hasattr(method, "syns"): syns = getattr(method, "syns") - await self.synonyms.set(short_cmd, syns) + await self.synonyms.set(cmd, syns) return(f'Built synonym list: {self.synonyms}') @requires_admin async def do_clear_synonyms(self, _) -> str: + "Remove all synonyms from persistent storage. Admin-only" cmds = await self.synonyms.keys() for cmd in cmds: await self.synonyms.remove(cmd) return('Synonym list cleared') async def do_list_synonyms(self, msg: Message) -> str: - valid_commands = self.commands if is_admin(msg) else self.visible_commands - if msg.arg1 in valid_commands: + "Print synonyms for all commands, or a single command if included" + valid_cmds, valid_syns = self.get_valid_syns(msg) + if msg.arg1 in valid_cmds: syns = await self.synonyms.get(msg.arg1) - return f"Synonyms for {msg.arg1} are: {syns}" + return f"Synonyms for '{msg.arg1}' are: {syns}" + elif any(msg.arg1 in v for v in valid_syns.values()): + cmds = [k for k,v in valid_syns.items() if msg.arg1 in v] + return f"'{msg.arg1}' is a synonym for {cmds}" else: - valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_commands} return f"Synonym list: {valid_syns}" async def do_link(self, msg: Message) -> str: - valid_commands = self.commands if is_admin(msg) else self.visible_commands - if msg.arg1 in valid_commands: + "Link a command to a synonym" + valid_cmds, valid_syns = self.get_valid_syns(msg) + if msg.arg1 in valid_cmds: if msg.arg2: - syns = await self.synonyms.get(msg.arg1) - if syns is None: + # Check if the synonym already in use + if msg.arg2 in valid_cmds: + return f"Sorry, '{msg.arg2}' is a command" + if any(msg.arg2 in v for v in valid_syns.values()): + cmds = [k for k,v in valid_syns.items() if msg.arg2 in v] + return f"Sorry, '{msg.arg2}' is already associated with one or more commands: {cmds}" + # Happy path, add the synonym + if msg.arg1 not in valid_syns.keys(): await self.synonyms.set(msg.arg1, [msg.arg2]) else: await self.synonyms.extend(msg.arg1, msg.arg2) - return f"Linked synonym {msg.arg2} to command {msg.arg1}" + return f"Linked synonym '{msg.arg2}' to command '{msg.arg1}'" + # No synonym detected else: return f"Need a synonym to link to command '{msg.arg1}', try again" - return "Syntax for linking commands is 'link command synonym'. Synonyms must be a single word or snake_cased. Please try again" + # No command detected + return "Not a valid command. Syntax for linking commands is 'link command synonym'. Please try again" async def do_unlink(self, msg: Message) -> str: - valid_commands = self.commands if is_admin(msg) else self.visible_commands - if msg.arg1 in await self.synonyms.keys(): - syns = await self.synonyms.get(msg.arg1) - if msg.arg2 in syns: + "Remove a command from a synonym" + valid_cmds, valid_syns = self.get_valid_syns(msg) + # Look for a command + if msg.arg1 in valid_cmds: + syns = valid_syns[msg.arg1] + # Happy path, remove the synonym + if (msg.arg2 and msg.arg2 in syns): await self.synonyms.remove_from(msg.arg1, msg.arg2) - return f"Unlinked synonym {msg.arg2} from command {msg.arg1}" + return f"Unlinked synonym '{msg.arg2}' from command '{msg.arg1}'" + # No synonym detected else: return f"Need a synonym to unlink from command '{msg.arg1}'. Valid synonyms are {syns}" + # Look for a synonym by itself + if any(msg.arg1 in v for v in valid_syns.values()): + cmds = [k for k,v in valid_syns.items() if msg.arg1 in v] + print(cmds) + # Synonym points to multiple commands + if len(cmds) > 1: + return f"Multiple commands have that synonym: {cmds}. Please try again in the form 'unlink command synonym'" + # Only points to one command, remove the synonym + elif len(cmds) == 1 : + await self.synonyms.remove_from(cmds[0], msg.arg1) + return f"Synonym '{msg.arg1}' removed from command '{cmds[0]}'" return "Syntax for unlinking commands is 'unlink command synonym', try again" def match_command(self, msg: Message) -> str: if not msg.arg0: return "" - - valid_commands = self.commands if is_admin(msg) else self.visible_commands - valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_commands} - - if msg.arg0 in valid_commands: + # Look for direct match before checking synonyms + if hasattr(self, "do_" + msg.arg0): return msg.arg0 - + # Try synonyms + _, valid_syns = self.get_valid_syns(msg) for k, v in valid_syns.items(): if msg.arg0 in v: return k + # Pass the buck return super().match_command(msg) async def do_hello(self, _: Message) -> str: return "Hello, world!" - do_hello.syns = ['hi', 'hey', 'whatup'] + # We can add synonyms in development, just register a .syns attribute on any method + do_hello.syns = ['hi', 'hey', 'whatup', 'aloha'] async def do_goodbye(self, _: Message) -> str: return "Goodbye, cruel world!" - do_goodbye.syns = ['bye', 'goodby', 'later' ] + do_goodbye.syns = ['bye', 'goodby', 'later', 'aloha'] + + async def do_help(self, msg: Message) -> Response: + return await super().do_help(msg) + # We can also add .syns attributes to inherited methods in this manner + do_help.syns = ['documentation', 'docs', 'commands', 'man'] + if __name__ == "__main__": run_bot(SynonymBot) From 10a8b438ed238115b798630dc88d4bc10149fd8a Mon Sep 17 00:00:00 2001 From: deepfates Date: Mon, 21 Feb 2022 16:16:32 -0700 Subject: [PATCH 4/8] lint and format --- Pipfile | 1 + Pipfile.lock | 54 +++++++++++++++++++++++++++++++++++++++++++-- synonymbot.py | 61 ++++++++++++++++++++++++++------------------------- 3 files changed, 84 insertions(+), 32 deletions(-) diff --git a/Pipfile b/Pipfile index 076918af..41746321 100644 --- a/Pipfile +++ b/Pipfile @@ -22,6 +22,7 @@ python_version = "3.9" allow_prereleases = true [dev-packages] +mypy = "*" [packages.aiohttp] extras = [ "speedups",] diff --git a/Pipfile.lock b/Pipfile.lock index c00be2e7..c204dbc4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "500e5c319674d72a813bad7de6f5dd9ad28984b2ec222a4d8c58ff081795451d" + "sha256": "c83d7ee35425fad7737403af43639fe31d2a09a0883ce6fd7015edb1ac38b0ee" }, "pipfile-spec": 6, "requires": { @@ -23,5 +23,55 @@ "version": "*" } }, - "develop": {} + "develop": { + "mypy": { + "hashes": [ + "sha256:0038b21890867793581e4cb0d810829f5fd4441aa75796b53033af3aa30430ce", + "sha256:1171f2e0859cfff2d366da2c7092b06130f232c636a3f7301e3feb8b41f6377d", + "sha256:1b06268df7eb53a8feea99cbfff77a6e2b205e70bf31743e786678ef87ee8069", + "sha256:1b65714dc296a7991000b6ee59a35b3f550e0073411ac9d3202f6516621ba66c", + "sha256:1bf752559797c897cdd2c65f7b60c2b6969ffe458417b8d947b8340cc9cec08d", + "sha256:300717a07ad09525401a508ef5d105e6b56646f7942eb92715a1c8d610149714", + "sha256:3c5b42d0815e15518b1f0990cff7a705805961613e701db60387e6fb663fe78a", + "sha256:4365c60266b95a3f216a3047f1d8e3f895da6c7402e9e1ddfab96393122cc58d", + "sha256:50c7346a46dc76a4ed88f3277d4959de8a2bd0a0fa47fa87a4cde36fe247ac05", + "sha256:5b56154f8c09427bae082b32275a21f500b24d93c88d69a5e82f3978018a0266", + "sha256:74f7eccbfd436abe9c352ad9fb65872cc0f1f0a868e9d9c44db0893440f0c697", + "sha256:7b3f6f557ba4afc7f2ce6d3215d5db279bcf120b3cfd0add20a5d4f4abdae5bc", + "sha256:8c11003aaeaf7cc2d0f1bc101c1cc9454ec4cc9cb825aef3cafff8a5fdf4c799", + "sha256:8ca7f8c4b1584d63c9a0f827c37ba7a47226c19a23a753d52e5b5eddb201afcd", + "sha256:c89702cac5b302f0c5d33b172d2b55b5df2bede3344a2fbed99ff96bddb2cf00", + "sha256:d8f1ff62f7a879c9fe5917b3f9eb93a79b78aad47b533911b853a757223f72e7", + "sha256:d9d2b84b2007cea426e327d2483238f040c49405a6bf4074f605f0156c91a47a", + "sha256:e839191b8da5b4e5d805f940537efcaa13ea5dd98418f06dc585d2891d228cf0", + "sha256:f9fe20d0872b26c4bba1c1be02c5340de1019530302cf2dcc85c7f9fc3252ae0", + "sha256:ff3bf387c14c805ab1388185dd22d6b210824e164d4bb324b195ff34e322d166" + ], + "index": "pypi", + "version": "==0.931" + }, + "mypy-extensions": { + "hashes": [ + "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d", + "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8" + ], + "version": "==0.4.3" + }, + "tomli": { + "hashes": [ + "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", + "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" + ], + "markers": "python_version >= '3.7'", + "version": "==2.0.1" + }, + "typing-extensions": { + "hashes": [ + "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42", + "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2" + ], + "markers": "python_version >= '3.6'", + "version": "==4.1.1" + } + } } diff --git a/synonymbot.py b/synonymbot.py index e9fb51ec..7a7b977d 100755 --- a/synonymbot.py +++ b/synonymbot.py @@ -8,7 +8,6 @@ class SynonymBot(Bot): - def __init__(self) -> None: self.synonyms = aPersistDict("synonyms") super().__init__() @@ -16,13 +15,13 @@ def __init__(self) -> None: def get_valid_syns(self, msg: Message) -> Tuple: "Get commands and synonyms without leaking admin commands" valid_cmds = self.commands if is_admin(msg) else self.visible_commands - valid_syns = {k:v for k, v in self.synonyms.dict_.items() if k in valid_cmds} - return(valid_cmds, valid_syns) + valid_syns = {k: v for k, v in self.synonyms.dict_.items() if k in valid_cmds} + return (valid_cmds, valid_syns) @requires_admin - async def do_build_synonyms(self, _) -> str: - """Build synonyms from in-code definitions. - + async def do_build_synonyms(self, _: Message) -> str: + """Build synonyms from in-code definitions. + Run this command as admin when bot is first deployed. """ for cmd in self.commands: @@ -35,27 +34,26 @@ async def do_build_synonyms(self, _) -> str: if hasattr(method, "syns"): syns = getattr(method, "syns") await self.synonyms.set(cmd, syns) - return(f'Built synonym list: {self.synonyms}') - + return f"Built synonym list: {self.synonyms}" + @requires_admin - async def do_clear_synonyms(self, _) -> str: + async def do_clear_synonyms(self, _: Message) -> str: "Remove all synonyms from persistent storage. Admin-only" cmds = await self.synonyms.keys() for cmd in cmds: await self.synonyms.remove(cmd) - return('Synonym list cleared') + return "Synonym list cleared" async def do_list_synonyms(self, msg: Message) -> str: "Print synonyms for all commands, or a single command if included" valid_cmds, valid_syns = self.get_valid_syns(msg) if msg.arg1 in valid_cmds: - syns = await self.synonyms.get(msg.arg1) + syns = await self.synonyms.get(str(msg.arg1)) return f"Synonyms for '{msg.arg1}' are: {syns}" - elif any(msg.arg1 in v for v in valid_syns.values()): - cmds = [k for k,v in valid_syns.items() if msg.arg1 in v] + if any(msg.arg1 in v for v in valid_syns.values()): + cmds = [k for k, v in valid_syns.items() if msg.arg1 in v] return f"'{msg.arg1}' is a synonym for {cmds}" - else: - return f"Synonym list: {valid_syns}" + return f"Synonym list: {valid_syns}" async def do_link(self, msg: Message) -> str: "Link a command to a synonym" @@ -66,13 +64,13 @@ async def do_link(self, msg: Message) -> str: if msg.arg2 in valid_cmds: return f"Sorry, '{msg.arg2}' is a command" if any(msg.arg2 in v for v in valid_syns.values()): - cmds = [k for k,v in valid_syns.items() if msg.arg2 in v] + cmds = [k for k, v in valid_syns.items() if msg.arg2 in v] return f"Sorry, '{msg.arg2}' is already associated with one or more commands: {cmds}" # Happy path, add the synonym if msg.arg1 not in valid_syns.keys(): - await self.synonyms.set(msg.arg1, [msg.arg2]) + await self.synonyms.set(str(msg.arg1), [msg.arg2]) else: - await self.synonyms.extend(msg.arg1, msg.arg2) + await self.synonyms.extend(str(msg.arg1), msg.arg2) return f"Linked synonym '{msg.arg2}' to command '{msg.arg1}'" # No synonym detected else: @@ -87,22 +85,21 @@ async def do_unlink(self, msg: Message) -> str: if msg.arg1 in valid_cmds: syns = valid_syns[msg.arg1] # Happy path, remove the synonym - if (msg.arg2 and msg.arg2 in syns): - await self.synonyms.remove_from(msg.arg1, msg.arg2) + if msg.arg2 and msg.arg2 in syns: + await self.synonyms.remove_from(str(msg.arg1), str(msg.arg2)) return f"Unlinked synonym '{msg.arg2}' from command '{msg.arg1}'" # No synonym detected - else: - return f"Need a synonym to unlink from command '{msg.arg1}'. Valid synonyms are {syns}" + return f"Need a synonym to unlink from command '{msg.arg1}'. Valid synonyms are {syns}" # Look for a synonym by itself if any(msg.arg1 in v for v in valid_syns.values()): - cmds = [k for k,v in valid_syns.items() if msg.arg1 in v] + cmds = [k for k, v in valid_syns.items() if msg.arg1 in v] print(cmds) # Synonym points to multiple commands if len(cmds) > 1: return f"Multiple commands have that synonym: {cmds}. Please try again in the form 'unlink command synonym'" # Only points to one command, remove the synonym - elif len(cmds) == 1 : - await self.synonyms.remove_from(cmds[0], msg.arg1) + if len(cmds) == 1: + await self.synonyms.remove_from(cmds[0], str(msg.arg1)) return f"Synonym '{msg.arg1}' removed from command '{cmds[0]}'" return "Syntax for unlinking commands is 'unlink command synonym', try again" @@ -113,7 +110,7 @@ def match_command(self, msg: Message) -> str: if hasattr(self, "do_" + msg.arg0): return msg.arg0 # Try synonyms - _, valid_syns = self.get_valid_syns(msg) + _, valid_syns = self.get_valid_syns(msg) for k, v in valid_syns.items(): if msg.arg0 in v: return k @@ -122,18 +119,22 @@ def match_command(self, msg: Message) -> str: async def do_hello(self, _: Message) -> str: return "Hello, world!" + # We can add synonyms in development, just register a .syns attribute on any method - do_hello.syns = ['hi', 'hey', 'whatup', 'aloha'] + # This seems to be unsupported in mypy though, ergo ↓ + do_hello.syns = ["hi", "hey", "whatup", "aloha"] # type: ignore async def do_goodbye(self, _: Message) -> str: return "Goodbye, cruel world!" - do_goodbye.syns = ['bye', 'goodby', 'later', 'aloha'] + + do_goodbye.syns = ["bye", "goodby", "later", "aloha"] # type: ignore async def do_help(self, msg: Message) -> Response: return await super().do_help(msg) + # We can also add .syns attributes to inherited methods in this manner - do_help.syns = ['documentation', 'docs', 'commands', 'man'] - + do_help.syns = ["documentation", "docs", "commands", "man"] # type: ignore + if __name__ == "__main__": run_bot(SynonymBot) From 99992b853332b16074724b42f92326656b6612e7 Mon Sep 17 00:00:00 2001 From: deepfates Date: Wed, 23 Feb 2022 16:54:00 -0700 Subject: [PATCH 5/8] fix attribute typing with a decorator --- synonymbot.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/synonymbot.py b/synonymbot.py index 7a7b977d..41ce9021 100755 --- a/synonymbot.py +++ b/synonymbot.py @@ -2,11 +2,19 @@ # Copyright (c) 2021 MobileCoin Inc. # Copyright (c) 2021 The Forest Team -from typing import Tuple +from typing import Tuple, Protocol, Any from forest.core import Bot, Message, Response, requires_admin, is_admin, run_bot from forest.pdictng import aPersistDict +class SynonymAttributes(Protocol): + syns: list + + +def has_synonyms(func: Any) -> SynonymAttributes: + return func + + class SynonymBot(Bot): def __init__(self) -> None: self.synonyms = aPersistDict("synonyms") @@ -117,23 +125,27 @@ def match_command(self, msg: Message) -> str: # Pass the buck return super().match_command(msg) + # We can add synonyms in development. give your command the + # @has_synonyms decorator and register a .syns attribute + @has_synonyms async def do_hello(self, _: Message) -> str: return "Hello, world!" - # We can add synonyms in development, just register a .syns attribute on any method - # This seems to be unsupported in mypy though, ergo ↓ - do_hello.syns = ["hi", "hey", "whatup", "aloha"] # type: ignore + do_hello.syns = ["hi", "hey", "whatup", "aloha"] + @has_synonyms async def do_goodbye(self, _: Message) -> str: return "Goodbye, cruel world!" - do_goodbye.syns = ["bye", "goodby", "later", "aloha"] # type: ignore + do_goodbye.syns = ["bye", "goodby", "later", "aloha"] + # We can also add.syns attributes to inherited methods in this manner + # but doesn't play well with mypy, becuase the signature doesn't match + # the supertype, so we use type:ignore, as seen below ↓ async def do_help(self, msg: Message) -> Response: return await super().do_help(msg) - # We can also add .syns attributes to inherited methods in this manner - do_help.syns = ["documentation", "docs", "commands", "man"] # type: ignore + do_help.syns = ["documentation", "docs", "commands", "man"] # type:ignore if __name__ == "__main__": From 396715def3c4c459a385ed16743ef51f677a65f9 Mon Sep 17 00:00:00 2001 From: technillogue Date: Thu, 17 Mar 2022 17:03:29 -0400 Subject: [PATCH 6/8] move synonymbot to forest and update for new pdictng --- synonymbot.py => forest/synonymbot.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename synonymbot.py => forest/synonymbot.py (96%) diff --git a/synonymbot.py b/forest/synonymbot.py similarity index 96% rename from synonymbot.py rename to forest/synonymbot.py index 41ce9021..1f5004a5 100755 --- a/synonymbot.py +++ b/forest/synonymbot.py @@ -4,7 +4,7 @@ from typing import Tuple, Protocol, Any from forest.core import Bot, Message, Response, requires_admin, is_admin, run_bot -from forest.pdictng import aPersistDict +from forest.pdictng import aPersistDictOfLists class SynonymAttributes(Protocol): @@ -17,7 +17,7 @@ def has_synonyms(func: Any) -> SynonymAttributes: class SynonymBot(Bot): def __init__(self) -> None: - self.synonyms = aPersistDict("synonyms") + self.synonyms: aPersistDictOfLists[str] = aPersistDictOfLists("synonyms") super().__init__() def get_valid_syns(self, msg: Message) -> Tuple: @@ -81,8 +81,7 @@ async def do_link(self, msg: Message) -> str: await self.synonyms.extend(str(msg.arg1), msg.arg2) return f"Linked synonym '{msg.arg2}' to command '{msg.arg1}'" # No synonym detected - else: - return f"Need a synonym to link to command '{msg.arg1}', try again" + return f"Need a synonym to link to command '{msg.arg1}', try again" # No command detected return "Not a valid command. Syntax for linking commands is 'link command synonym'. Please try again" From f73732c98d85655b1a3b27af738dd2d69d1fdf06 Mon Sep 17 00:00:00 2001 From: technillogue Date: Thu, 17 Mar 2022 17:47:40 -0400 Subject: [PATCH 7/8] switch from a protocol to only setting the synonyms in a decorator, similarly to requires_admin, hide, and group_help_text on the imogen branch --- forest/synonymbot.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/forest/synonymbot.py b/forest/synonymbot.py index 1f5004a5..6c9a322f 100755 --- a/forest/synonymbot.py +++ b/forest/synonymbot.py @@ -1,18 +1,24 @@ #!/usr/bin/python3.9 # Copyright (c) 2021 MobileCoin Inc. # Copyright (c) 2021 The Forest Team - -from typing import Tuple, Protocol, Any +from functools import wraps +from typing import Tuple, Any, Callable, Coroutine from forest.core import Bot, Message, Response, requires_admin, is_admin, run_bot from forest.pdictng import aPersistDictOfLists +Command = Callable[[Bot, Message], Coroutine[Any, Any, Response]] + -class SynonymAttributes(Protocol): - syns: list +def synonyms(*syns: str) -> Callable: + def decorate(command: Command) -> Command: + @wraps(command) + async def synonym_command(self: "Bot", msg: Message) -> Response: + return await command(self, msg) + synonym_command.syns = syns # type: ignore + return synonym_command -def has_synonyms(func: Any) -> SynonymAttributes: - return func + return decorate class SynonymBot(Bot): @@ -125,27 +131,22 @@ def match_command(self, msg: Message) -> str: return super().match_command(msg) # We can add synonyms in development. give your command the - # @has_synonyms decorator and register a .syns attribute - @has_synonyms + # @synonyms decorator and pass some synonyms + @synonyms("hi", "hey", "whatup", "aloha") async def do_hello(self, _: Message) -> str: return "Hello, world!" - do_hello.syns = ["hi", "hey", "whatup", "aloha"] - - @has_synonyms + @synonyms("bye", "goodby", "later", "aloha") async def do_goodbye(self, _: Message) -> str: return "Goodbye, cruel world!" - do_goodbye.syns = ["bye", "goodby", "later", "aloha"] - # We can also add.syns attributes to inherited methods in this manner # but doesn't play well with mypy, becuase the signature doesn't match # the supertype, so we use type:ignore, as seen below ↓ + @synonyms("documentation", "docs", "commands", "man") async def do_help(self, msg: Message) -> Response: return await super().do_help(msg) - do_help.syns = ["documentation", "docs", "commands", "man"] # type:ignore - if __name__ == "__main__": run_bot(SynonymBot) From 524a866a2f8dc9aa270d3011529b33fe0a0825bd Mon Sep 17 00:00:00 2001 From: technillogue Date: Thu, 17 Mar 2022 20:47:26 -0400 Subject: [PATCH 8/8] drop unused comment --- forest/synonymbot.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/forest/synonymbot.py b/forest/synonymbot.py index 6c9a322f..72c7493f 100755 --- a/forest/synonymbot.py +++ b/forest/synonymbot.py @@ -140,9 +140,6 @@ async def do_hello(self, _: Message) -> str: async def do_goodbye(self, _: Message) -> str: return "Goodbye, cruel world!" - # We can also add.syns attributes to inherited methods in this manner - # but doesn't play well with mypy, becuase the signature doesn't match - # the supertype, so we use type:ignore, as seen below ↓ @synonyms("documentation", "docs", "commands", "man") async def do_help(self, msg: Message) -> Response: return await super().do_help(msg)