Sada8888 commited on
Commit
009d37a
·
verified ·
1 Parent(s): f7fd736

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -737
app.py CHANGED
@@ -16,9 +16,7 @@ app = Flask(__name__)
16
  # در این بخش می‌توانید هر تعداد حساب و ریپازیتوری که دارید را به همراه نام توکن تعریف کنید.
17
  GITHUB_ACCOUNTS_CONFIG = [
18
  {"repo": "hajiliker6-source/Action", "token_env": "GITHUB_TOKEN1"},
19
- {"repo": "hajiliker840/a", "token_env": "GITHUB_TOKEN2"},
20
- # در صورت نیاز حساب‌های بعدی را نیز به همین شکل اضافه کنید
21
- {"repo": "hajiliker4-cpu/a", "token_env": "GITHUB_TOKEN3"},
22
  ]
23
 
24
  GITHUB_ACCOUNTS = []
@@ -97,735 +95,6 @@ def create_error_image(run_id, message):
97
  except Exception:
98
  pass
99
 
100
- # --- ایجاد خودکار اسکریپت‌های مورد نیاز درون پوشه yml در بدو استارت آپ ---
101
- def write_default_scripts():
102
- scripts = {
103
- "generate-flux.py": """
104
- import os, sys, random, requests
105
- from gradio_client import Client
106
-
107
- def get_env_int(name, default=0):
108
- val = os.environ.get(name, '')
109
- try:
110
- return int(val) if val.strip() else default
111
- except ValueError:
112
- return default
113
-
114
- prompt = os.environ.get('PROMPT', '')
115
- width = get_env_int('WIDTH', 1024)
116
- height = get_env_int('HEIGHT', 1024)
117
- run_id = os.environ.get('RUN_ID')
118
- space_url = os.environ.get('SPACE_URL')
119
- github_run_id = os.environ.get('GITHUB_RUN_ID')
120
-
121
- def report_failure(error_msg):
122
- try:
123
- requests.post(
124
- f"{space_url}/api/webhook/fail",
125
- json={
126
- "run_id": run_id,
127
- "error": error_msg,
128
- "event_type": "generate-flux",
129
- "client_payload": {
130
- "prompt": prompt,
131
- "width": width,
132
- "height": height,
133
- "run_id": run_id,
134
- "space_url": space_url
135
- },
136
- "github_run_id": github_run_id
137
- },
138
- timeout=15
139
- )
140
- except Exception as e:
141
- print(f"Failed to report failure: {e}")
142
-
143
- print('1. Connecting to Flux...')
144
- try:
145
- client = Client('black-forest-labs/FLUX.1-dev')
146
- seed = random.randint(1, 2147483647)
147
-
148
- result = client.predict(prompt, seed, True, width, height, 3.5, 28, api_name='/infer')
149
- image_path = result[0] if isinstance(result, (tuple, list)) else result
150
-
151
- print(f'2. Uploading back to Docker Space...')
152
- with open(image_path, 'rb') as f:
153
- res = requests.post(f'{space_url}/api/webhook/upload', data={'run_id': run_id, 'github_run_id': github_run_id}, files={'file': f})
154
-
155
- if res.status_code == 200:
156
- print('3. SUCCESS!')
157
- else:
158
- sys.exit(1)
159
-
160
- except Exception as e:
161
- err_str = str(e)
162
- print(f'ERROR: {err_str}')
163
- report_failure(err_str)
164
- sys.exit(1)
165
- """,
166
- "generate-flux2.py": """
167
- import os, sys, random, requests, json
168
- from gradio_client import Client, handle_file
169
-
170
- def get_env_int(name, default=0):
171
- val = os.environ.get(name, '')
172
- try:
173
- return int(val) if val.strip() else default
174
- except ValueError:
175
- return default
176
-
177
- def get_env_float(name, default=0.0):
178
- val = os.environ.get(name, '')
179
- try:
180
- return float(val) if val.strip() else default
181
- except ValueError:
182
- return default
183
-
184
- prompt = os.environ.get('PROMPT', '')
185
- image_urls_raw = os.environ.get('IMAGE_URLS', '[]')
186
- width = get_env_int('WIDTH', 1024)
187
- height = get_env_int('HEIGHT', 1024)
188
- steps = get_env_int('STEPS', 30)
189
- guidance = get_env_float('GUIDANCE', 4.0)
190
- seed = get_env_int('SEED', 0)
191
- randomize_seed = os.environ.get('RANDOMIZE_SEED', 'true').lower() == 'true'
192
- prompt_upsampling = os.environ.get('PROMPT_UPSAMPLING', 'true').lower() == 'true'
193
- run_id = os.environ.get('RUN_ID')
194
- space_url = os.environ.get('SPACE_URL')
195
- github_run_id = os.environ.get('GITHUB_RUN_ID')
196
- hf_token = os.environ.get('HF_TOKEN', '')
197
-
198
- print(f'Starting direct Flux 2 generation for run_id: {run_id}')
199
-
200
- print('1. Parsing and downloading images...')
201
- image_urls = []
202
- if image_urls_raw:
203
- try:
204
- cleaned_json = image_urls_raw.replace('null', '').strip()
205
- if cleaned_json and cleaned_json != '[]':
206
- image_urls = json.loads(cleaned_json)
207
- except Exception as e:
208
- print(f'JSON parsing error: {e}')
209
-
210
- def report_failure(error_msg):
211
- try:
212
- requests.post(
213
- f"{space_url}/api/webhook/fail",
214
- json={
215
- "run_id": run_id,
216
- "error": error_msg,
217
- "event_type": "generate-flux2",
218
- "client_payload": {
219
- "data": {
220
- "prompt": prompt,
221
- "image_urls": image_urls,
222
- "width": width,
223
- "height": height,
224
- "steps": steps,
225
- "guidance": guidance,
226
- "seed": seed,
227
- "randomize_seed": randomize_seed,
228
- "prompt_upsampling": prompt_upsampling,
229
- "run_id": run_id,
230
- "space_url": space_url,
231
- "hf_token": hf_token
232
- }
233
- },
234
- "github_run_id": github_run_id
235
- },
236
- timeout=15
237
- )
238
- except Exception as e:
239
- print(f"Failed to report failure: {e}")
240
-
241
- files_to_send = []
242
- for idx, url in enumerate(image_urls):
243
- if url:
244
- print(f'Downloading input image {idx}: {url}')
245
- ext = url.split('.')[-1] if '.' in url else 'png'
246
- local_filename = f'input_{idx}.{ext}'
247
- try:
248
- req = requests.get(url, timeout=30)
249
- with open(local_filename, 'wb') as f:
250
- f.write(req.content)
251
- files_to_send.append({'image': handle_file(local_filename), 'caption': None})
252
- except Exception as e:
253
- print(f'Failed to download {url}: {e}')
254
-
255
- print('2. Connecting to FLUX.2-dev Space...')
256
- try:
257
- if hf_token:
258
- client = Client('black-forest-labs/FLUX.2-dev', token=hf_token)
259
- else:
260
- client = Client('black-forest-labs/FLUX.2-dev')
261
-
262
- if randomize_seed:
263
- seed = random.randint(1, 2147483647)
264
-
265
- print(f'Predicting with seed={seed}, width={width}, height={height}, steps={steps}, guidance={guidance}, upsampling={prompt_upsampling}...')
266
- result = client.predict(
267
- prompt,
268
- files_to_send,
269
- seed,
270
- randomize_seed,
271
- width,
272
- height,
273
- steps,
274
- guidance,
275
- prompt_upsampling,
276
- api_name='/infer'
277
- )
278
-
279
- image_path = result[0] if isinstance(result, (tuple, list)) else result
280
- seed_used = result[1] if (isinstance(result, (tuple, list)) and len(result) > 1) else seed
281
-
282
- print('3. Uploading metadata seed back...')
283
- with open('seed.txt', 'w') as sf:
284
- sf.write(str(seed_used))
285
- requests.post(
286
- f'{space_url}/api/webhook/upload',
287
- data={'run_id': f'{run_id}_seed', 'github_run_id': github_run_id, 'ext': 'txt'},
288
- files={'file': open('seed.txt', 'rb')}
289
- )
290
-
291
- print('4. Uploading generated image back...')
292
- with open(image_path, 'rb') as f:
293
- upload_res = requests.post(
294
- f'{space_url}/api/webhook/upload',
295
- data={'run_id': run_id, 'github_run_id': github_run_id},
296
- files={'file': f}
297
- )
298
-
299
- if upload_res.status_code == 200:
300
- print('SUCCESS!')
301
- else:
302
- print(f'Upload failed with status {upload_res.status_code}: {upload_res.text}')
303
- sys.exit(1)
304
-
305
- except Exception as e:
306
- err_str = str(e)
307
- print(f'Generation error: {err_str}')
308
- report_failure(err_str)
309
- sys.exit(1)
310
- """,
311
- "generate-cartoon.py": """
312
- import os, sys, random, requests
313
- from gradio_client import Client
314
-
315
- def get_env_int(name, default=0):
316
- val = os.environ.get(name, '')
317
- try:
318
- return int(val) if val.strip() else default
319
- except ValueError:
320
- return default
321
-
322
- prompt = os.environ.get('PROMPT', '')
323
- width = get_env_int('WIDTH', 1024)
324
- height = get_env_int('HEIGHT', 1024)
325
- run_id = os.environ.get('RUN_ID')
326
- space_url = os.environ.get('SPACE_URL')
327
- github_run_id = os.environ.get('GITHUB_RUN_ID')
328
-
329
- def report_failure(error_msg):
330
- try:
331
- requests.post(
332
- f"{space_url}/api/webhook/fail",
333
- json={
334
- "run_id": run_id,
335
- "error": error_msg,
336
- "event_type": "generate-cartoon",
337
- "client_payload": {
338
- "prompt": prompt,
339
- "width": width,
340
- "height": height,
341
- "run_id": run_id,
342
- "space_url": space_url
343
- },
344
- "github_run_id": github_run_id
345
- },
346
- timeout=15
347
- )
348
- except Exception as e:
349
- print(f"Failed to report failure: {e}")
350
-
351
- print('1. Connecting to LoRA DLC Space...')
352
- try:
353
- client = Client('prithivMLmods/FLUX-LoRA-DLC')
354
- print('2. Loading Cartoon Model (Long Toons)...')
355
- client.predict('prithivMLmods/Flux-Long-Toon-LoRA', api_name='/add_custom_lora')
356
-
357
- print('3. Generating Cartoon Image...')
358
- result = client.predict(
359
- prompt=f'Long toons {prompt}',
360
- image_input=None,
361
- cfg_scale=3.5,
362
- steps=28,
363
- randomize_seed=True,
364
- seed=random.randint(1, 2147483647),
365
- width=width,
366
- height=height,
367
- lora_scale=0.8,
368
- api_name='/run_lora'
369
- )
370
- image_path = result[0] if isinstance(result, (tuple, list)) else result
371
-
372
- print('4. Uploading back to Docker Space...')
373
- with open(image_path, 'rb') as f:
374
- res = requests.post(f'{space_url}/api/webhook/upload',
375
- data={'run_id': run_id, 'github_run_id': github_run_id},
376
- files={'file': f})
377
- if res.status_code == 200:
378
- print('5. SUCCESS!')
379
- else:
380
- sys.exit(1)
381
- except Exception as e:
382
- err_str = str(e)
383
- print(f'CRITICAL ERROR: {err_str}')
384
- report_failure(err_str)
385
- sys.exit(1)
386
- """,
387
- "generate-midjourney.py": """
388
- import os, sys, random, requests
389
- from gradio_client import Client
390
-
391
- def get_env_int(name, default=0):
392
- val = os.environ.get(name, '')
393
- try:
394
- return int(val) if val.strip() else default
395
- except ValueError:
396
- return default
397
-
398
- raw_prompt = os.environ.get('PROMPT', '')
399
- final_prompt = f'MJ v6 {raw_prompt}'
400
- width = get_env_int('WIDTH', 1024)
401
- height = get_env_int('HEIGHT', 1024)
402
- run_id = os.environ.get('RUN_ID')
403
- space_url = os.environ.get('SPACE_URL')
404
- github_run_id = os.environ.get('GITHUB_RUN_ID')
405
-
406
- def report_failure(error_msg):
407
- try:
408
- requests.post(
409
- f"{space_url}/api/webhook/fail",
410
- json={
411
- "run_id": run_id,
412
- "error": error_msg,
413
- "event_type": "generate-midjourney",
414
- "client_payload": {
415
- "prompt": raw_prompt,
416
- "width": width,
417
- "height": height,
418
- "run_id": run_id,
419
- "space_url": space_url
420
- },
421
- "github_run_id": github_run_id
422
- },
423
- timeout=15
424
- )
425
- except Exception as e:
426
- print(f"Failed to report failure: {e}")
427
-
428
- print('1. Connecting to LoRA DLC Space...')
429
- try:
430
- client = Client('prithivMLmods/FLUX-LoRA-DLC')
431
- print('2. Loading Midjourney Model...')
432
- client.predict('strangerzonehf/Flux-Midjourney-Mix2-LoRA', api_name='/add_custom_lora')
433
-
434
- print(f'3. Generating Image... Prompt: {final_prompt[:50]}...')
435
- result = client.predict(
436
- prompt=final_prompt,
437
- image_input=None,
438
- cfg_scale=3.5,
439
- steps=28,
440
- randomize_seed=True,
441
- seed=random.randint(1, 2147483647),
442
- width=width,
443
- height=height,
444
- lora_scale=0.8,
445
- api_name='/run_lora'
446
- )
447
- image_path = result[0] if isinstance(result, (tuple, list)) else result
448
-
449
- print('4. Uploading back to Docker Space...')
450
- with open(image_path, 'rb') as f:
451
- res = requests.post(f'{space_url}/api/webhook/upload',
452
- data={'run_id': run_id, 'github_run_id': github_run_id},
453
- files={'file': f})
454
- if res.status_code == 200:
455
- print('5. SUCCESS!')
456
- else:
457
- sys.exit(1)
458
- except Exception as e:
459
- err_str = str(e)
460
- print(f'CRITICAL ERROR: {err_str}')
461
- report_failure(err_str)
462
- sys.exit(1)
463
- """,
464
- "chat-gemma.py": """
465
- import os, sys, requests
466
- from gradio_client import Client, handle_file
467
-
468
- prompt = os.environ.get('PROMPT', '')
469
- file_url = os.environ.get('FILE_URL', '')
470
- run_id = os.environ.get('RUN_ID')
471
- space_url = os.environ.get('SPACE_URL')
472
- gh_run_id = os.environ.get('GITHUB_RUN_ID')
473
-
474
- files_to_send = []
475
- if file_url:
476
- print(f'Downloading attachment: {file_url}')
477
- ext = file_url.split('.')[-1] if '.' in file_url else 'bin'
478
- local_filename = f'attachment.{ext}'
479
- try:
480
- req = requests.get(file_url, timeout=30)
481
- with open(local_filename, 'wb') as f:
482
- f.write(req.content)
483
- files_to_send.append(handle_file(local_filename))
484
- except Exception as e:
485
- print(f'Failed to download file: {e}')
486
-
487
- print('Connecting to Gemma-4 Space...')
488
- bot_reply = ''
489
- try:
490
- client = Client('huggingface-projects/gemma-4-e4b-it')
491
- message_payload = {'text': prompt, 'files': files_to_send}
492
- result = client.predict(
493
- message=message_payload,
494
- thinking=False,
495
- max_new_tokens=4000,
496
- max_soft_tokens=1120,
497
- system_prompt='شما یک دستیار هوش مصنوعی بسیار باهوش، مفید و مودب به زبان فارسی هستید.',
498
- api_name='/generate'
499
- )
500
- bot_reply = result[0] if isinstance(result, (list, tuple)) else result
501
- if isinstance(bot_reply, dict):
502
- bot_reply = bot_reply.get('text', str(bot_reply))
503
- except Exception as e:
504
- err_str = str(e)
505
- print(f'Generation Error: {err_str}')
506
- if 'ZeroGPU quota' in err_str or 'quota' in err_str.lower():
507
- bot_reply = '⚠️ **پردازش متوقف شد:**\\nدرخواست شما طولانی و پرحجم است (پردازش فایل‌های صوتی یا حجیم نیازمند منابع بالایی است و سهمیه سرور موقتاً پر شده است).\\n\\nلطفاً چند ساعت دیگر امتحان کنید یا درخواست و فایل سبک‌تری ارسال نمایید.'
508
- else:
509
- bot_reply = f'⚠️ خطای سرور پردازش: {err_str}'
510
-
511
- print('Uploading response back to Docker Space...')
512
- try:
513
- with open('response.txt', 'w', encoding='utf-8') as f:
514
- f.write(bot_reply)
515
- with open('response.txt', 'rb') as f:
516
- res = requests.post(f'{space_url}/api/webhook/upload',
517
- data={'run_id': run_id, 'github_run_id': gh_run_id, 'ext': 'txt'},
518
- files={'file': f})
519
- if res.status_code == 200:
520
- print('SUCCESS!')
521
- else:
522
- sys.exit(1)
523
- except Exception as e:
524
- sys.exit(1)
525
- """,
526
- "generate-editor.py": """
527
- import os, sys, requests, re, time
528
-
529
- # =========================================================
530
- # رفع قطعی مشکل The read operation timed out
531
- # تنظیم دستی زمان انتظار به 5 دقیقه (300 ثانیه) مانند مرورگر
532
- import httpx
533
- original_client_init = httpx.Client.__init__
534
- def patched_client_init(self, *args, **kwargs):
535
- kwargs['timeout'] = httpx.Timeout(300.0)
536
- original_client_init(self, *args, **kwargs)
537
- httpx.Client.__init__ = patched_client_init
538
-
539
- original_async_init = httpx.AsyncClient.__init__
540
- def patched_async_init(self, *args, **kwargs):
541
- kwargs['timeout'] = httpx.Timeout(300.0)
542
- original_async_init(self, *args, **kwargs)
543
- httpx.AsyncClient.__init__ = patched_async_init
544
- # =========================================================
545
-
546
- from gradio_client import Client, handle_file
547
-
548
- prompt = os.environ.get('PROMPT', '')
549
- image_url = os.environ.get('IMAGE_URL', '')
550
- run_id = os.environ.get('RUN_ID')
551
- space_url = os.environ.get('SPACE_URL')
552
- github_run_id = os.environ.get('GITHUB_RUN_ID')
553
-
554
- def report_failure(error_msg):
555
- try:
556
- requests.post(
557
- f"{space_url}/api/webhook/fail",
558
- json={
559
- "run_id": run_id,
560
- "error": error_msg,
561
- "event_type": "generate-editor",
562
- "client_payload": {
563
- "prompt": prompt,
564
- "image_url": image_url,
565
- "run_id": run_id,
566
- "space_url": space_url
567
- },
568
- "github_run_id": github_run_id
569
- },
570
- timeout=15
571
- )
572
- except Exception as e:
573
- print(f"Failed to report failure: {e}")
574
-
575
- print('1. Downloading input image from Docker Space...')
576
- try:
577
- req = requests.get(image_url, timeout=30)
578
- with open('input.png', 'wb') as f:
579
- f.write(req.content)
580
- print(' -> Input image ready.')
581
- except Exception as e:
582
- print(f'Download failed: {e}')
583
- sys.exit(1)
584
-
585
- print('2. Connecting to Omni Editor and Processing (Timeout extended to 300s)...')
586
- result_str = ''
587
- success = False
588
-
589
- for attempt in range(3):
590
- try:
591
- print(f' -> Attempt {attempt + 1} of 3...')
592
- client = Client('selfit-camera/omni-image-editor')
593
- result = client.predict(
594
- handle_file('input.png'),
595
- prompt,
596
- api_name='/edit_image_interface'
597
- )
598
- result_str = str(result)
599
- if 'src=' in result_str or 'http' in result_str:
600
- success = True
601
- break
602
- else:
603
- print(f' -> Missing valid response format: {result_str[:100]}...')
604
- except Exception as client_err:
605
- print(f' -> Attempt {attempt + 1} failed: {client_err}')
606
- time.sleep(5)
607
-
608
- if not success:
609
- print(f'CRITICAL ERROR: All attempts failed. Raw result: {result_str}')
610
- sys.exit(1)
611
-
612
- print('3. Parsing result string...')
613
- urls = re.findall(r'src=[\'\"]([^\'\"]+)[\'\"]', result_str)
614
- final_remote_url = None
615
- for url in urls:
616
- if url.startswith('http'):
617
- final_remote_url = url
618
- break
619
-
620
- if not final_remote_url:
621
- direct_urls = re.findall(r'(https?://[^\s\'\"]+\.(?:png|jpg|jpeg|webp|gif))', result_str)
622
- if direct_urls:
623
- final_remote_url = direct_urls[0]
624
-
625
- if not final_remote_url:
626
- print(f'ERROR: Could not find valid URL. Raw result: {result_str}')
627
- sys.exit(1)
628
-
629
- print(f' -> Found Final Image URL: {final_remote_url}')
630
-
631
- print('4. Downloading final image from remote host...')
632
- try:
633
- img_req = requests.get(final_remote_url, timeout=60)
634
- content_type = img_req.headers.get('Content-Type', '')
635
- ext = 'png'
636
- if 'image/webp' in content_type:
637
- ext = 'webp'
638
- elif 'image/jpeg' in content_type or 'image/jpg' in content_type:
639
- ext = 'jpg'
640
-
641
- filename = f'output.{ext}'
642
- with open(filename, 'wb') as f:
643
- f.write(img_req.content)
644
- print(f' -> Saved locally as {filename}')
645
- except Exception as dl_err:
646
- print(f'Failed to download processed image: {dl_err}')
647
- sys.exit(1)
648
-
649
- print(f'5. Uploading back to Docker Space: {space_url}')
650
- try:
651
- with open(filename, 'rb') as f:
652
- res = requests.post(
653
- f'{space_url}/api/webhook/upload',
654
- data={'run_id': run_id, 'github_run_id': github_run_id, 'ext': ext},
655
- files={'file': f},
656
- timeout=60
657
- )
658
- if res.status_code == 200:
659
- print('6. SUCCESS!')
660
- else:
661
- sys.exit(1)
662
- except Exception as e:
663
- err_str = str(e)
664
- report_failure(err_str)
665
- sys.exit(1)
666
- """,
667
- "generate-video.py": """
668
- import os, sys, random, requests, time
669
- from gradio_client import Client, handle_file
670
- from PIL import Image, ImageOps
671
-
672
- prompt = os.environ.get('PROMPT', '').strip()
673
- if not prompt:
674
- prompt = 'make this image come alive, cinematic motion, smooth animation'
675
- else:
676
- prompt = f'{prompt}, cinematic motion, smooth animation, high quality'
677
-
678
- negative_prompt = '色调艳丽, 过曝, 静态, 细节模糊不清, 字幕, 风格, 作品, 画作, 画面, 静止, 整体发灰, 最差质量, 低质量, JPEG压缩残留, 丑陋의, 残缺의, 多余的手指, 画得不好的手部, 画得不好的脸部, 畸形の, 毁容의, 形态畸形的肢体, 手指融合, 静止不动的画面, 杂乱의 背景, 三条腿, 背景人很多, 倒着走'
679
-
680
- image_url = os.environ.get('IMAGE_URL', '')
681
- run_id = os.environ.get('RUN_ID')
682
- space_url = os.environ.get('SPACE_URL')
683
- github_run_id = os.environ.get('GITHUB_RUN_ID')
684
-
685
- try:
686
- duration = float(os.environ.get('DURATION', 5.0))
687
- except Exception:
688
- duration = 5.0
689
-
690
- def report_failure(error_msg):
691
- try:
692
- requests.post(
693
- f"{space_url}/api/webhook/fail",
694
- json={
695
- "run_id": run_id,
696
- "error": error_msg,
697
- "event_type": "generate-video",
698
- "client_payload": {
699
- "prompt": prompt,
700
- "duration": duration,
701
- "image_url": image_url,
702
- "run_id": run_id,
703
- "space_url": space_url
704
- },
705
- "github_run_id": github_run_id
706
- },
707
- timeout=15
708
- )
709
- except Exception as e:
710
- print(f"Failed to report failure: {e}")
711
-
712
- print('1. Downloading input image from Docker Space...')
713
- try:
714
- req = requests.get(image_url, timeout=30)
715
- with open('input_raw.png', 'wb') as f:
716
- f.write(req.content)
717
- except Exception as e:
718
- print(f'Download failed: {e}')
719
- sys.exit(1)
720
-
721
- print('2. Analyzing image dimensions to prevent stretching...')
722
- img = Image.open('input_raw.png').convert('RGB')
723
- orig_w, orig_h = img.size
724
- ratio = orig_w / orig_h
725
-
726
- if ratio > 1.2:
727
- target_w, target_h = 832, 480
728
- print(' -> Format: Landscape (16:9)')
729
- elif ratio < 0.8:
730
- target_w, target_h = 480, 832
731
- print(' -> Format: Portrait (9:16)')
732
- else:
733
- target_w, target_h = 480, 480
734
- print(' -> Format: Square (1:1)')
735
-
736
- img_resized = ImageOps.fit(img, (target_w, target_h), Image.Resampling.LANCZOS)
737
- img_resized.save('input.png')
738
- print(f' -> Image perfectly resized to {target_w}x{target_h}')
739
-
740
- print('3. Connecting to AI Video Space...')
741
- video_path = None
742
-
743
- space_id = 'zerogpu-aoti/wan2-2-fp8da-aoti-faster'
744
- print(f' -> Loading Space: {space_id}')
745
- try:
746
- client = Client(space_id)
747
- except Exception as e:
748
- print(f'CRITICAL ERROR: Could not load space. {e}')
749
- sys.exit(1)
750
-
751
- max_attempts = 4
752
- for attempt in range(max_attempts):
753
- seed = random.randint(1, 2147483647)
754
- print(f' -> Attempt {attempt + 1} of {max_attempts} with seed {seed} and duration {duration}s...')
755
-
756
- try:
757
- result = client.predict(
758
- handle_file('input.png'), # [0] عکس ورودی
759
- prompt, # [1] پرامپت مثبت
760
- 6, # [2] مقدار ثابت
761
- negative_prompt, # [3] پرامپت منفی
762
- duration, # [4] زمان انتخابی کاربر
763
- 1, # [5] مقدار ثابت
764
- 1, # [6] مقدار ثابت
765
- seed, # [7] هسته پردازش
766
- True, # [8] رندوم کردن Seed
767
- fn_index=0
768
- )
769
-
770
- if isinstance(result, list) and len(result) > 0:
771
- video_path = result[0].get('video') or result[0].get('path') if isinstance(result[0], dict) else result[0]
772
- elif isinstance(result, tuple) and len(result) > 0:
773
- video_path = result[0]
774
- elif isinstance(result, dict):
775
- video_path = result.get('video') or result.get('path')
776
- else:
777
- video_path = result
778
-
779
- if video_path and os.path.exists(str(video_path)):
780
- print(' -> Success! Video generated.')
781
- break
782
-
783
- except Exception as e:
784
- err_msg = str(e)
785
- print(f' -> Failed on attempt {attempt + 1}: {err_msg}')
786
- time.sleep(5)
787
-
788
- if not video_path or not os.path.exists(str(video_path)):
789
- err_str = "Video generation failed on all attempts"
790
- report_failure(err_str)
791
- sys.exit(1)
792
-
793
- print('4. Uploading back to your Docker Space...')
794
- try:
795
- with open(video_path, 'rb') as f:
796
- res = requests.post(f'{space_url}/api/webhook/upload',
797
- data={'run_id': run_id, 'github_run_id': github_run_id, 'ext': 'mp4'},
798
- files={'file': f})
799
- if res.status_code == 200:
800
- print('5. SUCCESS!')
801
- else:
802
- sys.exit(1)
803
- except Exception as e:
804
- err_str = str(e)
805
- report_failure(err_str)
806
- sys.exit(1)
807
- """
808
- }
809
- for name, content in scripts.items():
810
- path = os.path.join("yml", name)
811
-
812
- # مانیتورینگ تگ شکست برای بازنویسی و اعمال ساختار پویا و دفاعی جدید روی تمام فایل‌های پایتون یمل
813
- if os.path.exists(path):
814
- try:
815
- with open(path, "r", encoding="utf-8") as f:
816
- old_data = f.read()
817
- if "report_failure" not in old_data:
818
- os.remove(path)
819
- except:
820
- pass
821
-
822
- if not os.path.exists(path):
823
- with open(path, "w", encoding="utf-8") as f:
824
- f.write(content.strip())
825
-
826
- # اجرای تابع برای نوشتن کدهای پایتون به محض بارگذاری برنامه
827
- write_default_scripts()
828
-
829
  def init_db():
