Newer
Older
import marshmallow
import semver
import re
class VersionField(marshmallow.fields.Str):
def deserialize(self, value, *args, **kwargs):
value = super().deserialize(value, *args, **kwargs)
try:
return semver.parse(value)
except ValueError:
# funkwhale does not always include the patch version, so we add the 0 ourself and
# try again
try:
v_regex = r"(\d+\.\d+)"
match = re.match(v_regex, value)
if match and match[0]:
new_version = f"{match[0]}.0"
return semver.parse(value.replace(match[0], new_version, 1))
raise ValueError()
except (ValueError, IndexError):
raise marshmallow.ValidationError(
f"{value} is not a semver version number"
)
return value
class SoftwareSchema(marshmallow.Schema):
name = marshmallow.fields.String(
required=True, validate=[marshmallow.validate.OneOf(["funkwhale", "Funkwhale"])]
)
version = VersionField(required=True)
"""
"openRegistrations": False,
"usage": {"users": {"total": 78}},
"metadata": {
"private": False,
"nodeName": "Funkwhale 101",
"library": {
"federationEnabled": True,
"federationNeedsApproval": True,
"anonymousCanListen": True,
"tracks": {"total": 98552},
"artists": {"total": 9831},
"albums": {"total": 10872},
"music": {"hours": 7650.678055555555},
},
"usage": {
"favorites": {"tracks": {"total": 1683}},
"listenings": {"total": 50294},
},
},
}
"""
class StatisticsSchema(marshmallow.Schema):
total = marshmallow.fields.Integer(required=True)
class UsageStatisticsSchema(StatisticsSchema):
activeHalfyear = marshmallow.fields.Integer(required=False)
activeMonth = marshmallow.fields.Integer(required=False)
class UsageSchema(marshmallow.Schema):
users = marshmallow.fields.Nested(UsageStatisticsSchema, required=True)
class MusicSchema(marshmallow.Schema):
hours = marshmallow.fields.Integer(required=False)
class LibraryMetadataSchema(marshmallow.Schema):
anonymousCanListen = marshmallow.fields.Boolean(required=True)
federationEnabled = marshmallow.fields.Boolean(required=True)
tracks = marshmallow.fields.Nested(StatisticsSchema, required=False)
albums = marshmallow.fields.Nested(StatisticsSchema, required=False)
artists = marshmallow.fields.Nested(StatisticsSchema, required=False)
music = marshmallow.fields.Nested(MusicSchema, required=False)
class MetadataUsageSchema(marshmallow.Schema):
listenings = marshmallow.fields.Nested(StatisticsSchema, required=False)
downloads = marshmallow.fields.Nested(StatisticsSchema, required=False)
class MetadataSchema(marshmallow.Schema):
nodeName = marshmallow.fields.String(required=True)
private = marshmallow.fields.Boolean(required=True)
library = marshmallow.fields.Nested(LibraryMetadataSchema, required=True)
usage = marshmallow.fields.Nested(MetadataUsageSchema, required=True)
class NodeInfo2Schema(marshmallow.Schema):
software = marshmallow.fields.Nested(SoftwareSchema, required=True)
openRegistrations = marshmallow.fields.Boolean(required=True)
usage = marshmallow.fields.Nested(UsageSchema, required=True)
metadata = marshmallow.fields.Nested(MetadataSchema, required=True)
class Meta: