]>
jfr.im git - yt-dlp.git/blob - yt_dlp/downloader/mhtml.py
2 from __future__
import unicode_literals
9 from .fragment
import FragmentFD
13 srt_subtitles_timecode
,
16 from ..version
import __version__
as YT_DLP_VERSION
19 class MhtmlFD(FragmentFD
):
31 scroll-snap-type: y mandatory;
35 scroll-snap-type: y mandatory;
43 scroll-snap-align: center;
46 body > figure > figcaption {
55 max-height: calc(100vh - 5em);
58 _STYLESHEET
= re
.sub(r
'\s+', ' ', _STYLESHEET
)
59 _STYLESHEET
= re
.sub(r
'\B \B|(?<=[\w\-]) (?=[^\w\-])|(?<=[^\w\-]) (?=[\w\-])', '', _STYLESHEET
)
63 return '=?utf-8?Q?' + (b
''.join(
64 bytes((b
,)) if b
>= 0x20 else b
'=%02X' % b
65 for b
in quopri
.encodestring(s
.encode('utf-8'), header
=True)
66 )).decode('us-ascii') + '?='
68 def _gen_cid(self
, i
, fragment
, frag_boundary
):
69 return '%u.%s@yt-dlp.github.io.invalid' % (i
, frag_boundary
)
71 def _gen_stub(self
, *, fragments
, frag_boundary
, title
):
72 output
= io
.StringIO()
78 '' '<meta name="generator" content="yt-dlp {version}">'
79 '' '<title>{title}</title>'
80 '' '<style>{styles}</style>'
83 version
=escapeHTML(YT_DLP_VERSION
),
84 styles
=self
._STYLESHEET
,
85 title
=escapeHTML(title
)
89 for i
, frag
in enumerate(fragments
):
90 output
.write('<figure>')
92 t1
= t0
+ frag
['duration']
94 '<figcaption>Slide #{num}: {t0} – {t1} (duration: {duration})</figcaption>'
97 t0
=srt_subtitles_timecode(t0
),
98 t1
=srt_subtitles_timecode(t1
),
99 duration
=formatSeconds(frag
['duration'], msec
=True)
101 except (KeyError, ValueError, TypeError):
104 '<figcaption>Slide #{num}</figcaption>'
106 output
.write('<img src="cid:{cid}">'.format(
107 cid
=self
._gen
_cid
(i
, frag
, frag_boundary
)))
108 output
.write('</figure>')
111 return output
.getvalue()
113 def real_download(self
, filename
, info_dict
):
114 fragment_base_url
= info_dict
.get('fragment_base_url')
115 fragments
= info_dict
['fragments'][:1] if self
.params
.get(
116 'test', False) else info_dict
['fragments']
117 title
= info_dict
['title']
118 origin
= info_dict
['webpage_url']
121 'filename': filename
,
122 'total_frags': len(fragments
),
125 self
._prepare
_and
_start
_frag
_download
(ctx
)
127 extra_state
= ctx
.setdefault('extra_state', {
128 'header_written': False,
129 'mime_boundary': str(uuid
.uuid4()).replace('-', ''),
132 frag_boundary
= extra_state
['mime_boundary']
134 if not extra_state
['header_written']:
135 stub
= self
._gen
_stub
(
137 frag_boundary
=frag_boundary
,
141 ctx
['dest_stream'].write((
142 'MIME-Version: 1.0\r\n'
143 'From: <nowhere@yt-dlp.github.io.invalid>\r\n'
144 'To: <nowhere@yt-dlp.github.io.invalid>\r\n'
145 'Subject: {title}\r\n'
146 'Content-type: multipart/related; '
147 '' 'boundary="{boundary}"; '
148 '' 'type="text/html"\r\n'
149 'X.yt-dlp.Origin: {origin}\r\n'
152 'Content-Type: text/html; charset=utf-8\r\n'
153 'Content-Length: {length}\r\n'
158 boundary
=frag_boundary
,
160 title
=self
._escape
_mime
(title
),
163 extra_state
['header_written'] = True
165 for i
, fragment
in enumerate(fragments
):
166 if (i
+ 1) <= ctx
['fragment_index']:
169 fragment_url
= urljoin(fragment_base_url
, fragment
['path'])
170 success
, frag_content
= self
._download
_fragment
(ctx
, fragment_url
, info_dict
)
174 mime_type
= b
'image/jpeg'
175 if frag_content
.startswith(b
'\x89PNG\r\n\x1a\n'):
176 mime_type
= b
'image/png'
177 if frag_content
.startswith((b
'GIF87a', b
'GIF89a')):
178 mime_type
= b
'image/gif'
179 if frag_content
.startswith(b
'RIFF') and frag_content
[8:12] == 'WEBP':
180 mime_type
= b
'image/webp'
182 frag_header
= io
.BytesIO()
184 b
'--%b\r\n' % frag_boundary
.encode('us-ascii'))
186 b
'Content-ID: <%b>\r\n' % self
._gen
_cid
(i
, fragment
, frag_boundary
).encode('us-ascii'))
188 b
'Content-type: %b\r\n' % mime_type
)
190 b
'Content-length: %u\r\n' % len(frag_content
))
192 b
'Content-location: %b\r\n' % fragment_url
.encode('us-ascii'))
194 b
'X.yt-dlp.Duration: %f\r\n' % fragment
['duration'])
195 frag_header
.write(b
'\r\n')
196 self
._append
_fragment
(
197 ctx
, frag_header
.getvalue() + frag_content
+ b
'\r\n')
199 ctx
['dest_stream'].write(
200 b
'--%b--\r\n\r\n' % frag_boundary
.encode('us-ascii'))
201 self
._finish
_frag
_download
(ctx
)