]>
jfr.im git - yt-dlp.git/blob - yt_dlp/downloader/mhtml.py
6 from .fragment
import FragmentFD
7 from ..compat
import imghdr
8 from ..utils
import escapeHTML
, formatSeconds
, srt_subtitles_timecode
, urljoin
9 from ..version
import __version__
as YT_DLP_VERSION
12 class MhtmlFD(FragmentFD
):
22 scroll-snap-type: y mandatory;
26 scroll-snap-type: y mandatory;
34 scroll-snap-align: center;
37 body > figure > figcaption {
46 max-height: calc(100vh - 5em);
49 _STYLESHEET
= re
.sub(r
'\s+', ' ', _STYLESHEET
)
50 _STYLESHEET
= re
.sub(r
'\B \B|(?<=[\w\-]) (?=[^\w\-])|(?<=[^\w\-]) (?=[\w\-])', '', _STYLESHEET
)
54 return '=?utf-8?Q?' + (b
''.join(
55 bytes((b
,)) if b
>= 0x20 else b
'=%02X' % b
56 for b
in quopri
.encodestring(s
.encode(), header
=True)
57 )).decode('us-ascii') + '?='
59 def _gen_cid(self
, i
, fragment
, frag_boundary
):
60 return '%u.%s@yt-dlp.github.io.invalid' % (i
, frag_boundary
)
62 def _gen_stub(self
, *, fragments
, frag_boundary
, title
):
63 output
= io
.StringIO()
69 '' '<meta name="generator" content="yt-dlp {version}">'
70 '' '<title>{title}</title>'
71 '' '<style>{styles}</style>'
74 version
=escapeHTML(YT_DLP_VERSION
),
75 styles
=self
._STYLESHEET
,
76 title
=escapeHTML(title
)
80 for i
, frag
in enumerate(fragments
):
81 output
.write('<figure>')
83 t1
= t0
+ frag
['duration']
85 '<figcaption>Slide #{num}: {t0} – {t1} (duration: {duration})</figcaption>'
88 t0
=srt_subtitles_timecode(t0
),
89 t1
=srt_subtitles_timecode(t1
),
90 duration
=formatSeconds(frag
['duration'], msec
=True)
92 except (KeyError, ValueError, TypeError):
95 '<figcaption>Slide #{num}</figcaption>'
97 output
.write('<img src="cid:{cid}">'.format(
98 cid
=self
._gen
_cid
(i
, frag
, frag_boundary
)))
99 output
.write('</figure>')
102 return output
.getvalue()
104 def real_download(self
, filename
, info_dict
):
105 fragment_base_url
= info_dict
.get('fragment_base_url')
106 fragments
= info_dict
['fragments'][:1] if self
.params
.get(
107 'test', False) else info_dict
['fragments']
108 title
= info_dict
.get('title', info_dict
['format_id'])
109 origin
= info_dict
.get('webpage_url', info_dict
['url'])
112 'filename': filename
,
113 'total_frags': len(fragments
),
116 self
._prepare
_and
_start
_frag
_download
(ctx
, info_dict
)
118 extra_state
= ctx
.setdefault('extra_state', {
119 'header_written': False,
120 'mime_boundary': str(uuid
.uuid4()).replace('-', ''),
123 frag_boundary
= extra_state
['mime_boundary']
125 if not extra_state
['header_written']:
126 stub
= self
._gen
_stub
(
128 frag_boundary
=frag_boundary
,
132 ctx
['dest_stream'].write((
133 'MIME-Version: 1.0\r\n'
134 'From: <nowhere@yt-dlp.github.io.invalid>\r\n'
135 'To: <nowhere@yt-dlp.github.io.invalid>\r\n'
136 'Subject: {title}\r\n'
137 'Content-type: multipart/related; '
138 '' 'boundary="{boundary}"; '
139 '' 'type="text/html"\r\n'
140 'X.yt-dlp.Origin: {origin}\r\n'
143 'Content-Type: text/html; charset=utf-8\r\n'
144 'Content-Length: {length}\r\n'
149 boundary
=frag_boundary
,
151 title
=self
._escape
_mime
(title
),
154 extra_state
['header_written'] = True
156 for i
, fragment
in enumerate(fragments
):
157 if (i
+ 1) <= ctx
['fragment_index']:
160 fragment_url
= fragment
.get('url')
162 assert fragment_base_url
163 fragment_url
= urljoin(fragment_base_url
, fragment
['path'])
165 success
= self
._download
_fragment
(ctx
, fragment_url
, info_dict
)
168 frag_content
= self
._read
_fragment
(ctx
)
170 frag_header
= io
.BytesIO()
172 b
'--%b\r\n' % frag_boundary
.encode('us-ascii'))
174 b
'Content-ID: <%b>\r\n' % self
._gen
_cid
(i
, fragment
, frag_boundary
).encode('us-ascii'))
176 b
'Content-type: %b\r\n' % f
'image/{imghdr.what(h=frag_content) or "jpeg"}'.encode())
178 b
'Content-length: %u\r\n' % len(frag_content
))
180 b
'Content-location: %b\r\n' % fragment_url
.encode('us-ascii'))
182 b
'X.yt-dlp.Duration: %f\r\n' % fragment
['duration'])
183 frag_header
.write(b
'\r\n')
184 self
._append
_fragment
(
185 ctx
, frag_header
.getvalue() + frag_content
+ b
'\r\n')
187 ctx
['dest_stream'].write(
188 b
'--%b--\r\n\r\n' % frag_boundary
.encode('us-ascii'))
189 return self
._finish
_frag
_download
(ctx
, info_dict
)