]>
Commit | Line | Data |
---|---|---|
9dee4df5 L |
1 | # coding: utf-8 |
2 | ||
3 | from __future__ import unicode_literals | |
4 | ||
5 | from .common import InfoExtractor | |
6 | from ..utils import ExtractorError, try_get | |
7 | ||
8 | ||
9 | class SaitosanIE(InfoExtractor): | |
10 | IE_NAME = 'Saitosan' | |
11 | _VALID_URL = r'https?://(?:www\.)?saitosan\.net/bview.html\?id=(?P<id>[0-9]+)' | |
12 | _TESTS = [{ | |
13 | 'url': 'http://www.saitosan.net/bview.html?id=10031846', | |
14 | 'info_dict': { | |
15 | 'id': '10031846', | |
16 | 'ext': 'mp4', | |
17 | 'title': '井下原 和弥', | |
18 | 'uploader': '井下原 和弥', | |
19 | 'thumbnail': 'http://111.171.196.85:8088/921f916f-7f55-4c97-b92e-5d9d0fef8f5f/thumb', | |
20 | 'is_live': True, | |
21 | }, | |
22 | 'params': { | |
23 | # m3u8 download | |
24 | 'skip_download': True, | |
25 | }, | |
26 | 'skip': 'Broadcasts are ephemeral', | |
27 | }, | |
28 | { | |
29 | 'url': 'http://www.saitosan.net/bview.html?id=10031795', | |
30 | 'info_dict': { | |
31 | 'id': '10031795', | |
32 | 'ext': 'mp4', | |
33 | 'title': '橋本', | |
34 | 'uploader': '橋本', | |
35 | 'thumbnail': 'http://111.171.196.85:8088/1a3933e1-a01a-483b-8931-af15f37f8082/thumb', | |
36 | 'is_live': True, | |
37 | }, | |
38 | 'params': { | |
39 | # m3u8 download | |
40 | 'skip_download': True, | |
41 | }, | |
42 | 'skip': 'Broadcasts are ephemeral', | |
43 | }] | |
44 | ||
45 | def _real_extract(self, url): | |
46 | b_id = self._match_id(url) | |
47 | ||
48 | base = 'http://hankachi.saitosan-api.net:8002/socket.io/?transport=polling&EIO=3' | |
49 | sid = self._download_socket_json(base, b_id, note='Opening socket').get('sid') | |
50 | base += '&sid=' + sid | |
51 | ||
52 | self._download_webpage(base, b_id, note='Polling socket') | |
53 | payload = '420["room_start_join",{"room_id":"%s"}]' % b_id | |
54 | payload = '%s:%s' % (len(payload), payload) | |
55 | ||
56 | self._download_webpage(base, b_id, data=payload, note='Polling socket with payload') | |
57 | response = self._download_socket_json(base, b_id, note='Polling socket') | |
58 | if not response.get('ok'): | |
59 | err = response.get('error') or {} | |
60 | raise ExtractorError( | |
61 | '%s said: %s - %s' % (self.IE_NAME, err.get('code', '?'), err.get('msg', 'Unknown')) if err | |
62 | else 'The socket reported that the broadcast could not be joined. Maybe it\'s offline or the URL is incorrect', | |
63 | expected=True, video_id=b_id) | |
64 | ||
65 | self._download_webpage(base, b_id, data='26:421["room_finish_join",{}]', note='Polling socket') | |
66 | b_data = self._download_socket_json(base, b_id, note='Getting broadcast metadata from socket') | |
67 | m3u8_url = b_data.get('url') | |
68 | ||
69 | self._download_webpage(base, b_id, data='1:1', note='Closing socket', fatal=False) | |
70 | ||
71 | return { | |
72 | 'id': b_id, | |
73 | 'title': b_data.get('name'), | |
74 | 'formats': self._extract_m3u8_formats(m3u8_url, b_id, 'mp4', live=True), | |
75 | 'thumbnail': m3u8_url.replace('av.m3u8', 'thumb'), | |
76 | 'uploader': try_get(b_data, lambda x: x['broadcast_user']['name']), # same as title | |
77 | 'is_live': True | |
78 | } |