See #170: fixed several feed parsing issues, again 3
This commit is contained in:
parent
21972d9630
commit
e6df21b96c
|
@ -323,7 +323,7 @@ def retrieve_feed(url):
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def get_channel_from_rss_url(url):
|
def get_channel_from_rss_url(url, raise_exception=False):
|
||||||
# first, check if the url is blocked
|
# first, check if the url is blocked
|
||||||
is_valid, _ = mrf.inbox.apply({"id": url})
|
is_valid, _ = mrf.inbox.apply({"id": url})
|
||||||
if not is_valid:
|
if not is_valid:
|
||||||
|
@ -335,7 +335,7 @@ def get_channel_from_rss_url(url):
|
||||||
|
|
||||||
parsed_feed = feedparser.parse(response.text)
|
parsed_feed = feedparser.parse(response.text)
|
||||||
serializer = RssFeedSerializer(data=parsed_feed["feed"])
|
serializer = RssFeedSerializer(data=parsed_feed["feed"])
|
||||||
if not serializer.is_valid():
|
if not serializer.is_valid(raise_exception=raise_exception):
|
||||||
raise FeedFetchException("Invalid xml content: {}".format(serializer.errors))
|
raise FeedFetchException("Invalid xml content: {}".format(serializer.errors))
|
||||||
|
|
||||||
# second mrf check with validated data
|
# second mrf check with validated data
|
||||||
|
@ -372,7 +372,7 @@ def get_channel_from_rss_url(url):
|
||||||
for entry in entries[: settings.PODCASTS_RSS_FEED_MAX_ITEMS]:
|
for entry in entries[: settings.PODCASTS_RSS_FEED_MAX_ITEMS]:
|
||||||
logger.debug("Importing feed item %s", entry.id)
|
logger.debug("Importing feed item %s", entry.id)
|
||||||
s = RssFeedItemSerializer(data=entry)
|
s = RssFeedItemSerializer(data=entry)
|
||||||
if not s.is_valid():
|
if not s.is_valid(raise_exception=raise_exception):
|
||||||
logger.debug("Skipping invalid RSS feed item %s, ", entry, str(s.errors))
|
logger.debug("Skipping invalid RSS feed item %s, ", entry, str(s.errors))
|
||||||
continue
|
continue
|
||||||
uploads.append(
|
uploads.append(
|
||||||
|
@ -395,12 +395,13 @@ def get_channel_from_rss_url(url):
|
||||||
|
|
||||||
class RssFeedSerializer(serializers.Serializer):
|
class RssFeedSerializer(serializers.Serializer):
|
||||||
title = serializers.CharField()
|
title = serializers.CharField()
|
||||||
link = serializers.URLField()
|
link = serializers.URLField(required=False, allow_blank=True)
|
||||||
language = serializers.CharField(required=False, allow_blank=True)
|
language = serializers.CharField(required=False, allow_blank=True)
|
||||||
rights = serializers.CharField(required=False, allow_blank=True)
|
rights = serializers.CharField(required=False, allow_blank=True)
|
||||||
itunes_explicit = serializers.BooleanField(required=False, allow_null=True)
|
itunes_explicit = serializers.BooleanField(required=False, allow_null=True)
|
||||||
tags = serializers.ListField(required=False)
|
tags = serializers.ListField(required=False)
|
||||||
atom_link = serializers.DictField(required=False)
|
atom_link = serializers.DictField(required=False)
|
||||||
|
links = serializers.ListField(required=False)
|
||||||
summary_detail = serializers.DictField(required=False)
|
summary_detail = serializers.DictField(required=False)
|
||||||
author_detail = serializers.DictField(required=False)
|
author_detail = serializers.DictField(required=False)
|
||||||
image = serializers.DictField(required=False)
|
image = serializers.DictField(required=False)
|
||||||
|
@ -412,6 +413,11 @@ class RssFeedSerializer(serializers.Serializer):
|
||||||
):
|
):
|
||||||
return v["href"]
|
return v["href"]
|
||||||
|
|
||||||
|
def validate_links(self, v):
|
||||||
|
for link in v:
|
||||||
|
if link.get("rel") == "self":
|
||||||
|
return link.get("href")
|
||||||
|
|
||||||
def validate_summary_detail(self, v):
|
def validate_summary_detail(self, v):
|
||||||
content = v.get("value")
|
content = v.get("value")
|
||||||
if not content:
|
if not content:
|
||||||
|
@ -454,6 +460,14 @@ class RssFeedSerializer(serializers.Serializer):
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def validate(self, data):
|
||||||
|
validated_data = super().validate(data)
|
||||||
|
if not validated_data.get("link"):
|
||||||
|
validated_data["link"] = validated_data.get("links")
|
||||||
|
if not validated_data.get("link"):
|
||||||
|
raise serializers.ValidationError("Missing link")
|
||||||
|
return validated_data
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def save(self, rss_url):
|
def save(self, rss_url):
|
||||||
validated_data = self.validated_data
|
validated_data = self.validated_data
|
||||||
|
@ -605,9 +619,15 @@ class RssFeedItemSerializer(serializers.Serializer):
|
||||||
id = serializers.CharField()
|
id = serializers.CharField()
|
||||||
title = serializers.CharField()
|
title = serializers.CharField()
|
||||||
rights = serializers.CharField(required=False, allow_blank=True)
|
rights = serializers.CharField(required=False, allow_blank=True)
|
||||||
itunes_season = serializers.IntegerField(required=False)
|
itunes_season = serializers.IntegerField(
|
||||||
itunes_episode = PermissiveIntegerField(required=False, default=None)
|
required=False, allow_null=True, default=None
|
||||||
itunes_duration = ItunesDurationField(required=False)
|
)
|
||||||
|
itunes_episode = PermissiveIntegerField(
|
||||||
|
required=False, allow_null=True, default=None
|
||||||
|
)
|
||||||
|
itunes_duration = ItunesDurationField(
|
||||||
|
required=False, allow_null=True, default=None, allow_blank=True
|
||||||
|
)
|
||||||
links = serializers.ListField()
|
links = serializers.ListField()
|
||||||
tags = serializers.ListField(required=False)
|
tags = serializers.ListField(required=False)
|
||||||
summary_detail = serializers.DictField(required=False)
|
summary_detail = serializers.DictField(required=False)
|
||||||
|
@ -697,8 +717,8 @@ class RssFeedItemSerializer(serializers.Serializer):
|
||||||
track_defaults = track_defaults
|
track_defaults = track_defaults
|
||||||
track_defaults.update(
|
track_defaults.update(
|
||||||
{
|
{
|
||||||
"disc_number": validated_data.get("itunes_season", 1),
|
"disc_number": validated_data.get("itunes_season", 1) or 1,
|
||||||
"position": validated_data.get("itunes_episode", 1),
|
"position": validated_data.get("itunes_episode", 1) or 1,
|
||||||
"title": validated_data["title"][
|
"title": validated_data["title"][
|
||||||
: music_models.MAX_LENGTHS["TRACK_TITLE"]
|
: music_models.MAX_LENGTHS["TRACK_TITLE"]
|
||||||
],
|
],
|
||||||
|
@ -706,7 +726,7 @@ class RssFeedItemSerializer(serializers.Serializer):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if "rights" in validated_data:
|
if "rights" in validated_data:
|
||||||
track_defaults["rights"] = validated_data["rights"][
|
track_defaults["copyright"] = validated_data["rights"][
|
||||||
: music_models.MAX_LENGTHS["COPYRIGHT"]
|
: music_models.MAX_LENGTHS["COPYRIGHT"]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -719,7 +739,7 @@ class RssFeedItemSerializer(serializers.Serializer):
|
||||||
"source": validated_data["links"]["audio"]["source"],
|
"source": validated_data["links"]["audio"]["source"],
|
||||||
"size": validated_data["links"]["audio"]["size"],
|
"size": validated_data["links"]["audio"]["size"],
|
||||||
"mimetype": validated_data["links"]["audio"]["mimetype"],
|
"mimetype": validated_data["links"]["audio"]["mimetype"],
|
||||||
"duration": validated_data.get("itunes_duration"),
|
"duration": validated_data.get("itunes_duration") or None,
|
||||||
"import_status": "finished",
|
"import_status": "finished",
|
||||||
"library": channel.library,
|
"library": channel.library,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue