-
-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
forgot to add files.. will delete after (#332)
* fix: add missing modules --------- Co-authored-by: Spoked <Spoked@localhost> Co-authored-by: davidemarcoli <davide@marcoli.ch>
- Loading branch information
1 parent
10a92f5
commit 25cd6b2
Showing
3 changed files
with
257 additions
and
0 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 |
---|---|---|
@@ -0,0 +1,67 @@ | ||
from typing import Any, List, Literal, Optional | ||
|
||
from pydantic import BaseModel, field_validator | ||
|
||
MediaType = Literal["movie", "tv"] | ||
|
||
|
||
class Media(BaseModel): | ||
media_type: MediaType | ||
status: str | ||
imdbId: str | None = None | ||
tmdbId: int | ||
tvdbId: int | None = None | ||
|
||
@field_validator("imdbId", mode="after") | ||
@classmethod | ||
def stringify_imdb_id(cls, value: Any): | ||
if value and isinstance(value, int): | ||
return f"tt{int(value):07d}" | ||
return None | ||
|
||
@field_validator("tvdbId", "tmdbId", mode="before") | ||
@classmethod | ||
def validate_ids(cls, value: Any): | ||
if value and isinstance(value, str) and value != "": | ||
return int(value) | ||
return None | ||
|
||
|
||
class RequestInfo(BaseModel): | ||
request_id: str | ||
requestedBy_email: str | ||
requestedBy_username: str | ||
requestedBy_avatar: Optional[str] | ||
|
||
class IssueInfo(BaseModel): | ||
issue_id: str | ||
issue_type: str | ||
issue_status: str | ||
reportedBy_email: str | ||
reportedBy_username: str | ||
reportedBy_avatar: Optional[str] | ||
|
||
class CommentInfo(BaseModel): | ||
comment_message: str | ||
commentedBy_email: str | ||
commentedBy_username: str | ||
commentedBy_avatar: Optional[str] | ||
|
||
class OverseerrWebhook(BaseModel): | ||
notification_type: str | ||
event: str | ||
subject: str | ||
message: Optional[str] = None | ||
image: Optional[str] = None | ||
media: Media | ||
request: Optional[RequestInfo] = None | ||
issue: Optional[IssueInfo] = None | ||
comment: Optional[CommentInfo] = None | ||
extra: List[dict[str, Any]] = [] | ||
|
||
@property | ||
def requested_seasons(self) -> Optional[List[int]]: | ||
for extra in self.extra: | ||
if extra["name"] == "Requested Seasons": | ||
return [int(x) for x in extra["value"].split(",")] | ||
return None |
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 |
---|---|---|
@@ -0,0 +1,66 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, Field | ||
from rich.console import Console | ||
from rich.table import Table | ||
|
||
console = Console() | ||
|
||
|
||
class Account(BaseModel): | ||
id: int | ||
thumb: str | ||
title: str | ||
|
||
class Server(BaseModel): | ||
title: str | ||
uuid: str | ||
|
||
class Player(BaseModel): | ||
local: bool | ||
publicAddress: str | ||
title: str | ||
uuid: str | ||
|
||
class Metadata(BaseModel): | ||
librarySectionType: str | ||
ratingKey: str | ||
key: str | ||
guid: str | ||
type: str | ||
title: str | ||
librarySectionTitle: str | ||
librarySectionID: int | ||
librarySectionKey: str | ||
contentRating: str | ||
summary: str | ||
rating: Optional[float] = Field(None, description="Rating of the media") | ||
audienceRating: Optional[float] = Field(None, description="Audience rating of the media") | ||
year: int | ||
tagline: Optional[str] = Field(None, description="Tagline of the media") | ||
thumb: str | ||
|
||
class PlexPayload(BaseModel): | ||
event: str | ||
user: bool | ||
owner: bool | ||
Account: Account | ||
Server: Server | ||
Player: Player | ||
Metadata: Metadata | ||
|
||
|
||
def log_plex_payload(plex_payload): | ||
table = Table(title="Plex Payload Details") | ||
|
||
table.add_column("Field", style="bold cyan") | ||
table.add_column("Value", style="bold magenta") | ||
|
||
table.add_row("Event", plex_payload.event) | ||
table.add_row("User", plex_payload.Account.title) | ||
table.add_row("User ID", str(plex_payload.Account.id)) | ||
table.add_row("Media Title", plex_payload.Metadata.title) | ||
table.add_row("Media Type", plex_payload.Metadata.type) | ||
table.add_row("Year", str(plex_payload.Metadata.year)) | ||
|
||
console.print(table) |
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 |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import json | ||
from datetime import datetime | ||
|
||
import pydantic | ||
import requests | ||
from fastapi import APIRouter, HTTPException, Request | ||
from program.indexers.trakt import get_imdbid_from_tmdb | ||
from program.settings.manager import settings_manager | ||
from utils.logger import logger | ||
|
||
from .models.overseerr import OverseerrWebhook | ||
|
||
router = APIRouter( | ||
responses={404: {"description": "Not found"}}, | ||
) | ||
|
||
|
||
@router.post("/overseerr") | ||
async def overseerr_webhook(request: Request): | ||
response = await request.json() | ||
logger.debug(f"Received request for: {response.get('subject', 'Unknown')}") | ||
try: | ||
req = OverseerrWebhook.model_validate(response) | ||
except pydantic.ValidationError: | ||
return {"success": False, "message": "Invalid request"} | ||
imdb_id = req.media.imdbId | ||
if not imdb_id: | ||
imdb_id = get_imdbid_from_tmdb(req.media.tmdbId) | ||
if not imdb_id: | ||
logger.error(f"Failed to get imdb_id from TMDB: {req.media.tmdbId}") | ||
return {"success": False, "message": "Failed to get imdb_id from TMDB", "title": req.subject} | ||
item = {"imdb_id": imdb_id, "requested_by": "overseerr", "requested_at": datetime.now()} | ||
request.app.program.add_to_queue(item) | ||
return {"success": True} | ||
|
||
|
||
@router.post("/plex") | ||
async def plex_webhook(request: Request): | ||
form = await request.form() | ||
payload = form.get("payload") | ||
if not payload: | ||
logger.error("Missing payload in form data") | ||
raise HTTPException(status_code=400, detail="Missing payload in form data") | ||
|
||
try: | ||
payload_dict = json.loads(payload) | ||
plex_payload = PlexPayload(**payload_dict) | ||
except json.JSONDecodeError: | ||
logger.error("Invalid JSON payload") | ||
raise HTTPException(status_code=400, detail="Invalid JSON payload") | ||
except Exception as e: | ||
logger.error(f"Unexpected error: {str(e)}") | ||
raise HTTPException(status_code=500, detail=str(e)) | ||
|
||
if plex_payload.event == "media.play": | ||
logger.log("PLEX", f"Event: {plex_payload.event}") | ||
logger.log("PLEX", f"User: {plex_payload.Account.title} (ID: {plex_payload.Account.id})") | ||
logger.log("PLEX", f"Media Title: {plex_payload.Metadata.title}") | ||
logger.log("PLEX", f"Media Type: {plex_payload.Metadata.type}") | ||
logger.log("PLEX", f"Year: {plex_payload.Metadata.year}") | ||
|
||
logger.log("EVENT", f"Event: {plex_payload.event}") | ||
# Assuming you have a function to log the payload | ||
# log_plex_payload(plex_payload) | ||
|
||
return {"status": "received"} | ||
|
||
|
||
|
||
### Plex Models | ||
|
||
from pydantic import BaseModel | ||
|
||
|
||
class Account(BaseModel): | ||
id: int | ||
thumb: str | ||
title: str | ||
|
||
class Server(BaseModel): | ||
title: str | ||
uuid: str | ||
|
||
class Player(BaseModel): | ||
local: bool | ||
publicAddress: str | ||
title: str | ||
uuid: str | ||
|
||
class Metadata(BaseModel): | ||
librarySectionType: str | ||
ratingKey: str | ||
key: str | ||
guid: str | ||
type: str | ||
title: str | ||
librarySectionTitle: str | ||
librarySectionID: int | ||
librarySectionKey: str | ||
contentRating: str | ||
summary: str | ||
rating: float | ||
audienceRating: float | ||
year: int | ||
tagline: str | ||
thumb: str | ||
|
||
class PlexPayload(BaseModel): | ||
event: str | ||
user: bool | ||
owner: bool | ||
Account: Account | ||
Server: Server | ||
Player: Player | ||
Metadata: Metadata | ||
|
||
class TraktSettings(BaseModel): | ||
trakt_id: str | ||
trakt_secret: str | ||
|
||
class Config: | ||
env_file = ".env" | ||
|
||
settings = TraktSettings() |