-
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.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: dublUayaychtee <[email protected]> Co-authored-by: dublUayaychtee <[email protected]> Co-authored-by: kredcool <[email protected]>
- Loading branch information
1 parent
5841305
commit 178e959
Showing
79 changed files
with
4,345 additions
and
95 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
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,75 +1,42 @@ | ||
.PHONY: help clean clean-pyc clean-build list test coverage release | ||
|
||
# Help | ||
help: | ||
@echo " clean-build - Remove build artifacts" | ||
@echo " clean-pyc - Remove Python file artifacts" | ||
@echo " lint - Check style with flake8" | ||
@echo " test - Run tests quickly with the default Python" | ||
@echo " install-requirements - install the requirements for development" | ||
@echo " build Builds the docker images for the docker-compose setup" | ||
@echo " docker-rm Stops and removes all docker containers" | ||
@echo " run Run a command. Can run scripts, e.g. make run COMMAND=\"./scripts/schema_generator.sh\"" | ||
@echo " shell Opens a Bash shell" | ||
@echo " prod Is meant for running on the production env" | ||
|
||
# Clean everything | ||
clean: clean-build clean-pyc docker-rm | ||
|
||
# Clean build data | ||
clean-build: | ||
rm -fr build/ | ||
rm -fr dist/ | ||
rm -fr *.egg-info | ||
|
||
# Clean python cache | ||
clean-pyc: | ||
find . -name '*.pyc' -exec rm -f {} + | ||
find . -name '*.pyo' -exec rm -f {} + | ||
find . -name '*~' -exec rm -f {} + | ||
|
||
# Delint the code | ||
lint: | ||
flake8 . | ||
|
||
# Run the tests | ||
test: build | ||
docker-compose run admin_bot test | ||
|
||
# Install requirements (locally) | ||
install-requirements: | ||
pip install -r requirements/requirements.txt | ||
pip install -r requirements/test_requirements.txt | ||
|
||
# Build container locally | ||
build: | ||
# Shortcut makefile list | ||
|
||
help: ## Show this help. | ||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' | ||
|
||
|
||
test: build ## Currently broken, requires build | ||
docker compose run admin_bot test | ||
|
||
|
||
configure-pipenv: ## sets up pipenv for you | ||
pipenv install -r admin_bot/requirements/requirements.txt | ||
pipenv install -r admin_interface/requirements/requirements.txt | ||
pipenv shell | ||
|
||
|
||
build: ## Build containers locally | ||
# Generate tag | ||
echo TAG=$(shell git rev-parse --abbrev-ref HEAD | sed 's/[^a-zA-Z0-9]/-/g') > .env | ||
|
||
# Build | ||
docker-compose build --build-arg GIT_COMMIT=$(shell git describe --abbrev=8 --always --tags --dirty) --build-arg DEBUG=True | ||
docker compose build --build-arg GIT_COMMIT=$(shell git describe --abbrev=8 --always --tags --dirty) --build-arg DEBUG=True | ||
|
||
|
||
docker-rm: stop ## Delete containers, requires stop | ||
docker compose rm -f | ||
|
||
# Delete container | ||
docker-rm: stop | ||
docker-compose rm -f | ||
|
||
# Get container shell | ||
shell: | ||
docker-compose run --entrypoint "/bin/bash" admin_bot | ||
shell: ## Get container shell | ||
docker compose run --entrypoint "/bin/bash" admin_bot | ||
|
||
# Run command in container | ||
run: build | ||
docker-compose run admin_bot $(COMMAND) | ||
|
||
# Stop container | ||
stop: | ||
docker-compose down | ||
docker-compose stop | ||
run: build ## Run command in container, requires build | ||
docker compose up | ||
|
||
# "production" | ||
prod: | ||
docker-compose -f docker-compose-prod.yml up -d | ||
stop: ## Stop containers | ||
docker compose down | ||
docker compose stop | ||
|
||
# Development stuff | ||
dev: | ||
docker-compose -f docker-compose.yml build && docker-compose -f docker-compose.yml up | ||
# Specific stuff | ||
flask-local: ## Runs flask locally for you! | ||
cd admin_interface/admin_interface && flask --app main.py run |
File renamed without changes.
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,5 +1,4 @@ | ||
# See here https://hub.docker.com/r/gorialis/discord.py/ | ||
FROM gorialis/discord.py | ||
FROM python:3.11 | ||
|
||
# Authors | ||
LABEL authors="[email protected]" | ||
|
@@ -9,7 +8,7 @@ ARG APP_NAME=admin-bot | |
ENV APP_NAME=${APP_NAME} | ||
|
||
# Install special deps | ||
RUN apt update && apt install -y texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra | ||
RUN apt update && apt install -y texlive-latex-base texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra python-dev-is-python3 | ||
|
||
# Upgrade pip | ||
RUN pip install --upgrade pip | ||
|
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,10 @@ | ||
# Adminbot | ||
|
||
This is the discord bot component. | ||
|
||
To get started developing here, you'll need a `BOT_TOKEN`, you can get this by | ||
making your own discord bot here https://discord.com/developers/applications | ||
|
||
It can be a bit tricky to setup a server and a bot for testing but its worth it. | ||
Use `^sync` to manually sync any discord slash commands to your development server, | ||
and submit a pr! |
File renamed without changes.
File renamed without changes.
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,174 @@ | ||
# Tidal Force robotics | ||
# 2021, Admin Bot | ||
# MIT License | ||
|
||
|
||
import os | ||
import time | ||
import json | ||
import pytz | ||
import string | ||
import random | ||
import discord | ||
import logging | ||
import asyncio | ||
import requests | ||
import subprocess | ||
|
||
from typing import Literal, Optional | ||
from discord import app_commands | ||
from discord.ext import commands, tasks | ||
from ics import Calendar | ||
|
||
from PIL import Image, ImageDraw, ImageFilter, UnidentifiedImageError | ||
|
||
from profanity_check import predict, predict_prob | ||
|
||
from utilities.common import seconds_until | ||
|
||
|
||
# Minimal cog to provide an interface to the digital signage | ||
|
||
|
||
class InterfaceCog(commands.Cog, name="Interface"): | ||
def __init__(self, bot): | ||
self.bot = bot # Local instance of bot | ||
|
||
@app_commands.command(name="clear_promo") | ||
@commands.has_any_role("Leads", "Adult Mentor", "Student Mentor") | ||
async def clearPromo(self, ctx: discord.Interaction): | ||
""" | ||
Removes all promo materials in rotation | ||
""" | ||
msg = "Removing: " | ||
|
||
dir = "/app/promo" | ||
for f in os.listdir(dir): | ||
msg += f"{f}, " | ||
os.remove(os.path.join(dir, f)) | ||
|
||
await ctx.response.send_message(msg) | ||
|
||
@app_commands.command(name="show_promo") | ||
@commands.has_any_role("Leads", "Adult Mentor", "Student Mentor") | ||
async def showPromo(self, ctx: discord.Interaction): | ||
""" | ||
Lists all the currently shown promos | ||
""" | ||
msg = "Promo List: " | ||
|
||
dir = "/app/promo" | ||
for f in os.listdir(dir): | ||
# if its a json load it | ||
if ".json" in f: | ||
with open(dir + "/" + f) as file: | ||
rawData = json.loads(file.read()) | ||
|
||
# update expires | ||
_days = (time.time() - int(rawData["expires"])) / 86400 | ||
rawData["expires"] = f"{_days:.2f} days" | ||
|
||
msg += f"```{rawData}```" | ||
|
||
await ctx.response.send_message(msg) | ||
|
||
@app_commands.command(name="submit_promo") | ||
@commands.has_any_role("Leads", "Adult Mentor", "Student Mentor") | ||
async def submitPromo( | ||
self, ctx: discord.Interaction, img: str, days: int, caption: str = None | ||
): | ||
""" | ||
Submits a promotional image to be displayed in rotation. | ||
""" | ||
|
||
if days > 90: | ||
await ctx.response.send_message( | ||
"Sorry, thats too long for a submitted image to be in rotation. Contact <@&614313406345904148> to submit a permanent promo image." | ||
) | ||
else: | ||
# This may take a moment | ||
await ctx.response.defer() | ||
try: | ||
# Make a random string | ||
_rand = "".join( | ||
random.choices(string.ascii_lowercase + string.digits, k=7) | ||
) | ||
# Create a full filename | ||
filename = f"/app/promo/{(ctx.user.nick).replace(' ', '_')}_{_rand}" | ||
|
||
# Write metadata first | ||
imgData = { | ||
"expires": f"{int(time.time()) + (86400*days)}", | ||
"author": f"Submitted by {ctx.user.nick}", | ||
"caption": caption, | ||
} | ||
|
||
json_object = json.dumps(imgData, indent=4) | ||
with open(f"{filename}.json", "w") as outfile: | ||
outfile.write(json_object) | ||
|
||
# Download the file | ||
subprocess.run(["wget", img, "-O", f"{filename}.png"]) | ||
|
||
await ctx.followup.send( | ||
f"Done! Added `{filename}`, expires in `{days}` days! Caption was `{caption}`.", | ||
file=discord.File(f"{filename}.png"), | ||
) | ||
except Exception as e: | ||
await ctx.followup.send(f"Sorry! There was an error! {e}") | ||
|
||
@commands.Cog.listener() | ||
async def on_message(self, ctx: discord.message.Message): | ||
""" | ||
Pushes messages into the postgresql database. | ||
""" | ||
|
||
# We dont want to publish EVERY channel, just some specific ones! | ||
allowed_channels = [ | ||
634136760401526793, # announcements | ||
# 590312336414212107, # mechanical-cad | ||
# 1075174212723032064, # electrical | ||
# 590312300695650305, # software | ||
# 776835421976002570, # outreach-buisness | ||
# 1024362276951703552, # media | ||
# 1077252589697126523, # Quotes | ||
719692563405078620, # Joe's testing channel | ||
] | ||
|
||
# Check if bot or in pm | ||
if ( | ||
not isinstance(ctx.channel, discord.channel.DMChannel) | ||
and not ctx.author.bot | ||
): | ||
logging.info( | ||
f"Sending message from {ctx.channel.id}, author was {ctx.author.name}, forwarding it!" | ||
) | ||
|
||
webhookUrl = "http://interface:8000/dashboard/hook" | ||
|
||
dataToSend = { | ||
"channel": ctx.channel.name, | ||
"author": ctx.author.display_name, | ||
"author_avatar": str(ctx.author.avatar.url), | ||
"content": ctx.content, | ||
"version": self.bot.version, | ||
} | ||
|
||
if ctx.channel.id in allowed_channels: # If in allowed channel | ||
if predict([ctx.content]) == 0: # If not profanity | ||
req = requests.post( # post | ||
url=webhookUrl, | ||
data=json.dumps(dataToSend), | ||
headers={"Content-type": "application/json"}, | ||
) | ||
logging.debug(f"Sent webhook to signage, req was {req}") | ||
await ctx.add_reaction("📧") | ||
else: | ||
logging.warn(f"Profanity detected in {ctx.content}.") | ||
await ctx.add_reaction("⁉️") | ||
else: | ||
logging.debug(f"Channel {ctx.channel.id} was not in allowed channels.") | ||
|
||
|
||
async def setup(bot): | ||
await bot.add_cog(InterfaceCog(bot)) |
File renamed without changes.
Oops, something went wrong.