Update file strcuture

This commit is contained in:
Tyler Perkins 2022-10-28 14:21:47 -04:00
parent 90be4795d9
commit 9c14774edc
9 changed files with 287 additions and 4 deletions

6
.gitignore vendored
View File

@ -1,7 +1,5 @@
*.swp *.swp
src/lib
!src/lib/.gitkeep
src/.env src/.env
src/bin venv
!src/bin/active*

13
make_venv.sh Executable file
View File

@ -0,0 +1,13 @@
#!/bin/bash
mkdir ./venv 2> /dev/null
python -m venv ./venv
cp ./src/* ./venv/
cp ./src/.env ./venv/.env 2> /dev/null
cd ./venv
touch .env
env $(cat .env | xargs) python ./main.py

8
src/.env Normal file
View File

@ -0,0 +1,8 @@
DISCORD_TOKEN=
S3_URL=
S3_UN=
S3_PW=
S3_TLS=False
S3_BUCKET=memes
TAUTULLI_URL=
TAUTULLI_APIKEY=

46
src/main.py Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/python3
import discord
import requests
import os, random, sys
from fuzzywuzzy import fuzz, process
from minio import Minio
from minio.error import S3Error
from on_message_delete import message_delete
from on_message import parse_message
#globals for discord
if 'DISCORD_TOKEN' not in os.environ:
raise Exception("DISCORD_TOKEN was not set!")
token = os.environ['DISCORD_TOKEN']
client = discord.Client()
###############################################################################
# Discord client code
# primary message handler
@client.event
async def on_message(message):
if message.author == client.user:
return
return await parse_message(client, message)
# messege delete handler
@client.event
async def on_message_delete(message):
if message.author == client.user:
return
return await message_delete(client, message)
@client.event
async def on_ready():
print(f'{client.user} has connected to Discord!')
def main() -> int:
print('Connecting client to discord...')
client.run(token)
dclient = client
if __name__ == '__main__':
sys.exit(main())

156
src/memes.py Normal file
View File

@ -0,0 +1,156 @@
import discord
import os, random, io
from datetime import datetime
from fuzzywuzzy import fuzz, process
from minio import Minio
from minio.error import S3Error
from catbox import Uploader
# memes we have most recently gotten
last_memes = []
last_memes_max = 20
# list of all current memes' names
all_memes = []
last_checked_all_memes = datetime.strptime("2000-01-01 01:01:01", "%Y-%m-%d %H:%M:%S")
S3_URL = ""
S3_UN = ""
S3_PW = ""
S3_TLS = True
S3_BUCKET = ""
client = ""
#returns the S3 client
def getClient():
global client
global S3_URL
global S3_UN
global S3_PW
global S3_TLS
global S3_BUCKET
if client != "":
return client
if "S3_URL" not in os.environ:
raise Exception("S3_URL is not set!")
S3_URL = os.environ["S3_URL"]
if "S3_UN" not in os.environ:
raise Exception("S3_UN is not set!")
S3_UN = os.environ["S3_UN"]
if "S3_PW" not in os.environ:
raise Exception("S3_PW is not set!")
S3_PW = os.environ["S3_PW"]
if "S3_BUCKET" not in os.environ:
raise Exception("S3_BUCKET is not set!")
S3_BUCKET = os.environ["S3_BUCKET"]
# override defaults
if "S3_TLS" in os.environ:
S3_TLS = os.environ["S3_TLS"].lower() in ("yes", "true", "1", "t")
if client == "":
client = Minio(S3_URL,
access_key=S3_UN,
secret_key=S3_PW,
secure=S3_TLS)
found = client.bucket_exists(S3_BUCKET)
if not found:
client.make_bucket(S3_BUCKET)
else:
print(f"Found bucket {S3_BUCKET}")
return client
###############################################################################
# Helper methods
# Methods to break up the calldict methods
def getCurrentMemeList():
global last_checked_all_memes
global all_memes
now = datetime.now()
# if no update in the past 5 mins
if (last_checked_all_memes - now).seconds / 60 > 5:
last_checked_all_memes = now
all_memes.clear()
myClient = getClient()
for obj in myClient.list_objects(S3_BUCKET):
if not obj.is_dir:
print(f'{obj.object_name}')
all_memes.append(obj.object_name)
return all_memes
# given a file, we will return:
# A discord.File if its smaller than 8MB
# A catbox.moe link if its larger than 8mb
def getDiscordReadyObjectFromS3(file_name):
size = 0
out_file_path = "/tmp/" + file_name
#get the file
client = getClient()
stream = ""
try:
obj = client.get_object(bucket_name=S3_BUCKET,
object_name=file_name)
stream = obj.read()
size = len(stream)
except:
return "No such file " + file_name + " !"
# check the object size
if size >= 8000000: # to big, use catbox
catbox_uploader = Uploader(token='')
url = catbox_uploader.upload(file_raw=stream)
return url["file"]
else: #small enough, use discord
return discord.File(fp=io.BytesIO(stream), filename=file_name)
# get the name of the user who uploaded the file
# their tag is always under the 'uploader' tag
def getMemeUploader(file_name):
client = getClient()
tags = client.get_object_tags(S3_BUCKET, file_name)
if tags != None:
uploader = tags.get("uploader")
if uploader != None:
return uploader
return "Unkown"
###############################################################################
# Calldict methods
# parse for a meme that is simliar to a given query
# There are two possibilities for parseMeme, as there is a somewhat
# complex syntax
# !meme [QUERY_STRING]
# With QUERY_STRING being optional
# due to this, we need to cover both cases
# NOTE QUERY_STRING can also be an exact filename, in which case we should
# return that instead
async def parseMeme(command, message, client):
if len(command) > 1: # if there is a query
query_string = ' '.join(command[1:]) #get QUERY_STRING
all_memes = getCurrentMemeList()
#first, check if the exact meme exists
if query_string in all_memes: # found the exact meme, return it
return getDiscordReadyObjectFromS3(query_string)
#if we get here then we didnt find the meme, lets find the closest meme
else: #there is no query, get a random meme
pass
# get all ememes that are similar to the given query
async def allMemes(command, message, client):
pass
# get total number of memes stored
async def memeCount(command, message, client):
pass
# get a set of random memes
async def memeDump(command, message, client):
pass

32
src/on_message.py Normal file
View File

@ -0,0 +1,32 @@
#!/usr/bin/python3
import requests
import os, random, sys
from memes import parseMeme, memeCount, memeDump, allMemes
import discord
# dictionary associating
# a command to a function name
calldict = {
# S3 memes
"!meme" : parseMeme,
"!memecount" : memeCount,
"!memedump" : memeDump,
"!allmemes" : allMemes,
# plex
#"!plexleaderboard" : getTopUsers,
}
# parse the message
async def parse_message(client, message):
command = message.content.split()
# if i know this command
if command[0] in calldict.keys():
print(f'{client.user} was passed a command I know! ({message.content})')
result = await calldict[command[0]](command, message, client)
if isinstance(result, discord.File):
return await message.channel.send(file=result)
else:
return await message.channel.send(result)
pass

8
src/on_message_delete.py Normal file
View File

@ -0,0 +1,8 @@
#!/usr/bin/python3
async def message_delete(client, message):
response = "Cringe!"
await message.channel.send(response)
print(f'{client.user} replied to someone who deleted my message with {response}')

0
src/plex.py Normal file
View File

22
src/requirements.txt Normal file
View File

@ -0,0 +1,22 @@
aiohttp==3.7.4.post0
aiosignal==1.2.0
async-timeout==3.0.1
attrs==22.1.0
certifi==2022.9.24
chardet==4.0.0
charset-normalizer==2.1.1
discord==1.7.3
discord.py==1.7.3
frozenlist==1.3.1
fuzzywuzzy==0.18.0
idna==3.4
Levenshtein==0.20.7
minio==7.1.12
multidict==6.0.2
pycatbox==1.0.3
python-Levenshtein==0.20.7
rapidfuzz==2.12.0
requests==2.28.1
typing_extensions==4.4.0
urllib3==1.26.12
yarl==1.8.1