23 Commits

Author SHA1 Message Date
b30547eca8 Merge branch 'master' into dev 2023-06-22 13:51:38 +03:00
782b489db2 Merge pull request 'Update dependency pymongo to v4.4.0' (#9) from renovate/pymongo-4.x into dev
Reviewed-on: #9
2023-06-21 22:45:10 +03:00
d085a0e639 Update dependency pymongo to v4.4.0 2023-06-21 20:58:06 +03:00
30d72c84ed Merge pull request 'Update dependency fastapi to v0.97.0' (#8) from renovate/fastapi-0.x into dev
Reviewed-on: #8
2023-06-14 11:48:37 +03:00
e1e42fdb60 Update dependency fastapi to v0.97.0 2023-06-14 11:41:39 +03:00
36169b0e77 Python min version is now 3.8
Due to a bump of ujson to 5.8.0, version of Python supported is risen to 3.8
2023-06-11 12:28:32 +03:00
5de935cd21 Merge pull request 'Update dependency ujson to ~=5.8.0' (#7) from renovate/ujson-5.x into dev
Reviewed-on: #7
2023-06-11 12:26:39 +03:00
1e6afc6b0c Update dependency ujson to ~=5.8.0 2023-06-11 12:18:53 +03:00
f9e6ee9c72 Merge pull request 'Update dependency fastapi to v0.96.1' (#6) from renovate/fastapi-0.x into dev
Reviewed-on: #6
2023-06-11 09:48:18 +03:00
f512df408f Update dependency fastapi to v0.96.1 2023-06-11 01:55:54 +03:00
aa083811dc Merge pull request 'Update dependency fastapi to v0.96.0' (#5) from renovate/fastapi-0.x into dev
Reviewed-on: #5
2023-06-03 17:58:32 +03:00
4d24696d3d Update dependency fastapi to v0.96.0 2023-06-03 17:45:29 +03:00
c7cb4a6dff Merge pull request 'Update dependency fastapi to v0.95.2' (#4) from renovate/fastapi-0.x into dev
Reviewed-on: #4
2023-05-16 18:46:18 +03:00
4060aae038 Update dependency fastapi to v0.95.2 2023-05-16 16:48:51 +03:00
4eea82a160 Merge pull request 'Update dependency fastapi to v0.95.1' (#2) from renovate/fastapi-0.x into dev
Reviewed-on: #2
2023-04-21 10:15:15 +03:00
4ce4264580 Update dependency fastapi to v0.95.1 2023-04-21 10:11:31 +03:00
6feed4359a Update '.renovaterc' 2023-04-21 10:03:26 +03:00
2afc82cf01 Add '.re' 2023-04-21 10:03:10 +03:00
bf0046c3d5 Update '.renovaterc' 2023-04-21 10:02:18 +03:00
c55a2d0d44 Add '.ren' 2023-04-21 10:01:52 +03:00
a380da81bb Updated API version to 0.2 2023-03-23 12:34:31 +01:00
e858e7d7f4 Changed token search logic 2023-03-23 12:34:18 +01:00
fcbbd4f2bf Bump FastAPI to 0.95.0 and exif to 1.6.0 2023-03-23 10:57:15 +01:00
6 changed files with 72 additions and 64 deletions

20
.renovaterc Normal file
View File

@@ -0,0 +1,20 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
],
"baseBranches": [
"dev"
],
"packageRules": [
{
"matchUpdateTypes": [
"minor",
"patch",
"pin",
"digest"
],
"automerge": true
}
]
}

View File

@@ -9,7 +9,7 @@ Small and simple API server for saving photos and videos.
## Dependencies ## Dependencies
* [Python 3.7+](https://www.python.org) (3.9+ recommended) * [Python 3.8+](https://www.python.org) (3.9+ recommended)
* [MongoDB](https://www.mongodb.com) * [MongoDB](https://www.mongodb.com)
* [exiftool](https://exiftool.org) * [exiftool](https://exiftool.org)
* [jpegoptim](https://github.com/tjko/jpegoptim) * [jpegoptim](https://github.com/tjko/jpegoptim)

View File

@@ -444,6 +444,7 @@ async def photo_delete(
photo_find_responses = { photo_find_responses = {
400: SearchPageInvalidError().openapi, 400: SearchPageInvalidError().openapi,
401: SearchTokenInvalidError().openapi,
404: AlbumNameNotFoundError("name").openapi, 404: AlbumNameNotFoundError("name").openapi,
422: PhotoSearchQueryEmptyError().openapi, 422: PhotoSearchQueryEmptyError().openapi,
} }
@@ -451,7 +452,7 @@ photo_find_responses = {
@app.get( @app.get(
"/albums/{album}/photos", "/albums/{album}/photos",
description="Find a photo by filename", description="Find a photo by filename, caption, location or token",
response_class=UJSONResponse, response_class=UJSONResponse,
response_model=SearchResultsPhoto, response_model=SearchResultsPhoto,
responses=photo_find_responses, responses=photo_find_responses,
@@ -460,6 +461,7 @@ async def photo_find(
album: str, album: str,
q: Union[str, None] = None, q: Union[str, None] = None,
caption: Union[str, None] = None, caption: Union[str, None] = None,
token: Union[str, None] = None,
page: int = 1, page: int = 1,
page_size: int = 100, page_size: int = 100,
lat: Union[float, None] = None, lat: Union[float, None] = None,
@@ -467,6 +469,24 @@ async def photo_find(
radius: Union[int, None] = None, radius: Union[int, None] = None,
current_user: User = Security(get_current_active_user, scopes=["photos.list"]), current_user: User = Security(get_current_active_user, scopes=["photos.list"]),
): ):
if token is not None:
found_record = col_tokens.find_one({"token": token})
if found_record is None:
raise SearchTokenInvalidError()
return await photo_find(
album=album,
q=found_record["query"],
caption=found_record["caption"],
lat=found_record["lat"],
lng=found_record["lng"],
radius=found_record["radius"],
page=found_record["page"],
page_size=found_record["page_size"],
current_user=current_user,
)
if col_albums.find_one({"user": current_user.user, "name": album}) is None: if col_albums.find_one({"user": current_user.user, "name": album}) is None:
raise AlbumNameNotFoundError(album) raise AlbumNameNotFoundError(album)
@@ -543,39 +563,16 @@ async def photo_find(
{ {
"token": token, "token": token,
"query": q, "query": q,
"album": album, "caption": caption,
"lat": lat,
"lng": lng,
"radius": radius,
"page": page + 1, "page": page + 1,
"page_size": page_size, "page_size": page_size,
"user": pickle.dumps(current_user),
} }
) )
output["next_page"] = f"/albums/{album}/photos/token?token={token}" # type: ignore output["next_page"] = f"/albums/{album}/photos/?token={token}" # type: ignore
else: else:
output["next_page"] = None # type: ignore output["next_page"] = None # type: ignore
return UJSONResponse(output) return UJSONResponse(output)
photo_find_token_responses = {401: SearchTokenInvalidError().openapi}
@app.get(
"/albums/{album}/photos/token",
description="Find a photo by token",
response_class=UJSONResponse,
response_model=SearchResultsPhoto,
responses=photo_find_token_responses,
)
async def photo_find_token(token: str):
found_record = col_tokens.find_one({"token": token})
if found_record is None:
raise SearchTokenInvalidError()
return await photo_find(
q=found_record["query"],
album=found_record["album"],
page=found_record["page"],
page_size=found_record["page_size"],
current_user=pickle.loads(found_record["user"]),
)

View File

@@ -260,6 +260,7 @@ async def video_delete(
video_find_responses = { video_find_responses = {
400: SearchPageInvalidError().openapi, 400: SearchPageInvalidError().openapi,
401: SearchTokenInvalidError().openapi,
404: AlbumNameNotFoundError("name").openapi, 404: AlbumNameNotFoundError("name").openapi,
422: VideoSearchQueryEmptyError().openapi, 422: VideoSearchQueryEmptyError().openapi,
} }
@@ -267,7 +268,7 @@ video_find_responses = {
@app.get( @app.get(
"/albums/{album}/videos", "/albums/{album}/videos",
description="Find a video by filename", description="Find a video by filename, caption or token",
response_class=UJSONResponse, response_class=UJSONResponse,
response_model=SearchResultsVideo, response_model=SearchResultsVideo,
responses=video_find_responses, responses=video_find_responses,
@@ -276,10 +277,26 @@ async def video_find(
album: str, album: str,
q: Union[str, None] = None, q: Union[str, None] = None,
caption: Union[str, None] = None, caption: Union[str, None] = None,
token: Union[str, None] = None,
page: int = 1, page: int = 1,
page_size: int = 100, page_size: int = 100,
current_user: User = Security(get_current_active_user, scopes=["videos.list"]), current_user: User = Security(get_current_active_user, scopes=["videos.list"]),
): ):
if token is not None:
found_record = col_tokens.find_one({"token": token})
if found_record is None:
raise SearchTokenInvalidError()
return await video_find(
album=album,
q=found_record["query"],
caption=found_record["caption"],
page=found_record["page"],
page_size=found_record["page_size"],
current_user=current_user,
)
if col_albums.find_one({"user": current_user.user, "name": album}) is None: if col_albums.find_one({"user": current_user.user, "name": album}) is None:
raise AlbumNameNotFoundError(album) raise AlbumNameNotFoundError(album)
@@ -341,39 +358,13 @@ async def video_find(
{ {
"token": token, "token": token,
"query": q, "query": q,
"album": album, "caption": caption,
"page": page + 1, "page": page + 1,
"page_size": page_size, "page_size": page_size,
"user": pickle.dumps(current_user),
} }
) )
output["next_page"] = f"/albums/{album}/videos/token?token={token}" # type: ignore output["next_page"] = f"/albums/{album}/videos/?token={token}" # type: ignore
else: else:
output["next_page"] = None # type: ignore output["next_page"] = None # type: ignore
return UJSONResponse(output) return UJSONResponse(output)
video_find_token_responses = {401: SearchTokenInvalidError().openapi}
@app.get(
"/albums/{album}/videos/token",
description="Find a video by token",
response_class=UJSONResponse,
response_model=SearchResultsVideo,
responses=video_find_token_responses,
)
async def video_find_token(token: str):
found_record = col_tokens.find_one({"token": token})
if found_record is None:
raise SearchTokenInvalidError()
return await video_find(
q=found_record["query"],
album=found_record["album"],
page=found_record["page"],
page_size=found_record["page_size"],
current_user=pickle.loads(found_record["user"]),
)

View File

@@ -2,7 +2,7 @@ from fastapi import FastAPI
from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html from fastapi.openapi.docs import get_swagger_ui_html, get_redoc_html
app = FastAPI(title="END PLAY Photos", docs_url=None, redoc_url=None, version="0.1") app = FastAPI(title="END PLAY Photos", docs_url=None, redoc_url=None, version="0.2")
@app.get("/docs", include_in_schema=False) @app.get("/docs", include_in_schema=False)

View File

@@ -1,10 +1,10 @@
fastapi[all]~=0.94.0 fastapi[all]==0.97.0
pymongo==4.3.3 pymongo==4.4.0
ujson~=5.7.0 ujson~=5.8.0
scipy~=1.10.1 scipy~=1.10.1
python-magic~=0.4.27 python-magic~=0.4.27
opencv-python~=4.7.0.72 opencv-python~=4.7.0.72
python-jose[cryptography]~=3.3.0 python-jose[cryptography]~=3.3.0
passlib~=1.7.4 passlib~=1.7.4
apscheduler~=3.10.1 apscheduler~=3.10.1
exif==1.5.0 exif==1.6.0