1
This commit is contained in:
1 parent
53a5daab38
commit
7679e5510b
2 files changed
+157
-135
No files matched your search
@@ -66,6 +66,8 @@ def down_obj_fromoss(pid,order_id):
|
|||||||
if filename.endswith(f'{pid}.obj'):
|
if filename.endswith(f'{pid}.obj'):
|
||||||
find = True
|
find = True
|
||||||
localfile = os.path.join(path, filename)
|
localfile = os.path.join(path, filename)
|
||||||
|
if "process" in file.key or "human" in file.key:
|
||||||
|
continue
|
||||||
res = oss_client.get_object_to_file(file.key, localfile)
|
res = oss_client.get_object_to_file(file.key, localfile)
|
||||||
print(f'下载文件:{file.key},状态:{res.status}')
|
print(f'下载文件:{file.key},状态:{res.status}')
|
||||||
|
|
||||||
|
|||||||
+155
-135
@@ -1,52 +1,77 @@
|
|||||||
from ctypes import util
|
from ctypes import util
|
||||||
import os, oss2, time, redis, requests, shutil, sys, subprocess, json, qrcode
|
import os, oss2, time, redis, requests, shutil, sys, subprocess, json, platform
|
||||||
from PIL import Image, ImageDraw, ImageFont
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
from retrying import retry
|
||||||
|
import atexit,platform
|
||||||
|
import white_purification_v4,white_purification
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
sys.path.append('e:\\libs\\')
|
||||||
|
import common
|
||||||
|
import config
|
||||||
|
def find_blender_bin_path():
|
||||||
|
if platform.system() == 'Linux': return 'blender'
|
||||||
|
base_path = 'C:\\Program Files\\Blender Foundation\\'
|
||||||
|
if os.path.exists(base_path):
|
||||||
|
for dir in os.listdir(base_path):
|
||||||
|
if dir.startswith('Blender'):
|
||||||
|
blender_bin_path = base_path + dir + '\\blender.exe'
|
||||||
|
return f'"{blender_bin_path}"'
|
||||||
|
else:
|
||||||
|
print('未找到blender安装目录')
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
@retry(stop_max_attempt_number=10, wait_fixed=3000)
|
||||||
def gen_qrcode(pid):
|
def down_obj_fromoss(pid,order_id):
|
||||||
fontHeightMax = 40
|
|
||||||
fontsize = 1
|
|
||||||
qr = qrcode.QRCode()
|
|
||||||
qr.border = 2
|
|
||||||
qr.add_data(pid)
|
|
||||||
img = qr.make_image(fit=True)
|
|
||||||
img = img.transform((250, 294), Image.Transform.EXTENT, (0, 0, 250, 294), fillcolor='white')
|
|
||||||
|
|
||||||
cwd = os.path.dirname(os.path.abspath(__file__))
|
|
||||||
fontfile = os.path.join(cwd, 'fonts', 'Helvetica.ttf')
|
|
||||||
font = ImageFont.truetype(fontfile, fontsize)
|
|
||||||
while font.getsize(pid)[1] <= fontHeightMax and font.getsize(pid)[0] <= 240:
|
|
||||||
fontsize += 1
|
|
||||||
font = ImageFont.truetype(fontfile, fontsize)
|
|
||||||
fontsize -= 1
|
|
||||||
|
|
||||||
captionx = (250 - font.getsize(pid)[0]) / 2
|
|
||||||
draw = ImageDraw.Draw(img)
|
|
||||||
draw.text((captionx, 242), pid, font=font)
|
|
||||||
# img.show()
|
|
||||||
path = os.path.join(workdir, 'print', pid)
|
|
||||||
img.save(f'{path}/{pid}.png')
|
|
||||||
|
|
||||||
def down_obj_fromoss(pid, print_type=1):
|
|
||||||
# print_type:// 打印状态 1:正常打印 2:重打 3:加打,4: 样品
|
# print_type:// 打印状态 1:正常打印 2:重打 3:加打,4: 样品
|
||||||
print('开始下载obj文件...' , pid)
|
print('开始下载obj文件...' , pid)
|
||||||
if not os.path.exists(os.path.join(workdir, 'print')):
|
#请求接口 获取 对应的 oss 地址
|
||||||
os.mkdir(os.path.join(workdir, 'print'))
|
tempUrl = f'https://mp.api.suwa3d.com/api/order/getOssSuffixByOrderId?order_id={order_id}'
|
||||||
path = os.path.join(workdir, 'print', pid)
|
print(tempUrl)
|
||||||
if not os.path.exists(path): os.mkdir(path)
|
#发起请求
|
||||||
|
res = requests.get(tempUrl)
|
||||||
|
ossPath = ""
|
||||||
|
if res.json()['code'] == 1000:
|
||||||
|
ossPath = res.json()['data']
|
||||||
|
ossPath = ossPath.replace("\\","/")
|
||||||
|
print("AAAAAAAAA",ossPath)
|
||||||
|
|
||||||
|
|
||||||
|
path = os.path.join(workdir, 'print', pid,order_id)
|
||||||
|
if not os.path.exists(path): os.makedirs(path)
|
||||||
|
|
||||||
# 根据前缀获取文件列表
|
# 根据前缀获取文件列表
|
||||||
prefix = f'objs/print/{pid}/'
|
prefix = f'objs/print/{pid}/'
|
||||||
|
if ossPath != "":
|
||||||
|
prefix = os.path.join("objs","print",pid,ossPath)
|
||||||
|
if "base/" in ossPath:
|
||||||
|
prefix = os.path.join("objs","print",pid,ossPath)
|
||||||
|
prefix = prefix.replace("\\","/")
|
||||||
|
|
||||||
|
print(f'prefix:{prefix}')
|
||||||
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
|
||||||
|
|
||||||
|
if len(list(filelist)) == 0:
|
||||||
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=f"objs/print/{pid}")
|
||||||
|
else:
|
||||||
|
filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix)
|
||||||
|
|
||||||
|
|
||||||
find = False
|
find = False
|
||||||
for file in filelist:
|
for file in filelist:
|
||||||
filename = file.key.split('/')[-1]
|
filename = file.key.split('/')[-1]
|
||||||
if filename == '': continue
|
if filename == '': continue
|
||||||
|
if filename.endswith(f'.obj') and find == True:
|
||||||
|
continue
|
||||||
|
|
||||||
if filename.endswith(f'{pid}.obj'):
|
if filename.endswith(f'{pid}.obj'):
|
||||||
find = True
|
find = True
|
||||||
print('正在下载:', file.key)
|
|
||||||
localfile = os.path.join(path, filename)
|
localfile = os.path.join(path, filename)
|
||||||
oss_client.get_object_to_file(file.key, localfile)
|
if "process" in file.key or "human" in file.key:
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
res = oss_client.get_object_to_file(file.key, localfile)
|
||||||
|
print(f'下载文件:{file.key},状态:{res.status}')
|
||||||
|
|
||||||
if not find and print_type == 3:
|
if not find and print_type == 3:
|
||||||
for file in os.listdir(path):
|
for file in os.listdir(path):
|
||||||
@@ -59,137 +84,130 @@ def down_obj_fromoss(pid, print_type=1):
|
|||||||
print('找不到obj文件,异常退出')
|
print('找不到obj文件,异常退出')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
return ossPath
|
||||||
|
# print('下载完成后静默10秒,等待文件写入完成')
|
||||||
|
# time.sleep(10)
|
||||||
|
|
||||||
def getPidFromOrderId(orderId):
|
def getPidFromOrderId(orderId):
|
||||||
getPidFromOrderId_url = 'https://mp.api.suwa3d.com/api/printOrder/info'
|
getPidFromOrderId_url = 'https://mp.api.suwa3d.com/api/printOrder/info'
|
||||||
print(f'{getPidFromOrderId_url}?id={orderId}')
|
print(f'{getPidFromOrderId_url}?id={orderId}')
|
||||||
res = requests.get(f'{getPidFromOrderId_url}?id={orderId}')
|
res = requests.get(f'{getPidFromOrderId_url}?id={orderId}')
|
||||||
|
resCode = res.json()['code']
|
||||||
|
if int(resCode) != 1000:
|
||||||
|
return -1
|
||||||
print(res.text)
|
print(res.text)
|
||||||
return res.json()['data']
|
return res.json()['data']
|
||||||
|
|
||||||
def detect_obj4print(pid):
|
|
||||||
for file in os.listdir(os.path.join(workdir, 'print', pid)):
|
|
||||||
if file.endswith('.obj') and 'x' in file:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def make3d4print_task(r):
|
|
||||||
try:
|
|
||||||
if r.llen('model:printOrder') == 0:
|
|
||||||
time.sleep(5)
|
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,重新连接')
|
|
||||||
print(e)
|
|
||||||
time.sleep(5)
|
|
||||||
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
|
|
||||||
return
|
|
||||||
orderId = r.lpop('model:printOrder')
|
|
||||||
if orderId is None: return
|
|
||||||
orderId = orderId.decode('utf-8')
|
|
||||||
res = getPidFromOrderId(orderId)
|
|
||||||
pid = str(res['pid'])
|
|
||||||
print_type = res['print_type']
|
|
||||||
digital_type = res['digital_type'] # 0: 只有手办 1: 只有数字模型 2: 手办+数字模型
|
|
||||||
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 start', )
|
|
||||||
down_obj_fromoss(pid, print_type)
|
|
||||||
gen_qrcode(pid)
|
|
||||||
os.system(f'{blenderbin} -b -P d:\\apps\\blender\\resize_model.py -- {orderId}')
|
|
||||||
if not detect_obj4print(pid):
|
|
||||||
print('obj文件生成异常,退出')
|
|
||||||
sys.exit(1)
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 end')
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 上传生成的模型 start', )
|
|
||||||
for file in os.listdir(os.path.join(workdir, 'print', pid)):
|
|
||||||
if file.endswith('.obj') and (not file.endswith(f'{pid}.obj')):
|
|
||||||
oss_client.put_object_from_file(f'objs/print/{pid}/{file}', os.path.join(workdir, 'print', pid, file))
|
|
||||||
if file.endswith('.glb'):
|
|
||||||
oss_client.put_object_from_file(f'glbs/3d/{pid}.glb', os.path.join(workdir, 'print', pid, file))
|
|
||||||
|
|
||||||
oss_client.delete_object(f'objs/print/{pid}/{pid}.obj')
|
|
||||||
shutil.rmtree(os.path.join(workdir, 'print', pid), ignore_errors=True)
|
|
||||||
|
|
||||||
print(f'{update_makeprintobj_status_url}?id={orderId}')
|
|
||||||
if digital_type == 1:
|
|
||||||
print('只有数字模型,不需要推送手办打印任务')
|
|
||||||
else:
|
|
||||||
res = requests.get(f'{update_makeprintobj_status_url}?id={orderId}')
|
|
||||||
print('更新打印状态:', res.text)
|
|
||||||
if res.json()['code'] != 1000:
|
|
||||||
print('更新打印状态失败')
|
|
||||||
sys.exit(1)
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 上传生成的模型 end')
|
|
||||||
|
|
||||||
def team_check(r):
|
def team_check(r):
|
||||||
try:
|
# try:
|
||||||
if r.llen('model:IndependentRepairTeamcheckGLBQueue') == 0:
|
# if r.llen('model:IndependentRepairTeamcheckGLBQueue') == 0:
|
||||||
time.sleep(5)
|
# time.sleep(5)
|
||||||
return
|
# return
|
||||||
except Exception as e:
|
# except Exception as e:
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试')
|
# print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试')
|
||||||
print(e)
|
# print(e)
|
||||||
time.sleep(5)
|
# time.sleep(5)
|
||||||
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
|
# r = create_redis_connection()
|
||||||
return
|
# return
|
||||||
repair_id = r.lpop('model:IndependentRepairTeamcheckGLBQueue')
|
# repair_id = r.lpop('model:IndependentRepairTeamcheckGLBQueue')
|
||||||
if repair_id is None: return
|
# if repair_id is None: return
|
||||||
repair_id = repair_id.decode('utf-8')
|
# repair_id = repair_id.decode('utf-8')
|
||||||
|
|
||||||
|
repair_id = "66682"
|
||||||
|
|
||||||
res = requests.get(f'{getRepairInfo_url}?id={repair_id}')
|
res = requests.get(f'{getRepairInfo_url}?id={repair_id}')
|
||||||
|
print(f'getRepairInfo_url:{getRepairInfo_url}?id={repair_id}')
|
||||||
print(res.text)
|
print(res.text)
|
||||||
pid = res.json()['data']['pid']
|
pid = res.json()['data']['pid']
|
||||||
|
orderId = res.json()['data']['order_id']
|
||||||
pid = str(pid)
|
pid = str(pid)
|
||||||
|
orderId = str(orderId)
|
||||||
|
|
||||||
|
#print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} repair_id:{repair_id} 生成团队审核模型 start model:IndependentRepairTeamcheckGLBQueue', )
|
||||||
|
ossPath = down_obj_fromoss(pid,orderId)
|
||||||
|
|
||||||
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成团队审核模型 start', )
|
|
||||||
down_obj_fromoss(pid)
|
|
||||||
obj_filename = f'{pid}.obj'
|
obj_filename = f'{pid}.obj'
|
||||||
glb_filename = f'{pid}.glb'
|
glb_filename = f'{orderId}.glb'
|
||||||
print('开始转换obj文件为glb文件...')
|
print('开始转换obj文件为glb文件...')
|
||||||
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
|
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid,orderId, obj_filename)} -o {os.path.join(workdir, "print", pid,orderId, glb_filename)} -vt 16 -vc 16')
|
||||||
print('上传glb文件到oss...')
|
|
||||||
oss_client.put_object_from_file(f'glbs/print/{glb_filename}', os.path.join(workdir, "print", pid, glb_filename))
|
#处理封面图
|
||||||
|
#执行获取obj缩略图
|
||||||
|
print("执行获取obj全身缩略图脚本1111111111")
|
||||||
|
os.system(f'python d:\\make2\\tools\pic_for_obj\image_rander_small.py -pid {pid} -i D://print/{pid}/{orderId} -o D://print/{pid}/{orderId}')
|
||||||
|
print("判断是否存在封面图")
|
||||||
|
#判断文件是否存在,存在则上传到oss, 更新数据库内容
|
||||||
|
if os.path.exists(f'D://print/{pid}/{orderId}/{pid}_pic.png'):
|
||||||
|
#获取拍照订单的信息,从中得到拍照订单的信息
|
||||||
|
uuid = get_p3d_info(str(pid))
|
||||||
|
if uuid != 0 and uuid != None and uuid != "":
|
||||||
|
print("uuid",uuid)
|
||||||
|
config.oss_bucket_3d_view.put_object_from_file(f'{uuid}/3d_view.png', f'D://print/{pid}/{orderId}/{pid}_pic.png')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
oss_client.put_object_from_file(f'glbs/print/order_id/{glb_filename}', os.path.join(workdir, "print", pid,orderId, glb_filename))
|
||||||
|
|
||||||
|
#对文件进行白色提纯处理
|
||||||
|
imagePath = os.path.join(workdir, 'print', pid,orderId,pid+"Tex1.jpg")
|
||||||
|
print("开始处理白色提纯")
|
||||||
|
#white_purification.white_purification_utils(imagePath)
|
||||||
|
os.system(f'python D:\\make2\\apps\white_purification_v4.py -i {imagePath}')
|
||||||
|
|
||||||
|
print("贴图文件白色提纯完成",imagePath)
|
||||||
|
#提纯完重新上传提纯图片
|
||||||
|
ossImagePath = os.path.join("objs/print", pid,ossPath,"texture","process_"+pid+"Tex1.jpg")
|
||||||
|
oss_client.put_object_from_file(f"objs/print/{pid}/{ossPath}/texture/process_{pid}Tex1.jpg",imagePath)
|
||||||
|
print("白色提纯上传图片路径-",ossImagePath,imagePath)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print(f'{update_repair_status_url}?id={repair_id}')
|
print(f'{update_repair_status_url}?id={repair_id}')
|
||||||
res = requests.get(f'{update_repair_status_url}?id={repair_id}')
|
res = requests.get(f'{update_repair_status_url}?id={repair_id}')
|
||||||
print('更新团队审核状态:', res.text)
|
print('更新团队审核状态:', res.text)
|
||||||
shutil.rmtree(os.path.join(workdir, 'print', pid), ignore_errors=True)
|
shutil.rmtree(os.path.join(workdir, 'print', pid,orderId), ignore_errors=True)
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成团队审核模型 end')
|
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成团队审核模型 end')
|
||||||
|
|
||||||
def platform_check(r):
|
def get_p3d_info(pid):
|
||||||
try:
|
url = "https://mp.api.suwa3d.com/api/customerP3dLog/info?id="+pid
|
||||||
if r.llen('model:modelRepairGLBQueue') == 0:
|
res = requests.get(url)
|
||||||
|
res = res.json()
|
||||||
|
if res["code"] == 1000:
|
||||||
|
return res["data"]["guid"]
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def create_redis_connection():
|
||||||
|
"""创建 Redis 连接,若连接失败则重试"""
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
|
||||||
|
# 尝试进行一次操作,检查连接是否有效
|
||||||
|
r.ping() # ping 操作是一个简单的连接测试
|
||||||
|
print("Redis连接成功!")
|
||||||
|
return r
|
||||||
|
except ConnectionError:
|
||||||
|
print("Redis连接失败,正在重试...")
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
return
|
|
||||||
except Exception as e:
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,5秒后重试')
|
|
||||||
print(e)
|
|
||||||
time.sleep(5)
|
|
||||||
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
|
|
||||||
return
|
|
||||||
pid = r.lpop('model:modelRepairGLBQueue')
|
|
||||||
if pid is None: return
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成平台审核模型 start', )
|
|
||||||
|
|
||||||
pid = pid.decode('utf-8')
|
|
||||||
down_obj_fromoss(pid)
|
|
||||||
obj_filename = f'{pid}.obj'
|
|
||||||
glb_filename = f'{pid}.glb'
|
|
||||||
os.system(f'gltfpack -c -i {os.path.join(workdir, "print", pid, obj_filename)} -o {os.path.join(workdir, "print", pid, glb_filename)}')
|
|
||||||
oss_client.put_object_from_file(f'glbs/print/{glb_filename}', os.path.join(workdir, "print", pid, glb_filename))
|
|
||||||
|
|
||||||
print(f'{update_check_url}?id={pid}')
|
|
||||||
res = requests.get(f'{update_check_url}?id={pid}')
|
|
||||||
print(res.text)
|
|
||||||
shutil.rmtree(os.path.join(workdir, 'print', pid), ignore_errors=True)
|
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} 生成平台审核模型 end')
|
|
||||||
|
|
||||||
def main(r):
|
def main(r):
|
||||||
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '模型生成程序 start')
|
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), '模型生成程序 start')
|
||||||
while True:
|
while True:
|
||||||
# team_check(r)
|
try:
|
||||||
# platform_check(r)
|
team_check(r)
|
||||||
make3d4print_task(r)
|
except Exception as e:
|
||||||
|
print('出现异常:', e)
|
||||||
|
time.sleep(5)
|
||||||
|
r = create_redis_connection()
|
||||||
|
continue
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
atexit.register(common.notify,"R13-修模师审核通过,生成打印任务程序停止")
|
||||||
AccessKeyId = 'LTAI5tSReWm8hz7dSYxxth8f'
|
AccessKeyId = 'LTAI5tSReWm8hz7dSYxxth8f'
|
||||||
AccessKeySecret = '8ywTDF9upPAtvgXtLKALY2iMYHIxdS'
|
AccessKeySecret = '8ywTDF9upPAtvgXtLKALY2iMYHIxdS'
|
||||||
Endpoint = 'oss-cn-shanghai.aliyuncs.com'
|
Endpoint = 'oss-cn-shanghai.aliyuncs.com'
|
||||||
@@ -201,8 +219,10 @@ if __name__ == '__main__':
|
|||||||
update_makeprintobj_status_url = 'https://mp.api.suwa3d.com/api/printOrder/updateMakePrintObjSucceed'
|
update_makeprintobj_status_url = 'https://mp.api.suwa3d.com/api/printOrder/updateMakePrintObjSucceed'
|
||||||
getRepairInfo_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/teamCheckGLBInfo'
|
getRepairInfo_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/teamCheckGLBInfo'
|
||||||
update_repair_status_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/updateStatusToWaitingTeamCheckingStatus'
|
update_repair_status_url = 'https://repair.api.suwa3d.com/api/modelRepairOrder/updateStatusToWaitingTeamCheckingStatus'
|
||||||
workdir = 'D:\\'
|
if platform.system() == 'Windows':
|
||||||
blenderbin = '"C:\\Program Files\\Blender Foundation\\Blender 3.3\\blender.exe"'
|
workdir = 'D:\\'
|
||||||
|
else:
|
||||||
r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6)
|
workdir = '/data/datasets/'
|
||||||
|
blenderbin = find_blender_bin_path()
|
||||||
|
r = create_redis_connection()
|
||||||
main(r)
|
main(r)
|
||||||
Reference in new issue
Block a user