830
  conn = sqlite3.connect(DB_PATH)
831
  c = conn.cursor()
@@ -933,7 +202,7 @@ def is_today(created_at_str):
933
  except Exception:
934
  return False
935
 
936
- # تابع ارسال اکشن داینامیک به گیت‌هاب بر اساس کدهای پوشه yml
937
  def dispatch_github_workflow(event_type, client_payload):
938
  acc = get_next_account()
939
  if not acc:
@@ -948,6 +217,13 @@ def dispatch_github_workflow(event_type, client_payload):
948
  if os.path.exists(script_path):
949
  with open(script_path, "r", encoding="utf-8") as f:
950
  script_content = f.read()
 
 
 
 
 
 
 
951
 
952
  if "data" in client_payload:
953
  client_payload["data"]["script"] = script_content
@@ -1081,7 +357,7 @@ def cancel_delete_active_actions():
1081
  "deleted_count": deleted_count
1082
  })
1083
 
1084
- # وب‌هوک مدیریت دریافت خطا و اجرای تلاش مجدد تا سقف ۵ بار بدون قید و شرط کلمه کلیدی
1085
  @app.route('/api/webhook/fail', methods=['POST'])
1086
  def webhook_fail():
1087
  data = request.get_json()
@@ -1185,7 +461,6 @@ def generate():
1185
  return jsonify({"status": "error", "message": "متن ورودی شامل کلمات نامناسب است."}), 400
1186
 
1187
  try:
1188
- # تغییر مبدا به auto جهت پایداری بالا در پردازش حروف ترکیبی فارسی-انگلیسی
1189
  english_prompt = GoogleTranslator(source='auto', target='en').translate(persian_prompt)
1190
  print(f"[GOOGLE TRANSLATE SUCCESS] Original: {persian_prompt} -> Translated: {english_prompt}")
1191
  except Exception as e:
@@ -1428,6 +703,57 @@ def generate_video():
1428
  else:
1429
  return jsonify({"status": "error", "message": r_vid.text}), 400
1430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1431
  # ==========================================
1432
  # سیستم جدید چت بات (ارسال مستقیم و بدون تاخیر به گیت‌هاب)
1433
  # ==========================================
@@ -1468,7 +794,6 @@ def worker_poll():
1468
 
1469
  # ==========================================
1470
 
1471
-
1472
  # --- API میکس ویدیوها سمت سرور ---
1473
  @app.route('/api/merge-videos', methods=['POST'])
1474
  def merge_videos():
@@ -1729,7 +1054,6 @@ def use_edit_credit():
1729
  conn.close()
1730
  return jsonify({"status": "success", "credits_remaining": credits_remaining})
1731
 
1732
-
1733
  # --- دریافت و ارسال فایل ---
1734
  @app.route('/api/webhook/upload', methods=['POST'])
1735
  def webhook_upload():
 
16
  # در این بخش می‌توانید هر تعداد حساب و ریپازیتوری که دارید را به همراه نام توکن تعریف کنید.
17
  GITHUB_ACCOUNTS_CONFIG = [
18
  {"repo": "hajiliker6-source/Action", "token_env": "GITHUB_TOKEN1"},
19
+ {"repo": "hajiliker6-source2/Action2", "token_env": "GITHUB_TOKEN2"},
 
 
20
  ]
21
 
22
  GITHUB_ACCOUNTS = []
 
95
  except Exception:
96
  pass
97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  def init_db():
99
  conn = sqlite3.connect(DB_PATH)
100
  c = conn.cursor()
 
202
  except Exception:
203
  return False
204
 
205
+ # تابع ارسال اکشن داینامیک به گیت‌هاب بر اساس فایل‌های درون پوشه yml
206
  def dispatch_github_workflow(event_type, client_payload):
207
  acc = get_next_account()
208
  if not acc:
 
217
  if os.path.exists(script_path):
218
  with open(script_path, "r", encoding="utf-8") as f:
219
  script_content = f.read()
220
+
221
+ # تزریق داینامیک متغیرهایی که در یمل گیت‌هاب قرار ندارند برای تولید صدا
222
+ if event_type == "generate-audio":
223
+ audio_type = client_payload.get('audio_type', 'text')
224
+ negative_prompt = client_payload.get('negative_prompt', 'music')
225
+ script_content = script_content.replace("___AUDIO_TYPE___", audio_type)
226
+ script_content = script_content.replace("___NEGATIVE_PROMPT___", negative_prompt)
227
 
228
  if "data" in client_payload:
229
  client_payload["data"]["script"] = script_content
 
357
  "deleted_count": deleted_count
358
  })
359
 
360
+ # وب‌هوک مدیریت دریافت خطا و اجرای تلاش مجدد تا سقف ۵ بار
361
  @app.route('/api/webhook/fail', methods=['POST'])
362
  def webhook_fail():
363
  data = request.get_json()
 
461
  return jsonify({"status": "error", "message": "متن ورودی شامل کلمات نامناسب است."}), 400
462
 
463
  try:
 
464
  english_prompt = GoogleTranslator(source='auto', target='en').translate(persian_prompt)
465
  print(f"[GOOGLE TRANSLATE SUCCESS] Original: {persian_prompt} -> Translated: {english_prompt}")
466
  except Exception as e:
 
703
  else:
704
  return jsonify({"status": "error", "message": r_vid.text}), 400
705
 
706
+ # ==========================================
707
+ # API اختصاصی جهت پردازش فایل صوتی در گیت هاب
708
+ # ==========================================
709
+ @app.route('/api/generate-audio', methods=['POST'])
710
+ def generate_audio():
711
+ if not GITHUB_ACCOUNTS: return jsonify({"status": "error", "message": "Tokens missing"}), 500
712
+
713
+ audio_type = request.form.get('type', 'text')
714
+ persian_prompt = request.form.get('prompt', '')
715
+ persian_negative = request.form.get('negative_prompt', 'music')
716
+ duration = request.form.get('duration', '8')
717
+ seed = request.form.get('seed', '-1')
718
+
719
+ if has_forbidden_words(persian_prompt):
720
+ return jsonify({"status": "error", "message": "متن ورودی شامل کلمات نامناسب است."}), 400
721
+
722
+ try:
723
+ english_prompt = GoogleTranslator(source='auto', target='en').translate(persian_prompt) if persian_prompt else ""
724
+ english_negative = GoogleTranslator(source='auto', target='en').translate(persian_negative) if persian_negative else "music"
725
+ except Exception:
726
+ english_prompt = persian_prompt
727
+ english_negative = persian_negative
728
+
729
+ run_id = str(uuid.uuid4())
730
+ file_url = ""
731
+
732
+ if audio_type == 'video':
733
+ file = request.files.get('file')
734
+ if not file: return jsonify({"status": "error", "message": "Video file required"}), 400
735
+ ext = file.filename.split('.')[-1] if '.' in file.filename else 'mp4'
736
+ filename = f"{run_id}_input.{ext}"
737
+ file.save(f"static/images/{filename}")
738
+ file_url = f"{SPACE_URL}/static/images/{filename}"
739
+
740
+ client_payload = {
741
+ "prompt": english_prompt,
742
+ "negative_prompt": english_negative,
743
+ "duration": duration,
744
+ "seed": seed,
745
+ "audio_type": audio_type,
746
+ "file_url": file_url,
747
+ "run_id": run_id,
748
+ "space_url": SPACE_URL
749
+ }
750
+
751
+ r = dispatch_github_workflow("generate-audio", client_payload)
752
+ if r.status_code == 204:
753
+ return jsonify({"status": "success", "run_id": run_id, "translated": english_prompt})
754
+ else:
755
+ return jsonify({"status": "error", "message": r.text}), 400
756
+
757
  # ==========================================
758
  # سیستم جدید چت بات (ارسال مستقیم و بدون تاخیر به گیت‌هاب)
759
  # ==========================================
 
794
 
795
  # ==========================================
796
 
 
797
  # --- API میکس ویدیوها سمت سرور ---
798
  @app.route('/api/merge-videos', methods=['POST'])
799
  def merge_videos():
 
1054
  conn.close()
1055
  return jsonify({"status": "success", "credits_remaining": credits_remaining})
1056
 
 
1057
  # --- دریافت و ارسال فایل ---
1058
  @app.route('/api/webhook/upload', methods=['POST'])
1059
  def webhook_upload():