mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-23 02:25:11 +00:00
Merge pull request #8703 from dstftw/mark-watched
Add --mark-watched feature (Closes #5054)
This commit is contained in:
commit
269dd2c6a7
4 changed files with 40 additions and 0 deletions
|
@ -355,6 +355,7 @@ def _real_main(argv=None):
|
||||||
'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
|
'youtube_include_dash_manifest': opts.youtube_include_dash_manifest,
|
||||||
'encoding': opts.encoding,
|
'encoding': opts.encoding,
|
||||||
'extract_flat': opts.extract_flat,
|
'extract_flat': opts.extract_flat,
|
||||||
|
'mark_watched': opts.mark_watched,
|
||||||
'merge_output_format': opts.merge_output_format,
|
'merge_output_format': opts.merge_output_format,
|
||||||
'postprocessors': postprocessors,
|
'postprocessors': postprocessors,
|
||||||
'fixup': opts.fixup,
|
'fixup': opts.fixup,
|
||||||
|
|
|
@ -1620,6 +1620,15 @@ def extract_automatic_captions(self, *args, **kwargs):
|
||||||
def _get_automatic_captions(self, *args, **kwargs):
|
def _get_automatic_captions(self, *args, **kwargs):
|
||||||
raise NotImplementedError('This method must be implemented by subclasses')
|
raise NotImplementedError('This method must be implemented by subclasses')
|
||||||
|
|
||||||
|
def mark_watched(self, *args, **kwargs):
|
||||||
|
if (self._downloader.params.get('mark_watched', False) and
|
||||||
|
(self._get_login_info()[0] is not None or
|
||||||
|
self._downloader.params.get('cookiefile') is not None)):
|
||||||
|
self._mark_watched(*args, **kwargs)
|
||||||
|
|
||||||
|
def _mark_watched(self, *args, **kwargs):
|
||||||
|
raise NotImplementedError('This method must be implemented by subclasses')
|
||||||
|
|
||||||
|
|
||||||
class SearchInfoExtractor(InfoExtractor):
|
class SearchInfoExtractor(InfoExtractor):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
import json
|
||||||
import os.path
|
import os.path
|
||||||
|
import random
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
@ -1046,6 +1047,29 @@ def _get_automatic_captions(self, video_id, webpage):
|
||||||
self._downloader.report_warning(err_msg)
|
self._downloader.report_warning(err_msg)
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def _mark_watched(self, video_id, video_info):
|
||||||
|
playback_url = video_info.get('videostats_playback_base_url', [None])[0]
|
||||||
|
if not playback_url:
|
||||||
|
return
|
||||||
|
parsed_playback_url = compat_urlparse.urlparse(playback_url)
|
||||||
|
qs = compat_urlparse.parse_qs(parsed_playback_url.query)
|
||||||
|
|
||||||
|
# cpn generation algorithm is reverse engineered from base.js.
|
||||||
|
# In fact it works even with dummy cpn.
|
||||||
|
CPN_ALPHABET = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'
|
||||||
|
cpn = ''.join((CPN_ALPHABET[random.randint(0, 256) & 63] for _ in range(0, 16)))
|
||||||
|
|
||||||
|
qs.update({
|
||||||
|
'ver': ['2'],
|
||||||
|
'cpn': [cpn],
|
||||||
|
})
|
||||||
|
playback_url = compat_urlparse.urlunparse(
|
||||||
|
parsed_playback_url._replace(query=compat_urllib_parse.urlencode(qs, True)))
|
||||||
|
|
||||||
|
self._download_webpage(
|
||||||
|
playback_url, video_id, 'Marking watched',
|
||||||
|
'Unable to mark watched', fatal=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def extract_id(cls, url):
|
def extract_id(cls, url):
|
||||||
mobj = re.match(cls._VALID_URL, url, re.VERBOSE)
|
mobj = re.match(cls._VALID_URL, url, re.VERBOSE)
|
||||||
|
@ -1555,6 +1579,8 @@ def decrypt_sig(mobj):
|
||||||
|
|
||||||
self._sort_formats(formats)
|
self._sort_formats(formats)
|
||||||
|
|
||||||
|
self.mark_watched(video_id, video_info)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': video_id,
|
'id': video_id,
|
||||||
'uploader': video_uploader,
|
'uploader': video_uploader,
|
||||||
|
|
|
@ -170,6 +170,10 @@ def _hide_login_info(opts):
|
||||||
action='store_const', dest='extract_flat', const='in_playlist',
|
action='store_const', dest='extract_flat', const='in_playlist',
|
||||||
default=False,
|
default=False,
|
||||||
help='Do not extract the videos of a playlist, only list them.')
|
help='Do not extract the videos of a playlist, only list them.')
|
||||||
|
general.add_option(
|
||||||
|
'--mark-watched',
|
||||||
|
action='store_true', dest='mark_watched', default=False,
|
||||||
|
help='Mark videos watched (YouTube only)')
|
||||||
general.add_option(
|
general.add_option(
|
||||||
'--no-color', '--no-colors',
|
'--no-color', '--no-colors',
|
||||||
action='store_true', dest='no_color',
|
action='store_true', dest='no_color',
|
||||||
|
|
Loading…
Reference in a new issue