]> jfr.im git - yt-dlp.git/blame - youtube_dlc/update.py
Cleanup some code and fix typos
[yt-dlp.git] / youtube_dlc / update.py
CommitLineData
15938ab6
PH
1from __future__ import unicode_literals
2
d2790370 3import io
d5ed35b6
FV
4import json
5import traceback
6import hashlib
ce02ed60 7import os
d2790370 8import subprocess
46353f67 9import sys
d5ed35b6
FV
10from zipimport import zipimporter
11
bfe2b8cf 12from .compat import compat_realpath
c0384f22 13from .utils import encode_compat_str
d3d3e2e3 14
d5ed35b6
FV
15from .version import __version__
16
5f6a1245 17
3dd264bf 18''' # Not signed
d5ed35b6 19def rsa_verify(message, signature, key):
d5ed35b6 20 from hashlib import sha256
15938ab6 21 assert isinstance(message, bytes)
4d318be1
FV
22 byte_size = (len(bin(key[0])) - 2 + 8 - 1) // 8
23 signature = ('%x' % pow(int(signature, 16), key[1], key[0])).encode()
24 signature = (byte_size * 2 - len(signature)) * b'0' + signature
25 asn1 = b'3031300d060960864801650304020105000420'
26 asn1 += sha256(message).hexdigest().encode()
27 if byte_size < len(asn1) // 2 + 11:
5f6a1245 28 return False
4d318be1
FV
29 expected = b'0001' + (byte_size - len(asn1) // 2 - 3) * b'ff' + b'00' + asn1
30 return expected == signature
3dd264bf 31'''
d5ed35b6 32
d7386f62 33
0c3e5f49 34def update_self(to_screen, verbose, opener):
d5ed35b6
FV
35 """Update the program file with the latest version from the repository"""
36
3dd264bf 37 JSON_URL = 'https://api.github.com/repos/pukkandan/yt-dlp/releases/latest'
d5ed35b6 38
fa57af1e
U
39 def sha256sum():
40 h = hashlib.sha256()
41 b = bytearray(128 * 1024)
42 mv = memoryview(b)
43 with open(os.path.realpath(sys.executable), 'rb', buffering=0) as f:
44 for n in iter(lambda: f.readinto(mv), 0):
45 h.update(mv[:n])
46 return h.hexdigest()
47
48 to_screen('Current Build Hash %s' % sha256sum())
49
611c1dd9 50 if not isinstance(globals().get('__loader__'), zipimporter) and not hasattr(sys, 'frozen'):
cefecac1 51 to_screen('It looks like you installed youtube-dlc with a package manager, pip, setup.py or a tarball. Please use that to update.')
d5ed35b6
FV
52 return
53
d5ed35b6
FV
54 # Download and check versions info
55 try:
3dd264bf 56 version_info = opener.open(JSON_URL).read().decode('utf-8')
57 version_info = json.loads(version_info)
70a1165b 58 except Exception:
5f6a1245 59 if verbose:
c0384f22 60 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 61 to_screen('ERROR: can\'t obtain versions info. Please try again later.')
06869367 62 to_screen('Visit https://github.com/pukkandan/yt-dlp/releases/latest')
d5ed35b6
FV
63 return
64
3dd264bf 65 version_id = version_info['tag_name']
66 if version_id == __version__:
67 to_screen('youtube-dlc is up-to-date (' + __version__ + ')')
68 return
d7386f62
PH
69
70 def version_tuple(version_str):
71 return tuple(map(int, version_str.split('.')))
3dd264bf 72
2e767313 73 if version_tuple(__version__) >= version_tuple(version_id):
cefecac1 74 to_screen('youtube-dlc is up to date (%s)' % __version__)
d7386f62
PH
75 return
76
15938ab6 77 to_screen('Updating to version ' + version_id + ' ...')
3bf79c75 78
3dd264bf 79 version = {
80 'bin': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc'),
81 'exe': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc.exe'),
82 'exe_x86': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc_x86.exe'),
83 }
d5ed35b6 84
e9297256 85 # sys.executable is set to the full pathname of the exe-file for py2exe
bfe2b8cf
S
86 # though symlinks are not followed so that we need to do this manually
87 # with help of realpath
88 filename = compat_realpath(sys.executable if hasattr(sys, 'frozen') else sys.argv[0])
46353f67 89
d5ed35b6 90 if not os.access(filename, os.W_OK):
15938ab6 91 to_screen('ERROR: no write permissions on %s' % filename)
d5ed35b6
FV
92 return
93
3dd264bf 94 # PyInstaller
611c1dd9 95 if hasattr(sys, 'frozen'):
e9297256 96 exe = filename
d5ed35b6
FV
97 directory = os.path.dirname(exe)
98 if not os.access(directory, os.W_OK):
15938ab6 99 to_screen('ERROR: no write permissions on %s' % directory)
d5ed35b6
FV
100 return
101
102 try:
3dd264bf 103 urlh = opener.open(version['exe']['browser_download_url'])
d5ed35b6
FV
104 newcontent = urlh.read()
105 urlh.close()
0b63aed8 106 except (IOError, OSError):
5f6a1245 107 if verbose:
c0384f22 108 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 109 to_screen('ERROR: unable to download latest version')
06869367 110 to_screen('Visit https://github.com/pukkandan/yt-dlp/releases/latest')
d5ed35b6
FV
111 return
112
113 try:
114 with open(exe + '.new', 'wb') as outf:
115 outf.write(newcontent)
0b63aed8 116 except (IOError, OSError):
5f6a1245 117 if verbose:
c0384f22 118 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 119 to_screen('ERROR: unable to write the new version')
d5ed35b6
FV
120 return
121
122 try:
3dd264bf 123 bat = os.path.join(directory, 'yt-dlp-updater.cmd')
d2790370 124 with io.open(bat, 'w') as batfile:
15938ab6 125 batfile.write('''
3dd264bf 126@(
127 echo.Waiting for file handle to be closed ...
128 ping 127.0.0.1 -n 5 -w 1000 > NUL
129 move /Y "%s.new" "%s" > NUL
130 echo.Updated youtube-dlc to version %s.
131)
132@start /b "" cmd /c del "%%~f0"&exit /b
133 ''' % (exe, exe, version_id))
d5ed35b6 134
d2790370
PH
135 subprocess.Popen([bat]) # Continues to run in the background
136 return # Do not show premature success messages
0b63aed8 137 except (IOError, OSError):
5f6a1245 138 if verbose:
c0384f22 139 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 140 to_screen('ERROR: unable to overwrite current version')
d5ed35b6
FV
141 return
142
143 # Zip unix package
144 elif isinstance(globals().get('__loader__'), zipimporter):
145 try:
3dd264bf 146 urlh = opener.open(version['bin']['browser_download_url'])
d5ed35b6
FV
147 newcontent = urlh.read()
148 urlh.close()
0b63aed8 149 except (IOError, OSError):
5f6a1245 150 if verbose:
c0384f22 151 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 152 to_screen('ERROR: unable to download latest version')
06869367 153 to_screen('Visit https://github.com/pukkandan/yt-dlp/releases/latest')
d5ed35b6
FV
154 return
155
156 try:
157 with open(filename, 'wb') as outf:
158 outf.write(newcontent)
0b63aed8 159 except (IOError, OSError):
5f6a1245 160 if verbose:
c0384f22 161 to_screen(encode_compat_str(traceback.format_exc()))
15938ab6 162 to_screen('ERROR: unable to overwrite current version')
d5ed35b6
FV
163 return
164
cefecac1 165 to_screen('Updated youtube-dlc. Restart youtube-dlc to use the new version.')
3bf79c75 166
5f6a1245 167
3dd264bf 168''' # UNUSED
46a127ee 169def get_notes(versions, fromVersion):
3bf79c75 170 notes = []
5f6a1245 171 for v, vdata in sorted(versions.items()):
3bf79c75
PH
172 if v > fromVersion:
173 notes.extend(vdata.get('notes', []))
46a127ee
PH
174 return notes
175
5f6a1245 176
46a127ee
PH
177def print_notes(to_screen, versions, fromVersion=__version__):
178 notes = get_notes(versions, fromVersion)
3bf79c75 179 if notes:
15938ab6 180 to_screen('PLEASE NOTE:')
3bf79c75
PH
181 for note in notes:
182 to_screen(note)
3dd264bf 183'''