upload
This commit is contained in:
+218
-106
@@ -5,10 +5,10 @@ import re
|
||||
import urllib3
|
||||
import traceback
|
||||
import time
|
||||
import uuid
|
||||
|
||||
from bpy.props import PointerProperty, StringProperty
|
||||
from pathlib import Path
|
||||
from vse_toolbox.bl_utils import get_addon_prefs, get_scene_settings
|
||||
from vse_toolbox.file_utils import install_module, norm_str
|
||||
from vse_toolbox.resources.trackers.tracker import Tracker
|
||||
|
||||
@@ -18,34 +18,163 @@ except Exception as e:
|
||||
print('Could not install gazu')
|
||||
print(e)
|
||||
|
||||
LOGIN = None
|
||||
|
||||
class Kitsu(Tracker):
|
||||
name = "Kitsu"
|
||||
|
||||
|
||||
url: StringProperty()
|
||||
login: StringProperty()
|
||||
password: StringProperty(subtype='PASSWORD')
|
||||
|
||||
project_name = None
|
||||
def connect(self, url=None, login=None, password=None):
|
||||
'''Connect to kitsu api using provided url, login and password'''
|
||||
|
||||
global LOGIN
|
||||
|
||||
urllib3.disable_warnings()
|
||||
|
||||
if url is None:
|
||||
url = self.url
|
||||
if login is None:
|
||||
login = self.login
|
||||
if password is None:
|
||||
password = self.password
|
||||
|
||||
if not url:
|
||||
print(f'Kitsu Url: {self.url} is empty')
|
||||
return
|
||||
|
||||
if login == LOGIN:
|
||||
return
|
||||
|
||||
if not url.endswith('/api'):
|
||||
url += '/api'
|
||||
|
||||
print(f'Info: Setting Host for kitsu {url}')
|
||||
gazu.client.set_host(url)
|
||||
|
||||
if not gazu.client.host_is_up():
|
||||
print('Error: Kitsu Host is down')
|
||||
|
||||
try:
|
||||
print(f'Info: Log in to kitsu as {login}')
|
||||
res = gazu.log_in(login, password)
|
||||
LOGIN = login
|
||||
print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}')
|
||||
return res['user']
|
||||
except Exception as e:
|
||||
print(f'Error: {traceback.format_exc()}')
|
||||
|
||||
def get_id(self, data):
|
||||
if isinstance(data, str):
|
||||
if self.is_id(data):
|
||||
return data
|
||||
#return None
|
||||
elif isinstance(data, dict):
|
||||
return data['id']
|
||||
elif data: # Should be a Class
|
||||
return data.id
|
||||
|
||||
def is_id(self, id):
|
||||
if not isinstance(id, str):
|
||||
return False
|
||||
try:
|
||||
uuid.UUID(id)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
def get_project(self, project=None):
|
||||
if project:
|
||||
project_id = self.get_id(project)
|
||||
if project_id:
|
||||
return project_id
|
||||
return gazu.project.get_project_by_name(project)
|
||||
|
||||
if os.environ.get('TRACKER_PROJECT_ID'):
|
||||
return os.environ['TRACKER_PROJECT_ID']
|
||||
elif os.environ.get('TRACKER_PROJECT_NAME'):
|
||||
return os.environ['TRACKER_PROJECT_NAME']
|
||||
|
||||
def draw_prefs(self, layout):
|
||||
layout.prop(self, 'url', text='Url')
|
||||
layout.prop(self, 'login', text='Login')
|
||||
layout.prop(self, 'password', text='Password')
|
||||
|
||||
def get_projects(self):
|
||||
return gazu.project.all_open_projects()
|
||||
|
||||
def get_episode(self, episode, project=None):
|
||||
project = self.get_project(project)
|
||||
if episode:
|
||||
episode_id = self.get_id(episode)
|
||||
if episode_id:
|
||||
return episode_id
|
||||
return gazu.shot.get_episode_by_name(project, episode)
|
||||
|
||||
if os.environ.get('TRACKER_EPISODE_ID'):
|
||||
return os.environ['TRACKER_EPISODE_ID']
|
||||
elif os.environ.get('TRACKER_EPISODE_NAME'):
|
||||
return os.environ['TRACKER_EPISODE_NAME']
|
||||
|
||||
def get_episodes(self, project):
|
||||
return gazu.shot.all_episodes_for_project(project)
|
||||
|
||||
def get_episode(self, name):
|
||||
return gazu.shot.get_episode_by_name(self.project, name)
|
||||
def get_task_type(self, task_type=None):
|
||||
print('get_task_type', task_type)
|
||||
return gazu.task.get_task_type_by_name(task_type)
|
||||
|
||||
def get_asset_types(self, project):
|
||||
def get_shot_task_types(self, project=None):
|
||||
project = self.get_project(project)
|
||||
task_types = gazu.task.all_task_types_for_project(project)
|
||||
return [t for t in task_types if t['for_entity'].lower() == 'shot']
|
||||
|
||||
def get_shots_metadata(self, project=None):
|
||||
project = self.get_project(project)
|
||||
metadatas = []
|
||||
|
||||
for metadata in gazu.project.all_metadata_descriptors(project):
|
||||
if metadata['entity_type'] == 'Shot' and metadata['name']:
|
||||
metadatas.append(metadata)
|
||||
|
||||
return metadatas
|
||||
|
||||
def get_task_status(self, status=None):
|
||||
status_id = self.get_id(status)
|
||||
if status_id:
|
||||
return status_id
|
||||
|
||||
return gazu.client.fetch_first('task-status', {"short_name": status.lower()})
|
||||
|
||||
def get_task_statuses(self, project=None):
|
||||
project = self.get_project(project)
|
||||
return gazu.task.all_task_statuses_for_project(project)
|
||||
|
||||
def get_asset_types(self, project=None):
|
||||
project = self.get_project(project)
|
||||
return gazu.asset.all_asset_types_for_project(project)
|
||||
|
||||
def get_assets(self, project):
|
||||
def get_sequence(self, sequence, project=None):
|
||||
print(f'get_sequence({sequence=}, {project=})')
|
||||
project = self.get_project(project)
|
||||
|
||||
sequence_id = self.get_id(sequence)
|
||||
if sequence_id:
|
||||
return sequence_id
|
||||
|
||||
return gazu.shot.get_sequence_by_name(project, sequence)
|
||||
|
||||
def get_shot(self, shot, sequence, project=None):
|
||||
print(f'get_shot({shot=}, {sequence=}, {project=})')
|
||||
project = self.get_project(project)
|
||||
sequence = self.get_sequence(sequence, project)
|
||||
|
||||
if not sequence:
|
||||
return
|
||||
|
||||
shot_id = self.get_id(shot)
|
||||
if shot_id:
|
||||
return shot_id
|
||||
|
||||
return gazu.shot.get_shot_by_name(sequence, shot)
|
||||
|
||||
def get_assets(self, project=None):
|
||||
project = self.get_project(project)
|
||||
assets = gazu.asset.all_assets_for_project(project)
|
||||
entity_types = self.get_asset_types(project)
|
||||
entity_types_ids = {e['id']: e['name'] for e in entity_types}
|
||||
@@ -55,14 +184,54 @@ class Kitsu(Tracker):
|
||||
|
||||
return assets
|
||||
|
||||
def get_shots_metadata(self, project):
|
||||
metadatas = []
|
||||
def get_last_comment(self, task):
|
||||
task = self.get_id(task)
|
||||
return gazu.task.get_last_comment_for_task(task)
|
||||
|
||||
for metadata in gazu.project.all_metadata_descriptors(project):
|
||||
if metadata['entity_type'] == 'Shot' and metadata['name']:
|
||||
metadatas.append(metadata)
|
||||
def get_task(self, task=None, entity=None):
|
||||
entity = self.get_id(entity)
|
||||
|
||||
return metadatas
|
||||
task_type = self.get_task_type(task)
|
||||
|
||||
print('task_type', task_type)
|
||||
print('task_type', task_type)
|
||||
|
||||
task = gazu.task.get_task_by_name(entity, task_type)
|
||||
#task = gazu.task.get_task(task['id'])
|
||||
|
||||
task['last_comment'] = self.get_last_comment(task)
|
||||
|
||||
return task
|
||||
|
||||
def new_comment(self, task, status=None, comment='', preview=None, set_main_preview=False):
|
||||
#task = self.get_task(task)
|
||||
|
||||
#print('Add Comment', status)
|
||||
if status is None:
|
||||
#print(task)
|
||||
status = {'id' : task['task_status_id']}
|
||||
else:
|
||||
status = self.get_task_status(status)
|
||||
|
||||
|
||||
|
||||
comment = gazu.task.add_comment(
|
||||
task=task,
|
||||
task_status=status,
|
||||
comment=comment )
|
||||
|
||||
if preview:
|
||||
logging.info(f'Adding Preview to Kitsu {preview}')
|
||||
preview = self.add_preview(
|
||||
task=task,
|
||||
comment=comment,
|
||||
preview=str(preview) )
|
||||
|
||||
if set_main_preview:
|
||||
gazu.task.set_main_preview(preview)
|
||||
|
||||
|
||||
return comment
|
||||
|
||||
def download_preview(self, preview_id, filepath):
|
||||
if isinstance(filepath, str):
|
||||
@@ -74,100 +243,43 @@ class Kitsu(Tracker):
|
||||
filepath.parent.mkdir(parents=True, exist_ok=True)
|
||||
gazu.files.download_preview_file_thumbnail(preview_id, filepath.as_posix())
|
||||
|
||||
def connect(self, url=None, login=None, password=None):
|
||||
'''Connect to kitsu api using provided url, login and password'''
|
||||
def new_sequence(self, sequence, episode=None, project=None):
|
||||
project = self.get_project(project)
|
||||
|
||||
urllib3.disable_warnings()
|
||||
params = dict(name=sequence, project=project)
|
||||
episode = self.get_episode(episode)
|
||||
if episode:
|
||||
params['episode'] = episode
|
||||
|
||||
if not self.url:
|
||||
print(f'Kitsu Url: {self.url} is empty')
|
||||
return
|
||||
return gazu.shot.new_sequence(**params)
|
||||
|
||||
url = self.url
|
||||
if not url.endswith('/api'):
|
||||
url += '/api'
|
||||
def new_shot(self, shot, sequence, nb_frames=None, frame_in=None,
|
||||
frame_out=None, description='', custom_data=None, project=None):
|
||||
|
||||
print(f'Info: Setting Host for kitsu {url}')
|
||||
gazu.client.set_host(url)
|
||||
project = self.get_project(project)
|
||||
sequence = self.get_sequence(sequence)
|
||||
|
||||
if not gazu.client.host_is_up():
|
||||
print('Error: Kitsu Host is down')
|
||||
custom_data = custom_data or {}
|
||||
|
||||
try:
|
||||
print(f'Info: Log in to kitsu as {self.login}')
|
||||
res = gazu.log_in(self.login, self.password)
|
||||
print(f'Info: Sucessfully login to Kitsu as {res["user"]["full_name"]}')
|
||||
return res['user']
|
||||
except Exception as e:
|
||||
print(f'Error: {traceback.format_exc()}')
|
||||
if frame_in is not None:
|
||||
custom_data["frame_in"] = frame_in
|
||||
if frame_out is not None:
|
||||
custom_data["frame_out"] = frame_out
|
||||
|
||||
def get_asset_path(self, name, catalog, directory=None):
|
||||
directory = directory or self.source_directory
|
||||
return Path(directory, self.get_asset_relative_path(name, catalog))
|
||||
params = dict(name=shot, data=custom_data,
|
||||
sequence_id=self.get_id(sequence), description=description)
|
||||
|
||||
def get_asset_info(self, data, asset_path):
|
||||
modified = time.time_ns()
|
||||
catalog = data['entity_type_name'].title()
|
||||
asset_path = self.prop_rel_path(asset_path, 'source_directory')
|
||||
if nb_frames is not None:
|
||||
params["nb_frames"] = nb_frames
|
||||
|
||||
asset_info = dict(
|
||||
filepath=asset_path,
|
||||
modified=modified,
|
||||
library_id=self.library.id,
|
||||
assets=[dict(
|
||||
catalog=catalog,
|
||||
metadata=data.get('data', {}),
|
||||
description=data['description'],
|
||||
tags=[],
|
||||
type=self.data_type,
|
||||
name=data['name'])
|
||||
]
|
||||
)
|
||||
|
||||
return asset_info
|
||||
shot = self.get_shot(shot=shot, sequence=sequence)
|
||||
if shot:
|
||||
return shot
|
||||
else:
|
||||
path = f"data/projects/{self.get_id(project)}/shots"
|
||||
return gazu.client.post(path, params)
|
||||
|
||||
def fetch(self):
|
||||
"""Gather in a list all assets found in the folder"""
|
||||
print(f'Fetch Assets for {self.library.name}')
|
||||
|
||||
self.connect()
|
||||
|
||||
template_file = Template(self.template_file)
|
||||
template_name = Template(self.template_name)
|
||||
|
||||
project = gazu.client.fetch_first('projects', {'name': self.project_name})
|
||||
entity_types = gazu.client.fetch_all('entity-types')
|
||||
entity_types_ids = {e['id']: e['name'] for e in entity_types}
|
||||
|
||||
cache = self.read_cache()
|
||||
|
||||
for asset_data in gazu.asset.all_assets_for_project(project):
|
||||
asset_data['entity_type_name'] = entity_types_ids[asset_data.pop('entity_type_id')]
|
||||
asset_name = asset_data['name']
|
||||
|
||||
asset_field_data = dict(asset_name=asset_name, type=asset_data['entity_type_name'], source_directory=self.source_directory)
|
||||
|
||||
try:
|
||||
asset_field_data.update(template_name.parse(asset_name))
|
||||
except Exception:
|
||||
print(f'Warning: Could not parse {asset_name} with template {template_name}')
|
||||
|
||||
asset_path = template_file.find(asset_field_data)
|
||||
if not asset_path:
|
||||
print(f'Warning: Could not find file for {template_file.format(asset_field_data)}')
|
||||
continue
|
||||
|
||||
|
||||
asset_path = self.prop_rel_path(asset_path, 'source_directory')
|
||||
asset_cache_data = dict(
|
||||
catalog=asset_data['entity_type_name'].title(),
|
||||
metadata=asset_data.get('data', {}),
|
||||
description=asset_data['description'],
|
||||
tags=[],
|
||||
type=self.data_type,
|
||||
name=asset_data['name']
|
||||
)
|
||||
|
||||
cache.add_asset_cache(asset_cache_data, filepath=asset_path)
|
||||
|
||||
return cache
|
||||
def draw_prefs(self, layout):
|
||||
layout.prop(self, 'url', text='Url')
|
||||
layout.prop(self, 'login', text='Login')
|
||||
layout.prop(self, 'password', text='Password')
|
||||
@@ -1,4 +1,9 @@
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import PointerProperty, StringProperty
|
||||
from vse_toolbox.file_utils import norm_str
|
||||
|
||||
|
||||
class Tracker(PropertyGroup):
|
||||
pass
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user