nonJerry / VeraBot

Bot to verify and manage Memberships.
GNU General Public License v3.0
12 stars 7 forks source link

Self Hosting Documentation? #40

Closed JakeFrosty closed 1 year ago

JakeFrosty commented 1 year ago

I cannot seem to find a self hosting guide in the repository, Is it alright if I ask how to run the app with my own setup? I'm aware I need a mongodb and python, I'm confused on what I need to fully get it working on my local setup

RisingFog commented 1 year ago

The project was originally meant to be hosted using Heroku and tied to a free-tier MongoDB Atlus cloud database, making it run at zero cost. Ever since Heroku stopped offering their free-tier, I'm not sure how this project is hooked up anymore (maybe Oracle Cloud Free Tier?)

Self-hosting isn't really something the project was considered for from my experiences, but it is doable (I did it for a time before all of my changes got implemented in master). Even in my self-hosting period, I made use of the free MongoDB Atlus database while running the code on my VPS server.

In terms of actually setting it up for self-hosting, the python part should be pretty trivial once you install the prerequisites using pip -r requirements.txt. To a certain extent, the MongoDB setup should be easy as they provide documentation for installing the MongoDB Community Version.

If your issues lie beyond these points, you'll have to be more specific in order for me to properly provide help.

JakeFrosty commented 1 year ago

I wanna know what environment variables I need to provide to the app.py program to make it run, as I wanna take this project further and dockerize it hopefully, so far I've come across these

token = os.getenv("TOKEN") owner_id = int(os.getenv("OWNER_ID")) embed_color = int(os.getenv("EMBED_COLOR"), 16) db_user = os.getenv("DB_USER") db_pass = os.getenv("DB_PASS") db_url = os.getenv("DB_LINK") dm_log = int(os.getenv("DM_LOG")) stage = os.getenv("STAGE")

but I have zero clue what stage, db_url or dm_log may be for db_url, do I just use a typical URI for database like mongodb://host-ip?

RisingFog commented 1 year ago

db_url is in fact the mongodb URI used for connecting to the database.

