Repository: streamlink/streamlink

Issue:
[plugin request] delfi.lt
### Checklist

- [ ] This is a bug report.
- [ ] This is a feature request.
- [x] This is a plugin (improvement) request.
- [x] I have read the contribution guidelines.

### Description

[And just one more, please... :)] 

Would it be possible to add a plugin for the [Delfi](https://en.wikipedia.org/wiki/Delfi_(web_portal)) web portal? Video streams' examples can be found [here](http://www.delfi.lt/video/sportas/kroatiska-tvarka-kaliningrade-laisvai-liejosi-gerimai-dainos-sokiai-ir-ziezirbos.d?id=78322857), [here](https://www.delfi.lt/video/sportas/zalgiris-atsidure-per-pergale-nuo-lkl-aukso.d?id=78321125), and [here](https://www.delfi.lt/video/laidos/nba/warriors-cempioniskomis-tapusios-ketvirtos-finalo-rungtynes.d?id=78246059).

Thank you in advance :).


Discussion:

Resolving patch:
diff --git a/src/streamlink/plugins/delfi.py b/src/streamlink/plugins/delfi.py
new file mode 100644
--- /dev/null
+++ b/src/streamlink/plugins/delfi.py
@@ -0,0 +1,68 @@
+"""
+Plugin to support the videos from Delfi.lt
+
+https://en.wikipedia.org/wiki/Delfi_(web_portal)
+"""
+import re
+import logging
+
+import itertools
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api.utils import itertags
+from streamlink.stream import HTTPStream, HLSStream, DASHStream
+from streamlink.utils import update_scheme
+
+log = logging.getLogger(__name__)
+
+
+class Delfi(Plugin):
+    url_re = re.compile(r"https?://(?:[\w-]+\.)?delfi\.(lt|lv|ee)")
+    _api = {
+        "lt": "http://g2.dcdn.lt/vfe/data.php",
+        "lv": "http://g.delphi.lv/vfe/data.php",
+        "ee": "http://g4.nh.ee/vfe/data.php"
+    }
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls.url_re.match(url) is not None
+
+    @property
+    def api_server(self):
+        m = self.url_re.match(self.url)
+        domain = m and m.group(1)
+        return self._api.get(domain, "lt")  # fallback to lt
+
+    def _get_streams_api(self, video_id):
+        res = self.session.http.get(self.api_server,
+                                    params=dict(video_id=video_id))
+        data = self.session.http.json(res)
+        if data["success"]:
+            for x in itertools.chain(*data['data']['versions'].values()):
+                src = update_scheme(self.url, x['src'])
+                if x['type'] == "application/x-mpegurl":
+                    for s in HLSStream.parse_variant_playlist(self.session, src).items():
+                        yield s
+                elif x['type'] == "application/dash+xml":
+                    for s in DASHStream.parse_manifest(self.session, src).items():
+                        yield s
+                elif x['type'] == "video/mp4":
+                    yield "{0}p".format(x['res']), HTTPStream(self.session, src)
+        else:
+            log.error("Failed to get streams: {0} ({1})".format(
+                data['message'], data['code']
+            ))
+
+
+    def _get_streams(self):
+        res = self.session.http.get(self.url)
+        for div in itertags(res.text, 'div'):
+            if div.attributes.get("data-provider") == "dvideo":
+                video_id = div.attributes.get("data-id")
+                log.debug("Found video ID: {0}".format(video_id))
+                for s in self._get_streams_api(video_id):
+                    yield s
+
+
+__plugin__ = Delfi


Test patch:
diff --git a/tests/test_plugin_delfi.py b/tests/test_plugin_delfi.py
new file mode 100644
--- /dev/null
+++ b/tests/test_plugin_delfi.py
@@ -0,0 +1,22 @@
+import unittest
+
+from streamlink import Streamlink
+from streamlink.plugins.delfi import Delfi
+
+
+class TestPluginDelfi(unittest.TestCase):
+    def setUp(self):
+        self.session = Streamlink()
+
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(Delfi.can_handle_url("http://www.delfi.lt/video/sportas/kroatiska-tvarka-kaliningrade-laisvai-liejosi-gerimai-dainos-sokiai-ir-ziezirbos.d?id=78322857"))
+        self.assertTrue(Delfi.can_handle_url("https://www.delfi.lt/video/sportas/zalgiris-atsidure-per-pergale-nuo-lkl-aukso.d?id=78321125"))
+        self.assertTrue(Delfi.can_handle_url("https://www.delfi.lt/video/laidos/nba/warriors-cempioniskomis-tapusios-ketvirtos-finalo-rungtynes.d?id=78246059"))
+        self.assertTrue(Delfi.can_handle_url("http://rahvahaal.delfi.ee/news/videod/video-joviaalne-piduline-kaotab-raekoja-platsil-ilutulestiku-ule-kontrolli-ja-raketid-lendavad-rahva-sekka?id=82681069"))
+        self.assertTrue(Delfi.can_handle_url("http://www.delfi.lv/delfi-tv-ar-jani-domburu/pilnie-raidijumi/delfi-tv-ar-jani-domburu-atbild-veselibas-ministre-anda-caksa-pilna-intervija?id=49515013"))
+
+    def test_can_handle_url_negative(self):
+        # shouldn't match
+        self.assertFalse(Delfi.can_handle_url("http://www.tvcatchup.com/"))
+        self.assertFalse(Delfi.can_handle_url("http://www.youtube.com/"))