Skip to content

Commit

Permalink
feat(github): add github integration (#368)
Browse files Browse the repository at this point in the history
  • Loading branch information
ReenigneArcher authored Dec 14, 2024
1 parent 830ca7b commit 630e2c5
Show file tree
Hide file tree
Showing 36 changed files with 2,136 additions and 397 deletions.
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,16 @@ jobs:
- name: Test with pytest
id: test
env:
CI_EVENT_ID: ${{ github.event.number || github.sha }}
GITHUB_PYTEST: "true"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_TEST_BOT_TOKEN }}
DISCORD_WEBHOOK: ${{ secrets.DISCORD_TEST_BOT_WEBHOOK }}
DISCORD_GITHUB_STATUS_CHANNEL_ID: ${{ vars.DISCORD_GITHUB_STATUS_CHANNEL_ID }}
DISCORD_REDDIT_CHANNEL_ID: ${{ vars.DISCORD_REDDIT_CHANNEL_ID }}
DISCORD_SPONSORS_CHANNEL_ID: ${{ vars.DISCORD_SPONSORS_CHANNEL_ID }}
GRAVATAR_EMAIL: ${{ secrets.GRAVATAR_EMAIL }}
IGDB_CLIENT_ID: ${{ secrets.TWITCH_CLIENT_ID }}
IGDB_CLIENT_SECRET: ${{ secrets.TWITCH_CLIENT_SECRET }}
PRAW_CLIENT_ID: ${{ secrets.REDDIT_CLIENT_ID }}
PRAW_CLIENT_SECRET: ${{ secrets.REDDIT_CLIENT_SECRET }}
REDDIT_USERNAME: ${{ secrets.REDDIT_USERNAME }}
Expand Down
29 changes: 22 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,50 @@ ENV COMMIT=${COMMIT}
ARG DAILY_TASKS=true
ARG DAILY_RELEASES=true
ARG DAILY_TASKS_UTC_HOUR=12
ARG DISCORD_GITHUB_STATUS_CHANNEL_ID
ARG DISCORD_REDDIT_CHANNEL_ID
ARG DISCORD_SPONSORS_CHANNEL_ID

# Secret config
ARG DISCORD_BOT_TOKEN
ARG DAILY_CHANNEL_ID
ARG DISCORD_BOT_TOKEN
ARG DISCORD_CLIENT_ID
ARG DISCORD_CLIENT_SECRET

Check warning on line 28 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "DISCORD_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG DISCORD_REDIRECT_URI
ARG GITHUB_CLIENT_ID
ARG GITHUB_CLIENT_SECRET

Check warning on line 31 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GITHUB_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG GITHUB_REDIRECT_URI
ARG GITHUB_WEBHOOK_SECRET_KEY

Check warning on line 33 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "GITHUB_WEBHOOK_SECRET_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG GRAVATAR_EMAIL
ARG IGDB_CLIENT_ID
ARG IGDB_CLIENT_SECRET

Check warning on line 36 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "IGDB_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG PRAW_CLIENT_ID
ARG PRAW_CLIENT_SECRET

Check warning on line 38 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ARG "PRAW_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ARG PRAW_SUBREDDIT
ARG DISCORD_WEBHOOK
ARG GRAVATAR_EMAIL
ARG REDIRECT_URI

# Environment variables
ENV DAILY_TASKS=$DAILY_TASKS
ENV DAILY_RELEASES=$DAILY_RELEASES
ENV DAILY_CHANNEL_ID=$DAILY_CHANNEL_ID
ENV DAILY_TASKS_UTC_HOUR=$DAILY_TASKS_UTC_HOUR
ENV DISCORD_BOT_TOKEN=$DISCORD_BOT_TOKEN

Check warning on line 46 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "DISCORD_BOT_TOKEN") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV DISCORD_CLIENT_ID=$DISCORD_CLIENT_ID
ENV DISCORD_CLIENT_SECRET=$DISCORD_CLIENT_SECRET
ENV DISCORD_GITHUB_STATUS_CHANNEL_ID=$DISCORD_GITHUB_STATUS_CHANNEL_ID
ENV DISCORD_REDDIT_CHANNEL_ID=$DISCORD_REDDIT_CHANNEL_ID
ENV DISCORD_REDIRECT_URI=$DISCORD_REDIRECT_URI
ENV DISCORD_SPONSORS_CHANNEL_ID=$DISCORD_SPONSORS_CHANNEL_ID
ENV GITHUB_CLIENT_ID=$GITHUB_CLIENT_ID
ENV GITHUB_CLIENT_SECRET=$GITHUB_CLIENT_SECRET
ENV GITHUB_REDIRECT_URI=$GITHUB_REDIRECT_URI
ENV GITHUB_WEBHOOK_SECRET_KEY=$GITHUB_WEBHOOK_SECRET_KEY