stage is meant for testing/debug purposes, so you're fine to use something like PROD in it's place (it'll have no effect).

dm_log seems to be a deprecated/no longer used function which would send the logs of DMs to a specified channel (this seems to have been deprecated with the implementations of slash commands and the phasing out of DMs).

JakeFrosty commented 1 year ago

I commented dm_log out. The following gives me an error TOKEN=bot-token LOG_PORT=514 OWNER_ID=owner-userid EMBED_COLOR=45300 STAGE=PROD DB_USER=admin DB_PASS=example DB_LINK=mongodb://databaseip:27017/ python3 app.py

ERROR: Task exception was never retrieved future: <Task finished name='Task-2' coro=<background_main() done, defined at /root/VeraBot/app.py:314> exception=AttributeError("'NoneType' object has no attribute 'get'")> Traceback (most recent call last): File "/root/VeraBot/app.py", line 319, in background_main await asyncio.gather(*coroutines) File "/root/VeraBot/membership_handling.py", line 617, in check_membership_routine last_checked = self.db.get_last_checked() ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/root/VeraBot/database.py", line 335, in get_last_checked return self._get_general_settings().find_one({"name": "member_check"}).get("last_checked", None) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'get' --- Logging error --- Traceback (most recent call last): File "/usr/lib/python3.11/logging/handlers.py", line 1013, in emit self.socket.sendto(msg, self.address) TypeError: str, bytes or bytearray expected, not NoneType Call stack: File "/root/VeraBot/app.py", line 328, in <module> asyncio.run(main()) File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run return runner.run(main) File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run return self._loop.run_until_complete(task) File "/usr/lib/python3.11/asyncio/base_events.py", line 640, in run_until_complete self.run_forever() File "/usr/lib/python3.11/asyncio/base_events.py", line 607, in run_forever self._run_once() File "/usr/lib/python3.11/asyncio/base_events.py", line 1923, in _run_once handle = None # Needed to break cycles when an exception occurs. File "/usr/lib/python3.11/asyncio/base_events.py", line 1797, in call_exception_handler self.default_exception_handler(context) File "/usr/lib/python3.11/asyncio/base_events.py", line 1771, in default_exception_handler logger.error('\n'.join(log_lines), exc_info=exc_info) Message: 'Task exception was never retrieved\nfuture: <Task finished name=\'Task-2\' coro=<background_main() done, defined at /root/VeraBot/app.py:314> exception=AttributeError("\'NoneType\' object has no attribute \'get\'")>' Arguments: ()

RisingFog commented 1 year ago

It doesn't look related to commenting out the dm_log portion.

Can you check to see if the database tables have been made?

JakeFrosty commented 1 year ago

Is this all the tables created? image I think something went wrong here

RisingFog commented 1 year ago

There are two databases which VeraBot creates:

Servers (created upon adding a new server for the first time)

settings

Neither of them are created, which means that there's nothing for it to read from.

After looking through the code, it doesn't seem like the settings collection gets made automatically, so here is the schema as it was on my MongoDB Atlus database when I was self-hosting it:

image

Perhaps after the database and collection is made manually with this schema, it'll work properly (the _id entry is auto-generated so it can be ignored).

JakeFrosty commented 1 year ago

Hello, sorry for the late response. Is there any way you can export that schema or format? I am very new to mongodb and I honestly don't have a clue how to manipulate it

I have made the settings.general along with Servers and nothing happened yet except the same error

nonJerry commented 1 year ago

Your error implies to me that it doesn't even create the object instance in your execution. If you haven't changed your env vars and it still contains DB_LINK=mongodb://databaseip:27017 that is bound to happen except you allow anonymous access. It should contain placeholders for where user and password need to be inserted like this for example: DB_LINK=mongodb://{}:{}@databaseip:27017

JakeFrosty commented 1 year ago

TOKEN=bottoken LOG_PORT=514 OWNER_ID=415779962436452353 EMBED_COLOR=45300 STAGE=PROD DM_LOG=415779962436452353 DB_USER=admin DB_PASS=example DB_LINK=mongodb://{}:{}@databaseip:27017 python3 app.py

am I doing anything wrong?

also the following is how I setup the settings.general collection

Member Check

{
    _id: "653a3fe3a25afdfacba7b3d1",
    name: "member_check",
    last_checked: "2023-10-25-T12:00:00.000+00:00"
}

Supported Idols

{
    _id: "653a404da25afdfacba7b3d2",
    name: "supported_idols",
    supported_idols: [
        "Nanashi Mumei",
        "Shiori Novella"
    ]
}

Multi Server

{
    _id: "653a456eababf02b94d1244e",
    name: "multi_server",
    ids: [
        ""
    ]
}

error_log.txt

nonJerry commented 1 year ago

I can notice two things:

  1. last_checked should be a Date and not a String
  2. You haven't set the environment variable LOG_LINK. In my case it simply contains the link to my papertrail logging with the format: logsX.papertrailapp.com
JakeFrosty commented 1 year ago
  1. I modified it now, it should look like this now
    {
    _id: "653a3fe3a25afdfacba7b3d1",
    name: "member_check",
    last_checked: ISODate('2023-10-25T12:00:00.000Z')
    }
  2. Can I use a local RSYSLOG server instead? I have one on the same server verabot runs on, running on port 514
  3. My "Servers" Database is empty, can I ask for an example of how data in it should look like?

Error:

INFO: Started
WARNING: PyNaCl is not installed, voice will NOT be supported
WARNING: Privileged message content intent is missing, commands may not work as expected.
INFO: logging in using static token
INFO: Cogs added
INFO: Shard ID None has connected to Gateway (Session ID: e6e20912fdb0473b95ee0bac21d5c4ab).
Logged in as
VeraClon3
1166336390917783592
------
INFO: Checking memberships!
ERROR: Task exception was never retrieved
future: <Task finished name='Task-2' coro=<background_main() done, defined at /root/VeraBot/app.py:314> exception=TypeError("string indices must be integers, not 'str'")>
Traceback (most recent call last):
  File "/root/VeraBot/app.py", line 319, in background_main
    await asyncio.gather(*coroutines)
  File "/root/VeraBot/membership_handling.py", line 625, in check_membership_routine
    await self.delete_expired_memberships()
  File "/root/VeraBot/membership_handling.py", line 565, in delete_expired_memberships
    server_id = server['guild_id']
                ~~~~~~^^^^^^^^^^^^
TypeError: string indices must be integers, not 'str'
nonJerry commented 1 year ago
  1. Just try it, you could also just delete the remote log handler
  2. Don't have empty collections at hand, just create a collection in the Servers database with the id of the server your bot is in (all of them as it iterates through all servers it has joined), e.g. 1627272727 Tbh this feels like you are just asking for every little thing. The code is the truth and (almost) everything can be reconstructed from it. Especially all your questions regarding the db are in ONE file which should have most answers you seek. You are the one trying to run so experiment a little and try to solve some errors yourself please
JakeFrosty commented 1 year ago
  1. Just try it, you could also just delete the remote log handler
  2. Don't have empty collections at hand, just create a collection in the Servers database with the id of the server your bot is in (all of them as it iterates through all servers it has joined), e.g. 1627272727 Tbh this feels like you are just asking for every little thing. The code is the truth and (almost) everything can be reconstructed from it. Especially all your questions regarding the db are in ONE file which should have most answers you seek. You are the one trying to run so experiment a little and try to solve some errors yourself please

Apologies for asking too much, I think I have it working now, I really appreciate your help. I will open a PR when I get it working with docker!