From c5414610ea900ccd1acfb0627159ac71333454c5 Mon Sep 17 00:00:00 2001 From: Tyler Perkins Date: Fri, 24 Feb 2023 17:38:01 -0500 Subject: [PATCH] Add uploading functionality --- src/api/get.py | 68 ++++++++++++++++++++++++++++++++++++++++++++++- src/api/search.py | 3 +++ src/s3Client.py | 25 +++++++++++++++-- 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/api/get.py b/src/api/get.py index 2a5f994..412b8b1 100644 --- a/src/api/get.py +++ b/src/api/get.py @@ -1,6 +1,8 @@ from flask_restx import Namespace, Resource, fields from flask_restx import reqparse -from flask import make_response, abort +from flask import make_response, abort, request +from minio.commonconfig import Tags +from werkzeug.datastructures import FileStorage from api.clientGetter import getClientSafely import logging import random @@ -8,7 +10,43 @@ import random # Exported namespace api = Namespace('resource', description='Interact with the raw underlying files. This namespace does NOT speak json, just raw files') +uploadFields = {'name' : fields.String(title='Name', + description='File name of your meme', + required=True, + example='Funny.mp4'), + 'uploader' : fields.String(title='Uploader', + description='Name of the user who uploaded the meme', + required=True), + 'nsfw': fields.Boolean(title='NSFW', + description='Is this NSFW/Spoilable?', + default=False), + 'file': fields.String(title='File', + description='File as Base64'), + } + +uploadForm = api.parser() +uploadForm.add_argument('file', + location='files', + type=FileStorage, + required=True) +uploadForm.add_argument('name', + location='headers', + type=str, + required=True) +uploadForm.add_argument('uploader', + location='headers', + type=str, + required=True) +uploadForm.add_argument('nsfw', + location='headers', + type=bool, + required=True) + + @api.route('/exact/') +@api.route('/', doc={ + "description" : "Alias for /exact/{query}" + }) @api.doc(description="Interact with exact raw files.") class getExactFile(Resource): @api.doc('get') @@ -24,6 +62,34 @@ class getExactFile(Resource): else: abort(400, "Requested file '" + file_name + "' not found") +@api.route('/') +class addFile(Resource): + @api.response(200, 'Sucess') + @api.response(500, 'S3 Error') + @api.response(400, 'Bad request') + @api.expect(uploadForm) + def post(self): + client = getClientSafely() + if client is None: + abort(500, "S3 failed to start") + + args = uploadForm.parse_args() + file = args['file'] + fileName = args['name'] + uploader = args['uploader'] + nsfw = args['nsfw'] + + tags = Tags.new_object_tags() + tags["uploader"] = uploader + tags["nsfw"] = str(nsfw) + + if client.addMeme(fileContents=file, + name=fileName, + tags=tags): + return {"message" : "sucess"} + + + @api.route('/random') @api.doc(description="Returns a random meme") class getRandomFile(Resource): diff --git a/src/api/search.py b/src/api/search.py index 4d235a0..1035c0a 100644 --- a/src/api/search.py +++ b/src/api/search.py @@ -40,6 +40,9 @@ class exactSearch(Resource): 'query' : 'Search query to attempt to compare against' },description="Find a meme thats close using levenshtein distance") class textualClose(Resource): + @api.doc('fuzzy search') + @api.response(200, 'Sucess') + @api.response(500, 'S3 Error') def get(self, query): client = getClientSafely() if client is None: diff --git a/src/s3Client.py b/src/s3Client.py index ff13790..a80504a 100644 --- a/src/s3Client.py +++ b/src/s3Client.py @@ -1,13 +1,14 @@ import logging import os - - +from minio.commonconfig import Tags from minio import Minio from minio.commonconfig import Tags from minio.error import S3Error from datetime import datetime +from functools import lru_cache + S3_URL = "" S3_UN = "" @@ -108,6 +109,7 @@ class Client: return self.allMemes + @lru_cache(maxsize=32) def getMeme(self, memeName: str): """ Return a meme with the exact given name, or raise an exception @@ -125,6 +127,25 @@ class Client: raise Exception("Requested meme '" + memeName + "' not found") return None + def addMeme(self, fileContents, name: str, tags: Tags = Tags.new_object_tags()): + result = self.client.put_object(bucket_name=S3_BUCKET, + object_name=name, + data=fileContents, + length=-1, + tags=tags, + part_size=10*1024*1024) + if result.etag in self.memesToMd5: + logger.info('Uploaded meme named ' + name + ' already exists') + client.remove_object(bucket_name=S3_BUCKET, + object_name=name) + return False + else: + self.allMemes.add(name) + self.memesToMd5[name] = result.etag + self.memesToTags[name] = tags + return True + + @lru_cache(maxsize=32) def getTagsOnMeme(self, memeName: str): """ Returns the S3 Tags object for a given meme