Skip to content

Commit

Permalink
feat(binary i3d): add a button to fetch binary converter from GDN
Browse files Browse the repository at this point in the history
Add a button to fetch the binary i3d converter directly from GDN if provided a valid login.
For security reasons the login will not be remembered neither in the session nor between sessions.
  • Loading branch information
StjerneIdioten committed Nov 5, 2023
1 parent 4bb028f commit 98e125d
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 4 deletions.
2 changes: 1 addition & 1 deletion addon/i3dio/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
exporter_old.py

**/i3dConverter.exe
75 changes: 72 additions & 3 deletions addon/i3dio/ui/addon_preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import bpy
from bpy.types import AddonPreferences
from bpy.props import (StringProperty, EnumProperty)
from bpy.props import (StringProperty, EnumProperty, BoolProperty)

from .. import xml_i3d

Expand Down Expand Up @@ -78,6 +78,7 @@ def draw(self, context):
row.prop(self, 'i3d_converter_path')
if(next((True for addon in addon_utils.modules() if addon.bl_info.get("name") == "GIANTS I3D Exporter Tools"), False)):
row.operator('i3dio.i3d_converter_path_from_giants_addon', text="", icon="EVENT_G")
row.operator("i3dio.download_i3d_converter", text="", icon='WORLD_DATA')
case 'AUTOMATIC':
#row = c_box.row()
#row.operator("i3dio.download_i3d_converter", text="Manage Automatic Download")
Expand All @@ -101,11 +102,79 @@ def execute(self, context):
class I3D_IO_OT_download_i3d_converter(bpy.types.Operator):
bl_idname = "i3dio.download_i3d_converter"
bl_label = "Download I3D Converter"
bl_description = "Download I3D Converter"
bl_description = "Download from Giants Developer Network (Requires valid login)"
bl_options = {'INTERNAL'}

email: StringProperty(name="Email", default="")
password: StringProperty(name="Password", default="", subtype="PASSWORD")

def execute(self, context):
return {"FINISHED"}
import re
from io import BytesIO
from requests import Session
from zipfile import (ZipFile, BadZipfile)
from shutil import copyfileobj

# Attempt to login using provided credentials
session = Session()
request = session.post('https://gdn.giants-software.com/index.php', data={'greenstoneX':'1', 'redstoneX':self.email, 'bluestoneX':self.password})

## Clear email and password after usage
self.email = ""
self.password = ""

# Check if login was successful
if '<li id="topmenu1"><a href="index.php?logout=true" accesskey="1" title="">Logout</a></li>' not in request.text:
self.report({'WARNING'}, f"Could not login to https://gdn.giants-software.com/index.php with provided credentials!")
return {'CANCELLED'}

# Get download page
request = session.get('https://gdn.giants-software.com/downloads.php')

# Find the download IDs for the all Giants Blender Exporters (As long as Giants names them the same way)
result = re.findall(r'href="download.php\?downloadId=([0-9]+)">Blender Exporter Plugins v([0-9]+.[0-9]+.[0-9]+)', request.text)

# Assume the first found is the newest
download_id, exporter_version = result[0]

# Request download of Giants I3D Exporter
download_url = f'https://gdn.giants-software.com/download.php?downloadId={download_id}'
request = session.get(download_url)

try:
# Create in-memory zipfile from downloaded content
zipfile = ZipFile(BytesIO(request.content), 'r')
# Find path to this exporter addon
binary_path = 'i3dConverter.exe'
for addon in addon_utils.modules():
if addon.bl_info.get("name") == "Unofficial GIANTS I3D Exporter Tools":
binary_path = pathlib.PurePath(addon.__file__).parent.joinpath(binary_path)
# Extract I3D Converter Binary from zipfile and save to disk
with zipfile.open('io_export_i3d/util/i3dConverter.exe') as zipped_binary, open(binary_path, 'wb') as saved_binary:
copyfileobj(zipped_binary, saved_binary)
# Set I3D Converter Binary path to newly downloaded converter
bpy.context.preferences.addons['i3dio'].preferences.i3d_converter_path = str(binary_path)
except (BadZipfile, KeyError, OSError) as e:
self.report({'WARNING'}, f"The Community I3D Exporter did not succesfully fetch and install the Giants I3D Converter binary! ({e})")
return {'CANCELLED'}

self.report({'INFO'}, f"Fetched i3dConverter.exe from version {exporter_version} of the Giants Exporter downloaded from {download_url}")
return {'FINISHED'}

def invoke(self, context, event):
wm = bpy.context.window_manager
# Width increased to fit the warning about the download freezing the UI
return wm.invoke_props_dialog(self, width=350)

def draw(self, context):
layout = self.layout
row = layout.row()
row.prop(self, "email")
row = layout.row()
row.prop(self, "password")
row = layout.row()
row.alignment = "CENTER"
row.label(text="Blender UI will appear frozen during file download (~15MB) ", icon="ERROR")


def register():
Expand Down

0 comments on commit 98e125d

Please sign in to comment.