-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Changed external API stream information
- Loading branch information
1 parent
86b86a3
commit 8a7de30
Showing
1 changed file
with
141 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,69 +1,151 @@ | ||
from litestar import Controller, get, Request | ||
from litestar.exceptions import * | ||
from uuid import UUID | ||
|
||
from modules.weather_information import get_weather_information | ||
from litestar import Controller, Request, get | ||
from litestar.contrib.sqlalchemy.repository import SQLAlchemyAsyncRepository | ||
from litestar.datastructures import State | ||
from litestar.di import Provide | ||
from litestar.exceptions import * | ||
from litestar.response import Redirect | ||
from models.country import Country | ||
from models.stream import Stream, StreamTag | ||
from models.stream_animal import StreamAnimal | ||
from modules.weather_information import get_weather_information | ||
from pydantic import BaseModel as _BaseModel | ||
from sqlalchemy import select | ||
from sqlalchemy.ext.asyncio import AsyncSession | ||
from sqlalchemy.orm import selectinload | ||
|
||
|
||
class BaseModel(_BaseModel): | ||
"""Extend Pydantic's BaseModel to enable ORM mode""" | ||
|
||
model_config = {"from_attributes": True} | ||
|
||
|
||
class StreamTagData(BaseModel): | ||
name: str | ||
model: str | None = None | ||
|
||
|
||
class StreamCountryData(BaseModel): | ||
iso: str | ||
name: str | ||
|
||
|
||
class StreamAnimalData(BaseModel): | ||
common_name: str | ||
scientific_name: str | ||
count: int | ||
|
||
|
||
class StreamData(BaseModel): | ||
id: UUID | ||
name: str | ||
url: str | ||
tag: StreamTagData | ||
country: StreamCountryData | ||
location: str | ||
latitude: float | ||
longitude: float | ||
weather: dict | ||
animals: list[StreamAnimalData] | ||
|
||
|
||
class StreamRepository(SQLAlchemyAsyncRepository[Stream]): | ||
model_type = Stream | ||
|
||
|
||
async def provide_streams_repository(db_session: AsyncSession) -> StreamRepository: | ||
return StreamRepository( | ||
session=db_session, | ||
) | ||
|
||
|
||
class StreamsController(Controller): | ||
path = "/streams" | ||
tags = ["streams"] | ||
|
||
@get("/test") | ||
async def test(self, state: State, score_number: int | None = None) -> None: | ||
print(state.db_engine) | ||
|
||
@get() | ||
async def get_stream_url( | ||
self, state: State, score_number: int | None = None | ||
) -> str: | ||
""" | ||
Get the stream URL. | ||
:param score_number: Which stream to get based on its score. | ||
Score of 0 meaning the best scored stream for a set op preferences. | ||
:return: stream URL. | ||
""" | ||
|
||
youtube_ids = [ | ||
yt_id.split(":")[1] | ||
for yt_id in reversed(state.r.lrange("stream_order", 0, -1)) | ||
] | ||
|
||
if not youtube_ids: | ||
raise ClientException(detail="No streams available") | ||
|
||
if score_number is None: | ||
return f"https://www.youtube.com/watch?v={youtube_ids[0]}" | ||
|
||
try: | ||
youtube_ids[score_number] | ||
except IndexError: | ||
raise ClientException(detail="Score number out of range") | ||
|
||
return f"https://www.youtube.com/watch?v={youtube_ids[0]}" | ||
|
||
@get("/weather") | ||
async def get_weather(self) -> dict: | ||
""" | ||
Get the stream's current location weather. | ||
:return: weather information. | ||
""" | ||
|
||
# Get current stream being shown. | ||
# TODO | ||
|
||
# Load stream's information from database. | ||
stream_info = { | ||
"latitude": -24.759908603843932, | ||
"longitude": 26.2777502150771, | ||
} # TODO Make based on current stream being shown, and retrieve from database. | ||
|
||
# Get weather using stream latitude and longitude information. | ||
weather_info = get_weather_information( | ||
latitude=stream_info["latitude"], | ||
longitude=stream_info["longitude"], | ||
dependencies = {"streams_repository": Provide(provide_streams_repository)} | ||
|
||
@get("/current") | ||
async def get_current_stream(self, db_session: AsyncSession) -> Redirect: | ||
# TODO: Get current stream id, instead of first. | ||
current_stream_id = ( | ||
(await db_session.execute(select(Stream.id))).scalars().first() | ||
) | ||
|
||
return Redirect(path=f"/v1/streams/{current_stream_id}") | ||
|
||
@get("/{stream_id:uuid}") | ||
async def get_stream( | ||
self, streams_repository: StreamRepository, stream_id: UUID | ||
) -> StreamData: | ||
stream = await streams_repository.get( | ||
item_id=stream_id, | ||
load=[ | ||
Stream.tag, | ||
Stream.country, | ||
selectinload(Stream.stream_animals).selectinload(StreamAnimal.animal), | ||
], | ||
) | ||
|
||
stream_weather = get_weather_information( | ||
latitude=stream.latitude, | ||
longitude=stream.longitude, | ||
) | ||
|
||
return weather_info | ||
return StreamData( | ||
id=stream.id, | ||
name=stream.name, | ||
url=stream.url, | ||
tag=StreamTagData( | ||
name=stream.tag.name, | ||
model=stream.tag.model, | ||
), | ||
country=StreamCountryData( | ||
iso=stream.country.iso, | ||
name=stream.country.name, | ||
), | ||
location=stream.location, | ||
latitude=stream.latitude, | ||
longitude=stream.longitude, | ||
weather=stream_weather["current"], | ||
animals=[ | ||
StreamAnimalData( | ||
common_name=stream_animal.animal.common_name, | ||
scientific_name=stream_animal.animal.scientific_name, | ||
count=stream_animal.count, | ||
) | ||
for stream_animal in stream.stream_animals | ||
], | ||
) | ||
|
||
# @get() | ||
# async def get_stream_url( | ||
# self, state: State, score_number: int | None = None | ||
# ) -> str: | ||
# """ | ||
# Get the stream URL. | ||
|
||
# :param score_number: Which stream to get based on its score. | ||
# Score of 0 meaning the best scored stream for a set op preferences. | ||
# :return: stream URL. | ||
# """ | ||
|
||
# youtube_ids = [ | ||
# yt_id.split(":")[1] | ||
# for yt_id in reversed(state.r.lrange("stream_order", 0, -1)) | ||
# ] | ||
|
||
# if not youtube_ids: | ||
# raise ClientException(detail="No streams available") | ||
|
||
# if score_number is None: | ||
# return f"https://www.youtube.com/watch?v={youtube_ids[0]}" | ||
|
||
# try: | ||
# youtube_ids[score_number] | ||
# except IndexError: | ||
# raise ClientException(detail="Score number out of range") | ||
|
||
# return f"https://www.youtube.com/watch?v={youtube_ids[0]}" |