Skip to content

Commit

Permalink
feat: add awsl pic
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamhunter2333 committed Jul 12, 2024
1 parent 696c7ce commit 01abc25
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 6 deletions.
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

class Settings(BaseSettings):
cookie_sub: str = ""
allow_empty_keyword: bool = False
token: str = Field(deafult="token", exclude=True)
db_client_type: str = "mysql"
db_url: str = Field(deafult="", exclude=True)
Expand Down
2 changes: 2 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from src.awsl_producers import router as producer_router
from src.awsl_blob import router as blob_router
from src.awsl_pic import router as pic_router
from src.health_check import router as health_check_router


Expand Down Expand Up @@ -35,6 +36,7 @@ def filter(self, record: logging.LogRecord) -> bool:

app.include_router(producer_router, prefix="")
app.include_router(blob_router, prefix="")
app.include_router(pic_router, prefix="")
app.include_router(health_check_router, prefix="")

# 301 Redirect to /docs
Expand Down
36 changes: 36 additions & 0 deletions src/awsl_pic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import logging

from typing import List, Optional
from fastapi import APIRouter
from fastapi.responses import JSONResponse

from .response_models import BlobItem, Message
from src.db.base import DBClientBase

router = APIRouter()
_logger = logging.getLogger(__name__)


@router.get("/awsl_pic/list", response_model=List[BlobItem], responses={404: {"model": Message}}, tags=["Awsl Pic"])
def awsl_pic_list(uid: Optional[str] = "", limit: Optional[int] = 10, offset: Optional[int] = 0):
if limit > 1000:
return JSONResponse(
status_code=404,
content=Message(message="to large limit = {}".format(limit))
)
return DBClientBase.get_client().awsl_pic_list(uid, limit, offset)


@router.get("/awsl_pic/list_count", response_model=int, tags=["Awsl Pic"])
def awsl_pic_list_count(uid: Optional[str] = "") -> int:
return DBClientBase.get_client().awsl_pic_list_count(uid)


@router.get("/awsl_pic/random", response_model=str, tags=["Awsl Pic"])
def awsl_pic_random() -> str:
return DBClientBase.get_client().awsl_pic_random()


@router.get("/awsl_pic/random_json", response_model=BlobItem, tags=["Awsl Pic"])
def awsl_pic_random_json() -> str:
return DBClientBase.get_client().awsl_pic_random_json()
2 changes: 1 addition & 1 deletion src/awsl_producers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def add_awsl_producers(producer: ProducerItem):
status_code=status.HTTP_400_BAD_REQUEST,
content={"message": "uid is None"}
)
if not producer.keyword:
if not settings.allow_empty_keyword and not producer.keyword:
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"message": "keyword is null"}
Expand Down
16 changes: 16 additions & 0 deletions src/db/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,19 @@ def awsl_random(cls) -> str:
@classmethod
def awsl_random_json(cls) -> str:
...

@classmethod
def awsl_pic_list(cls, uid: str, limit: int, offset: int) -> List[BlobItem]:
...

@classmethod
def awsl_pic_list_count(cls, uid: str) -> int:
...

@classmethod
def awsl_pic_random(cls) -> str:
...

@classmethod
def awsl_pic_random_json(cls) -> str:
...
60 changes: 58 additions & 2 deletions src/db/mysql_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from sqlalchemy.orm import sessionmaker

from config import WB_URL_PREFIX, settings
from src.models.models import AwslBlob, AwslProducer, Mblog
from src.models.models import AwslBlob, AwslProducer, Mblog, Pic
from src.models.pydantic_models import Blob, Blobs
from src.response_models import BlobItem, ProducerItem, ProducerRes
from src.response_models import BlobItem, PicInfo, ProducerItem, ProducerRes

from .base import DBClientBase

Expand Down Expand Up @@ -170,3 +170,59 @@ def awsl_random_json(cls) -> str:
for blob_key, blob_pic in Blobs.model_validate_json(blob.pic_info).blobs.items()
}
)

@classmethod
def awsl_pic_list(cls, uid: str, limit: int, offset: int) -> List[BlobItem]:
with cls.DBSession() as session:
pics = session.query(Pic).join(
Mblog, Pic.awsl_id == Mblog.id
).filter(
Mblog.uid == uid
).order_by(
Pic.awsl_id.desc()
).limit(limit).offset(offset).all() if uid else session.query(
Pic
).join(
Mblog, Pic.awsl_id == Mblog.id
).order_by(
Pic.awsl_id.desc()
).limit(limit).offset(offset).all()
res = [BlobItem(
wb_url=WB_URL_PREFIX.format(
pic.awsl_mblog.re_user_id, pic.awsl_mblog.re_mblogid),
pic_id=pic.pic_id,
pic_info=PicInfo.model_validate_json(pic.pic_info).root
) for pic in pics if pic.awsl_mblog]
return res

@classmethod
def awsl_pic_list_count(cls, uid: str) -> int:
with cls.DBSession() as session:
res = session.query(func.count(Pic.id)).join(
Mblog, Pic.awsl_id == Mblog.id
).filter(
Mblog.uid == uid
).one() if uid else session.query(func.count(Pic.id)).one()
return int(res[0]) if res else 0

@classmethod
def awsl_pic_random(cls) -> str:
with cls.DBSession() as session:
pic = session.query(Pic).order_by(
func.rand()
).limit(1).one()
url_dict = PicInfo.model_validate_json(pic.pic_info).root
return url_dict["original"].url

@classmethod
def awsl_pic_random_json(cls) -> str:
with cls.DBSession() as session:
blob = session.query(Pic).order_by(
func.rand()
).limit(1).one()
return BlobItem(
wb_url=WB_URL_PREFIX.format(
blob.awsl_mblog.re_user_id, blob.awsl_mblog.re_mblogid),
pic_id=blob.pic_id,
pic_info=PicInfo.model_validate_json(blob.pic_info).root
)
65 changes: 64 additions & 1 deletion src/db/tidb_http_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from src.db.tidb_models import TiDBResponse
from src.models.models import AwslProducer
from src.models.pydantic_models import Blob, Blobs
from src.response_models import BlobItem, ProducerItem, ProducerRes
from src.response_models import BlobItem, PicInfo, ProducerItem, ProducerRes

from .base import DBClientBase

Expand Down Expand Up @@ -212,3 +212,66 @@ def awsl_random_json(cls) -> str:
for blob_key, blob_pic in Blobs.model_validate_json(blob['pic_info']).blobs.items()
}
)

@classmethod
def awsl_pic_list(cls, uid: str, limit: int, offset: int) -> List[BlobItem]:
res_json = cls.post_query(
"SELECT awsl_pic.pic_id, awsl_pic.pic_info,"
" awsl_mblog.re_user_id, awsl_mblog.re_mblogid"
" FROM awsl_pic"
" INNER JOIN awsl_mblog ON awsl_pic.awsl_id=awsl_mblog.id"
+ (f" WHERE awsl_mblog.uid = '{sql_escape(uid)}'" if uid else "")
+ " ORDER BY awsl_pic.awsl_id DESC"
f" LIMIT {sql_escape(offset)}, {sql_escape(limit)}"
)
res = [BlobItem(
wb_url=WB_URL_PREFIX.format(pic['re_user_id'], pic['re_mblogid']),
pic_id=pic['pic_id'],
pic_info=PicInfo.model_validate_json(pic['pic_info']).root
) for pic in res_json]
return res

@classmethod
def awsl_pic_list_count(cls, uid: str) -> int:
res = cls.post_query(
"SELECT count(1) AS count FROM awsl_pic"
+ (
" INNER JOIN awsl_mblog ON awsl_pic.awsl_id=awsl_mblog.id"
f" WHERE awsl_mblog.uid = '{sql_escape(uid)}'"
) if uid else ""
)
if not res or not res[0] or not res[0].get("count"):
return 0
return res[0]["count"]

@classmethod
def awsl_pic_random(cls) -> str:
res = cls.post_query("SELECT pic_info FROM awsl_pic ORDER BY rand() LIMIT 1")
if not res or not res[0]:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="No random pic found"
)
url_dict = PicInfo.model_validate_json(res[0]['pic_info']).root
return url_dict["original"].url

@classmethod
def awsl_pic_random_json(cls) -> str:
res_json = cls.post_query(
"SELECT awsl_pic.pic_id, awsl_pic.pic_info,"
" awsl_mblog.re_user_id, awsl_mblog.re_mblogid"
" FROM awsl_pic"
" INNER JOIN awsl_mblog ON awsl_pic.awsl_id=awsl_mblog.id"
" ORDER BY rand() LIMIT 1"
)
if not res_json:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="No random pic found"
)
res = res_json[0]
return BlobItem(
wb_url=WB_URL_PREFIX.format(res['re_user_id'], res['re_mblogid']),
pic_id=res['pic_id'],
pic_info=PicInfo.model_validate_json(res['pic_info']).root
)
21 changes: 19 additions & 2 deletions src/response_models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Dict, List
from pydantic import BaseModel
from typing import Any, Dict
from pydantic import BaseModel, RootModel, model_validator

from .models.pydantic_models import Blob

Expand All @@ -20,5 +20,22 @@ class BlobItem(BaseModel):
pic_info: Dict[str, Blob]


class PicInfo(RootModel):
root: Dict[str, Blob]

@model_validator(mode='before')
@classmethod
def pre_process_and_validate(cls, values: Dict[str, Any]) -> Dict[str, Any]:
return {
k: v
for k, v in values.items()
if isinstance(v, dict)
and all(
kk in v.keys()
for kk in Blob.model_fields.keys()
)
}


class Message(BaseModel):
message: str

0 comments on commit 01abc25

Please sign in to comment.