Update venv
This commit is contained in:
parent
9c14774edc
commit
995eacbb30
11
README.md
11
README.md
@ -3,15 +3,16 @@ Memerr
|
|||||||
|
|
||||||
A discord bot to manage you and your friend's meme collection
|
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
|
Features
|
||||||
----
|
----
|
||||||
|
|
||||||
- [ ] Run in a docker container
|
- [X] Run in a docker container
|
||||||
- [ ] Query for memes by name
|
- [X] Query for memes by name
|
||||||
- [ ] Fuzzy search for memes
|
- [X] Fuzzy search for memes
|
||||||
- [ ] Get a random meme
|
- [X] Get a random meme
|
||||||
- [ ] Get a set of memes
|
- [X] Get a set of memes
|
||||||
- [ ] Upload memes to bucket
|
- [ ] Upload memes to bucket
|
||||||
- [ ] Check status of Plex instance
|
- [ ] Check status of Plex instance
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ ! -d "./venv" ]; then
|
||||||
mkdir ./venv 2> /dev/null
|
mkdir ./venv 2> /dev/null
|
||||||
|
|
||||||
python -m venv ./venv
|
python -m venv ./venv
|
||||||
|
fi
|
||||||
|
|
||||||
cp ./src/* ./venv/
|
cp ./src/* ./venv/
|
||||||
cp ./src/.env ./venv/.env 2> /dev/null
|
cp ./src/.env ./venv/.env 2> /dev/null
|
||||||
|
|
||||||
cd ./venv
|
cd ./venv
|
||||||
|
pip install -r requirements.txt --user
|
||||||
touch .env
|
touch .env
|
||||||
|
echo "evn $(cat .env | xargs) python ./main.py" >> run.sh
|
||||||
|
chmod +x run.sh
|
||||||
|
|
||||||
env $(cat .env | xargs) python ./main.py
|
env $(cat .env | xargs) python ./main.py
|
||||||
|
@ -24,6 +24,8 @@ client = discord.Client()
|
|||||||
async def on_message(message):
|
async def on_message(message):
|
||||||
if message.author == client.user:
|
if message.author == client.user:
|
||||||
return
|
return
|
||||||
|
if len(message.content) == 0: # if its empty, like an uploaded image, ignore it
|
||||||
|
return
|
||||||
return await parse_message(client, message)
|
return await parse_message(client, message)
|
||||||
|
|
||||||
# messege delete handler
|
# messege delete handler
|
||||||
|
126
src/memes.py
126
src/memes.py
@ -7,8 +7,22 @@ from minio.error import S3Error
|
|||||||
from catbox import Uploader
|
from catbox import Uploader
|
||||||
|
|
||||||
# memes we have most recently gotten
|
# memes we have most recently gotten
|
||||||
last_memes = []
|
class RecentMemeQueue:
|
||||||
last_memes_max = 20
|
#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
|
# list of all current memes' names
|
||||||
all_memes = []
|
all_memes = []
|
||||||
@ -72,14 +86,16 @@ def getCurrentMemeList():
|
|||||||
global all_memes
|
global all_memes
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
# if no update in the past 5 mins
|
# 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
|
last_checked_all_memes = now
|
||||||
all_memes.clear()
|
all_memes.clear()
|
||||||
myClient = getClient()
|
myClient = getClient()
|
||||||
for obj in myClient.list_objects(S3_BUCKET):
|
for obj in myClient.list_objects(S3_BUCKET):
|
||||||
if not obj.is_dir:
|
if not obj.is_dir:
|
||||||
print(f'{obj.object_name}')
|
#print(f'{obj.object_name}')
|
||||||
all_memes.append(obj.object_name)
|
all_memes.append(obj.object_name)
|
||||||
|
print(f"Got {len(all_memes)} memes")
|
||||||
return all_memes
|
return all_memes
|
||||||
|
|
||||||
# given a file, we will return:
|
# given a file, we will return:
|
||||||
@ -87,7 +103,6 @@ def getCurrentMemeList():
|
|||||||
# A catbox.moe link if its larger than 8mb
|
# A catbox.moe link if its larger than 8mb
|
||||||
def getDiscordReadyObjectFromS3(file_name):
|
def getDiscordReadyObjectFromS3(file_name):
|
||||||
size = 0
|
size = 0
|
||||||
out_file_path = "/tmp/" + file_name
|
|
||||||
#get the file
|
#get the file
|
||||||
client = getClient()
|
client = getClient()
|
||||||
stream = ""
|
stream = ""
|
||||||
@ -101,12 +116,58 @@ def getDiscordReadyObjectFromS3(file_name):
|
|||||||
|
|
||||||
# check the object size
|
# check the object size
|
||||||
if size >= 8000000: # to big, use catbox
|
if size >= 8000000: # to big, use catbox
|
||||||
|
print(f"{file_name} was to big, uploading to catbox...")
|
||||||
catbox_uploader = Uploader(token='')
|
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"]
|
return url["file"]
|
||||||
else: #small enough, use discord
|
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)
|
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
|
# get the name of the user who uploaded the file
|
||||||
# their tag is always under the 'uploader' tag
|
# their tag is always under the 'uploader' tag
|
||||||
def getMemeUploader(file_name):
|
def getMemeUploader(file_name):
|
||||||
@ -118,6 +179,17 @@ def getMemeUploader(file_name):
|
|||||||
return uploader
|
return uploader
|
||||||
return "Unkown"
|
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
|
# Calldict methods
|
||||||
|
|
||||||
@ -133,24 +205,56 @@ async def parseMeme(command, message, client):
|
|||||||
if len(command) > 1: # if there is a query
|
if len(command) > 1: # if there is a query
|
||||||
query_string = ' '.join(command[1:]) #get QUERY_STRING
|
query_string = ' '.join(command[1:]) #get QUERY_STRING
|
||||||
|
|
||||||
all_memes = getCurrentMemeList()
|
|
||||||
#first, check if the exact meme exists
|
#first, check if the exact meme exists
|
||||||
|
all_memes = getCurrentMemeList()
|
||||||
if query_string in all_memes: # found the exact meme, return it
|
if query_string in all_memes: # found the exact meme, return it
|
||||||
return getDiscordReadyObjectFromS3(query_string)
|
return getDiscordReadyObjectFromS3(query_string)
|
||||||
|
|
||||||
#if we get here then we didnt find the meme, lets find the closest meme
|
#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
|
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
|
# get all ememes that are similar to the given query
|
||||||
async def allMemes(command, message, client):
|
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
|
# get total number of memes stored
|
||||||
async def memeCount(command, message, client):
|
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
|
# get a set of random memes
|
||||||
async def memeDump(command, message, client):
|
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 :)"
|
||||||
|
@ -4,6 +4,21 @@ import os, random, sys
|
|||||||
from memes import parseMeme, memeCount, memeDump, allMemes
|
from memes import parseMeme, memeCount, memeDump, allMemes
|
||||||
import discord
|
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
|
# dictionary associating
|
||||||
# a command to a function name
|
# a command to a function name
|
||||||
calldict = {
|
calldict = {
|
||||||
@ -12,10 +27,12 @@ calldict = {
|
|||||||
"!memecount" : memeCount,
|
"!memecount" : memeCount,
|
||||||
"!memedump" : memeDump,
|
"!memedump" : memeDump,
|
||||||
"!allmemes" : allMemes,
|
"!allmemes" : allMemes,
|
||||||
|
"!help" : showHelp,
|
||||||
# plex
|
# plex
|
||||||
#"!plexleaderboard" : getTopUsers,
|
#"!plexleaderboard" : getTopUsers,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# parse the message
|
# parse the message
|
||||||
async def parse_message(client, message):
|
async def parse_message(client, message):
|
||||||
command = message.content.split()
|
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})')
|
print(f'{client.user} was passed a command I know! ({message.content})')
|
||||||
result = await calldict[command[0]](command, message, client)
|
result = await calldict[command[0]](command, message, client)
|
||||||
if isinstance(result, discord.File):
|
if isinstance(result, discord.File):
|
||||||
|
print(f'{client.user} is replying with a file ({result.filename})')
|
||||||
return await message.channel.send(file=result)
|
return await message.channel.send(file=result)
|
||||||
else:
|
else:
|
||||||
|
print(f'{client.user} is replying with the string ({result})')
|
||||||
return await message.channel.send(result)
|
return await message.channel.send(result)
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
Loading…
Reference in New Issue
Block a user