rename bin path
This commit is contained in:
parent
27eef3d714
commit
250eb24a93
4 changed files with 57 additions and 38 deletions
|
|
@ -1,2 +1,2 @@
|
||||||
./tools-ubuntu/TwitchDownloaderCLI -m ChatDownload --id $1 -o $2 --embed-emotes
|
./bin/TwitchDownloaderCLI -m ChatDownload --id $1 -o $2 --embed-emotes
|
||||||
./tools-ubuntu/TwitchDownloaderCLI -m ChatRender -i $2 -o $3 --background-color "#FF111111" -w 500 -h 1080 --outline true -f Arial --font-size 22 --update-rate 1.0 --ffmpeg-path ./bin/ffmpeg --temp-path ./bin/temp
|
./bin/TwitchDownloaderCLI -m ChatRender -i $2 -o $3 --background-color "#FF111111" -w 500 -h 1080 --outline true -f Arial --font-size 22 --update-rate 1.0 --ffmpeg-path ./bin/ffmpeg --temp-path ./bin/temp
|
||||||
8
extra.md
8
extra.md
|
|
@ -1,10 +1,8 @@
|
||||||
- install and configure rclone
|
- install and configure rclone
|
||||||
```
|
```
|
||||||
cd tools-ubuntu
|
cd bin
|
||||||
sudo chmod +x chat.sh
|
sudo chmod +x chat.sh upload.sh TwitchDownloaderCLI ffmpeg
|
||||||
sudo chmod +x upload.sh
|
|
||||||
sudo chmod +x TwitchDownloaderCLI
|
|
||||||
sudo chmod +x ffmpeg
|
|
||||||
```
|
```
|
||||||
## Explanation
|
## Explanation
|
||||||
### Record live stream:
|
### Record live stream:
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,9 @@ class TwitchArchive:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
# start streamlink process
|
# start streamlink process
|
||||||
subprocess.call(["streamlink", '--http-header', 'Authorization=OAuth ' + os.environ.get('OAUTH-PRIVATE-TOKEN'), "--hls-segment-threads", str(self.hls_segments), "--hls-live-restart", "--twitch-disable-hosting", "twitch.tv/" + self.username, self.quality, "--retry-streams", str(self.refresh)] + self.debug_cmd + ["-o", recorded_filename])
|
subprocess.call(["streamlink", '--http-header', 'Authorization=OAuth ' + os.environ.get('OAUTH-PRIVATE-TOKEN'), "--hls-segment-threads", str(self.hls_segments), "--hls-live-restart", "--twitch-disable-hosting", "twitch.tv/" + self.username, self.quality, "--retry-streams", str(self.refresh)] + self.debug_cmd + ["-o", recorded_filename])
|
||||||
|
|
@ -209,19 +212,24 @@ class TwitchArchive:
|
||||||
raw_filename = created_at + ".ts"
|
raw_filename = created_at + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + created_at + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + created_at + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + created_at + ".json"
|
||||||
try:
|
try:
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
print('first exception as e\nAn error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
print('first exception as e\nAn error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
||||||
self.sendNotif('ERROR - '+ present_datetime, 'An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n ' + e)
|
self.sendNotif('ERROR - '+ present_datetime, 'An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n ' + e)
|
||||||
if self.downloadMETADATA == 1:
|
if self.downloadMETADATA == 1:
|
||||||
metadata_filename = "metadata_" + created_at + ".json"
|
|
||||||
self.sendNotif('Metadata - ' + created_at,'Downloading and saving metadata:\n' + json.dumps(vodsinfodic["data"][0], indent=4))
|
self.sendNotif('Metadata - ' + created_at,'Downloading and saving metadata:\n' + json.dumps(vodsinfodic["data"][0], indent=4))
|
||||||
with open(os.path.join(self.metadata_path, metadata_filename), 'w', encoding='utf-8') as f:
|
with open(os.path.join(self.metadata_path, metadata_filename), 'w', encoding='utf-8') as f:
|
||||||
json.dump(vodsinfodic["data"][0], f, ensure_ascii=False, indent=4)
|
json.dump(vodsinfodic["data"][0], f, ensure_ascii=False, indent=4)
|
||||||
|
|
@ -236,28 +244,30 @@ class TwitchArchive:
|
||||||
if self.downloadCHAT == 1:
|
if self.downloadCHAT == 1:
|
||||||
print('Downloading and rendering CHAT: ' + vodsinfodic["data"][0]["title"])
|
print('Downloading and rendering CHAT: ' + vodsinfodic["data"][0]["title"])
|
||||||
self.sendNotif('CHAT - ' + created_at,'Downloading JSON and rendering chat logs from VOD:\n' + vodsinfodic["data"][0]["title"])
|
self.sendNotif('CHAT - ' + created_at,'Downloading JSON and rendering chat logs from VOD:\n' + vodsinfodic["data"][0]["title"])
|
||||||
chat_filename = "CHAT_" + raw_filename[:-2] + "json"
|
|
||||||
render_filename = "CHAT_" + raw_filename[:-2] + "mp4"
|
|
||||||
outputJSON = os.path.join(self.chatJSON_path, chat_filename)
|
|
||||||
outputMP4 = os.path.join(self.chatMP4_path, render_filename)
|
|
||||||
try:
|
try:
|
||||||
subprocess.call(["bash","./bin/chat.sh", vod_id, outputJSON, outputMP4])
|
subprocess.call(["bash","./bin/chat.sh", vod_id, os.path.join(self.chatJSON_path, chat_json_filename), os.path.join(self.chatMP4_path, chat_mp4_filename)])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.sendNotif('ERROR - ' + created_at, "A ERROR has ocurred and chat will need to be downloaded and rendered manually.\n" + e)
|
self.sendNotif('ERROR - ' + created_at, "A ERROR has ocurred and chat will need to be downloaded and rendered manually.\n" + e)
|
||||||
print("A ERROR has ocurred and chat will need to be downloaded and rendered manually\n" + e)
|
print("A ERROR has ocurred and chat will need to be downloaded and rendered manually\n" + e)
|
||||||
else:
|
else:
|
||||||
print('A ERROR has ocurred, the latest VOD doesnt match with the livestream, the VOD is not published')
|
print('A ERROR has ocurred, the latest VOD doesnt match with the livestream, the VOD is not published\nThe VOD and chat will not be downloaded and rendered.')
|
||||||
self.sendNotif('ERROR - ' + present_datetime, 'A ERROR has ocurred, the latest VOD doesnt match with the livestream, the VOD is not published')
|
self.sendNotif('ERROR - ' + present_datetime, 'A ERROR has ocurred, the latest VOD doesnt match with the livestream, the VOD is not published\nThe VOD and chat will not be downloaded and rendered.')
|
||||||
else:
|
else:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
print('An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
print('An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
||||||
|
|
@ -294,12 +304,12 @@ class TwitchArchive:
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.processed_path, vod_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.processed_path, vod_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.processed_path, vod_filename))
|
os.remove(os.path.join(self.processed_path, vod_filename))
|
||||||
if self.downloadCHAT == 1:
|
if self.downloadCHAT == 1:
|
||||||
if(os.path.exists(os.path.join(self.chatJSON_path, chat_filename)) is True):
|
if(os.path.exists(os.path.join(self.chatJSON_path, chat_json_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatJSON_path, chat_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatJSON_path, chat_json_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.chatJSON_path, chat_filename))
|
os.remove(os.path.join(self.chatJSON_path, chat_json_filename))
|
||||||
if(os.path.exists(os.path.join(self.chatMP4_path, render_filename)) is True):
|
if(os.path.exists(os.path.join(self.chatMP4_path, chat_mp4_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatMP4_path, render_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatMP4_path, chat_mp4_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.chatMP4_path, render_filename))
|
os.remove(os.path.join(self.chatMP4_path, chat_mp4_filename))
|
||||||
if self.downloadMETADATA == 1:
|
if self.downloadMETADATA == 1:
|
||||||
if(os.path.exists(os.path.join(self.metadata_path, metadata_filename)) is True):
|
if(os.path.exists(os.path.join(self.metadata_path, metadata_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.metadata_path, metadata_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.metadata_path, metadata_filename) + f'{Style.RESET_ALL}')
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,9 @@ class TwitchArchive:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
# start streamlink process
|
# start streamlink process
|
||||||
subprocess.call(["streamlink", '--http-header', 'Authorization=OAuth ' + os.environ.get('OAUTH-PRIVATE-TOKEN'), "--hls-segment-threads", str(self.hls_segments), "--hls-live-restart", "--twitch-disable-hosting", "twitch.tv/" + self.username, self.quality, "--retry-streams", str(self.refresh)] + self.debug_cmd + ["-o", recorded_filename])
|
subprocess.call(["streamlink", '--http-header', 'Authorization=OAuth ' + os.environ.get('OAUTH-PRIVATE-TOKEN'), "--hls-segment-threads", str(self.hls_segments), "--hls-live-restart", "--twitch-disable-hosting", "twitch.tv/" + self.username, self.quality, "--retry-streams", str(self.refresh)] + self.debug_cmd + ["-o", recorded_filename])
|
||||||
|
|
@ -209,13 +212,19 @@ class TwitchArchive:
|
||||||
raw_filename = created_at + ".ts"
|
raw_filename = created_at + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + created_at + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + created_at + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + created_at + ".json"
|
||||||
try:
|
try:
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
print('first exception as e\nAn error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
print('first exception as e\nAn error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
||||||
|
|
@ -236,12 +245,8 @@ class TwitchArchive:
|
||||||
if self.downloadCHAT == 1:
|
if self.downloadCHAT == 1:
|
||||||
print('Downloading and rendering CHAT: ' + vodsinfodic["data"][0]["title"])
|
print('Downloading and rendering CHAT: ' + vodsinfodic["data"][0]["title"])
|
||||||
self.sendNotif('CHAT - ' + created_at,'Downloading JSON and rendering chat logs from VOD:\n' + vodsinfodic["data"][0]["title"])
|
self.sendNotif('CHAT - ' + created_at,'Downloading JSON and rendering chat logs from VOD:\n' + vodsinfodic["data"][0]["title"])
|
||||||
chat_filename = "CHAT_" + raw_filename[:-2] + "json"
|
|
||||||
render_filename = "CHAT_" + raw_filename[:-2] + "mp4"
|
|
||||||
outputJSON = os.path.join(self.chatJSON_path, chat_filename)
|
|
||||||
outputMP4 = os.path.join(self.chatMP4_path, render_filename)
|
|
||||||
try:
|
try:
|
||||||
subprocess.call(["powershell.exe","./bin/chat.bat", vod_id, '../'+outputJSON, '../'+outputMP4])
|
subprocess.call(["powershell.exe","./bin/chat.bat", vod_id, '../'+os.path.join(self.chatJSON_path, chat_json_filename), '../'+os.path.join(self.chatMP4_path, chat_mp4_filename)])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.sendNotif('ERROR - ' + created_at, "A ERROR has ocurred and chat will need to be downloaded and rendered manually.\n" + e)
|
self.sendNotif('ERROR - ' + created_at, "A ERROR has ocurred and chat will need to be downloaded and rendered manually.\n" + e)
|
||||||
print("A ERROR has ocurred and chat will need to be downloaded and rendered manually\n" + e)
|
print("A ERROR has ocurred and chat will need to be downloaded and rendered manually\n" + e)
|
||||||
|
|
@ -251,13 +256,19 @@ class TwitchArchive:
|
||||||
else:
|
else:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raw_filename = present_datetime + ".ts"
|
raw_filename = present_datetime + ".ts"
|
||||||
live_filename = "LIVE_" + raw_filename
|
live_filename = "LIVE_" + raw_filename
|
||||||
raw_vod_filename = "VOD_" + raw_filename
|
raw_vod_filename = "VOD_" + raw_filename
|
||||||
|
chat_json_filename = "CHAT_" + present_datetime + ".json"
|
||||||
|
chat_mp4_filename = "CHAT_" + present_datetime + ".mp4"
|
||||||
|
metadata_filename = "metadata_" + present_datetime + ".json"
|
||||||
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
os.rename(recorded_filename,os.path.join(self.recorded_path, live_filename))
|
||||||
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
recorded_filename = os.path.join(self.recorded_path, live_filename)
|
||||||
print('An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
print('An error has occurred. VOD and chat will not be downloaded. Please check them manually.\n' + e)
|
||||||
|
|
@ -294,12 +305,12 @@ class TwitchArchive:
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.processed_path, vod_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.processed_path, vod_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.processed_path, vod_filename))
|
os.remove(os.path.join(self.processed_path, vod_filename))
|
||||||
if self.downloadCHAT == 1:
|
if self.downloadCHAT == 1:
|
||||||
if(os.path.exists(os.path.join(self.chatJSON_path, chat_filename)) is True):
|
if(os.path.exists(os.path.join(self.chatJSON_path, chat_json_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatJSON_path, chat_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatJSON_path, chat_json_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.chatJSON_path, chat_filename))
|
os.remove(os.path.join(self.chatJSON_path, chat_json_filename))
|
||||||
if(os.path.exists(os.path.join(self.chatMP4_path, render_filename)) is True):
|
if(os.path.exists(os.path.join(self.chatMP4_path, chat_mp4_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatMP4_path, render_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.chatMP4_path, chat_mp4_filename) + f'{Style.RESET_ALL}')
|
||||||
os.remove(os.path.join(self.chatMP4_path, render_filename))
|
os.remove(os.path.join(self.chatMP4_path, chat_mp4_filename))
|
||||||
if self.downloadMETADATA == 1:
|
if self.downloadMETADATA == 1:
|
||||||
if(os.path.exists(os.path.join(self.metadata_path, metadata_filename)) is True):
|
if(os.path.exists(os.path.join(self.metadata_path, metadata_filename)) is True):
|
||||||
print(f'{Fore.RED}Deleting ' + os.path.join(self.metadata_path, metadata_filename) + f'{Style.RESET_ALL}')
|
print(f'{Fore.RED}Deleting ' + os.path.join(self.metadata_path, metadata_filename) + f'{Style.RESET_ALL}')
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue