mirror of https://github.com/streamlink/streamlink
docs: add support for $metadata plugin metadata
This allows plugins to optionally define which stream metadata variables are available, with an optional comment for each variable. `$metadata` can be repeated multiple times, once for each supported variable, and it must be set immediately after the mandatory `$type`. The supported variables must be defined in the following order: - id - author - category - title The optional comment is separated by a simple space character, but it is rendered differently in the docs.
This commit is contained in:
parent
4631aeffed
commit
b547fe41b5
|
@ -52,10 +52,24 @@ class MetadataList(IMetadataItem):
|
|||
def generate(self) -> Iterator[str]:
|
||||
if not self.value:
|
||||
return
|
||||
yield f":{self.title}: - {' '.join(self.get_item(0))}"
|
||||
indent = " " * len(f":{self.title}:")
|
||||
yield f":{self.title}: - {self.value[0]}"
|
||||
for val in self.value[1:]:
|
||||
yield f"{indent} - {val}"
|
||||
for idx in range(1, len(self.value)):
|
||||
yield f"{indent} - {' '.join(self.get_item(idx))}"
|
||||
|
||||
def get_item(self, idx: int) -> Iterator[str]:
|
||||
yield self.value[idx]
|
||||
|
||||
|
||||
class MetadataMetadataList(MetadataList):
|
||||
def __init__(self):
|
||||
super().__init__("Metadata")
|
||||
|
||||
def get_item(self, idx: int) -> Iterator[str]:
|
||||
variable, *data = str(self.value[idx]).split(" ")
|
||||
yield f":ref:`{variable} <cli/metadata:Variables>`"
|
||||
if data:
|
||||
yield " ".join(["-", *data])
|
||||
|
||||
|
||||
class PluginOnGithub(IDatalistItem):
|
||||
|
@ -144,6 +158,7 @@ class PluginMetadata:
|
|||
description=MetadataItem("Description"),
|
||||
url=MetadataList("URL(s)"),
|
||||
type=MetadataItem("Type"),
|
||||
metadata=MetadataMetadataList(),
|
||||
region=MetadataItem("Region"),
|
||||
account=MetadataItem("Account"),
|
||||
notes=MetadataList("Notes"),
|
||||
|
|
|
@ -36,6 +36,12 @@ plugintests = [
|
|||
if tname.startswith("test_") and tname not in plugintests_ignore
|
||||
]
|
||||
|
||||
PLUGIN_TYPES = "live", "vod", "live, vod"
|
||||
PLUGIN_METADATA = "id", "author", "category", "title"
|
||||
|
||||
re_url = re.compile("^https?://")
|
||||
re_metadata = re.compile(rf"^({'|'.join(re.escape(item) for item in PLUGIN_METADATA)})(\s.+)?$")
|
||||
|
||||
|
||||
def unique(iterable):
|
||||
seen = set()
|
||||
|
@ -102,6 +108,7 @@ class TestPluginMetadata:
|
|||
"description",
|
||||
"url",
|
||||
"type",
|
||||
"metadata",
|
||||
"region",
|
||||
"account",
|
||||
"notes",
|
||||
|
@ -119,6 +126,7 @@ class TestPluginMetadata:
|
|||
def metadata_keys_repeat(self):
|
||||
return (
|
||||
"url",
|
||||
"metadata",
|
||||
"notes",
|
||||
)
|
||||
|
||||
|
@ -186,9 +194,16 @@ class TestPluginMetadata:
|
|||
assert keys == tuple(unique(keys)), "Non-repeatable keys are set at most only once"
|
||||
|
||||
def test_key_url(self, metadata_items):
|
||||
assert not any(re.match("^https?://", val) for key, val in metadata_items if key == "url"), \
|
||||
"URL metadata values don't start with http:// or https://"
|
||||
assert not any(re_url.match(val) for key, val in metadata_items if key == "url"), \
|
||||
"$url metadata values don't start with http:// or https://"
|
||||
|
||||
def test_key_type(self, metadata_dict):
|
||||
assert metadata_dict.get("type") in ("live", "vod", "live, vod"), \
|
||||
"Type metadata has the correct value"
|
||||
assert metadata_dict.get("type") in PLUGIN_TYPES, \
|
||||
"$type metadata has the correct value"
|
||||
|
||||
def test_key_metadata(self, metadata_items):
|
||||
assert all(re_metadata.match(val) for key, val in metadata_items if key == "metadata"), \
|
||||
"$metadata metadata values have the correct format"
|
||||
indexes = [PLUGIN_METADATA.index(val.split(" ")[0]) for key, val in metadata_items if key == "metadata"]
|
||||
assert [PLUGIN_METADATA[i] for i in indexes] == [PLUGIN_METADATA[i] for i in sorted(indexes)], \
|
||||
"$metadata metadata values are ordered correctly"
|
||||
|
|
Loading…
Reference in New Issue