diff --git a/.gitignore b/.gitignore index 3a8816c..2999d61 100644 --- a/.gitignore +++ b/.gitignore @@ -1,162 +1,9 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm-project.org/#use-with-ide -.pdm.toml -.pdm-python -.pdm-build/ - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments +node_modules +dist +package-lock.json +npm-debug.log +.nyc .env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ +.DS_Store +config.json +*.db \ No newline at end of file diff --git a/README.md b/README.md index 811f297..9f1db77 100644 --- a/README.md +++ b/README.md @@ -1 +1,14 @@ -# pluralcakepy +# PluriPastries +PluriPastries is a pluralkit alternative for the revolt chat platform. +It supports creating members and sending messages as one of the members. + +## How to host the bot yourself. +### requirements. +SQLite on arch. +```bash +sudo pacman -S sqlite +``` +You will need to install the bun runtime from their installation script. +```bash +curl -fsSL https://bun.sh/install | bash +``` diff --git a/bun.lockb b/bun.lockb new file mode 100755 index 0000000..8f3c2ee Binary files /dev/null and b/bun.lockb differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..6bd7e02 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "pluripastries", + "version": "0.5.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "cake", + "license": "GPLv3", + "devDependencies": { + "bun-types": "^1.0.31", + "typescript": "^5.1.3", + "typescript-language-server": "^3.3.2" + }, + "dependencies": { + "revolt.js": "^7.0.0-beta.9", + "shlex": "^2.1.2" + } +} diff --git a/pdm.lock b/pdm.lock deleted file mode 100644 index 6ae4dbb..0000000 --- a/pdm.lock +++ /dev/null @@ -1,239 +0,0 @@ -# This file is @generated by PDM. -# It is not intended for manual editing. - -[metadata] -groups = ["default"] -strategy = ["cross_platform", "inherit_metadata"] -lock_version = "4.4.1" -content_hash = "sha256:5cd19c2d8cd5b70d4f61f66164d3d27b583373b94f43afd456e68d6f9fe70c63" - -[[package]] -name = "aenum" -version = "3.1.15" -summary = "Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants" -groups = ["default"] -files = [ - {file = "aenum-3.1.15-py3-none-any.whl", hash = "sha256:e0dfaeea4c2bd362144b87377e2c61d91958c5ed0b4daf89cb6f45ae23af6288"}, - {file = "aenum-3.1.15.tar.gz", hash = "sha256:8cbd76cd18c4f870ff39b24284d3ea028fbe8731a58df3aa581e434c575b9559"}, -] - -[[package]] -name = "aiohttp" -version = "3.8.6" -requires_python = ">=3.6" -summary = "Async http client/server framework (asyncio)" -groups = ["default"] -dependencies = [ - "aiosignal>=1.1.2", - "async-timeout<5.0,>=4.0.0a3", - "attrs>=17.3.0", - "charset-normalizer<4.0,>=2.0", - "frozenlist>=1.1.1", - "multidict<7.0,>=4.5", - "yarl<2.0,>=1.0", -] -files = [ - {file = "aiohttp-3.8.6.tar.gz", hash = "sha256:b0cf2a4501bff9330a8a5248b4ce951851e415bdcce9dc158e76cfd55e15085c"}, -] - -[[package]] -name = "aiosignal" -version = "1.3.1" -requires_python = ">=3.7" -summary = "aiosignal: a list of registered asynchronous callbacks" -groups = ["default"] -dependencies = [ - "frozenlist>=1.1.0", -] -files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, -] - -[[package]] -name = "async-timeout" -version = "4.0.3" -requires_python = ">=3.7" -summary = "Timeout context manager for asyncio programs" -groups = ["default"] -files = [ - {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, - {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -requires_python = ">=3.7" -summary = "Classes Without Boilerplate" -groups = ["default"] -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.3.2" -requires_python = ">=3.7.0" -summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -groups = ["default"] -files = [ - {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, - {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, - {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, -] - -[[package]] -name = "frozenlist" -version = "1.4.1" -requires_python = ">=3.8" -summary = "A list-like structure which implements collections.abc.MutableSequence" -groups = ["default"] -files = [ - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1979bc0aeb89b33b588c51c54ab0161791149f2461ea7c7c946d95d5f93b56ae"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cc7b01b3754ea68a62bd77ce6020afaffb44a590c2289089289363472d13aedb"}, - {file = "frozenlist-1.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9c92be9fd329ac801cc420e08452b70e7aeab94ea4233a4804f0915c14eba9b"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3894db91f5a489fc8fa6a9991820f368f0b3cbdb9cd8849547ccfab3392d86"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba60bb19387e13597fb059f32cd4d59445d7b18b69a745b8f8e5db0346f33480"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8aefbba5f69d42246543407ed2461db31006b0f76c4e32dfd6f42215a2c41d09"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780d3a35680ced9ce682fbcf4cb9c2bad3136eeff760ab33707b71db84664e3a"}, - {file = "frozenlist-1.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9acbb16f06fe7f52f441bb6f413ebae6c37baa6ef9edd49cdd567216da8600cd"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:23b701e65c7b36e4bf15546a89279bd4d8675faabc287d06bbcfac7d3c33e1e6"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3e0153a805a98f5ada7e09826255ba99fb4f7524bb81bf6b47fb702666484ae1"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:dd9b1baec094d91bf36ec729445f7769d0d0cf6b64d04d86e45baf89e2b9059b"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:1a4471094e146b6790f61b98616ab8e44f72661879cc63fa1049d13ef711e71e"}, - {file = "frozenlist-1.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5667ed53d68d91920defdf4035d1cdaa3c3121dc0b113255124bcfada1cfa1b8"}, - {file = "frozenlist-1.4.1-cp312-cp312-win32.whl", hash = "sha256:beee944ae828747fd7cb216a70f120767fc9f4f00bacae8543c14a6831673f89"}, - {file = "frozenlist-1.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:64536573d0a2cb6e625cf309984e2d873979709f2cf22839bf2d61790b448ad5"}, - {file = "frozenlist-1.4.1-py3-none-any.whl", hash = "sha256:04ced3e6a46b4cfffe20f9ae482818e34eba9b5fb0ce4056e4cc9b6e212d09b7"}, - {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, -] - -[[package]] -name = "idna" -version = "3.7" -requires_python = ">=3.5" -summary = "Internationalized Domain Names in Applications (IDNA)" -groups = ["default"] -files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, -] - -[[package]] -name = "multidict" -version = "6.0.5" -requires_python = ">=3.7" -summary = "multidict implementation" -groups = ["default"] -files = [ - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, - {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, - {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, - {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, - {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, - {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, - {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, - {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, -] - -[[package]] -name = "peewee" -version = "3.17.6" -summary = "a little orm" -groups = ["default"] -files = [ - {file = "peewee-3.17.6.tar.gz", hash = "sha256:cea5592c6f4da1592b7cff8eaf655be6648a1f5857469e30037bf920c03fb8fb"}, -] - -[[package]] -name = "revolt-py" -version = "0.2.0" -requires_python = ">=3.9" -summary = "Python wrapper for the revolt.chat API" -groups = ["default"] -dependencies = [ - "aenum==3.1.*", - "aiohttp==3.8.*", - "typing-extensions>=4.4.0", - "ulid-py==1.1.*", -] -files = [ - {file = "revolt.py-0.2.0-py3-none-any.whl", hash = "sha256:d40876db30ff23904e3bc46cfda62ddfff8abf4147df41d2811b9a565cefc4ae"}, - {file = "revolt.py-0.2.0.tar.gz", hash = "sha256:06d54d3796df20d7382502c25060fe3eed061f8d200626f3ed171e927ce8b371"}, -] - -[[package]] -name = "typing-extensions" -version = "4.12.2" -requires_python = ">=3.8" -summary = "Backported and Experimental Type Hints for Python 3.8+" -groups = ["default"] -files = [ - {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, - {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, -] - -[[package]] -name = "ulid-py" -version = "1.1.0" -summary = "Universally Unique Lexicographically Sortable Identifier" -groups = ["default"] -files = [ - {file = "ulid-py-1.1.0.tar.gz", hash = "sha256:dc6884be91558df077c3011b9fb0c87d1097cb8fc6534b11f310161afd5738f0"}, - {file = "ulid_py-1.1.0-py2.py3-none-any.whl", hash = "sha256:b56a0f809ef90d6020b21b89a87a48edc7c03aea80e5ed5174172e82d76e3987"}, -] - -[[package]] -name = "yarl" -version = "1.9.4" -requires_python = ">=3.7" -summary = "Yet another URL library" -groups = ["default"] -dependencies = [ - "idna>=2.0", - "multidict>=4.0", -] -files = [ - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, -] diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 1532824..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,19 +0,0 @@ -[project] -name = "pluralcakepy" -version = "0.1.0" -description = "Default template for PDM package" -authors = [ - {name = "cake", email = "cake@cakey.me"}, -] -dependencies = [ - "revolt-py>=0.2.0", - "aiohttp>=3.8.6", - "peewee>=3.17.6", -] -requires-python = "==3.11.*" -readme = "README.md" -license = {text = "AGPLv3"} - - -[tool.pdm] -distribution = false diff --git a/src/commandHandler/__init__.py b/src/commandHandler/__init__.py deleted file mode 100644 index 59302e1..0000000 --- a/src/commandHandler/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from revolt import Message -from utils import split_args - -def commandHandler(message: Message, debug: bool = False) -> None: - content: str | None = message.content - arguments: list[str] = split_args(content) - prefix = arguments.pop(0) - command: str = arguments.pop(0) - - if debug: - print(f"author id: {message.author.id}\ - \nauthor name: {message.author.nickname}\ - \ncontent: {content}\ - \ncommand: {command}\ - \nargs: {arguments}" - ) - - if message.author.bot or not content: - return diff --git a/src/commands/avatarMemberChange.ts b/src/commands/avatarMemberChange.ts new file mode 100644 index 0000000..4200fb5 --- /dev/null +++ b/src/commands/avatarMemberChange.ts @@ -0,0 +1,28 @@ +import { Database } from "bun:sqlite"; +import MemberModel from "../models/MemberModel" +import { MemberRepo } from "../repositories/MemberRepo" + +export async function avatarMemberChange(userId: string, args: string[], database: Database){ + const memberRepo = new MemberRepo(database); + const userAlters : MemberModel[] = memberRepo.getAltersByUserId(userId) + + let userAltersNames : string[] = []; + userAlters.forEach(alter => userAltersNames.push(alter.name)); + + if (args.length == 2) { + if (userAltersNames.includes(args[0])){ + userAlters.forEach( alter => { + if (alter.name == args[0]) { + alter.profile_pic_url = args[1]; + memberRepo.editAlter(alter) + } + }) + } + return "The profile picture for the Member has been changed" + } + + if (args.length != 2) { + return "Error: Insufficent number of arguments. \nexample: !ck avatar < name > < url >" + } + +} diff --git a/src/commands/colorMemberChange.ts b/src/commands/colorMemberChange.ts new file mode 100644 index 0000000..f949d16 --- /dev/null +++ b/src/commands/colorMemberChange.ts @@ -0,0 +1,32 @@ +import { MemberRepo } from "../repositories/MemberRepo" +import MemberModel from "../models/MemberModel" +import { Database } from "bun:sqlite"; + +async function colorMemberChange(userId: string, args: string[], database: Database){ + const memberRepo = new MemberRepo(database); + const regexHex = /^#[0-9A-F]{6}$/i; + + if (args.length == 2 && regexHex.test(args[1])){ + const alterName = args[0]; + const alterColor = args[1]; + + const alters: MemberModel[] = memberRepo.getAltersByUserId(userId) // fetching alters from user. + if (alters.length == 0) return "This user has no Members." // checking if returned array is at least not 0, if len 0, then return. + + let alterToEdit: MemberModel; + alters.forEach( alter => { + if (alter.name == alterName) { + alterToEdit = alter; + } + }) + + alterToEdit.color = alterColor; + memberRepo.editAlter(alterToEdit) + + return "The Member's colour has been changed." + } + + return "Error: Insufficent Arguments" +} + +export default colorMemberChange diff --git a/src/commands/createMember.ts b/src/commands/createMember.ts new file mode 100644 index 0000000..257eabc --- /dev/null +++ b/src/commands/createMember.ts @@ -0,0 +1,56 @@ +import { Database } from "bun:sqlite"; +import { MemberRepo } from "../repositories/MemberRepo"; +import MemberModel from "models/MemberModel" + +async function createMember(userId: string, args: string[], database: Database){ + const memberRepo = new MemberRepo(database); + + const model: MemberModel = { + owner: userId, + name: args[0], + prefix: args[1], + profile_pic_url: "https://tse3.mm.bing.net/th?id=OIP.yte7rRnbCnWi1giriwTOvwHaHa&pid=15.1" + } + + const userAlters: MemberModel[] = memberRepo.getAltersByUserId(userId) + + let alterTags : string[] = []; + userAlters.forEach( alter => { + alterTags.push(alter.prefix) + }) + + let alterNames : string[] = []; + userAlters.forEach ( alter => { + alterNames.push(alter.name) + }) + + if (args.length == 2 + && args[1].includes("text") + && !alterTags.includes(args[1]) + && args[1] != "text" + && !alterNames.includes(args[0])) { + + memberRepo.addAlterForUser(model); + return {message: "Member < " + model.name + " > has been succefully created", code: 0} + + } + else { + if (args.length != 2){ + return {message: "Error: Insufficent arguments", code: 1}; + } + if (args[1] === "text"){ + return {message: "Error: Tag may not be only ", code: 2}; + } + if (!args[1].includes("text")) { + return {message: "Error: This command requires a tag that contains in it", code: 3}; + } + if (alterTags.includes(args[1])) { + return {message: "Error: You already have a Member with that tag", code: 4} + } + if (alterNames.includes(args[0])) { + return {message: "Error: You can only have one Member with that name", code: 5} + } + } +} + +export default createMember; diff --git a/src/commands/deleteMember.ts b/src/commands/deleteMember.ts new file mode 100644 index 0000000..c12cc68 --- /dev/null +++ b/src/commands/deleteMember.ts @@ -0,0 +1,24 @@ +import { MemberRepo } from "../repositories/MemberRepo" +import MemberModel from "../models/MemberModel" +import { Database } from "bun:sqlite"; + +export async function deleteMember(userId: string, args: string[], database: Database) { + const memberRepo = new MemberRepo(database); + let success: boolean = false; + + if (args.length === 1) { + const alters: MemberModel[] = memberRepo.getAltersByUserId(userId) + alters.forEach(alter => { + if (alter.name == args[0]) { + memberRepo.delete(alter.id) + success = true; + } + }) + } + if (success) { + return "Member has been deleted" + } + else { + return "Failed to delete Member" + } +} diff --git a/src/commands/help.ts b/src/commands/help.ts new file mode 100644 index 0000000..456c901 --- /dev/null +++ b/src/commands/help.ts @@ -0,0 +1,18 @@ +export function returnHelpText() { + return "# Howdy user, welcome to pluralcake\n" + + "pluralcake is a bot that allows you to send messages as your system's Members, with a custom profile picture, tag and nickname. \n" + + "It's pretty much a work in progress, and doesn't allow you to edit or delete messages, and to send pictures." + + "The currently available commands are : \n" + + "### Members:\n" + + "- list | allows you to see your currently available Members.\n" + + "- create <'name of the Member'> <'your Member's tag'>| Allows you to add a Member\n" + + "- delete <'name of the Member'> | Deletes the choosen Member\n" + + "- name <'name of the Member'> | Changes the choosen Member's name\n" + + "- avatar <'Member's name'> <'picture url'> | Allows you to edit your Member's profile picture\n" + + "- color <'Member's name'> <'color hex'> | Allows you to change the color of your Member ( may be integrated with the future website )\n"+ + "### Migrations\n"+ + "- tupper < Json file attached > | Migrates your Member from tupper\n" + +"### Auto proxy\n" + +"- setAutoProxy | Sets the member to automatically send messages as\n" + +"- toggleAutoProxy | Enable or disable the autoproxy" +} diff --git a/src/commands/listMember.ts b/src/commands/listMember.ts new file mode 100644 index 0000000..757e5fe --- /dev/null +++ b/src/commands/listMember.ts @@ -0,0 +1,18 @@ +import { MemberRepo } from "../repositories/MemberRepo" +import { tableConstructor } from '../utils/tableConstructor' +import { Database } from "bun:sqlite"; +import MemberModel from "../models/MemberModel"; + +async function listMember(userId: string, database: Database) { + const memberRepo = new MemberRepo(database); + const alters: MemberModel[] = memberRepo.getAltersByUserId(userId) + + if (alters.length > 0 ) { + return tableConstructor(alters) + } + else { + return "No Members found for this user" + } +} + +export default listMember diff --git a/src/commands/migrateMember.ts b/src/commands/migrateMember.ts new file mode 100644 index 0000000..b7e1b6c --- /dev/null +++ b/src/commands/migrateMember.ts @@ -0,0 +1,41 @@ +import { File } from "revolt.js" +import { Database } from "bun:sqlite" +import createMember from "./createMember" +import { avatarMemberChange } from "./avatarMemberChange" + +export default async function migrateAlters(author: string, attachments: File[] | undefined, source: String, database: Database) { + // source is not utilized for now, it is put as an argument in case the bot evolves further + + let file = attachments[0] + + if (file.contentType === "text/plain") { + + const fileResponse = await fetch(file.url) + const fileResponseBlob = await fileResponse.blob() + const textFromBlob = fileResponseBlob.text() + const jsonFromText = JSON.parse(await textFromBlob) + + if (jsonFromText.tuppers === "undefined"){ + return "wrong json file, be certain that this is a tupperbox migration file" + } + + const tuppers = jsonFromText.tuppers + + tuppers.forEach(async element => { + let name = element.name + let avatar = element.avatar_url + let brackets = element.brackets[0] + "text" + element.brackets[1] + const createResult = await createMember(author, [name, brackets], database) + if ( createResult.code === 0 ) { + await avatarMemberChange(author, [name, avatar], database) + } + let tupperStruct = {tupper: name, message: createResult} + + console.log(tupperStruct) + }); + return "Migration finished, check your Members to confirm" + } + else { + return "This is not a valid json file" + } +} diff --git a/src/commands/setAutoProxy.ts b/src/commands/setAutoProxy.ts new file mode 100644 index 0000000..a0a302f --- /dev/null +++ b/src/commands/setAutoProxy.ts @@ -0,0 +1,30 @@ +import Database from "bun:sqlite"; +import { MemberRepo } from "repositories/MemberRepo"; +import UserRepo from "repositories/UserRepo"; +import UserModel from "models/UserModel"; + +function setAutoProxy(author_id: string, args: string[], database: Database) { + + if (args.length != 1) {return 0} + + const memberRepo = new MemberRepo(database); + const userRepo = new UserRepo(database); + + const member = memberRepo.getByName(args[0], author_id); + if (member == null) {return 1} + + if ( + userRepo.getIdByRevoltId(author_id) + ){ + const user_model: UserModel = { + "revolt_id": author_id, + "autoProxy": false + } + userRepo.new(user_model) + } + + const bot_user_id = userRepo.getIdByRevoltId(author_id) + userRepo.setSelectedAutoProxyId(member.id, bot_user_id) +} + +export default setAutoProxy diff --git a/src/commands/toggleAutoProxy.ts b/src/commands/toggleAutoProxy.ts new file mode 100644 index 0000000..fc6ec4e --- /dev/null +++ b/src/commands/toggleAutoProxy.ts @@ -0,0 +1,25 @@ +import Database from "bun:sqlite" +import UserModel from "models/UserModel" +import UserRepo from "repositories/UserRepo" + +function toggleAutoProxy(revolt_id: string, database: Database) { + const userRepo = new UserRepo(database) + + if (userRepo.getById( + userRepo.getIdByRevoltId(revolt_id) + ) == null){ + const model: UserModel = { + "revolt_id": revolt_id, + "autoProxy": false, + } + userRepo.new(model) + } + const user_id = userRepo.getIdByRevoltId(revolt_id) + const is_enabled = userRepo.isProxyEnabled( + userRepo.getIdByRevoltId(revolt_id) + ) + + userRepo.setProxyStatus(user_id, !is_enabled) +} + +export default toggleAutoProxy diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..caa7c21 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,40 @@ +import { Client, Message } from "revolt.js"; +import { commandHandler } from "./utils/commandHandler" +import { nonCommandHandler } from "./utils/nonCommandHandler" +import { Database } from "bun:sqlite"; +import config from "../config.json" +import dbInit from "utils/dbInit"; + +const client : Client = new Client({ eagerFetching: false }); +const db = new Database(config.databaseName); +dbInit(db); + +client.on("ready", async () => { + console.info(`logged in as ${client.user.username}!`) + client.user.edit( + { + status : { + text: config.prefix + " help for the help menu" + } + } + ) +}); + + +client.on("messageCreate", async (message: Message) => { + try{ if (!message.author) { await client.users.fetch(message.authorId) } } + catch(e){console.log(e)} + + if (message.content === undefined) {return} + if (message.author?.bot) {return} + + // checks if the message's body starts with the prefix + if (message.content.startsWith(config.prefix)) { + commandHandler(message, db, config.prefix); + } + else { + nonCommandHandler(message, db); + } +}); + +client.loginBot(config.botKey); diff --git a/src/models/MemberModel.ts b/src/models/MemberModel.ts new file mode 100644 index 0000000..412c7d4 --- /dev/null +++ b/src/models/MemberModel.ts @@ -0,0 +1,10 @@ +interface MemberModel { + id?: number; + owner: string; + prefix: string; + name: string; + profile_pic_url: string; + color?: string; +} + +export default MemberModel; diff --git a/src/models/UserModel.ts b/src/models/UserModel.ts new file mode 100644 index 0000000..94d60be --- /dev/null +++ b/src/models/UserModel.ts @@ -0,0 +1,8 @@ +interface UserModel { + id?: number, + revolt_id: string, + autoProxy: boolean, + autoProxyMember?: number +} + +export default UserModel; diff --git a/src/models/alter.py b/src/models/alter.py deleted file mode 100644 index 76f8e25..0000000 --- a/src/models/alter.py +++ /dev/null @@ -1,2 +0,0 @@ -class Alter: - ... diff --git a/src/models/user.py b/src/models/user.py deleted file mode 100644 index 8e981d1..0000000 --- a/src/models/user.py +++ /dev/null @@ -1,2 +0,0 @@ -class User: - ... diff --git a/src/pluralcakepy/__init__.py b/src/pluralcakepy/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/pluralcakepy/__main__.py b/src/pluralcakepy/__main__.py deleted file mode 100644 index 14554e1..0000000 --- a/src/pluralcakepy/__main__.py +++ /dev/null @@ -1,28 +0,0 @@ -import revolt -import asyncio -import os - -from commandHandler import commandHandler - - -class Client(revolt.Client): - async def on_message(self, message: revolt.Message) -> None: - commandHandler(message, debug=os.environ.get("debug")) - - -async def main(): - revolt_token: str | None = os.environ.get("REVOLTTOKEN") - - if not revolt_token: - raise Exception("no REVOLTTOKEN environment variable") - - async with revolt.utils.client_session() as revolt_session: - revolt_client: Client = Client( - session=revolt_session, - token=revolt_token - ) - - await revolt_client.start() - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/src/repositories/MemberRepo.ts b/src/repositories/MemberRepo.ts new file mode 100644 index 0000000..61af4ee --- /dev/null +++ b/src/repositories/MemberRepo.ts @@ -0,0 +1,79 @@ +import { Database } from 'bun:sqlite'; +import MemberModel from '../models/MemberModel'; + +export class MemberRepo { + db : Database + + constructor(database_instance: Database) { + this.db = database_instance; + } + + getById(member_id: number): MemberModel { + const row: any = this.db.query("SELECT * FROM members WHERE members.id=?") + .get(member_id) + + const mapped_row: MemberModel = { + "id": row.id, + "name": row.name, + "prefix": row.prefix, + "owner": row.owner, + "profile_pic_url": row.profile_pic_url + } + + return mapped_row + } + + getByName(name: string, user_id: string) { + if (name == null || user_id == null) {return null} + + const query = this.db.query(` + SELECT * + FROM members + WHERE members.name=? + AND members.owner=? + `) + + const row: any = query.get(name, user_id) + if (row == null) {return null} + + const mapped_row: MemberModel = { + "id": row.id, + "name": row.name, + "prefix": row.prefix, + "owner": row.owner, + "profile_pic_url": row.profile_pic_url + } + + return mapped_row + } + + getAltersByUserId(userId : string) : MemberModel[] { + const query = this.db.query("SELECT * FROM members WHERE members.owner=?") + + let result: MemberModel[] = query.all(userId).map( (row: any) => { + const mapped_row: MemberModel = { + "id": row.id, + "name": row.name, + "prefix": row.prefix, + "owner": row.owner, + "profile_pic_url": row.profile_pic_url + } + return mapped_row + }) + return result + } + + addAlterForUser(alter: MemberModel){ + this.db.query("INSERT INTO members (owner, prefix, name, profile_pic_url) VALUES(?, ?, ?, ?)") + .run(alter.owner, alter.prefix, alter.name, alter.profile_pic_url) + } + + editAlter(alter: MemberModel){ + this.db.query("UPDATE members SET owner=?, prefix=?, name=?, profile_pic_url=?, color=? WHERE members.id=?") + .run(alter.owner, alter.prefix, alter.name, alter.profile_pic_url, alter.color, alter.id) + } + + delete(alterId: number) { + this.db.query("DELETE FROM members WHERE members.id=?").run(alterId) + } +} diff --git a/src/repositories/UserRepo.ts b/src/repositories/UserRepo.ts new file mode 100644 index 0000000..c79189d --- /dev/null +++ b/src/repositories/UserRepo.ts @@ -0,0 +1,89 @@ +import UserModel from "models/UserModel"; +import { Database } from "bun:sqlite"; + +class UserRepo { + db: Database + + constructor(database: Database) { + this.db = database + } + + getById(id) { + const row: any = this.db.query(` + SELECT * + FROM users + WHERE users.id = ? + `).get(id) + if (row != null){ + return row.id + } + + return null + } + new(model: UserModel) { + this.db.query(` + INSERT INTO users (revolt_id, auto_proxy) values ( ?, ? ) + `) + .run(model.revolt_id, model.autoProxy) + } + delete(id) { + this.db.query(` + DELETE * + FROM users + WHERE users.id=? + `).run(id) + } + + isProxyEnabled(id: number) { + if (id == null) { return false } + const row: any = this.db.query(` + SELECT auto_proxy + FROM users + WHERE users.id=? + `).get(id) + + let is_enabled: boolean + + is_enabled = row.auto_proxy == "TRUE" ? true : false + return is_enabled + } + + setProxyStatus(id: number, status: boolean) { + const string_status = status == true ? "TRUE" : "FALSE" + this.db.query("UPDATE users SET auto_proxy=? WHERE users.id=?").run(string_status, id) + } + + getIdByRevoltId(revolt_id: string): number | null { + const row: any = this.db.query(` + SELECT id + FROM users + WHERE users.revolt_id=? + `).get(revolt_id) + + if (row != null) { + const id: number = row.id + return id + } + return null + } + + setSelectedAutoProxyId(id: number, user_id: number){ + const query = this.db.query(` + UPDATE users + SET auto_proxy_member=? + WHERE users.id=? + `).run(id, user_id) + } + + getSelectedAutoProxyIdByUserId(id: number) { + const row: any = this.db.query(` + SELECT auto_proxy_member + FROM users + WHERE users.id=? + `).get(id) + + return row.auto_proxy_member + } +} + +export default UserRepo diff --git a/src/utils.py b/src/utils.py deleted file mode 100644 index cf1321b..0000000 --- a/src/utils.py +++ /dev/null @@ -1,4 +0,0 @@ -from shlex import split - -def split_args(message: str) -> list[str]: - return split(message) diff --git a/src/utils/checkAutoProxy.ts b/src/utils/checkAutoProxy.ts new file mode 100644 index 0000000..416fe0e --- /dev/null +++ b/src/utils/checkAutoProxy.ts @@ -0,0 +1,17 @@ +import UserRepo from "repositories/UserRepo"; +import { Database } from "bun:sqlite"; + +function checkAutoProxy +( + userId: string, + database: Database +): boolean +{ + const repo = new UserRepo(database); + const user_id = repo.getIdByRevoltId(userId); + const is_enabled = repo.isProxyEnabled(user_id); + + return is_enabled +} + +export default checkAutoProxy; diff --git a/src/utils/commandHandler.ts b/src/utils/commandHandler.ts new file mode 100644 index 0000000..6ab57e8 --- /dev/null +++ b/src/utils/commandHandler.ts @@ -0,0 +1,73 @@ +import { Message } from "revolt.js" +import { Database } from "bun:sqlite" +import { split } from "shlex" + +import { returnHelpText } from "../commands/help" +import listMember from "../commands/listMember" +import createMember from "../commands/createMember" +import { deleteMember } from "../commands/deleteMember" +import { avatarMemberChange } from "../commands/avatarMemberChange" +import colorMemberChange from "../commands/colorMemberChange" +import migrationCommand from "../commands/migrateMember" +import toggleAutoProxy from "commands/toggleAutoProxy" +import setAutoProxy from "commands/setAutoProxy" + + + +export async function commandHandler(message : Message, db: Database, _prefix : String) { + let args : string[] = split(message.content); + args.shift() + const command = args[0] + args.shift() + + switch(command) { + case "help" : { + await message.reply(returnHelpText()); + break; + } + case "list" : { + await message.reply(await listMember(message.author.id, db)); + break; + } + case "create" : { + const commandResponse = await createMember(message.author.id, args, db); + await message.reply (commandResponse.message) + break + } + case "delete" : { + await message.reply(await deleteMember(message.author.id, args, db)) + break + } + case "avatar" : { + await message.reply(await avatarMemberChange(message.author.id, args, db)); + break + } + case "setAutoProxy": { + const status = setAutoProxy(message.author.id, args, db); + switch(status) { + case 0: { + await message.reply("not enough arguments") + break + } + case 1: { + message.reply("no member found with that member name") + break + } + } + break + } + case "toggleAutoProxy": { + toggleAutoProxy(message.author.id, db) + await message.reply("toggled") + break + } + case "color" : { + await message.reply(await colorMemberChange(message.author.id, args, db)); + break + } + case "tupper" : { + await message.reply(await migrationCommand(message.author.id, message.attachments, "placeholder", db)) + break + } + } +} diff --git a/src/utils/dbInit.ts b/src/utils/dbInit.ts new file mode 100644 index 0000000..23a1c63 --- /dev/null +++ b/src/utils/dbInit.ts @@ -0,0 +1,17 @@ +import { Database } from "bun:sqlite"; + +function dbInit(database: Database){ + database.run("CREATE TABLE IF NOT EXISTS members (id INTEGER PRIMARY KEY AUTOINCREMENT, owner TEXT, prefix TEXT, name TEXT, profile_pic_url TEXT, color TEXT)"); + + database.run(` + CREATE TABLE IF NOT EXISTS users( + id INTEGER PRIMARY KEY AUTOINCREMENT, + revolt_id TEXT NOT NULL, + auto_proxy BOOLEAN NOT NULL, + auto_proxy_member INTEGER, + FOREIGN KEY (auto_proxy_member) + REFERENCES members (id)) + `); +} + +export default dbInit diff --git a/src/utils/nonCommandHandler.ts b/src/utils/nonCommandHandler.ts new file mode 100644 index 0000000..d918f86 --- /dev/null +++ b/src/utils/nonCommandHandler.ts @@ -0,0 +1,16 @@ +import { Message } from "revolt.js" +import { Database } from "bun:sqlite"; +import sendAsMember from "./sendAsMemberHandler"; +import checkAutoProxy from "./checkAutoProxy"; +import sendAsAutoProxyMember from "./sendAsAutoProxyMember"; + +export async function nonCommandHandler(message : Message, database: Database){ + const should_auto_proxy = checkAutoProxy(message.author.id, database) + + if (should_auto_proxy) { + await sendAsAutoProxyMember(message.author.id, message, database) + } + else { + await sendAsMember(message, database); + } +} diff --git a/src/utils/sendAsAutoProxyMember.ts b/src/utils/sendAsAutoProxyMember.ts new file mode 100644 index 0000000..a76572b --- /dev/null +++ b/src/utils/sendAsAutoProxyMember.ts @@ -0,0 +1,46 @@ +import Database from "bun:sqlite"; +import { Message } from "revolt.js" +import { MemberRepo } from "repositories/MemberRepo"; +import UserRepo from "repositories/UserRepo"; +import MemberModel from "models/MemberModel"; + +async function sendAsAutoProxyMember(revolt_uid: string, message: Message, database: Database) { + // assumes that every check has been done previously + + const userRepo = new UserRepo(database) + const memberRepo = new MemberRepo(database) + + const user_id = userRepo.getIdByRevoltId(revolt_uid) + const auto_proxy_id = userRepo.getSelectedAutoProxyIdByUserId(user_id) + + const member_to_proxy_as: MemberModel = memberRepo.getById(auto_proxy_id) + const replyIds: string[] | undefined = message.replyIds; + let replies: any[] = []; + + if (replyIds !== undefined) { + replyIds.forEach( replyId => { + replies.push({ + id: replyId, + mention: false + }) + }) + } + + try{ + await message.channel.sendMessage({ + content: message.content, + masquerade: { + name: member_to_proxy_as.name, + avatar: member_to_proxy_as.profile_pic_url + }, + replies: replies + }) + await message.delete(); + } + catch(e){ + console.log(e) + await message.channel.sendMessage("Error: PluralCake requires at least these permissions: \n- Masquerade permissions. \n- Message editing permissions.") + } +} + +export default sendAsAutoProxyMember diff --git a/src/utils/sendAsMemberHandler.ts b/src/utils/sendAsMemberHandler.ts new file mode 100644 index 0000000..1f75840 --- /dev/null +++ b/src/utils/sendAsMemberHandler.ts @@ -0,0 +1,50 @@ +import { Message } from "revolt.js" +import { Database } from "bun:sqlite"; +import { MemberRepo } from "../repositories/MemberRepo" +import MemberModel from "../models/MemberModel" + +export default async function sendAsMember(message: Message, database: Database) { + const memberRepo: MemberRepo = new MemberRepo(database); + let members: MemberModel[] = memberRepo.getAltersByUserId(message.author.id); + + members.forEach( async alter => { + const pre_prefix = alter.prefix.split("text"); + if ( + message.content.startsWith(pre_prefix[0]) + && message.content.endsWith(pre_prefix[1]) + && message.content.length > 1 + ){ + let actualContent: string = message.content; + actualContent = actualContent.slice(pre_prefix[0].length, actualContent.length - pre_prefix[1].length) + + const replyIds: string[] | undefined = message.replyIds; + let replies: any[] = []; + + if (replyIds !== undefined) { + replyIds.forEach( replyId => { + replies.push({ + id: replyId, + mention: false + }) + }) + } + + try{ + await message.channel.sendMessage({ + content: actualContent, + masquerade: { + name: alter.name , + avatar: alter.profile_pic_url, + color: alter.color + }, + replies: replies + }) + await message.delete(); + } + catch(e){ + console.log(e) + await message.channel.sendMessage("Error: PluralCake requires at least these permissions: \n- Masquerade permissions. \n- Message editing permissions.") + } + } + }) +} diff --git a/src/utils/tableConstructor.ts b/src/utils/tableConstructor.ts new file mode 100644 index 0000000..416fa47 --- /dev/null +++ b/src/utils/tableConstructor.ts @@ -0,0 +1,11 @@ +import { AlterModel } from '../models/alterModel' +export function tableConstructor(data: AlterModel[]){ + const header = "| Name | tag |\n|----|----|\n" + let body : string = ""; + data.forEach(alter => { + body = body + + "|" + alter.name + "|" + alter.prefix + "|\n" + }) + body = body.slice(0, body.length - 2) + return header + body +} diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a650685 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "resolveJsonModule" : true, + "target": "es6", + "types": [ + "bun-types" + ], + "moduleResolution": "node", + "sourceMap": true, + "outDir": "dist", + "baseUrl": "./src" + }, + "lib": ["es2015"] + } +