Skip to content

Commit d914a9a

Browse files
committed
^q^
1 parent edb9a6b commit d914a9a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1206
-884
lines changed

src/extractor/_4chan_downloader.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import downloader
2-
from utils import Downloader, File, clean_title, urljoin, get_ext
3-
from ratelimit import limits, sleep_and_retry
2+
from utils import Downloader, File, clean_title, urljoin, get_ext, limits
43
import utils
54

65

@@ -9,8 +8,7 @@ class File_4chan(File):
98
type = '4chan'
109
format = 'page:04;'
1110

12-
@sleep_and_retry
13-
@limits(2, 1)
11+
@limits(.5)
1412
def get(self):
1513
return {}
1614

@@ -21,6 +19,7 @@ class Downloader_4chan(Downloader):
2119
URLS = [r'regex:boards.(4chan|4channel).org']
2220
MAX_CORE = 4
2321
display_name = '4chan'
22+
ACCEPT_COOKIES = [r'(.*\.)?(4chan|4channel)\.org']
2423

2524
@classmethod
2625
def fix_url(cls, url):

src/extractor/afreeca_downloader.py

Lines changed: 96 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import downloader
2-
from utils import Soup, Downloader, Session, try_n, format_filename, cut_pair, File, get_print
2+
from utils import Soup, Downloader, Session, try_n, format_filename, cut_pair, File, get_print, print_error, json
33
import ree as re
44
from io import BytesIO
55
from m3u8_tools import playlist2stream, M3u8_stream
66
import errors
7-
import json
7+
import utils
8+
import os
89

910

1011
class LoginRequired(errors.LoginRequired):
@@ -18,6 +19,7 @@ class Downloader_afreeca(Downloader):
1819
URLS = ['afreecatv.com']
1920
single = True
2021
display_name = 'AfreecaTV'
22+
ACCEPT_COOKIES = [r'(.*\.)?afreecatv\.com']
2123

2224
def init(self):
2325
self.session = Session()
@@ -35,27 +37,40 @@ def read(self):
3537
downloader.download(video['url_thumb'], buffer=thumb)
3638
self.setIcon(thumb)
3739

38-
self.title = video['title']
40+
self.title = os.path.splitext(video['name'])[0].replace(':', ':')
41+
self.artist = video['artist']
42+
43+
if video['live']:
44+
d = {}
45+
d['url'] = self.url
46+
d['title'] = self.artist
47+
d['thumb'] = thumb.getvalue()
48+
utils.update_live(d, self.cw)
3949

4050

4151
@try_n(4)
42-
def _get_stream(url_m3u8):
43-
print('_get_stream', url_m3u8)
52+
def _get_stream(url_m3u8, session, referer, cw=None):
53+
print_ = get_print(cw)
54+
print_(f'_get_stream: {url_m3u8}')
4455
try:
45-
stream = playlist2stream(url_m3u8)
56+
stream = playlist2stream(url_m3u8, referer=referer, session=session)
4657
except Exception as e:
47-
print(e)
48-
stream = M3u8_stream(url_m3u8)
58+
print_(print_error(e))
59+
stream = M3u8_stream(url_m3u8, referer=referer, session=session)
4960
return stream
5061

5162

5263

5364
class Video(File):
5465
type = 'afreeca'
66+
_live_info = None
5567

5668
def get(self):
5769
print_ = get_print(self.cw)
5870
url, session = self['referer'], self.session
71+
if session is None:
72+
session = Session()
73+
session.purge('afreeca')
5974

6075
html = downloader.read_html(url, session=session)
6176
if "document.location.href='https://login." in html:
@@ -69,8 +84,34 @@ def get(self):
6984
url_thumb = soup.find('meta', {'property': 'og:image'}).attrs['content']
7085
print_('url_thumb: {}'.format(url_thumb))
7186

