Skip to content

Commit

Permalink
Using sketchfab API v3
Browse files Browse the repository at this point in the history
  • Loading branch information
yorikvanhavre committed Mar 11, 2017
1 parent 623fcea commit bf3b6d4
Showing 1 changed file with 87 additions and 17 deletions.
104 changes: 87 additions & 17 deletions src/Mod/Web/Webscripts/Sketchfab.py
Expand Up @@ -26,7 +26,7 @@
__author__ = "Yorik van Havre"
__url__ = "http://www.freecadweb.org"

import FreeCAD, FreeCADGui, WebGui, os, zipfile, requests, tempfile
import FreeCAD, FreeCADGui, WebGui, os, zipfile, requests, tempfile, json, time
from PySide import QtCore, QtGui

# \cond
Expand All @@ -38,7 +38,7 @@ def translate(context, text, disambig=None):
return QtGui.QApplication.translate(context, text, disambig)
# \endcond

SKETCHFAB_UPLOAD_URL = "https://api.sketchfab.com/v1/models"
SKETCHFAB_UPLOAD_URL = "https://api.sketchfab.com/v3/models"
SKETCHFAB_TOKEN_URL = "https://sketchfab.com/settings/password"
SKETCHFAB_MODEL_URL = "https://sketchfab.com/show/"

Expand Down Expand Up @@ -80,6 +80,16 @@ def getToken(self):

QtGui.QDesktopServices.openUrl(SKETCHFAB_TOKEN_URL)

def get_request_payload(self, token, data={}, files={}, json_payload=False):

"""Helper method that returns the authentication token and proper content
type depending on whether or not we use JSON payload."""
headers = {'Authorization': 'Token {}'.format(token)}
if json_payload:
headers.update({'Content-Type': 'application/json'})
data = json.dumps(data)
return {'data': data, 'files': files, 'headers': headers}

def saveFile(self):

import FreeCADGui
Expand Down Expand Up @@ -120,7 +130,6 @@ def saveFile(self):

def packFiles(self,filename,fileslist):

originalname = os.path.basename(fileslist[0])
for f in fileslist:
if not os.path.exists(f):
return None
Expand All @@ -135,7 +144,7 @@ def packFiles(self,filename,fileslist):
size = str(s >> 20)+" MB"
else:
size = str(s >> 10)+" KB"
return (filename+".zip",originalname,size)
return (filename+".zip",size)

def upload(self):

Expand All @@ -151,42 +160,103 @@ def upload(self):
QtGui.QMessageBox.critical(None,translate("Web","File packing error"),translate("Unable to save and zip a file for upload"))
return
data = {
"title": self.form.Text_Name.text(),
"name": self.form.Text_Name.text(),
"description": self.form.Text_Description.text(),
"filename": pack[1],
"tags": "freecad,"+self.form.Text_Tags.text(),
"tags": ["freecad"]+[t.strip() for t in self.form.Text_Tags.text().split(",")],
"private": self.form.Check_Private.isChecked(),
"token": self.form.Text_Token.text(),
"source": "freecad",
}
files = {
"fileModel": open(pack[0], 'rb'),
"modelFile": open(pack[0], 'rb')
}
self.form.Button_Upload.hide()
# for now this is a fake progress bar, it won't move, just to show the user that the upload is in progress
self.form.ProgressBar.setFormat(translate("Web","Uploading")+" "+pack[2]+"...")
self.form.ProgressBar.setFormat(translate("Web","Uploading")+" "+pack[1]+"...")
self.form.ProgressBar.show()
try:
r = requests.post(SKETCHFAB_UPLOAD_URL, data=data, files=files, verify=False)
r = requests.post(SKETCHFAB_UPLOAD_URL, **self.get_request_payload(self.form.Text_Token.text(), data, files=files))
except requests.exceptions.RequestException as e:
QtGui.QMessageBox.critical(None,translate("Web","Upload error"),translate("Upload failed:")+" "+str(e))
self.form.ProgressBar.hide()
self.form.Button_Upload.show()
return
result = r.json()
if r.status_code != requests.codes.ok:
QtGui.QMessageBox.critical(None,translate("Web","Upload error"),translate("Upload failed:")+" "+result["error"])
if r.status_code != requests.codes.created:
QtGui.QMessageBox.critical(None,translate("Web","Upload error"),translate("Upload failed:")+" "+r.json())
self.form.ProgressBar.hide()
self.form.Button_Upload.show()
return
self.url = SKETCHFAB_MODEL_URL + result["result"]["id"]
self.url = r.headers['Location']
if self.form.Combo_Filetype.currentIndex() in [0,1]: # OBJ format, sketchfab expects inverted Y/Z axes
self.form.ProgressBar.setFormat(translate("Web","Awaiting confirmation..."))
self.form.ProgressBar.setValue(75)
if self.poll(self.url):
self.form.ProgressBar.setFormat(translate("Web","Fixing model..."))
self.patch(self.url)
else:
QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:"))
self.form.ProgressBar.hide()
self.form.Button_View.show()

def poll(self,url):

"""GET the model endpoint to check the processing status."""
max_errors = 10
errors = 0
retry = 0
max_retries = 50
retry_timeout = 5 # seconds
while (retry < max_retries) and (errors < max_errors):
try:
r = requests.get(url, **self.get_request_payload(self.form.Text_Token.text()))
except requests.exceptions.RequestException as e:
print ('Sketchfab: Polling failed with error {}'.format(e))
errors += 1
retry += 1
continue
result = r.json()
if r.status_code != requests.codes.ok:
print ('Sketchfab: Polling failed with error: {}'.format(result['error']))
errors += 1
retry += 1
continue
processing_status = result['status']['processing']
if processing_status == 'PENDING':
retry += 1
time.sleep(retry_timeout)
continue
elif processing_status == 'PROCESSING':
retry += 1
time.sleep(retry_timeout)
continue
elif processing_status == 'FAILED':
print ('Sketchfab: Polling failed: {}'.format(result['error']))
return False
elif processing_status == 'SUCCEEDED':
return True
retry += 1
print ('Sketchfab: Stopped polling after too many retries or too many errors')
return False

def patch(self,url):

"applies different fixes to the uploaded model"
options_url = os.path.join(url, 'options')
data = {
'orientation': '{"axis": [1, 0, 0], "angle": 270}'
}
try:
r = requests.patch(options_url, **self.get_request_payload(self.form.Text_Token.text(), data, json_payload=True))
except requests.exceptions.RequestException as e:
QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:")+" "+str(e))
else:
if r.status_code != 204:
QtGui.QMessageBox.warning(None,translate("Web","Patch error"),translate("Web","Patching failed. The model was successfully uploaded, but might still require manual adjustments:")+" "+str(r.content))

def viewModel(self):

if self.url:
QtGui.QDesktopServices.openUrl(self.url)
url = self.url.replace("api","www")
url = url.replace("/v3","")
QtGui.QDesktopServices.openUrl(url)



Expand Down

0 comments on commit bf3b6d4

Please sign in to comment.