Check warning on line 56 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "GITHUB_WEBHOOK_SECRET_KEY") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV GRAVATAR_EMAIL=$GRAVATAR_EMAIL
ENV IGDB_CLIENT_ID=$IGDB_CLIENT_ID
ENV IGDB_CLIENT_SECRET=$IGDB_CLIENT_SECRET

Check warning on line 59 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "IGDB_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV PRAW_CLIENT_ID=$PRAW_CLIENT_ID
ENV PRAW_CLIENT_SECRET=$PRAW_CLIENT_SECRET

Check warning on line 61 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Sensitive data should not be used in the ARG or ENV commands

SecretsUsedInArgOrEnv: Do not use ARG or ENV instructions for sensitive data (ENV "PRAW_CLIENT_SECRET") More info: https://docs.docker.com/go/dockerfile/rule/secrets-used-in-arg-or-env/
ENV PRAW_SUBREDDIT=$PRAW_SUBREDDIT
ENV DISCORD_WEBHOOK=$DISCORD_WEBHOOK

Check warning on line 63 in Dockerfile

View workflow job for this annotation

GitHub Actions / Docker

Variables should be defined before their use

UndefinedVar: Usage of undefined variable '$DISCORD_WEBHOOK' More info: https://docs.docker.com/go/dockerfile/rule/undefined-var/
ENV GRAVATAR_EMAIL=$GRAVATAR_EMAIL
ENV REDIRECT_URI=$REDIRECT_URI

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# install dependencies
Expand All @@ -69,7 +84,7 @@ RUN <<_SETUP
set -e

# replace the version in the code
sed -i "s/version = '0.0.0'/version = '${BUILD_VERSION}'/g" src/common.py
sed -i "s/version = '0.0.0'/version = '${BUILD_VERSION}'/g" src/common/common.py

