[tasks] Allow scrobbling tasks from URLs

This commit is contained in:
2024-10-05 15:08:38 -04:00
parent 342e86d7fb
commit c251c5f413
4 changed files with 74 additions and 24 deletions

View File

@ -22,11 +22,20 @@ MEDIA_END_PADDING_SECONDS = {
"Video": 3600, # 60 min "Video": 3600, # 60 min
} }
TASK_SOURCE_URL_PATTERNS = [
("https://app.shortcut.com/sure/story/{id}", "Shortcut"),
("https://app.todoist.com/app/task/{id}", "Todoist"),
]
for task_pattern in TASK_SOURCE_URL_PATTERNS:
task_urls = ", ".join([t[0] for t in TASK_SOURCE_URL_PATTERNS])
SCROBBLE_CONTENT_URLS = { SCROBBLE_CONTENT_URLS = {
"-i": "https://www.imdb.com/title/", "-i": "https://www.imdb.com/title/",
"-s": "https://www.thesportsdb.com/event/", "-s": "https://www.thesportsdb.com/event/",
"-g": "https://boardgamegeek.com/boardgame/", "-g": "https://boardgamegeek.com/boardgame/",
"-b": "https://www.amazon.com/", "-b": "https://www.amazon.com/",
"-t": task_urls,
} }
EXCLUDE_FROM_NOW_PLAYING = ("GeoLocation",) EXCLUDE_FROM_NOW_PLAYING = ("GeoLocation",)
@ -38,6 +47,7 @@ MANUAL_SCROBBLE_FNS = {
"-i": "manual_scrobble_video", "-i": "manual_scrobble_video",
"-g": "manual_scrobble_board_game", "-g": "manual_scrobble_board_game",
"-w": "manual_scrobble_webpage", "-w": "manual_scrobble_webpage",
"-t": "manual_scrobble_task",
} }

View File

@ -22,10 +22,12 @@ from sports.thesportsdb import lookup_event_from_thesportsdb
from videogames.howlongtobeat import lookup_game_from_hltb from videogames.howlongtobeat import lookup_game_from_hltb
from videogames.models import VideoGame from videogames.models import VideoGame
from videos.models import Video from videos.models import Video
from vrobbler.apps.scrobbles.constants import ( from scrobbles.constants import (
MANUAL_SCROBBLE_FNS, MANUAL_SCROBBLE_FNS,
SCROBBLE_CONTENT_URLS, SCROBBLE_CONTENT_URLS,
TASK_SOURCE_URL_PATTERNS,
) )
from tasks.models import Task
from webpages.models import WebPage from webpages.models import WebPage
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -273,23 +275,73 @@ def manual_scrobble_board_game(bggeek_id: str, user_id: int):
def manual_scrobble_from_url(url: str, user_id: int) -> Scrobble: def manual_scrobble_from_url(url: str, user_id: int) -> Scrobble:
"""We have scrobblable media URLs, and then any other webpages that
we want to scrobble as a media type in and of itself. This checks whether
we know about the content type, and routes it to the appropriate media
scrobbler. Otherwise, return nothing."""
content_key = "" content_key = ""
try:
domain = url.split("//")[-1].split("/")[0]
except IndexError:
domain = None
for key, content_url in SCROBBLE_CONTENT_URLS.items(): for key, content_url in SCROBBLE_CONTENT_URLS.items():
if content_url in url: if domain in content_url:
content_key = key content_key = key
item_id = None
if not content_key: if not content_key:
return content_key = "-w"
item_id = url
try: if not item_id:
item_id = re.findall("\d+", url)[0] try:
except IndexError: item_id = re.findall("\d+", url)[0]
item_id = None except IndexError:
pass
if content_key == "-t":
item_id = url
scrobble_fn = MANUAL_SCROBBLE_FNS[content_key] scrobble_fn = MANUAL_SCROBBLE_FNS[content_key]
return eval(scrobble_fn)(item_id, user_id) return eval(scrobble_fn)(item_id, user_id)
def manual_scrobble_task(url: str, user_id: int):
source_id = re.findall("\d+", url)[0]
if "shortcut" in url:
source = "Shortcut"
title = "Generic Shortcut task"
description = url.split("/")[-1]
if "todoist" in url:
source = "Todoist"
title = "Generic Todoist task"
description = url.split("-")[-1]
task = Task.find_or_create(title)
scrobble_dict = {
"user_id": user_id,
"timestamp": timezone.now(),
"playback_position_seconds": 0,
"source": source,
"log": {"description": description, "source_id": source_id},
}
logger.info(
"[webhook] webpage scrobble request received",
extra={
"task_id": task.id,
"user_id": user_id,
"scrobble_dict": scrobble_dict,
"media_type": Scrobble.MediaType.WEBPAGE,
},
)
scrobble = Scrobble.create_or_update(task, user_id, scrobble_dict)
return scrobble
def manual_scrobble_webpage(url: str, user_id: int): def manual_scrobble_webpage(url: str, user_id: int):
webpage = WebPage.find_or_create({"url": url}) webpage = WebPage.find_or_create({"url": url})

View File

@ -44,7 +44,7 @@ from scrobbles.models import (
RetroarchImport, RetroarchImport,
Scrobble, Scrobble,
) )
from scrobbles.scrobblers import * from scrobbles.scrobblers import manual_scrobble_from_url
from scrobbles.tasks import ( from scrobbles.tasks import (
process_koreader_import, process_koreader_import,
process_lastfm_import, process_lastfm_import,
@ -97,16 +97,8 @@ class RecentScrobbleList(ListView):
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
user = self.request.user user = self.request.user
if user.is_authenticated: if user.is_authenticated:
if scrobble_url := self.request.GET.get("scrobble_url"): if scrobble_url := self.request.GET.get("scrobble_url", ""):
for content_url in SCROBBLE_CONTENT_URLS.values(): scrobble = manual_scrobble_from_url(
if content_url in scrobble_url:
scrobble = manual_scrobble_from_url(
scrobble_url, self.request.user.id
)
return HttpResponseRedirect(
scrobble.redirect_url(user.id)
)
scrobble = manual_scrobble_webpage(
scrobble_url, self.request.user.id scrobble_url, self.request.user.id
) )
return HttpResponseRedirect(scrobble.redirect_url(user.id)) return HttpResponseRedirect(scrobble.redirect_url(user.id))

View File

@ -7,14 +7,10 @@ from django.db import models
from django.urls import reverse from django.urls import reverse
from scrobbles.dataclasses import LongPlayLogData from scrobbles.dataclasses import LongPlayLogData
from scrobbles.mixins import LongPlayScrobblableMixin from scrobbles.mixins import LongPlayScrobblableMixin
from scrobbles.constants import TASK_SOURCE_URL_PATTERNS
BNULL = {"blank": True, "null": True} BNULL = {"blank": True, "null": True}
TASK_SOURCE_URL_PATTERNS = [
("https://app.shortcut.com/sure/story/{id}", "Shortcut"),
("https://app.todoist.com/app/task/{id}", "Todoist"),
]
@dataclass @dataclass
class TaskLogData(LongPlayLogData): class TaskLogData(LongPlayLogData):
@ -66,7 +62,7 @@ class Task(LongPlayScrobblableMixin):
@classmethod @classmethod
def find_or_create(cls, title: str) -> "Task": def find_or_create(cls, title: str) -> "Task":
return cls.objects.filter(title=title).first() return cls.objects.get_or_create(title=title)[0]
def scrobbles(self, user_id): def scrobbles(self, user_id):
Scrobble = apps.get_model("scrobbles", "Scrobble") Scrobble = apps.get_model("scrobbles", "Scrobble")