Update venv

This commit is contained in:
Tyler Perkins 2022-11-04 21:45:06 -04:00
parent 9c14774edc
commit 995eacbb30
5 changed files with 149 additions and 19 deletions

View File

@ -3,15 +3,16 @@ Memerr
A discord bot to manage you and your friend's meme collection
You can get this on [Docker](https://hub.docker.com/r/clortox/memerr)
Features
----
- [ ] Run in a docker container
- [ ] Query for memes by name
- [ ] Fuzzy search for memes
- [ ] Get a random meme
- [ ] Get a set of memes
- [X] Run in a docker container
- [X] Query for memes by name
- [X] Fuzzy search for memes
- [X] Get a random meme
- [X] Get a set of memes
- [ ] Upload memes to bucket
- [ ] Check status of Plex instance

View File

@ -1,13 +1,17 @@
#!/bin/bash
if [ ! -d "./venv" ]; then
mkdir ./venv 2> /dev/null
python -m venv ./venv
fi
cp ./src/* ./venv/
cp ./src/.env ./venv/.env 2> /dev/null
cd ./venv
pip install -r requirements.txt --user
touch .env
echo "evn $(cat .env | xargs) python ./main.py" >> run.sh
chmod +x run.sh
env $(cat .env | xargs) python ./main.py

View File

@ -24,6 +24,8 @@ client = discord.Client()
async def on_message(message):
if message.author == client.user:
return
if len(message.content) == 0: # if its empty, like an uploaded image, ignore it
return
return await parse_message(client, message)
# messege delete handler

View File

@ -7,8 +7,22 @@ from minio.error import S3Error
from catbox import Uploader
# memes we have most recently gotten
last_memes = []
last_memes_max = 20
class RecentMemeQueue:
#last_memes = []
#last_memes_max = 20
def __init__(self):
self.last_memes = []
self.last_memes_max = 20
def insertMeme(self, meme):
self.last_memes.insert(0, meme)
if len(self.last_memes) > self.last_memes_max:
self.last_memes.pop()
def inQueue(self, meme) -> bool:
return meme in self.last_memes
def getList(self):
return self.last_memes
recentMemes = RecentMemeQueue()
# list of all current memes' names
all_memes = []
@ -72,14 +86,16 @@ def getCurrentMemeList():
global all_memes
now = datetime.now()
# if no update in the past 5 mins
if (last_checked_all_memes - now).seconds / 60 > 5:
if (now - last_checked_all_memes).seconds > 300:
print("Enough time has elapsed, refreshing meme cache...")
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}')
#print(f'{obj.object_name}')
all_memes.append(obj.object_name)
print(f"Got {len(all_memes)} memes")
return all_memes
# given a file, we will return:
@ -87,7 +103,6 @@ def getCurrentMemeList():
# 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 = ""
@ -101,12 +116,58 @@ def getDiscordReadyObjectFromS3(file_name):
# check the object size
if size >= 8000000: # to big, use catbox
print(f"{file_name} was to big, uploading to catbox...")
catbox_uploader = Uploader(token='')
url = catbox_uploader.upload(file_raw=stream)
extension = file_name.split('.')[-1]
if len(extension) == 0:
extension = None
url = catbox_uploader.upload(file_raw=stream, file_type=extension)
return url["file"]
else: #small enough, use discord
print(f"{file_name} was small enough to send using discord")
return discord.File(fp=io.BytesIO(stream), filename=file_name)
# get a meme whos name closest matches the provided query
def getCloseMemeToQuery(query, returnAllClose = False):
global all_memes
all_memes = getCurrentMemeList()
top_meme = ''
top_memes = []
top_score = 0
for meme in all_memes:
current_score = fuzz.partial_ratio(query, meme)
if current_score > top_score:
top_meme = meme
top_score = current_score
if current_score == 100:
top_memes.append(meme)
top_meme = meme
print("Top memes we found:")
if len(top_memes) > 0:
print(top_memes)
if top_meme != '':
print(top_meme)
# if there was one or more perfect matches, get them
if top_score == 100:
top_meme = random.choice(top_memes)
if not all(elem in recentMemes.getList() for elem in top_memes):
while top_meme in recentMemes.getList():
top_meme = random.choice(top_memes)
recentMemes.insertMeme(top_meme)
if returnAllClose and len(top_memes) > 1:
print("Returning all found memes...")
for meme in top_memes:
recentMemes.insertMeme(meme)
return top_memes, 1 if len(top_memes) <= 1 else len(top_memes)
else:
print(f"Returning {top_meme}...")
recentMemes.insertMeme(top_meme)
return top_meme, 1 if len(top_memes) <= 1 else len(top_memes)
# get the name of the user who uploaded the file
# their tag is always under the 'uploader' tag
def getMemeUploader(file_name):
@ -118,6 +179,17 @@ def getMemeUploader(file_name):
return uploader
return "Unkown"
# gets a random meme
# this will ensure that the meme is not in the last_memes list
def getRandomMeme():
all_memes = getCurrentMemeList()
choice = random.choice(all_memes)
while recentMemes.inQueue(choice):
choice = random.choice(all_memes)
recentMemes.insertMeme(choice)
return choice
###############################################################################
# Calldict methods
@ -133,24 +205,56 @@ 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
all_memes = getCurrentMemeList()
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
close_meme, total_close_memes = getCloseMemeToQuery(query_string)
await message.channel.send(f"Found a close meme (from {total_close_memes} choices)")
return getDiscordReadyObjectFromS3(close_meme)
else: #there is no query, get a random meme
pass
print(f'Getting a random meme...')
meme = getRandomMeme()
print(f'Got a random meme ({meme})')
return getDiscordReadyObjectFromS3(meme)
# get all ememes that are similar to the given query
async def allMemes(command, message, client):
pass
if len(command) > 1:
query_string = ' '.join(command[1:])
close_memes, total_close_memes = getCloseMemeToQuery(query_string,
returnAllClose=True)
if total_close_memes == 0:
return "I found nothing similar to " + query_string
elif total_close_memes == 1:
return getDiscordReadyObjectFromS3(close_memes)
else:
for meme in close_memes:
ready_meme = getDiscordReadyObjectFromS3(meme)
if isinstance(ready_meme, str):
await message.channel.send(ready_meme)
else:
await message.channel.send(file=ready_meme)
return "Enjoy your memes :)"
else:
return "I need a query!"
# get total number of memes stored
async def memeCount(command, message, client):
pass
all_memes = getCurrentMemeList()
return "Currently we have " + str(len(all_memes)) + " memes"
# get a set of random memes
async def memeDump(command, message, client):
pass
await message.channel.send("Getting your memes...")
for i in range(0,5):
meme = getRandomMeme()
ready_meme = getDiscordReadyObjectFromS3(meme)
if isinstance(ready_meme, str):
await message.channel.send(ready_meme)
else:
await message.channel.send(file=ready_meme)
return "Enjoy your memes :)"

View File

@ -4,6 +4,21 @@ import os, random, sys
from memes import parseMeme, memeCount, memeDump, allMemes
import discord
async def showHelp(very, useless, arguments):
str = "```Usage:\n"
str += "!meme [QUERY]\n"
str += " Get a meme. Query for the exact name or search. Paramater is optional\n"
str += "!memecount\n"
str += " Print total number of memes in the store\n"
str += "!memedump\n"
str += " Get 5 random memes\n"
str += "!allmemes QUERY\n"
str += " Get all memes that are like the given query\n"
str += "!help\n"
str += " Print this message\n"
str += "```"
return str
# dictionary associating
# a command to a function name
calldict = {
@ -12,10 +27,12 @@ calldict = {
"!memecount" : memeCount,
"!memedump" : memeDump,
"!allmemes" : allMemes,
"!help" : showHelp,
# plex
#"!plexleaderboard" : getTopUsers,
}
# parse the message
async def parse_message(client, message):
command = message.content.split()
@ -25,8 +42,10 @@ async def parse_message(client, message):
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):
print(f'{client.user} is replying with a file ({result.filename})')
return await message.channel.send(file=result)
else:
print(f'{client.user} is replying with the string ({result})')
return await message.channel.send(result)
pass