# install dependencies
python -m pip install --no-cache-dir -r requirements.txt
Expand Down
83 changes: 45 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
[![GitHub Workflow Status (CI)](https://img.shields.io/github/actions/workflow/status/lizardbyte/support-bot/ci.yml.svg?branch=master&label=CI%20build&logo=github&style=for-the-badge)](https://github.com/LizardByte/support-bot/actions/workflows/ci.yml?query=branch%3Amaster)
[![Codecov](https://img.shields.io/codecov/c/gh/LizardByte/support-bot.svg?token=900Q93P1DE&style=for-the-badge&logo=codecov&label=codecov)](https://app.codecov.io/gh/LizardByte/support-bot)

Support bot written in python to help manage LizardByte communities. The current focus is discord and reddit, but other
platforms such as GitHub discussions/issues could be added.
Support bot written in python to help manage LizardByte communities. The current focus is Discord and Reddit, but other
platforms such as GitHub discussions/issues might be added in the future.


## Overview
Expand All @@ -24,45 +24,52 @@ platforms such as GitHub discussions/issues could be added.
* Presence Intent
* Server Members Intent
* Copy the `Token`
* Add the following as environment variables or in a `.env` file (use `sample.env` as an example).
:exclamation: if using Docker these can be arguments.
:warning: Never publicly expose your tokens, secrets, or ids.

| variable | required | default | description |
|-------------------------|----------|------------------------------------------------------|---------------------------------------------------------------|
| DISCORD_BOT_TOKEN | True | `None` | Token from Bot page on discord developer portal. |
| DAILY_TASKS | False | `true` | Daily tasks on or off. |
| DAILY_RELEASES | False | `true` | Send a message for each game released on this day in history. |
| DAILY_CHANNEL_ID | False | `None` | Required if daily_tasks is enabled. |
| DAILY_TASKS_UTC_HOUR | False | `12` | The hour to run daily tasks. |
| GRAVATAR_EMAIL | False | `None` | Gravatar email address for bot avatar. |
| IGDB_CLIENT_ID | False | `None` | Required if daily_releases is enabled. |
| IGDB_CLIENT_SECRET | False | `None` | Required if daily_releases is enabled. |
| SUPPORT_COMMANDS_REPO | False | `https://github.com/LizardByte/support-bot-commands` | Repository for support commands. |
| SUPPORT_COMMANDS_BRANCH | False | `master` | Branch for support commands. |

* Running bot:
* `python -m src`
* Invite bot to server:
* `https://discord.com/api/oauth2/authorize?client_id=<the client id of the bot>&permissions=8&scope=bot%20applications.commands`


### Reddit

* Set up an application at [reddit apps](https://www.reddit.com/prefs/apps/).
* The redirect uri should be https://localhost:8080
* Take note of the `client_id` and `client_secret`
* Enter the following as environment variables

| Parameter | Required | Default | Description |
|--------------------|----------|---------|-------------------------------------------------------------------------|
| PRAW_CLIENT_ID | True | None | `client_id` from reddit app setup page. |
| PRAW_CLIENT_SECRET | True | None | `client_secret` from reddit app setup page. |
| PRAW_SUBREDDIT | True | None | Subreddit to monitor (reddit user should be moderator of the subreddit) |
| DISCORD_WEBHOOK | False | None | URL of webhook to send discord notifications to |
| GRAVATAR_EMAIL | False | None | Gravatar email address to get avatar from |
| REDDIT_USERNAME | True | None | Reddit username |
* | REDDIT_PASSWORD | True | None | Reddit password |

* Running bot:
* `python -m src`

### Environment Variables

* Add the following as environment variables or in a `.env` file (use `sample.env` as an example).
:exclamation: if using Docker these can be arguments.
:warning: Never publicly expose your tokens, secrets, or ids.

| variable | required | default | description |
|----------------------------------|----------|------------------------------------------------------|-------------------------------------------------------------------------|
| DAILY_TASKS | False | `true` | Daily tasks on or off. |
| DAILY_RELEASES | False | `true` | Send a message for each game released on this day in history. |
| DAILY_CHANNEL_ID | False | `None` | Required if daily_tasks is enabled. |
| DAILY_TASKS_UTC_HOUR | False | `12` | The hour to run daily tasks. |
| DISCORD_BOT_TOKEN | True | `None` | Token from Bot page on discord developer portal. |
| DISCORD_CLIENT_ID | True | `None` | Discord OAuth2 client id. |
| DISCORD_CLIENT_SECRET | True | `None` | Discord OAuth2 client secret. |
| DISCORD_GITHUB_STATUS_CHANNEL_ID | True | `None` | Channel ID to send GitHub status updates to. |
| DISCORD_REDDIT_CHANNEL_ID | True | `None` | Channel ID to send Reddit post updates to. |
| DISCORD_REDIRECT_URI | False | `https://localhost:8080/discord/callback` | The redirect uri for OAuth2. Must be publicly accessible. |
| DISCORD_SPONSORS_CHANNEL_ID | True | `None` | Channel ID to send sponsorship updates to. |
| GITHUB_CLIENT_ID | True | `None` | GitHub OAuth2 client id. |
| GITHUB_CLIENT_SECRET | True | `None` | GitHub OAuth2 client secret. |
| GITHUB_REDIRECT_URI | False | `https://localhost:8080/github/callback` | The redirect uri for OAuth2. Must be publicly accessible. |
| GITHUB_WEBHOOK_SECRET_KEY | True | `None` | A secret value to ensure webhooks are from trusted sources. |
| GRAVATAR_EMAIL | False | `None` | Gravatar email address for bot avatar. |
| IGDB_CLIENT_ID | False | `None` | Required if daily_releases is enabled. |
| IGDB_CLIENT_SECRET | False | `None` | Required if daily_releases is enabled. |
| PRAW_CLIENT_ID | True | None | `client_id` from reddit app setup page. |
| PRAW_CLIENT_SECRET | True | None | `client_secret` from reddit app setup page. |
| PRAW_SUBREDDIT | True | None | Subreddit to monitor (reddit user should be moderator of the subreddit) |
| REDDIT_USERNAME | True | None | Reddit username |
| REDDIT_PASSWORD | True | None | Reddit password |
| SUPPORT_COMMANDS_REPO | False | `https://github.com/LizardByte/support-bot-commands` | Repository for support commands. |
| SUPPORT_COMMANDS_BRANCH | False | `master` | Branch for support commands. |

### Start

```bash
python -m src
```

* Invite bot to server:
* `https://discord.com/api/oauth2/authorize?client_id=<the client id of the bot>&permissions=8&scope=bot%20applications.commands`
Binary file added assets/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ betamax-serializers==0.2.1
pytest==8.3.4
pytest-asyncio==0.24.0
pytest-cov==6.0.0
pytest-mock==3.14.0
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cryptography==43.0.3
Flask==3.1.0
GitPython==3.1.43
igdb-api-v4==0.3.3
Expand All @@ -7,3 +8,4 @@ praw==7.8.1
py-cord==2.6.1
python-dotenv==1.0.1
requests==2.32.3
requests-oauthlib==2.0.0
17 changes: 13 additions & 4 deletions sample.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,27 @@ DAILY_TASKS=true
DAILY_RELEASES=true
DAILY_CHANNEL_ID=
DAILY_TASKS_UTC_HOUR=12
SUPPORT_COMMANDS_BRANCH=master

# Secret settings
DISCORD_BOT_TOKEN=
GRAVATAR_EMAIL=

# discord/github oauth2
DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
DISCORD_REDIRECT_URI=
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GITHUB_REDIRECT_URI=

# igdb
IGDB_CLIENT_ID=
IGDB_CLIENT_SECRET=
READTHEDOCS_TOKEN=

# reddit bot
PRAW_CLIENT_ID=
PRAW_CLIENT_SECRET=
PRAW_SUBREDDIT=AskReddit
DISCORD_WEBHOOK=
GRAVATAR_EMAIL=
REDIRECT_URI=
REDDIT_USERNAME=
REDDIT_PASSWORD=
33 changes: 13 additions & 20 deletions src/__main__.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,33 @@
# standard imports
import os
import time

# development imports
from dotenv import load_dotenv
load_dotenv(override=False) # environment secrets take priority over .env file

# local imports
if True: # hack for flake8
from src.discord import bot as d_bot
from src import keep_alive
from src.reddit import bot as r_bot
# local imports, import after env loaded
from src.common import globals # noqa: E402
from src.discord import bot as d_bot # noqa: E402
from src.common import webapp # noqa: E402
from src.reddit import bot as r_bot # noqa: E402


def main():
# to run in replit
try:
os.environ['REPL_SLUG']
except KeyError:
pass # not running in replit
else:
keep_alive.keep_alive() # Start the web server
webapp.start() # Start the web server

discord_bot = d_bot.Bot()
discord_bot.start_threaded() # Start the discord bot
globals.DISCORD_BOT = d_bot.Bot()
globals.DISCORD_BOT.start_threaded() # Start the discord bot

reddit_bot = r_bot.Bot()
reddit_bot.start_threaded() # Start the reddit bot
globals.REDDIT_BOT = r_bot.Bot()
globals.REDDIT_BOT.start_threaded() # Start the reddit bot

try:
while discord_bot.bot_thread.is_alive() or reddit_bot.bot_thread.is_alive():
while globals.DISCORD_BOT.bot_thread.is_alive() or globals.REDDIT_BOT.bot_thread.is_alive():
time.sleep(0.5)
except KeyboardInterrupt:
print("Keyboard Interrupt Detected")
discord_bot.stop()
reddit_bot.stop()
globals.DISCORD_BOT.stop()
globals.REDDIT_BOT.stop()


if __name__ == '__main__': # pragma: no cover
Expand Down
Empty file added src/common/__init__.py
Empty file.
21 changes: 17 additions & 4 deletions src/common.py → src/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
import requests


colors = {
'black': 0x000000,
'green': 0x00ff00,
'orange': 0xffa500,
'purple': 0x9147ff,
'red': 0xff0000,
'white': 0xffffff,
'yellow': 0xffff00,
}


def get_bot_avatar(gravatar: str) -> str:
"""
Get Gravatar image url.
Expand Down Expand Up @@ -36,21 +47,23 @@ def get_avatar_bytes():
return avatar_img


def get_data_dir():
def get_app_dirs():
# parent directory name of this file, not full path
parent_dir = os.path.dirname(os.path.abspath(__file__)).split(os.sep)[-2]
parent_dir = os.path.dirname(os.path.abspath(__file__)).split(os.sep)[-3]
if parent_dir == 'app': # running in Docker container
a = '/app'
d = '/data'
else: # running locally
a = os.getcwd()
d = os.path.join(os.getcwd(), 'data')
os.makedirs(d, exist_ok=True)
return d
return a, d


# constants
avatar = get_bot_avatar(gravatar=os.environ['GRAVATAR_EMAIL'])
org_name = 'LizardByte'
bot_name = f'{org_name}-Bot'
bot_url = 'https://app.lizardbyte.dev'
data_dir = get_data_dir()
app_dir, data_dir = get_app_dirs()
version = '0.0.0'
Loading

0 comments on commit 630e2c5

Please sign in to comment.