Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d4f82f2d6f | |||
| 106d25c20f | |||
| d77caa2783 | |||
| b5bfad73ef | |||
| 274b2704ed | |||
| 80fcb6c002 | |||
| c6f3c90006 | |||
| 387dee7d37 |
20
PROJECT.org
20
PROJECT.org
@ -92,7 +92,7 @@ fetching and simple saving.
|
||||
:LOGBOOK:
|
||||
CLOCK: [2025-07-09 Wed 09:55]--[2025-07-09 Wed 10:15] => 0:20
|
||||
:END:
|
||||
* Backlog [3/27]
|
||||
* Backlog [2/26]
|
||||
** TODO [#C] Create small utility to clean up tracks scrobbled with wonky playback times :vrobbler:personal:bug:music:scrobbles:
|
||||
** TODO [#C] Move to using more robust mopidy-webhooks pacakge form pypi :utility:improvement:
|
||||
:PROPERTIES:
|
||||
@ -479,6 +479,24 @@ https://life.lab.unbl.ink/scrobble/e39779c8-62a5-46a6-bdef-fb7662810dc6/start/
|
||||
- Note taken on [2025-09-30 Tue 09:33]
|
||||
|
||||
This may have already been resolved ... need to just confirm it.
|
||||
* Version 30.0 [3/3]
|
||||
** DONE [#A] Fix readcomicsonline browsing to update pages :vrobbler:books:feature:comicbook:personal:project:scrobbling:
|
||||
:PROPERTIES:
|
||||
:ID: 981b215a-6473-5fc7-d4cc-51b3eddec4c3
|
||||
:END:
|
||||
** DONE [#B] Redirect webpages back to the original page when starting or stopping :vrobbler:project:webpages:bug:
|
||||
:PROPERTIES:
|
||||
:ID: 6183d03a-452b-51d5-cceb-5bfeada947aa
|
||||
:END:
|
||||
|
||||
** DONE [#B] Fix ComicVine as source for comic book metadata :vrobbler:books:feature:comicbook:personal:project:scrobbling:
|
||||
:PROPERTIES:
|
||||
:ID: d22cec3f-117f-f203-33a5-efbefa8a5cee
|
||||
:END:
|
||||
* Version 29.0 [1/1]
|
||||
** DONE HOTFIX podcast lookups, final
|
||||
* Version 28.0 [1/1]
|
||||
** DONE HOTFIX podcast lookups
|
||||
* Version 27.0 [3/3]
|
||||
** DONE [#A] Fix bug where podcast scrobbling creates duplicate Podcast :project:vrobbler:scrobbling:podcasts:bug:personal:
|
||||
:PROPERTIES:
|
||||
|
||||
16
poetry.lock
generated
16
poetry.lock
generated
@ -4756,6 +4756,20 @@ webencodings = ">=0.4"
|
||||
doc = ["sphinx", "sphinx_rtd_theme"]
|
||||
test = ["pytest", "ruff"]
|
||||
|
||||
[[package]]
|
||||
name = "titlecase"
|
||||
version = "2.4.1"
|
||||
description = "Python Port of John Gruber's titlecase.pl"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main"]
|
||||
files = [
|
||||
{file = "titlecase-2.4.1.tar.gz", hash = "sha256:7d83a277ccbbda11a2944e78a63e5ccaf3d32f828c594312e4862f9a07f635f5"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
regex = ["regex (>=2020.4.4)"]
|
||||
|
||||
[[package]]
|
||||
name = "tld"
|
||||
version = "0.13"
|
||||
@ -5525,4 +5539,4 @@ cffi = ["cffi (>=1.11)"]
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.9,<3.12"
|
||||
content-hash = "cd3b566597e09aa444f9af30f95f94f922bf3dca71fbd05c887fb10cbc11d7bf"
|
||||
content-hash = "2e297ef6f8c524840a381ad793946c87b601d81afd569e882fe58120a5f84626"
|
||||
|
||||
@ -57,6 +57,7 @@ orgparse = "^0.4.20250520"
|
||||
tmdbv3api = "^1.9.0"
|
||||
themoviedb = "^1.0.2"
|
||||
feedparser = "^6.0.12"
|
||||
titlecase = "^2.4.1"
|
||||
|
||||
[tool.poetry.group.test]
|
||||
optional = true
|
||||
|
||||
@ -5,3 +5,5 @@ BOOKS_TITLES_TO_IGNORE = [
|
||||
"zb2rhkSwygt9vjkAEBj7tP5KVgFqejJqsJ2W3bYsrgiiKK8XL",
|
||||
"zb2rhchGpo7P27mofV9hYjT63d9ZaQnbQ6LSfzmkvsYzvARif",
|
||||
]
|
||||
|
||||
READCOMICSONLINE_URL = "https://readcomicsonline.ru"
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
# Generated by Django 4.2.19 on 2025-10-20 18:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('books', '0028_delete_page'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='comicvine_id',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='issue_number',
|
||||
field=models.IntegerField(blank=True, max_length=5, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='original_title',
|
||||
field=models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='book',
|
||||
name='volume_number',
|
||||
field=models.IntegerField(blank=True, max_length=5, null=True),
|
||||
),
|
||||
]
|
||||
@ -26,7 +26,7 @@ from scrobbles.mixins import (
|
||||
from scrobbles.utils import get_scrobbles_for_media
|
||||
from taggit.managers import TaggableManager
|
||||
from thefuzz import fuzz
|
||||
from vrobbler.apps.books.comicvine import (
|
||||
from vrobbler.apps.books.sources.comicvine import (
|
||||
ComicVineClient,
|
||||
lookup_comic_from_comicvine,
|
||||
)
|
||||
@ -135,6 +135,7 @@ class Book(LongPlayScrobblableMixin):
|
||||
)
|
||||
|
||||
title = models.CharField(max_length=255)
|
||||
original_title = models.CharField(max_length=255, **BNULL)
|
||||
authors = models.ManyToManyField(Author, blank=True)
|
||||
koreader_data_by_hash = models.JSONField(**BNULL)
|
||||
isbn_13 = models.CharField(max_length=255, **BNULL)
|
||||
@ -145,6 +146,11 @@ class Book(LongPlayScrobblableMixin):
|
||||
publish_date = models.DateField(**BNULL)
|
||||
publisher = models.CharField(max_length=255, **BNULL)
|
||||
first_sentence = models.TextField(**BNULL)
|
||||
# ComicVine
|
||||
comicvine_id = models.CharField(max_length=255, **BNULL)
|
||||
issue_number = models.IntegerField(max_length=5, **BNULL)
|
||||
volume_number = models.IntegerField(max_length=5, **BNULL)
|
||||
# OpenLibrary
|
||||
openlibrary_id = models.CharField(max_length=255, **BNULL)
|
||||
cover = models.ImageField(upload_to="books/covers/", **BNULL)
|
||||
cover_small = ImageSpecField(
|
||||
@ -188,6 +194,43 @@ class Book(LongPlayScrobblableMixin):
|
||||
def get_absolute_url(self):
|
||||
return reverse("books:book_detail", kwargs={"slug": self.uuid})
|
||||
|
||||
@classmethod
|
||||
def get_from_comicvine(cls, title: str, overwrite: bool = False, force_new: bool =False) -> "Book":
|
||||
book, created = cls.objects.get_or_create(title=title)
|
||||
if not created and not overwrite and not force_new:
|
||||
book, created = cls.objects.get_or_create(original_title=title)
|
||||
logger.info("Found comic by original title, use force_new=True to override")
|
||||
return book
|
||||
|
||||
book_dict = lookup_comic_from_comicvine(title)
|
||||
|
||||
if created or overwrite:
|
||||
author_list = []
|
||||
author_dicts = book_dict.pop("author_dicts")
|
||||
if author_dicts:
|
||||
for author_dict in author_dicts:
|
||||
if author_dict.get("authorId"):
|
||||
author, a_created = Author.objects.get_or_create(
|
||||
semantic_id=author_dict.get("authorId")
|
||||
)
|
||||
author_list.append(author)
|
||||
if a_created:
|
||||
author.name = author_dict.get("name")
|
||||
author.save()
|
||||
# TODO enrich author?
|
||||
...
|
||||
|
||||
for k, v in book_dict.items():
|
||||
setattr(book, k, v)
|
||||
book.save()
|
||||
|
||||
if author_list:
|
||||
book.authors.add(*author_list)
|
||||
genres = book_dict.pop("genres", [])
|
||||
if genres:
|
||||
book.genre.add(*genres)
|
||||
return book
|
||||
|
||||
@classmethod
|
||||
def find_or_create(
|
||||
cls, title: str, enrich: bool = False, commit: bool = True
|
||||
@ -215,6 +258,8 @@ class Book(LongPlayScrobblableMixin):
|
||||
return book
|
||||
|
||||
book_dict = lookup_book_from_google(title)
|
||||
if not book_dict or book_dict.get("isbn_10"):
|
||||
book_dict = lookup_comic_from_comicvine(title)
|
||||
|
||||
author_list = []
|
||||
authors = book_dict.pop("authors")
|
||||
|
||||
@ -3,7 +3,6 @@ ComicVine API Information & Documentation:
|
||||
https://comicvine.gamespot.com/api/
|
||||
https://comicvine.gamespot.com/api/documentation
|
||||
"""
|
||||
import json
|
||||
import logging
|
||||
from django.conf import settings
|
||||
|
||||
@ -200,34 +199,71 @@ class ComicVineClient(object):
|
||||
|
||||
|
||||
def lookup_comic_from_comicvine(title: str) -> dict:
|
||||
original_title = title
|
||||
|
||||
issue_number = None
|
||||
volume_nubmer = None
|
||||
resource_type = "issue"
|
||||
if "Issue " in title:
|
||||
resource_type = "issue"
|
||||
issue_number = title.split("Issue ")[1]
|
||||
volume_number = None
|
||||
if "Volume " in title:
|
||||
resource_type = "volume"
|
||||
volume_number = title.split("Volume ")[1]
|
||||
|
||||
api_key = getattr(settings, "COMICVINE_API_KEY", "")
|
||||
if not api_key:
|
||||
logger.warn("No ComicVine API key configured, not looking anything up")
|
||||
logger.warning("No ComicVine API key configured, not looking anything up")
|
||||
return {}
|
||||
|
||||
client = ComicVineClient(
|
||||
api_key=getattr(settings, "COMICVINE_API_KEY", None)
|
||||
)
|
||||
result = [
|
||||
r
|
||||
for r in client.search(title).get("results")
|
||||
if r.get("resource_type") == "volume"
|
||||
][0]
|
||||
|
||||
if "volume" not in result.keys():
|
||||
logger.warn("No result found on ComicVine", extra={"title": title})
|
||||
raw_results = client.search(title).get("results")
|
||||
results = [
|
||||
r
|
||||
for r in raw_results
|
||||
if r.get("resource_type") == resource_type
|
||||
]
|
||||
print(results)
|
||||
if not results:
|
||||
logger.warning("No comic found on ComicVine")
|
||||
return {}
|
||||
|
||||
title = " ".join([result.get("volume").get("name"), result.get("name)")])
|
||||
found_result = None
|
||||
for result in results:
|
||||
print("checking ", result.get("issue_number"), " to ", str(issue_number))
|
||||
if result.get("issue_number") == str(issue_number):
|
||||
found_result = result
|
||||
break
|
||||
if result.get("volume_number") == str(volume_number):
|
||||
found_result = result
|
||||
break
|
||||
|
||||
if not found_result:
|
||||
found_result = results[0]
|
||||
|
||||
logger.info("ComicVine results", extra={"results": results})
|
||||
|
||||
if not found_result:
|
||||
logger.warning("No matches found on ComicVine")
|
||||
return {}
|
||||
|
||||
title = found_result.get("name")
|
||||
|
||||
if found_result.get("volume"):
|
||||
title = found_result.get("volume").get("name")
|
||||
|
||||
data_dict = {
|
||||
"title": title,
|
||||
"cover_url": result.get("image").get("original_url"),
|
||||
"comicvine_data": {
|
||||
"id": result.get("id"),
|
||||
"site_detail_url": result.get("site_detail_url"),
|
||||
"description": result.get("description"),
|
||||
"image": result.get("image").get("original_url"),
|
||||
},
|
||||
"original_title": original_title,
|
||||
"issue_number": found_result.get("issue_number"),
|
||||
"volume_number": found_result.get("volume_number"),
|
||||
"cover_url": found_result.get("image").get("original_url"),
|
||||
"comicvine_id": found_result.get("id"),
|
||||
"comicvine_data": found_result,
|
||||
}
|
||||
|
||||
return data_dict
|
||||
@ -59,13 +59,15 @@ def lookup_book_from_google(title: str) -> dict:
|
||||
book_dict["genres"] = google_result.get("categories")
|
||||
book_dict["cover_url"] = (
|
||||
google_result.get("imageLinks", {})
|
||||
.get("thumbnail")
|
||||
.get("thumbnail", "")
|
||||
.replace("zoom=1", "zoom=15")
|
||||
.replace("&edge=curl", "")
|
||||
)
|
||||
|
||||
book_dict["run_time_seconds"] = book_dict.get("pages", 10) * getattr(
|
||||
settings, "AVERAGE_PAGE_READING_SECONDS", 60
|
||||
)
|
||||
book_dict["run_time_seconds"] = 3600
|
||||
if book_dict.get("pages"):
|
||||
book_dict["run_time_seconds"] = book_dict.get("pages", 10) * getattr(
|
||||
settings, "AVERAGE_PAGE_READING_SECONDS", 60
|
||||
)
|
||||
|
||||
return book_dict
|
||||
|
||||
18
vrobbler/apps/books/utils.py
Normal file
18
vrobbler/apps/books/utils.py
Normal file
@ -0,0 +1,18 @@
|
||||
from titlecase import titlecase
|
||||
|
||||
def parse_readcomicsonline_uri(uri: str) -> tuple:
|
||||
path = uri.split("comic/")[1]
|
||||
|
||||
parts = path.split('/')
|
||||
title = ""
|
||||
volume = 1
|
||||
page = 1
|
||||
if len(parts) == 2:
|
||||
title = titlecase(parts[0].replace("-", " "))
|
||||
volume = parts[1]
|
||||
if len(parts) == 3:
|
||||
title = titlecase(parts[0].replace("-", " "))
|
||||
volume = parts[1]
|
||||
page = parts[2]
|
||||
|
||||
return title, volume, page
|
||||
@ -4,6 +4,7 @@ from typing import Any
|
||||
from urllib.parse import unquote
|
||||
|
||||
import feedparser
|
||||
import requests
|
||||
from dateutil.parser import ParserError, parse
|
||||
from podcasts.models import PodcastEpisode
|
||||
|
||||
@ -27,30 +28,40 @@ def fetch_metadata_from_rss(uri: str) -> dict[str, Any]:
|
||||
log_context = {"mopidy_uri": uri, "media_type": "Podcast"}
|
||||
podcast_data: dict[str, Any] = {}
|
||||
|
||||
rss_url = uri.split("#")[0].split("podcast+")[1]
|
||||
target_guid = uri.split("#")[1]
|
||||
|
||||
log_context["rss_url"] = rss_url
|
||||
log_context["target_guid"] = target_guid
|
||||
|
||||
try:
|
||||
feed = feedparser.parse(uri.split("#")[0])
|
||||
target_guid = uri.split("#")[1]
|
||||
resp = requests.get(rss_url, timeout=10)
|
||||
feed = feedparser.parse(resp.text)
|
||||
except IndexError:
|
||||
logger.warning("Tried to parse uri as RSS feed, but no target found", extra=log_context)
|
||||
return podcast_data
|
||||
|
||||
podcast_publisher = feed.feed.get("itunes_publisher")
|
||||
podcast_owner = feed.feed.itunes_owner.get("name") if isinstance(feed.feed.itunes_owner, dict) else feed.feed.itunes_owner
|
||||
podcast_other = feed.feed.get("managingeditor") or feed.feed.get("copyright")
|
||||
podcast_publisher = getattr(feed.feed, "itunes_publisher", "")
|
||||
try:
|
||||
podcast_owner = feed.feed.itunes_owner.get("name") if isinstance(feed.feed.itunes_owner, dict) else feed.feed.itunes_owner
|
||||
podcast_other = feed.feed.get("managingeditor") or feed.feed.get("copyright")
|
||||
except AttributeError:
|
||||
podcast_owner = None
|
||||
podcast_other = None
|
||||
|
||||
podcast_data = {
|
||||
"podcast_name": feed.feed.get("title", "Unknown Podcast"),
|
||||
# "podcast_description": feed.feed.get("description", ""),
|
||||
# "podcast_link": feed.feed.get("link", ""),
|
||||
"podcast_name": getattr(feed.feed, "title", ""),
|
||||
# "podcast_description": getattr(feed.feed, "description", ""),
|
||||
# "podcast_link": getattr(feed.feed, "link", ""),
|
||||
"podcast_producer": podcast_publisher or podcast_owner or podcast_other
|
||||
}
|
||||
|
||||
for entry in feed.entries:
|
||||
if target_guid in target_guid:
|
||||
if entry.get("guid") == target_guid:
|
||||
logger.info("🎧 Episode found in RSS feed", extra=log_context)
|
||||
podcast_data["title"] = entry.title
|
||||
podcast_data["episode_num"] = entry.guid
|
||||
podcast_data["pub_date"] = entry.get("published", None)
|
||||
podcast_data["episode_num"] = int(entry.get("itunes_episode", 0))
|
||||
podcast_data["pub_date"] = parse(entry.get("published", None))
|
||||
podcast_data["run_time_seconds"] = parse_duration(entry.get("itunes_duration", None))
|
||||
# podcast_data["description"] = entry.get("description", None)
|
||||
# podcast_data["episode_url"] = entry.enclosures[0].href if entry.get("enclosures") else None
|
||||
@ -63,7 +74,7 @@ def parse_mopidy_uri(uri: str) -> dict[str, Any]:
|
||||
podcast_data: dict[str, Any] = {}
|
||||
|
||||
logger.debug(f"Parsing URI: {uri}")
|
||||
if "https://" in uri:
|
||||
if "podcast+https" in uri:
|
||||
return fetch_metadata_from_rss(uri)
|
||||
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@ import pytz
|
||||
from beers.models import Beer
|
||||
from boardgames.models import BoardGame
|
||||
from books.koreader import process_koreader_sqlite_file
|
||||
from books.models import Book, Paper
|
||||
from books.models import Book, Paper, BookPageLogData, BookLogData
|
||||
from bricksets.models import BrickSet
|
||||
from dataclass_wizard.errors import ParseError
|
||||
from django.conf import settings
|
||||
@ -775,7 +775,7 @@ class Scrobble(TimeStampedModel):
|
||||
and user.profile.redirect_to_webpage
|
||||
):
|
||||
logger.info(f"Redirecting to {self.media_obj.url}")
|
||||
redirect_url = self.media_obj.get_read_url()
|
||||
redirect_url = self.media_obj.url
|
||||
|
||||
if (
|
||||
self.media_type == self.MediaType.VIDEO
|
||||
@ -1131,6 +1131,8 @@ class Scrobble(TimeStampedModel):
|
||||
media_query = models.Q(**{key: media})
|
||||
scrobble_data[key + "_id"] = media.id
|
||||
skip_in_progress_check = kwargs.get("skip_in_progress_check", False)
|
||||
read_log_page = kwargs.get("read_log_page", None)
|
||||
|
||||
|
||||
# Find our last scrobble of this media item (track, video, etc)
|
||||
scrobble = (
|
||||
@ -1154,7 +1156,7 @@ class Scrobble(TimeStampedModel):
|
||||
)
|
||||
return scrobble
|
||||
|
||||
if not skip_in_progress_check:
|
||||
if not skip_in_progress_check or read_log_page:
|
||||
logger.info(
|
||||
f"[create_or_update] check for existing scrobble to update ",
|
||||
extra={
|
||||
@ -1170,15 +1172,34 @@ class Scrobble(TimeStampedModel):
|
||||
# If it's marked as stopped, send it through our update mechanism, which will complete it
|
||||
if scrobble and (
|
||||
scrobble.can_be_updated
|
||||
or read_log_page
|
||||
or scrobble_data["playback_status"] == "stopped"
|
||||
):
|
||||
if "log" in scrobble_data.keys() and scrobble.log:
|
||||
if read_log_page:
|
||||
page_list = scrobble.log.get("page_data", [])
|
||||
if page_list:
|
||||
for page in page_list:
|
||||
if not page.get("end_ts", None):
|
||||
page["end_ts"] = int(timezone.now().timestamp())
|
||||
|
||||
page_list.append(
|
||||
BookPageLogData(
|
||||
page_number=read_log_page,
|
||||
start_ts=int(timezone.now().timestamp())
|
||||
)
|
||||
)
|
||||
scrobble.log["page_data"] = page_list
|
||||
scrobble.save(update_fields=["log"])
|
||||
elif "log" in scrobble_data.keys() and scrobble.log:
|
||||
scrobble_data["log"] = scrobble.log | scrobble_data["log"]
|
||||
return scrobble.update(scrobble_data)
|
||||
|
||||
# Discard status before creating
|
||||
scrobble_data.pop("playback_status")
|
||||
|
||||
if read_log_page:
|
||||
scrobble_data["log"] = BookLogData(page_data=BookPageLogData(page_number=read_log_page, start_ts=int(timezone.now().timestamp())))
|
||||
|
||||
logger.info(
|
||||
f"[scrobbling] creating new scrobble",
|
||||
extra={
|
||||
|
||||
@ -7,7 +7,9 @@ import pendulum
|
||||
import pytz
|
||||
from beers.models import Beer
|
||||
from boardgames.models import BoardGame, BoardGameDesigner, BoardGameLocation
|
||||
from books.models import Book
|
||||
from books.constants import READCOMICSONLINE_URL
|
||||
from books.models import Book, BookLogData, BookPageLogData
|
||||
from books.utils import parse_readcomicsonline_uri
|
||||
from bricksets.models import BrickSet
|
||||
from dateutil.parser import parse
|
||||
from django.utils import timezone
|
||||
@ -255,13 +257,31 @@ def manual_scrobble_video_game(
|
||||
def manual_scrobble_book(
|
||||
title: str, user_id: int, action: Optional[str] = None
|
||||
):
|
||||
book = Book.find_or_create(title)
|
||||
log = {}
|
||||
source = "Vrobbler"
|
||||
page = None
|
||||
|
||||
if READCOMICSONLINE_URL in title:
|
||||
title, volume, page = parse_readcomicsonline_uri(title)
|
||||
title = f"{title} - Issue {volume}"
|
||||
|
||||
if not page:
|
||||
page = 1
|
||||
|
||||
log = BookLogData(page_data=BookPageLogData(page_number=page, start_ts=int(timezone.now().timestamp())))
|
||||
logger.info("[scrobblers] Book page included in scrobble, should update!")
|
||||
|
||||
source = READCOMICSONLINE_URL
|
||||
|
||||
# TODO: Check for scrobble of this book already and if so, update the page count
|
||||
|
||||
book = Book.find_or_create(title, enrich=True)
|
||||
|
||||
scrobble_dict = {
|
||||
"user_id": user_id,
|
||||
"timestamp": timezone.now(),
|
||||
"playback_position_seconds": 0,
|
||||
"source": "Vrobbler",
|
||||
"source": source,
|
||||
"long_play_complete": False,
|
||||
}
|
||||
|
||||
@ -275,7 +295,13 @@ def manual_scrobble_book(
|
||||
},
|
||||
)
|
||||
|
||||
return Scrobble.create_or_update(book, user_id, scrobble_dict)
|
||||
|
||||
scrobble = Scrobble.create_or_update(book, user_id, scrobble_dict, read_log_page=page)
|
||||
|
||||
if action == "stop":
|
||||
scrobble.stop(force_finish=True)
|
||||
|
||||
return scrobble
|
||||
|
||||
|
||||
def manual_scrobble_board_game(
|
||||
@ -532,6 +558,8 @@ def manual_scrobble_from_url(
|
||||
|
||||
if content_key == "-i" and "v=" in url:
|
||||
item_id = url.split("v=")[1].split("&")[0]
|
||||
elif content_key == "-c" and "comics" in url:
|
||||
item_id = url
|
||||
elif content_key == "-i" and "title/tt" in url:
|
||||
item_id = "tt" + str(item_id)
|
||||
|
||||
|
||||
@ -627,7 +627,7 @@ def scrobble_start(request, uuid):
|
||||
user.profile.redirect_to_webpage
|
||||
and media_obj.__class__.__name__ == Scrobble.MediaType.WEBPAGE
|
||||
):
|
||||
logger.info(f"Redirecting to {media_obj} detail apge")
|
||||
logger.info(f"Redirecting to {media_obj} detail page")
|
||||
return HttpResponseRedirect(media_obj.url)
|
||||
|
||||
return HttpResponseRedirect(success_url)
|
||||
|
||||
Reference in New Issue
Block a user