Repository: streamlink/streamlink
Pull request #2793 (2020-02-08 01:56:47)

Added support for Latina (formerly Frecuencia Latina), southamerican …
…television network located in Peru.

codecov[bot]: # [Codecov](https://codecov.io/gh/streamlink/streamlink/pull/2793?src=pr&el=h1) Report
> Merging [#2793](https://codecov.io/gh/streamlink/streamlink/pull/2793?src=pr&el=desc) into [master](https://codecov.io/gh/streamlink/streamlink/commit/045f2c6f3f4aefd2f9f75d79c44bce92d1dbec98&el=desc) will **decrease** coverage by `1.08%`.
> The diff coverage is `n/a`.


```diff
@@            Coverage Diff             @@
##           master    #2793      +/-   ##
==========================================
- Coverage   52.87%   51.78%   -1.09%     
==========================================
  Files         246      247       +1     
  Lines       15428    15118     -310     
==========================================
- Hits         8157     7829     -328     
- Misses       7271     7289      +18     
```


Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index 7f02e8a1..b21f4233 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -110,6 +110,7 @@ itvplayer               itv.com/itvplayer    Yes   Yes   Streams may be geo-rest
 kanal7                  - kanal7.com         Yes   No
                         - tvt.tv.tr
 kingkong                kingkong.com.tw      Yes   --
+latina                  latina.pe            Yes   No    Streams may be geo-restricted to Peru.
 linelive                live.line.me         Yes   Yes
 live_russia_tv          live.russia.tv       Yes   --
 liveedu                 - liveedu.tv         Yes   --    Some streams require a login.
diff --git a/src/streamlink/plugins/latina.py b/src/streamlink/plugins/latina.py
new file mode 100644
index 00000000..4fcc9cd2
--- /dev/null
+++ b/src/streamlink/plugins/latina.py
@@ -0,0 +1,40 @@
+import logging
+import re
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import useragents
+from streamlink.plugin.api.utils import itertags
+from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
+
+
+class Latina(Plugin):
+    _url_re = re.compile(r"https?://(?:www\.)?latina\.pe/tvenvivo")
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
+
+    def get_title(self):
+        return "Latina"
+
+    def _get_streams(self):
+        self.session.http.headers.update({
+            "User-Agent": useragents.CHROME,
+            "Referer": self.url})
+
+        self.session.http.get(self.url)
+        stream_url = None
+        for div in itertags(self.session.http.get(self.url).text, "div"):
+            if div.attributes.get("id") == "player":
+                stream_url = div.attributes.get("data-stream")
+
+        if stream_url:
+            log.debug("URL={0}".format(stream_url))
+            return HLSStream.parse_variant_playlist(self.session,
+                                                    stream_url,
+                                                    name_fmt="{pixels}_{bitrate}")
+
+
+__plugin__ = Latina


Test patch:
diff --git a/tests/plugins/test_latina.py b/tests/plugins/test_latina.py
new file mode 100644
index 00000000..6a312996
--- /dev/null
+++ b/tests/plugins/test_latina.py
@@ -0,0 +1,19 @@
+import unittest
+
+from streamlink.plugins.latina import Latina
+
+
+class TestPluginLatina(unittest.TestCase):
+    def test_can_handle_url(self):
+        should_match = [
+            'http://www.latina.pe/tvenvivo/',
+        ]
+        for url in should_match:
+            self.assertTrue(Latina.can_handle_url(url), url)
+
+    def test_can_handle_url_negative(self):
+        should_not_match = [
+            'http://www.latina.pe/',
+        ]
+        for url in should_not_match:
+            self.assertFalse(Latina.can_handle_url(url), url)