-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from Local-Connectivity-Lab/ticket-484
Ticket 484 - blocked users
- Loading branch information
Showing
16 changed files
with
856 additions
and
172 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,155 +1,49 @@ | ||
# netbot | ||
|
||
[![Python application](https://github.com/philion/netbot/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/philion/netbot/actions/workflows/python-app.yml) | ||
|
||
Testing currently requires VPN access, so automanted tests are skipped for now. To test manually, run `python -m unittest` from the commandline with a valid `.env` file. | ||
|
||
community **NET**work discord **BOT**, for integrating network management functions | ||
|
||
## Deploy netbot | ||
To mangage authorization, security tokens and other credentials are stored in a local `.env` file and read by the code. The following credentials are needed for full integrarion: | ||
``` | ||
DISCORD_TOKEN=ABC | ||
REDMINE_TOKEN=123 | ||
REDMINE_URL=http://do/re/mi | ||
IMAP_HOST=imap.example.com | ||
[email protected] | ||
IMAP_PASSWORD=u&me | ||
``` | ||
|
||
`netbot` uses standard Docker compose: | ||
|
||
To run `netbot` using a standard container system: | ||
``` | ||
git clone https://github.com/philion/netbot | ||
cd netbox | ||
cp ~/.env ./.env | ||
sudo docker compose up -d | ||
``` | ||
|
||
to stop: | ||
``` | ||
sudo docker compose down | ||
``` | ||
|
||
|
||
## Discord Token & Invite Bot | ||
To enable netbot on your Discord server, you need to generate a valid `DISCORD_TOKEN` and then invite the bot to your Discord instance. | ||
|
||
1. Go to https://discord.com/developers/applications and login. | ||
2. Create a **New Application** (top-right button). | ||
2. Fill in the *Name* and click the Terms of Service. | ||
3. Add a Description on the General Information page and save changes. | ||
4. In the OAuth2/URL Generator section, generate a URL for a **bot** with **Administrator** permissions. | ||
5. That URL will look something like: | ||
https://discord.com/api/oauth2/authorize?client_id=[client-id]&permissions=8&scope=bot | ||
6. Open a browser with that URL and login. | ||
7. You'll be presented with a window to add your bot to any server you have admin permissions for. | ||
8. Select your server and click OK. | ||
4. Back in the bot setup, in the "Bot" section, under "Build-A-Bot", **Copy** the Token. This is the DISCORD_TOKEN | ||
3. On the same page, a little lower, *unset* the **Public Bot** switch. | ||
4. Under "Privlidged Gateway Intents", enable "Message Content Intent". | ||
5. Create an `.env` file in the `netbot` directory containing: | ||
`DISCORD_TOKEN=your-token-contents` | ||
|
||
Note: Not all admin permissions are needed. If you want a very targeted bot, select: | ||
* Manage Server | ||
* Manage Roles | ||
* Manage Channels | ||
* Manage Expressions | ||
* Read Messages/View Channels | ||
* Send Messages | ||
* Create Pubilc Threads | ||
* Create Private Threads | ||
* Send Messages in Threads | ||
* Manage Messages | ||
* Manage Threads | ||
* Embed Links | ||
* Attach Files | ||
* Read Message History | ||
* Use Slash Commands | ||
|
||
## Deploy threader | ||
The threader functionality, managed by `threader.py`, needs to be registered as a cron job to run every 5 minutes. | ||
|
||
``` | ||
sudo crontab -e | ||
``` | ||
|
||
and add the following entry to the bottom: | ||
``` | ||
*/5 * * * * /home/scn/github/netbot/threader_job.sh | /usr/bin/logger -t threader | ||
``` | ||
|
||
This cron job uses the Python venv to execute, and captures std and err output to syslog (tagged "threader"). | ||
|
||
Logs from the runs are stored in `/home/scn/github/netbot/logs` folder, one per cron jon with timestamps. | ||
## community **NET**work discord **BOT**, for integrating network management functions | ||
|
||
[![Python application](https://github.com/philion/netbot/actions/workflows/python-app.yml/badge.svg?branch=main)](https://github.com/philion/netbot/actions/workflows/python-app.yml) | ||
|
||
## Discord Usage | ||
The following Discord commands are implemented: | ||
|
||
``` | ||
/scn add [login] - Map current discord userid to redmine [login] | ||
/scn join [team] - discord user joins [team] (and maps user id) | ||
/scn leave [team] - discord user leaves [team] | ||
/scn reindex - rebuild the bot's index of users, teams and other metadata. | ||
Use after adding new users and teams to Redmine. | ||
A collection of Seattle Community Network ([SCN](https://seattlecommunitynetwork.org/)) tools, including: | ||
* **`threader.ph`**: SCN's email threading service to collect and categorize SCN messages. | ||
* **`netbot.py`**: SCN's Discord bot to manage Redmine tickets from Discord. | ||
* **`cli.py`**: A rich-terminal CLI version of the `netbot` commands. | ||
* **`redmine.py`**: A Redmine client written in Python, designed for SCN use cases. | ||
|
||
/tickets me - (default) tickets assigned to me or my teams | ||
/tickets [team] - tickets assigned to team [team] | ||
/tickets [user] - tickets assigned to a specific [user] | ||
/tickets [query] - tickets that match the term [query] | ||
This code base currently supports several different services due to the reliance on the Redmine client code. (In the future, this should be split into several projects, and redmine.py cleaned up and submitted to PyPI.) | ||
|
||
/ticket # show - (default) show ticket info for ticket # | ||
/ticket # details - show ticket # with all notes (in a decent format) | ||
/ticket # assign - Assign ticket n to the specified user - not yet implemented | ||
/ticket # unassign - Mark ticket n new and unassigned. | ||
/ticket # progress - Assign the ticket to yourself and set it yourself. | ||
/ticket # resolve - Mark the ticket resolved. | ||
|
||
/new [title] - Create a new ticket with the title [title] | ||
``` | ||
## threader | ||
|
||
## CLI | ||
The email threader functionality is implemented in `threader.py`, is designed to run periodically as a cron job. | ||
|
||
A command-line interface version of the `tickets` Discord bot command provides the same capablities as the bot on Discord. This CLI was developed to help testing, which the asynchonous nature of Discord interactions adds a layer of complexity to. | ||
For design and implementation details, see [Design](docs/design.md). | ||
|
||
``` | ||
cli.py - List the new tickets assigned to me or teams I'm on | ||
cli.py [user] - List the tickets assigned to user | ||
cli.py [#] - List details for ticket # | ||
cli.py [query] - Search for tickets containing the term [query] | ||
cli.py [#] assign [user] - Assign ticket # to the specified user | ||
cli.py [#] unassign - Mark ticket # new and unassigned. | ||
cli.py [#] progress - Assign ticket # to yourself and set it yourself. | ||
cli.py [#] resolve - Mark ticket number # resolved. | ||
``` | ||
For deployment and operational details, see [Threader Operation](docs/threader.md). | ||
|
||
### CLI Configuration | ||
|
||
To configure the API key needed for `cli.py` to access the Redmine server, create a API key as per: https://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication, notably: | ||
## netbot | ||
|
||
> You can find your API key on your account page ( /my/account ) when logged in, on the right-hand pane of the default layout. | ||
The netbot functionality is implemented in `netbot.py` (and supporting `cog_*.py` implementations), is designed to run in as a container using a standard `compose.yaml` file. | ||
|
||
Once you have you API key, create a file in the local directoy named `.env`. | ||
For design and implementation details, see [Design](docs/design.md). | ||
|
||
In the new file, create entries for: | ||
For deployment and operational details, see [Netbot Operation](docs/netbot.md). | ||
|
||
REDMINE_TOKEN=[your redmine api token] | ||
REDMINE_URL=http://your.redmine.server | ||
|
||
Now you should be able to see a list of interesting tickets, specifically for the user with the supplied API key. | ||
## cli | ||
|
||
./cli.py | ||
`cli.py` provides an implementation of the netbot Discord commands that can be run on a local command line. | ||
|
||
For details about configuration and usage, see [CLI](docs/cli.md) | ||
|
||
## Build and Test | ||
|
||
## Development | ||
A `Makefile` is provided with the following targets: | ||
- `venv` : build a Python virtual environment ("venv") in `.venv` | ||
- `venv` : build a Python virtual environment ("venv") | ||
- `test` : run the unit test suite | ||
- `coverage` : run the unit tests and generate a minimal coverage report | ||
- `htmlcov` : run the unit tests and generate a full report in htmlcov/ | ||
|
||
Testing and coverage requires standing up a local testbed. For details, see [Design](docs/design.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Netbot Command Line Interface (CLI) | ||
|
||
`cli.py` provides command-line interface version of the `netbot` capablities. | ||
|
||
|
||
## Configuration: `.env` file | ||
|
||
`cli.py` relies on the following environment settings: | ||
* `REDMINE_TOKEN`: Secure Redmine API token | ||
* `REDMINE_URL`: URL of Redmine service | ||
|
||
To configure the API key needed for `cli.py` to access the Redmine server, create a API key as per: https://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication, notably: | ||
|
||
> You can find your API key on your account page (/my/account) when logged in, on the right-hand pane of the default layout. | ||
Once you have you API key, create a file in the local directoy named `.env`. | ||
|
||
In the new file, create entries for: | ||
|
||
``` | ||
REDMINE_TOKEN=[your redmine api token] | ||
REDMINE_URL=http://your.redmine.server | ||
``` | ||
|
||
Once the `.env` file has been created, the `cli.py` should "just work". | ||
|
||
|
||
## CLI Usage | ||
|
||
``` | ||
cli.py - List the new tickets assigned to me or teams I'm on | ||
cli.py [user] - List the tickets assigned to user | ||
cli.py [#] - List details for ticket # | ||
cli.py [query] - Search for tickets containing the term [query] | ||
cli.py [#] assign [user] - Assign ticket # to the specified user | ||
cli.py [#] unassign - Mark ticket # new and unassigned. | ||
cli.py [#] progress - Assign ticket # to yourself and set it yourself. | ||
cli.py [#] resolve - Mark ticket number # resolved. | ||
``` | ||
|
||
|
||
## Logging | ||
|
||
All CLI logs are output to the console, and can be redirected using standard Unix tools. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Netbot Design and Implementation | ||
|
||
## netbot | ||
|
||
|
||
### Discord User Mapping | ||
To maintain accurate attribution in Redmine when comments are made in Discord, a mapping is setup between Discord users and Redmine users. | ||
|
||
This mapping is stored in a custom field, "Discord ID", in the Redmine user data. | ||
|
||
|
||
## Email Threader | ||
|
||
cron job | ||
|
||
script to encapsulate loadin python environment | ||
|
||
processes each new IMAP message: | ||
- extracts sender from From header | ||
- creates account for sender if one does not exist, based on email | ||
- extracts 'content' of email | ||
- if content is HTML, it is converted to text (quick and dirty, this could be better) | ||
- searches for a ticket with the same Subject as the new email | ||
- if a matching ticket is found, the content is appended to that ticket, attributed to the account | ||
- if not, a new Redmine ticket is created with the email subject and content, attributed to the account | ||
- if the user is blocked (see below), the ticket is created as above, and will immediately be put in a `Reject` state. | ||
|
||
|
||
## Block system | ||
|
||
A "block" system allows messages from certain users be recorded as rejected tickets when processing. | ||
|
||
This in initiated when the user is added to a `blocked` team in Redmine. New tickets from users in the `blocked` team are automatically rejected. Updates (new messages using the same subject) from blocked users are still append to rejected ticket, but doesn't change the status of the ticket. | ||
|
||
When the `/scn block <email>` command is issued, the user is added to the `blocked` team, then all tickets created by the user are put in a `Reject`ed state. If a user is moved to the `blocked` team without using the Discord command, reject post-action will not trigger (currently). `/scn block` is designed to be idempotent, and multiple calls for the same email should result in the same outcome: user in blocked team and all authored tickets rejected. | ||
|
||
The user can be "unblocked" by removing them from the `blocked` team or issuing `/scn unblock <email>`. None of the `Reject`ed tickets will be updated, but new tickets will be created and not rejected. | ||
|
||
|
||
## Build and Test | ||
A `Makefile` is provided with the following targets: | ||
- `venv` : build a Python virtual environment ("venv") in `.venv` | ||
- `test` : run the unit test suite | ||
- `coverage` : run the unit tests and generate a minimal coverage report | ||
- `htmlcov` : run the unit tests and generate a full report in htmlcov/ | ||
- `lint` : generate a pylint report, based on settings in `pylintrc` | ||
|
||
All the [`make`](https://en.wikipedia.org/wiki/Make_(software)) targets depend on `venv`, which builds a [standard Python virtual environment](https://docs.python.org/3/library/venv.html). | ||
|
||
### Constructing a Virtual Environment | ||
|
||
Creating the virtual environment with `make`: | ||
``` | ||
make venv | ||
``` | ||
|
||
If you prefer to do so by hand: | ||
``` | ||
python3.11 -m venv .venv | ||
./.venv/bin/pip install --upgrade pip | ||
./.venv/bin/pip install -r requirements.txt | ||
``` | ||
|
||
`python3.11` is used specificlly as a widely available version. That version can be managed in the `Makefile`. | ||
|
||
Any builds targeted with `make` will used the `venv` automatically (and generate it, if it's not already there). Users operating Python from the command line will need to [load their environment](https://docs.python.org/3/library/venv.html#how-venvs-work). | ||
|
||
For example, `bash` and `zsh` users would: | ||
``` | ||
$ source .venv/bin/activate | ||
``` | ||
|
||
### Testing | ||
|
||
This is a Python project, and tests can be run using Python unittest: | ||
``` | ||
python -m unittest | ||
``` | ||
or | ||
``` | ||
make test | ||
``` | ||
|
||
Each `test_*.py` file can be run independantly, which targets the specific sub-system and turns on DEBUG logging. | ||
|
||
Full integration testing requires standing up a local testbed with the [SCN Redmine](https://github.com/Local-Connectivity-Lab/scn-redmine) container composition. Tests that cannot be run without access to Redmine will skip when the `.env` file is absent. | ||
|
||
Automated testing using Github Actions is disabled without valid `.env` settings. *When/if SCN releases public containers*, Github Actions could be updated to run the full integration suite with an `.env` configured for an ephemeral test instance built from the public container. | ||
|
||
|
||
### Deploying a Redmine Testbed | ||
|
||
All the services rely on redmine for testing. | ||
|
||
To setup a test instance, follow https://github.com/Local-Connectivity-Lab/scn-redmine/blob/main/README.md | ||
|
||
* Deploy scn_redmine | ||
* add custom fields and admin user - covered in Initial Setup (or will be) | ||
* Setup access token in .env as per [redmine](./redmine.md) |
File renamed without changes.
Oops, something went wrong.