Compare commits
No commits in common. "mistress" and "rewrite" have entirely different histories.
35 changed files with 475 additions and 787 deletions
169
.gitignore
vendored
169
.gitignore
vendored
|
@ -1,9 +1,162 @@
|
|||
node_modules
|
||||
dist
|
||||
package-lock.json
|
||||
npm-debug.log
|
||||
.nyc
|
||||
# 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
|
||||
.env
|
||||
.DS_Store
|
||||
config.json
|
||||
*.db
|
||||
.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/
|
||||
|
|
15
README.md
15
README.md
|
@ -1,14 +1 @@
|
|||
# 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
|
||||
```
|
||||
# pluralcakepy
|
||||
|
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
20
package.json
20
package.json
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
239
pdm.lock
Normal file
239
pdm.lock
Normal file
|
@ -0,0 +1,239 @@
|
|||
# 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"},
|
||||
]
|
19
pyproject.toml
Normal file
19
pyproject.toml
Normal file
|
@ -0,0 +1,19 @@
|
|||
[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
|
19
src/commandHandler/__init__.py
Normal file
19
src/commandHandler/__init__.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
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
|
|
@ -1,28 +0,0 @@
|
|||
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 >"
|
||||
}
|
||||
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
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
|
|
@ -1,56 +0,0 @@
|
|||
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 <text>", code: 2};
|
||||
}
|
||||
if (!args[1].includes("text")) {
|
||||
return {message: "Error: This command requires a tag that contains <text> 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;
|
|
@ -1,24 +0,0 @@
|
|||
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"
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
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 <member name> | Sets the member to automatically send messages as\n"
|
||||
+"- toggleAutoProxy | Enable or disable the autoproxy"
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
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
|
|
@ -1,41 +0,0 @@
|
|||
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"
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
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
|
|
@ -1,25 +0,0 @@
|
|||
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
|
40
src/index.ts
40
src/index.ts
|
@ -1,40 +0,0 @@
|
|||
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);
|
|
@ -1,10 +0,0 @@
|
|||
interface MemberModel {
|
||||
id?: number;
|
||||
owner: string;
|
||||
prefix: string;
|
||||
name: string;
|
||||
profile_pic_url: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export default MemberModel;
|
|
@ -1,8 +0,0 @@
|
|||
interface UserModel {
|
||||
id?: number,
|
||||
revolt_id: string,
|
||||
autoProxy: boolean,
|
||||
autoProxyMember?: number
|
||||
}
|
||||
|
||||
export default UserModel;
|
2
src/models/alter.py
Normal file
2
src/models/alter.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
class Alter:
|
||||
...
|
2
src/models/user.py
Normal file
2
src/models/user.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
class User:
|
||||
...
|
0
src/pluralcakepy/__init__.py
Normal file
0
src/pluralcakepy/__init__.py
Normal file
28
src/pluralcakepy/__main__.py
Normal file
28
src/pluralcakepy/__main__.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
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())
|
|
@ -1,79 +0,0 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
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
|
4
src/utils.py
Normal file
4
src/utils.py
Normal file
|
@ -0,0 +1,4 @@
|
|||
from shlex import split
|
||||
|
||||
def split_args(message: str) -> list[str]:
|
||||
return split(message)
|
|
@ -1,17 +0,0 @@
|
|||
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;
|
|
@ -1,73 +0,0 @@
|
|||
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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
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
|
|
@ -1,16 +0,0 @@
|
|||
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);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
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
|
|
@ -1,50 +0,0 @@
|
|||
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.")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
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
|
||||
}
|
0
tests/__init__.py
Normal file
0
tests/__init__.py
Normal file
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule" : true,
|
||||
"target": "es6",
|
||||
"types": [
|
||||
"bun-types"
|
||||
],
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"baseUrl": "./src"
|
||||
},
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
|
Loading…
Reference in a new issue