Skip to content

Instantly share code, notes, and snippets.

@kostyay
Last active January 25, 2019 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kostyay/74ad9e6f95aa1436c6349c3f0d9595e4 to your computer and use it in GitHub Desktop.
Save kostyay/74ad9e6f95aa1436c6349c3f0d9595e4 to your computer and use it in GitHub Desktop.
Python script to download Zwift updates. Fixes the Z113 error/ Update failure "at line 594 in patcher.cpp"
#
# To use make sure to install the following packages:
# pip install requests pyOpenSSL ndg-httpsclient pyasn1
#
import sys
import xml.etree.ElementTree as ET
#import ipdb
import requests
import binascii
import os.path
import os
ZWIFT_CUR_VER_FILE = "Zwift_ver_cur.xml"
ZWIFT_BASE_URL = "https://cdn.zwift.com/gameassets/Zwift_Updates_Root/"
ZWIFT_CUR_VER_URL = "https://cdn.zwift.com/gameassets/Zwift_Updates_Root/{}".format(ZWIFT_CUR_VER_FILE)
def get_latest_zwift_manifest(output_dir):
cur_ver_file = requests.get(ZWIFT_CUR_VER_URL)
file(os.path.join(output_dir, ZWIFT_CUR_VER_FILE), "w+").write(cur_ver_file.content)
ver = ET.fromstring(cur_ver_file.content)
return ver.get('manifest')
def get_manifest_file(fname, output_dir):
r = requests.get("{}{}".format(ZWIFT_BASE_URL, fname))
file(os.path.join(output_dir, fname), "w+").write(r.content)
return r.content
def create_dir_if_missing(path):
path, fn = os.path.split(path)
if not os.path.isdir(path):
os.makedirs(path)
def format_asset_url(zwift_folder, path):
return "{}{}/{}".format(ZWIFT_BASE_URL, zwift_folder, path.replace("\\", "/"))
def download_file(url, dst, checksum):
print "Downloading file from {} to {} [expected crc={}]".format(url, dst, checksum)
if os.path.isfile(dst):
current_crc = binascii.crc32(file(dst, "rb").read())
if str(current_crc) == str(checksum):
print "File already downloaded.. skipping"
return
headers = {'Cache-Control': 'no-cache', 'Pragma': 'no-cache'}
r = requests.get(url, headers=headers)
with open(dst, "w+b") as code:
content = r.content
crc = binascii.crc32(content)
code.write(content)
if str(crc) != str(checksum) and checksum != '-1':
print "checksum mismatch"
ipdb.set_trace()
print "Total bytes: {} CRC: {}".format(len(content), crc)
print " Done"
def main():
try:
prog, outdir = sys.argv
except:
print "Error: download_zwift.py <outdir>"
sys.exit(0)
print "Downloading manifest.."
latest_manifest = get_latest_zwift_manifest(outdir)
manifest_file = get_manifest_file(latest_manifest, outdir)
print "Manifest version: {}".format(latest_manifest)
print "Reading manifest..."
root = ET.fromstring(manifest_file)
folder_name = root.get('folder')
print "Folder is {}".format(folder_name,)
files = root.getchildren()[0]
assert files.tag == 'files'
files = files.getchildren()
print "Total files to download {}".format(len(files),)
for f in files:
path = f.find('path').text
checksum = f.find('checksum').text
download_url = format_asset_url(folder_name, path)
output_file = os.path.join(outdir, path)
create_dir_if_missing(output_file)
print "Download url: {}".format(download_url)
download_file(download_url, output_file, checksum)
print "All done"
if __name__ == "__main__":
main()
@kostyay
Copy link
Author

kostyay commented Mar 6, 2017

Zwift seem to be having issues with their CDN from time to time for certain ISPS. I wrote this script to use at work to download the updates and get them home on USB drive.

@kostyay
Copy link
Author

kostyay commented Mar 6, 2017

Downloading updates over SSL in affected ISP works fine.
So run the script, pass the full path to zwift as an argument: for example c:\Program Files (x86)\Zwift
It will update successfully and you will enjoy the game.

@kostyay
Copy link
Author

kostyay commented Mar 6, 2017

The script is provided as is without any warranty and is not related to the Zwift team in any way. Use at your own risk.

@kostyay
Copy link
Author

kostyay commented Mar 7, 2017

How to get the script to work:

  1. Download and install python for windows from https://www.python.org/ftp/python/2.7/python-2.7.msi
  2. Install PIP following the instructions here https://github.com/BurntSushi/nfldb/wiki/Python-&-pip-Windows-installation#pip-install
  3. Open Command Prompt as Administrator and run C:\Python27\Scripts\pip install requests pyOpenSSL ndg-httpsclient pyasn1
  4. Run the script C:\Python27\python download_zwift_updates.py "<path\to\zwift\install\dir>"

@brucem1976
Copy link

brucem1976 commented Sep 26, 2017

Awesome - really grateful for this, the Z113 error has been so frustrating! In your instruction above:
Open Command Prompt and run C:\Python27\Scripts\pip install requests install pyOpenSSL ndg-httpsclient pyasn1
there is one extra 'install' that stops the command running, and it might be worth mentioning that people should open command prompt as Administrator - oh, and I needed to put my path to zwift install dir in double quotes....

last thing: I needed to Install pip for python as well.... https://github.com/BurntSushi/nfldb/wiki/Python-&-pip-Windows-installation

@kostyay
Copy link
Author

kostyay commented May 13, 2018

Surprised Zwift havent fixed it yet.
Just reinstalled my PC and still having this problem.
Used the script to download the updates and everything is working again.

@grimfusion
Copy link

I'm kinda surprised this works. Usually, the Z113 error is caused when files pulled down from Zwift's update server don't match correct checksum values - basically when components in the update fail to completely download or end up corrupted. I take it your Python script works more reliably because it tries to download the files multiple times after a checksum mismatch whereas Zwift simply reports the update failed?

@nadodiganesh
Copy link

Can I get a Python 3+ compatible version of this code... tried now and started seeing quite some Print syntax errors, was about parantheses...tried my best to get that going. Now, I face ....

Downloading manifest..
Traceback (most recent call last):
File "D:\Zwift\download_zwift_updates.py", line 104, in
main()
File "D:\Zwift\download_zwift_updates.py", line 74, in main
latest_manifest = get_latest_zwift_manifest(outdir)
File "D:\Zwift\download_zwift_updates.py", line 22, in get_latest_zwift_manifest
file(os.path.join(output_dir, ZWIFT_CUR_VER_FILE), "w+").write(cur_ver_file.content)
NameError: name 'file' is not defined

... my little reading around it points to Python version compatibility, etc.

@Sivridis
Copy link

I had Z113 patcher.cpp problem while trying to install Zwift.
The method provided by Kostyay helped me and finally Zwift is working!!!
Dear @nadodiganesh yo should change "<path\to\zwift\install\dir>" to insall dir where Zwift was installed. I mean you should write this command to cmd

C:\Python27\python download_zwift_updates.py "C:\Program Files (x86)\Zwift"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment