File size: 6,557 Bytes
a1da63c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
import glob
import os
from copy import copy
from typing import List, Optional

from facefusion.choices import job_statuses
from facefusion.date_helper import get_current_date_time
from facefusion.filesystem import create_directory, is_directory, is_file, move_file, remove_directory, remove_file
from facefusion.jobs.job_helper import get_step_output_path
from facefusion.json import read_json, write_json
from facefusion.temp_helper import create_base_directory
from facefusion.typing import Args, Job, JobSet, JobStatus, JobStep, JobStepStatus

JOBS_PATH : Optional[str] = None


def init_jobs(jobs_path : str) -> bool:
	global JOBS_PATH

	JOBS_PATH = jobs_path
	job_status_paths = [ os.path.join(JOBS_PATH, job_status) for job_status in job_statuses ]

	create_base_directory()
	for job_status_path in job_status_paths:
		create_directory(job_status_path)
	return all(is_directory(status_path) for status_path in job_status_paths)


def clear_jobs(jobs_path : str) -> bool:
	return remove_directory(jobs_path)


def create_job(job_id : str) -> bool:
	job : Job =\
	{
		'version': '1',
		'date_created': get_current_date_time().isoformat(),
		'date_updated': None,
		'steps': []
	}

	return create_job_file(job_id, job)


def submit_job(job_id : str) -> bool:
	drafted_job_ids = find_job_ids('drafted')
	steps = get_steps(job_id)

	if job_id in drafted_job_ids and steps:
		return set_steps_status(job_id, 'queued') and move_job_file(job_id, 'queued')
	return False


def submit_jobs() -> bool:
	drafted_job_ids = find_job_ids('drafted')

	if drafted_job_ids:
		for job_id in drafted_job_ids:
			if not submit_job(job_id):
				return False
		return True
	return False


def delete_job(job_id : str) -> bool:
	return delete_job_file(job_id)


def delete_jobs() -> bool:
	job_ids = find_job_ids('drafted') + find_job_ids('queued') + find_job_ids('failed') + find_job_ids('completed')

	if job_ids:
		for job_id in job_ids:
			if not delete_job(job_id):
				return False
		return True
	return False


def find_jobs(job_status : JobStatus) -> JobSet:
	job_ids = find_job_ids(job_status)
	jobs : JobSet = {}

	for job_id in job_ids:
		jobs[job_id] = read_job_file(job_id)
	return jobs


def find_job_ids(job_status : JobStatus) -> List[str]:
	job_pattern = os.path.join(JOBS_PATH, job_status, '*.json')
	job_files = glob.glob(job_pattern)
	job_files.sort(key = os.path.getmtime)
	job_ids = []

	for job_file in job_files:
		job_id, _ = os.path.splitext(os.path.basename(job_file))
		job_ids.append(job_id)
	return job_ids


def validate_job(job_id : str) -> bool:
	job = read_job_file(job_id)
	return bool(job and 'version' in job and 'date_created' in job and 'date_updated' in job and 'steps' in job)


def has_step(job_id : str, step_index : int) -> bool:
	step_total = count_step_total(job_id)
	return step_index in range(step_total)


def add_step(job_id : str, step_args : Args) -> bool:
	job = read_job_file(job_id)

	if job:
		job.get('steps').append(
		{
			'args': step_args,
			'status': 'drafted'
		})
		return update_job_file(job_id, job)
	return False


def remix_step(job_id : str, step_index : int, step_args : Args) -> bool:
	steps = get_steps(job_id)
	step_args = copy(step_args)

	if step_index and step_index < 0:
		step_index = count_step_total(job_id) - 1

	if has_step(job_id, step_index):
		output_path = steps[step_index].get('args').get('output_path')
		step_args['target_path'] = get_step_output_path(job_id, step_index, output_path)
		return add_step(job_id, step_args)
	return False


def insert_step(job_id : str, step_index : int, step_args : Args) -> bool:
	job = read_job_file(job_id)
	step_args = copy(step_args)

	if step_index and step_index < 0:
		step_index = count_step_total(job_id) - 1

	if job and has_step(job_id, step_index):
		job.get('steps').insert(step_index,
		{
			'args': step_args,
			'status': 'drafted'
		})
		return update_job_file(job_id, job)
	return False


def remove_step(job_id : str, step_index : int) -> bool:
	job = read_job_file(job_id)

	if step_index and step_index < 0:
		step_index = count_step_total(job_id) - 1

	if job and has_step(job_id, step_index):
		job.get('steps').pop(step_index)
		return update_job_file(job_id, job)
	return False


def get_steps(job_id : str) -> List[JobStep]:
	job = read_job_file(job_id)

	if job:
		return job.get('steps')
	return []


def count_step_total(job_id : str) -> int:
	steps = get_steps(job_id)

	if steps:
		return len(steps)
	return 0


def set_step_status(job_id : str, step_index : int, step_status : JobStepStatus) -> bool:
	job = read_job_file(job_id)

	if job:
		steps = job.get('steps')

		if has_step(job_id, step_index):
			steps[step_index]['status'] = step_status
			return update_job_file(job_id, job)
	return False


def set_steps_status(job_id : str, step_status : JobStepStatus) -> bool:
	job = read_job_file(job_id)

	if job:
		for step in job.get('steps'):
			step['status'] = step_status
		return update_job_file(job_id, job)
	return False


def read_job_file(job_id : str) -> Optional[Job]:
	job_path = find_job_path(job_id)
	return read_json(job_path) #type:ignore[return-value]


def create_job_file(job_id : str, job : Job) -> bool:
	job_path = find_job_path(job_id)

	if not is_file(job_path):
		job_create_path = suggest_job_path(job_id, 'drafted')
		return write_json(job_create_path, job) #type:ignore[arg-type]
	return False


def update_job_file(job_id : str, job : Job) -> bool:
	job_path = find_job_path(job_id)

	if is_file(job_path):
		job['date_updated'] = get_current_date_time().isoformat()
		return write_json(job_path, job) #type:ignore[arg-type]
	return False


def move_job_file(job_id : str, job_status : JobStatus) -> bool:
	job_path = find_job_path(job_id)
	job_move_path = suggest_job_path(job_id, job_status)
	return move_file(job_path, job_move_path)


def delete_job_file(job_id : str) -> bool:
	job_path = find_job_path(job_id)
	return remove_file(job_path)


def suggest_job_path(job_id : str, job_status : JobStatus) -> Optional[str]:
	job_file_name = get_job_file_name(job_id)

	if job_file_name:
		return os.path.join(JOBS_PATH, job_status, job_file_name)
	return None


def find_job_path(job_id : str) -> Optional[str]:
	job_file_name = get_job_file_name(job_id)

	if job_file_name:
		for job_status in job_statuses:
			job_pattern = os.path.join(JOBS_PATH, job_status, job_file_name)
			job_paths = glob.glob(job_pattern)

			for job_path in job_paths:
				return job_path
	return None


def get_job_file_name(job_id : str) -> Optional[str]:
	if job_id:
		return job_id + '.json'
	return None