72-
vid = re.find('/player/([0-9]+)', url, err='no vid')
73-
if f'{vid}/catch' in url: #6215
87+
vid = re.find('/player/([0-9]+)', url)
88+
if vid is None: # live
89+
bid = re.find('afreecatv.com/([^/]+)', url, err='no bid')
90+
91+
url_api = f'https://st.afreecatv.com/api/get_station_status.php?szBjId={bid}'
92+
r = session.post(url_api, headers={'Referer': url})
93+
d = json.loads(r.text)
94+
artist = d['DATA']['user_nick']
95+
if self._live_info is not None:
96+
self._live_info['title'] = artist
97+
98+
url_api = f'https://live.afreecatv.com/afreeca/player_live_api.php?bjid={bid}'
99+
#bno = re.find('afreecatv.com/[^/]+/([0-9]+)', url, err='no bno')
100+
bno = re.find(r'nBroadNo\s=\s([0-9]+)', html, err='no bno') #6915
101+
r = session.post(url_api, data={'bid': bid, 'bno': bno, 'type': 'aid', 'pwd': '', 'player_type': 'html5', 'stream_type': 'common', 'quality': 'master', 'mode': 'landing', 'from_api': '0'}, headers={'Referer': url})
102+
d = json.loads(r.text)
103+
res = d['CHANNEL'].get('RESULT')
104+
print_(f'result: {res}')
105+
if res == -6:
106+
raise LoginRequired()
107+
aid = d['CHANNEL']['AID']
108+
109+
data = {}
110+
data['title'] = soup.find('meta', {'property': 'og:title'})['content'].strip()
111+
data['files'] = [{'file': f'https://pc-web.stream.afreecatv.com/live-stm-16/auth_master_playlist.m3u8?aid={aid}'}]
112+
data['writer_nick'] = artist
113+
data['live'] = True
114+
elif f'{vid}/catch' in url: #6215
74115
url_api = 'https://api.m.afreecatv.com/station/video/a/catchview'
75116
r = session.post(url_api, data={'nPageNo': '1', 'nLimit': '10', 'nTitleNo': vid}, headers={'Referer': url})
76117
try:
@@ -92,6 +133,7 @@ def get(self):
92133
data = d['data']
93134

94135
title = data.get('full_title') or data['title']
136+
artist = data.get('copyright_nickname') or data.get('original_user_nick') or data['writer_nick']
95137

96138
if data.get('adult_status') == 'notLogin':
97139
raise LoginRequired(title)
@@ -105,16 +147,47 @@ def get(self):
105147
urls_m3u8.append(file)
106148
print_(f'urls_m3u8: {len(urls_m3u8)}')
107149

108-
streams = []
109-
for url_m3u8 in urls_m3u8:
110-
try:
111-
stream = _get_stream(url_m3u8)
112-
except Exception as e:
113-
print(e)
114-
continue #2193
115-
streams.append(stream)
116-
for stream in streams[1:]:
117-
streams[0] += stream
118-
stream = streams[0]
119-
120-
return {'url': stream, 'title': title, 'name': format_filename(title, vid, '.mp4'), 'url_thumb': url_thumb}
150+
if data.get('live'):
151+
hdr = session.headers.copy()
152+
hdr['Referer'] = url
153+
stream = utils.LiveStream(urls_m3u8[0], headers=hdr, cw=self.cw)
154+
else:
155+
streams = []
156+
for url_m3u8 in urls_m3u8:
157+
try:
158+
stream = _get_stream(url_m3u8, session, url, cw=self.cw)
159+
except Exception as e:
160+
print_(print_error(e))
161+
continue #2193
162+
streams.append(stream)
163+
for stream in streams[1:]:
164+
streams[0] += stream
165+
stream = streams[0]
166+
167+
live = data.get('live') or False
168+
return {'url': stream, 'title': title, 'name': format_filename(title, vid, '.mp4', artist=artist, live=live), 'url_thumb': url_thumb, 'artist': artist, 'live': live}
169+
170+
171+
172+
class Live_afreeca(utils.Live):
173+
type = 'afreeca'
174+
175+
@classmethod
176+
def is_live(cls, url):
177+
return bool(re.match(r'https?://(play|bj).afreecatv.com/([^/?#]+)', url))
178+
179+
@classmethod
180+
def fix_url(cls, url):
181+
bj = re.find(r'https?://(play|bj).afreecatv.com/([^/?#]+)', url)[1]
182+
return f'https://play.afreecatv.com/{bj}'
183+
184+
@classmethod
185+
def check_live(cls, url, info=None):
186+
try:
187+
video = Video({'referer': url})
188+
video._live_info = info
189+
video.ready(None)
190+
return True
191+
except Exception as e:
192+
print(e)
193+
return False

