Repository: streamlink/streamlink

Issue:
player.tamago.live Plugin
<!--
Thanks for requesting a plugin!
USE THE TEMPLATE. Otherwise your plugin request may be rejected.

First, see the contribution guidelines and plugin request requirements:
https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink

Plugin requests which fall into the categories we will not implement will be closed immediately.

Also check the list of open and closed plugin requests:
https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+request%22

Please see the text preview to avoid unnecessary formatting errors.
-->


## Plugin Request

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a plugin request and I have read the contribution guidelines and plugin request requirements.


### Description

https://player.tamago.live

**Tamago** is a live streaming social network that lets you watch or broadcast live video anytime, anywhere. Like *Twitch*, streamers can interact with their viewers in a chat box. Get exclusive content, from your favourite TV shows and concerts, to the hottest e-sports leagues and more, get front row seats or go behind the scenes with Tamago.  

Showcase your talent to a wide audience of viewers and fellow broadcasters. Live video streaming is spontaneous and does not have to be perfect, so anyone can be a broadcaster! You can get rewarded for broadcasting too! Collect gifts during your live streams and keep the profits when you cash out. 

https://download.tamago.live/faq

### Example stream URLs

<!-- Example URLs for streams are required. Plugin requests which do not have example URLs will be closed. -->

1. https://player.tamago.live/w/2009642
2. https://player.tamago.live/w/1882066
3. https://player.tamago.live/w/1870142
4. https://player.tamago.live/w/1729968
5. ...

### Additional comments, screenshots, etc.



[Love Streamlink? Please consider supporting our collective. Thanks!](https://opencollective.com/streamlink/donate)



Discussion:

Resolving patch:
diff --git a/src/streamlink/plugins/tamago.py b/src/streamlink/plugins/tamago.py
new file mode 100644
--- /dev/null
+++ b/src/streamlink/plugins/tamago.py
@@ -0,0 +1,52 @@
+import re
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import validate
+from streamlink.stream import HTTPStream
+from streamlink import NoStreamsError
+
+
+class Tamago(Plugin):
+
+    _url_re = re.compile(r"https?://(?:player\.)?tamago\.live/w/(?P<id>\d+)")
+
+    _api_url_base = "https://player.tamago.live/api/rooms/{id}"
+
+    _api_response_schema = validate.Schema({
+        u"status": 200,
+        u"message": u"Success",
+        u"data": {
+            u"room_number": validate.text,
+            u"stream": {validate.text: validate.url()}
+        }
+    })
+
+    _stream_qualities = {
+        u"150": "144p",
+        u"350": "360p",
+        u"550": "540p",
+        u"900": "720p",
+    }
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url) is not None
+
+    def _get_streams(self):
+        user_id = self._url_re.match(self.url).group('id')
+
+        try:
+            api_response = self.session.http.get(self._api_url_base.format(id=user_id))
+            streams = self.session.http.json(api_response, schema=self._api_response_schema)['data']['stream']
+        except Exception:
+            raise NoStreamsError(self.url)
+
+        unique_stream_urls = []
+        for stream in streams.keys():
+            if streams[stream] not in unique_stream_urls:
+                unique_stream_urls.append(streams[stream])
+                quality = self._stream_qualities[stream] if stream in self._stream_qualities.keys() else "720p+"
+                yield quality, HTTPStream(self.session, streams[stream])
+
+
+__plugin__ = Tamago


Test patch:
diff --git a/tests/plugins/test_tamago.py b/tests/plugins/test_tamago.py
new file mode 100644
--- /dev/null
+++ b/tests/plugins/test_tamago.py
@@ -0,0 +1,24 @@
+import unittest
+
+from streamlink.plugins.tamago import Tamago
+
+
+class TestPluginTamago(unittest.TestCase):
+    def test_can_handle_url(self):
+        should_match = [
+            'https://player.tamago.live/w/2009642',
+            'https://player.tamago.live/w/1882066',
+            'https://player.tamago.live/w/1870142',
+            'https://player.tamago.live/w/1729968',
+        ]
+        for url in should_match:
+            self.assertTrue(Tamago.can_handle_url(url))
+
+    def test_can_handle_url_negative(self):
+        should_not_match = [
+            'https://download.tamago.live/faq',
+            'https://player.tamago.live/gaming/pubg',
+            'https://www.twitch.tv/twitch'
+        ]
+        for url in should_not_match:
+            self.assertFalse(Tamago.can_handle_url(url))