src/extractor/asmhentai_downloader.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#coding: utf8
22
import downloader
33
import ree as re
4-
from utils import Soup, urljoin, Downloader, join, Session, File, clean_title
4+
from utils import Soup, urljoin, Downloader, join, Session, File, clean_title, limits
55
import os
6-
from ratelimit import limits, sleep_and_retry
76
import utils
87

98

@@ -19,8 +18,7 @@ class File_asmhentai(File):
1918
type = 'asmhentai'
2019
format = 'name'
2120

22-
@sleep_and_retry
23-
@limits(4, 1)
21+
@limits(.25)
2422
def get(self):
2523
soup = downloader.read_soup(self['referer'], self['rereferer'], session=self.session)
2624
img = soup.find('img', id='fimg')
@@ -38,6 +36,7 @@ class Downloader_asmhentai(Downloader):
3836
URLS = ['asmhentai.com']
3937
MAX_CORE = 8
4038
display_name = 'AsmHentai'
39+
ACCEPT_COOKIES = [r'(.*\.)?asmhentai\.com']
4140

4241
def init(self):
4342
self.session = Session()

src/extractor/avgle_downloader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
#coding: utf8
22
import downloader
33
from m3u8_tools import M3u8_stream
4-
from utils import Soup, Downloader, LazyUrl, get_print, try_n, check_alive, format_filename
4+
from utils import Soup, Downloader, LazyUrl, get_print, try_n, check_alive, format_filename, json
55
from io import BytesIO
66
import base64
7-
import json
87
import webbrowser
98
import errors
109

@@ -14,6 +13,7 @@ class Downloader_avgle(Downloader):
1413
type = 'avgle'
1514
single = True
1615
URLS = ['avgle.com']
16+
ACCEPT_COOKIES = [r'(.*\.)?avgle\.com']
1717

1818
def init(self):
1919
if not self.cw.data_:

src/extractor/bcy_downloader.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#coding:utf8
22
import downloader
3-
from utils import Soup, cut_pair, LazyUrl, Downloader, get_print, get_max_range, try_n, clean_title, check_alive
4-
import json
3+
from utils import Soup, cut_pair, LazyUrl, Downloader, get_print, get_max_range, try_n, clean_title, check_alive, json
54
import os
65
from translator import tr_
76

@@ -12,6 +11,7 @@ class Downloader_bcy(Downloader):
1211
URLS = ['bcy.net/item/detail/', 'bcy.net/u/']
1312
MAX_CORE = 8
1413
display_name = '半次元'
14+
ACCEPT_COOKIES = [r'(.*\.)?bcy\.net']
1515

1616
def init(self):
1717
self.html = downloader.read_html(self.url)

src/extractor/bdsmlr_downloader.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class Downloader_bdsmlr(Downloader):
1515
type = 'bdsmlr'
1616
URLS = ['bdsmlr.com']
1717
display_name = 'BDSMlr'
18+
ACCEPT_COOKIES = [r'(.*\.)?bdsmlr\.com']
1819

1920
def init(self):
2021
if 'bdsmlr.com/post/' in self.url:

0 commit comments

Comments
 (0)