File size: 30,480 Bytes
0a94d20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
Ap='FP32 (Lambat, Kualitas Terbaik)'
Ao='FP16 (Cepat, Kualitas Baik)'
An='Semua Waktu'
Am='contain'
Al='http://127.0.0.1:7860/'
Ak='Grayscale'
Aj='### β“˜ Detail Gambar\nKlik pada sebuah gambar untuk melihat detailnya.'
Ai='3 Bulan Terakhir'
Ah='2 Minggu Terakhir'
Ag='1 Minggu Terakhir'
Af='caidas/swin2sr-realworld-sr-x4-64-bsrgan-psnr'
Ae='User Agent'
Ad='IP Address'
Ac=ImportError
AJ='%Y-%m-%d %H:%M:%S'
y='secondary'
x='N/A'
w='Filename'
v='cuda'
m='primary'
l='Steps'
k='NegativePrompt'
j='utf-8'
i=str
h=Exception
g=open
b='Seed'
a='Prompt'
Z=len
T='history'
S=1.
R='Total Pengunjung'
O='title'
N=''
M=int
G='panel'
F='Timestamp'
E=print
D=True
C=False
B=None
import gradio as A,torch as H,numpy as z
from diffusers import DiffusionPipeline as Aq
import random as AK,time as A0,os as K
from datetime import datetime as n,timedelta as A1
import csv as o,pandas as I,threading as Ar
from PIL import Image as AL,ImageEnhance as c
from pathlib import Path
import uuid,urllib.parse
try:import psutil as p,platform as q;from transformers import Swin2SRForImageSuperResolution as A2,Swin2SRImageProcessor as AM;E('βœ… Library tambahan (psutil, transformers) berhasil diimpor.')
except Ac:E("❌ Peringatan: Library 'psutil' atau 'transformers' tidak ditemukan. Fitur System Monitor & Upscaler tidak akan berfungsi.");p=B;q=B;A2=B;AM=B
try:import google.generativeai as r;E("βœ… Library 'google-generativeai' berhasil diimpor.")
except Ac:E("❌ Peringatan: Library 'google-generativeai' tidak ditemukan. Fitur Chatbot & Prompt Enhancer tidak akan berfungsi.");r=B
As='\n<head>\n    <meta charset="UTF-8">\n    <meta name="viewport" content="width=device-width, initial-scale=1.0">\n    <title>RenXploit\'s Creative AI Suite</title>\n    <link rel="preconnect" href="https://fonts.googleapis.com">\n    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>\n    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Fira+Code:wght@500&display=swap" rel="stylesheet">\n    <script>\n        function typewriterEffect(element, text, speed) {\n            let i = 0;\n            element.innerHTML = ""; \n            const cursor = document.createElement(\'span\');\n            cursor.className = \'typewriter-cursor\';\n            cursor.innerHTML = \'|\';\n            element.appendChild(cursor);\n            function type() {\n                if (i < text.length) {\n                    element.insertBefore(document.createTextNode(text.charAt(i)), cursor);\n                    i++;\n                    setTimeout(type, speed);\n                } else {\n                    cursor.style.animation = \'blink 1s step-end infinite\';\n                }\n            }\n            type();\n        }\n\n        document.addEventListener("DOMContentLoaded", function(event) {\n            const titleElement = document.querySelector(\'#main-title h1\');\n            if (titleElement) {\n                const titleText = "πŸš€ RenXploit\'s Creative AI Suite 🌌";\n                titleElement.textContent = "";\n                setTimeout(() => typewriterEffect(titleElement, titleText, 50), 500);\n            }\n            \n            setInterval(() => {\n                const triggerButton = document.querySelector(\'#system-info-trigger-btn button\');\n                if (triggerButton) {\n                    triggerButton.click();\n                }\n            }, 5000);\n        });\n    </script>\n    <style>\n        :root { --primary-color: #00aaff; --primary-hover-color: #0088cc; --background-color: #0d1117; --content-background-color: #161b22; --border-color: #30363d; --text-color: #c9d1d9; --text-muted-color: #8b949e; --font-family-main: \'Inter\', sans-serif; --font-family-mono: \'Fira Code\', monospace; --border-radius: 12px; --shadow-light: 0 4px 14px 0 rgba(0, 170, 255, 0.1); --shadow-strong: 0 6px 20px 0 rgba(0, 170, 255, 0.15); }\n        body, .gradio-container { font-family: var(--font-family-main); background-color: var(--background-color) !important; color: var(--text-color); }\n        h1, h2, h3 { color: #ffffff; font-weight: 600; }\n        #main-title h1 { font-size: 2.5em !important; font-weight: 700 !important; text-align: center; padding: 2rem 1rem; color: #ffffff; background: linear-gradient(90deg, #00aaff, #00ffaa); -webkit-background-clip: text; -webkit-text-fill-color: transparent; display: inline-block; }\n        #main-title .typewriter-cursor { color: var(--primary-color); font-weight: bold; }\n        @keyframes blink { from, to { opacity: 1 } 50% { opacity: 0 } }\n        #main-subtitle p { font-size: 1.2em !important; text-align: center; color: var(--text-muted-color); margin-top: -1.5rem !important; margin-bottom: 2rem !important; }\n        .gradio-tabs { border: none !important; background-color: transparent !important; margin-bottom: 1.5rem; }\n        .gradio-tabs > div[role="tablist"] { display: flex; justify-content: center; flex-wrap: wrap; gap: 10px; border-bottom: 2px solid var(--border-color); padding-bottom: 10px; }\n        .gradio-tabs > div[role="tablist"] > button { background-color: transparent !important; color: var(--text-muted-color) !important; border: none !important; border-bottom: 3px solid transparent !important; font-size: 1.1em !important; font-weight: 600 !important; padding: 12px 20px !important; border-radius: 8px 8px 0 0 !important; transition: all 0.3s ease; }\n        .gradio-tabs > div[role="tablist"] > button:hover { background-color: var(--content-background-color) !important; color: var(--primary-color) !important; }\n        .gradio-tabs > div[role="tablist"] > button.selected { color: var(--primary-color) !important; border-bottom: 3px solid var(--primary-color) !important; background-color: var(--content-background-color) !important; }\n        .tabitem { background-color: transparent !important; border: none !important; padding: 0 !important; }\n        .gradio-row.panel, .gradio-accordion, .gradio-group { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; border-radius: var(--border-radius) !important; padding: 24px !important; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }\n        .gradio-accordion { margin-top: 1rem; }\n        .gradio-button.primary { background: linear-gradient(90deg, var(--primary-color), #00c6ff) !important; color: #ffffff !important; font-weight: 600 !important; font-size: 1.1em !important; border-radius: 8px !important; border: none !important; padding: 12px 24px !important; transition: all 0.3s ease; box-shadow: var(--shadow-light); }\n        .gradio-button.primary:hover { transform: translateY(-2px); box-shadow: var(--shadow-strong); }\n        .gradio-button.secondary { background-color: var(--content-background-color) !important; border: 1px solid var(--primary-color) !important; color: var(--primary-color) !important; transition: all 0.3s ease; }\n        .gradio-button.secondary:hover { background-color: var(--primary-color) !important; color: #ffffff !important; }\n        .gradio-textbox, .gradio-number, .gradio-image { background-color: var(--background-color) !important; border: 1px solid var(--border-color) !important; color: var(--text-color) !important; border-radius: 8px !important; }\n        .gradio-textbox textarea, .gradio-number input { color: var(--text-color) !important; }\n        .gradio-textbox:focus-within, .gradio-number:focus-within { border-color: var(--primary-color) !important; box-shadow: 0 0 0 2px rgba(0, 170, 255, 0.3); }\n        div.info { color: var(--text-muted-color) !important; font-style: italic; }\n        #gallery, #history_gallery { border-radius: var(--border-radius) !important; overflow: hidden; border: 1px solid var(--border-color); background-color: #010409; }\n        #gallery .gallery-item, #history_gallery .gallery-item { transition: transform 0.3s ease, box-shadow 0.3s ease; }\n        #gallery .gallery-item:hover, #history_gallery .gallery-item:hover { transform: scale(1.03); box-shadow: 0 8px 30px rgba(0, 170, 255, 0.3); }\n        .loader-container { border: 1px solid var(--border-color); border-radius: var(--border-radius); padding: 30px; background: var(--content-background-color); text-align: center; overflow: hidden; }\n        .loader-text { font-family: var(--font-family-mono); font-size: 1.1em; color: var(--primary-color); margin-bottom: 20px; }\n        .loader-bar-container { height: 8px; background: var(--background-color); border-radius: 4px; overflow: hidden; }\n        .loader-bar { width: 100%; height: 100%; background: linear-gradient(90deg, transparent, var(--primary-color), transparent); background-size: 200% 100%; animation: scan 2s linear infinite; }\n        @keyframes scan { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }\n        #chatbot-container { display: flex; flex-direction: column; height: 70vh; max-height: 750px; }\n        #chatbot-display { flex-grow: 1; overflow-y: auto; padding: 10px; border-bottom: 1px solid var(--border-color); }\n        #chatbot-display .message { border-radius: 18px !important; padding: 12px 18px !important; box-shadow: none !important; max-width: 80%; }\n        #chatbot-display .user { background-color: var(--primary-color) !important; color: white !important; align-self: flex-end; border-bottom-right-radius: 5px !important; }\n        #chatbot-display .bot { background-color: var(--content-background-color) !important; border: 1px solid var(--border-color) !important; align-self: flex-start; border-bottom-left-radius: 5px !important; }\n        #chat-history-sidebar { background-color: transparent !important; border: none !important; padding: 0 !important; box-shadow: none !important; }\n        #chat-history-sidebar .gradio-radio > div { display: flex; flex-direction: column; gap: 8px; }\n        #chat-history-sidebar .gradio-radio label { width: 100%; text-align: left; padding: 10px; border: 1px solid var(--border-color); border-radius: 8px; transition: all 0.2s ease; }\n        #chat-history-sidebar .gradio-radio input:checked + label { border-color: var(--primary-color); background-color: rgba(0, 170, 255, 0.1); color: var(--primary-color); font-weight: 600; }\n        .footer { text-align: center; margin: 2rem auto; padding: 1rem; color: var(--text-muted-color); border-top: 1px solid var(--border-color); }\n        .footer b { color: var(--primary-color); }\n    </style>\n</head>\n'
L='visitor_log.csv'
P='generation_log.csv'
U=Path('generated_images')
V=Ar.Lock()
Q=v if H.cuda.is_available()else'cpu'
E(f"➑️ Menggunakan device: {Q.upper()}")
def At():
	if not K.path.exists(L):
		with V:
			if not K.path.exists(L):
				with g(L,mode='w',newline=N,encoding=j)as A:B=o.writer(A);B.writerow([F,Ad,Ae])
				E(f"βœ… File log '{L}' berhasil dibuat.")
	U.mkdir(exist_ok=D)
	if not K.path.exists(P):
		with V:
			if not K.path.exists(P):
				with g(P,mode='w',newline=N,encoding=j)as A:B=o.writer(A);B.writerow([F,w,a,k,b,l])
				E(f"βœ… File log riwayat '{P}' dan direktori '{U}' siap.")
At()
E('➑️ Memuat model SDXL-Turbo...')
AN=Aq.from_pretrained('stabilityai/sdxl-turbo',torch_dtype=H.float16 if Q==v else H.float32,variant='fp16'if Q==v else B,use_safetensors=D).to(Q)
if H.cuda.is_available():AN.enable_xformers_memory_efficient_attention()
E('βœ… Model SDXL-Turbo berhasil dimuat.')
A3=B
A4=B
if A2:
	try:E('➑️ Memuat model AI Upscaler (Swin2SR)...');A3=A2.from_pretrained(Af).to(Q);A4=AM.from_pretrained(Af);E('βœ… Model AI Upscaler berhasil dimuat.')
	except h as Au:E(f"❌ Gagal memuat model Upscaler: {Au}. Fitur upscale akan dinaktifkan.")
class Av:
	def __init__(A):
		A.api_keys=[];A.is_configured=C
		if not r:return
		B=1
		while D:
			F=K.getenv(f"GEMINI_API_KEY_{B}")
			if F:A.api_keys.append(F);B+=1
			else:break
		if A.api_keys:E(f"βœ… Berhasil memuat {Z(A.api_keys)} API Key Gemini. Sistem rotasi aktif.");A.is_configured=D
		else:E('❌ PERINGATAN: Tidak ada API Key Gemini yang ditemukan. Fitur AI Chat & Prompt Enhancer tidak akan berfungsi.')
	def chat(B,message,history,system_prompt=B):
		K='parts';J='role';F=system_prompt;D=history;C=message
		if not B.is_configured:return'Maaf, fitur ini tidak terkonfigurasi karena tidak ada API Key.'
		try:
			L=AK.choice(B.api_keys);r.configure(api_key=L);M=r.GenerativeModel('gemini-2.5-flash');A=[]
			for(G,H)in D:
				if G:A.append({J:'user',K:[G]})
				if H:A.append({J:'model',K:[H]})
			N=M.start_chat(history=A);I=C
			if F and not D:I=f"{F}\n\nUser query: {C}"
			O=N.send_message(I);return O.text
		except h as P:E(f"❌ Terjadi error pada API Key Gemini: {P}");return'Terjadi kesalahan saat menghubungi API AI. Mungkin salah satu API Key tidak valid atau ada masalah jaringan. Silakan coba lagi.'
s=Av()
def Aw(request):
	A=request;C=n.now().strftime(AJ);B=A.client.host if A else x;D=A.headers.get('user-agent','Unknown')if A else x
	with V:
		with g(L,mode='a',newline=N,encoding=j)as F:G=o.writer(F);G.writerow([C,B,D])
	E(f"βœ… Pengunjung baru tercatat: IP {B}")
def Ax(prompt,negative_prompt,steps,seed,num_images):
	C=prompt;B=seed
	if not C:raise A.Error('Prompt tidak boleh kosong!')
	if B==-1:B=AK.randint(0,2**32-1)
	D=H.manual_seed(B);E=AN(prompt=C,negative_prompt=negative_prompt,generator=D,num_inference_steps=steps,guidance_scale=.0,num_images_per_prompt=num_images).images;return E,B
def Ay(prompt,negative_prompt,steps,seed,num_images):
	G=steps;F=negative_prompt;E=prompt;yield(A.update(visible=C),A.update(visible=D,value="<div class='loader-container'><div class='loader-text'>AI sedang melukis mahakarya Anda...</div><div class='loader-bar-container'><div class='loader-bar'></div></div></div>"),A.update(interactive=C),A.update(visible=C));J=A0.time();H,B=Ax(E,F,M(G),M(seed),M(num_images));K=A0.time();L=n.now().strftime(AJ)
	for(O,Q)in enumerate(H):
		I=f"{M(A0.time())}_{B}_{O}.png";R=U/I;Q.save(R)
		with V:
			with g(P,mode='a',newline=N,encoding=j)as S:T=o.writer(S);T.writerow([L,I,E,F,B,M(G)])
	W=K-J;X=f"Seed yang digunakan: {B}\nTotal waktu generasi: {W:.2f} detik";yield(A.update(value=H,visible=D),A.update(visible=C),A.update(interactive=D),A.update(value=X,visible=D))
def Az(name,email,message):
	B=message
	if not name or not B:A.Warning('Nama dan Pesan tidak boleh kosong!');return A.update(visible=C)
	F=n.now().strftime(AJ);G=f"""--- Laporan Baru ({F}) ---
Nama: {name}
Email: {email}
Pesan: {B}

"""
	with g('reports.log','a',encoding=j)as H:H.write(G)
	E('βœ… Laporan baru telah disimpan ke reports.log');return A.update(value='βœ… Terima kasih! Laporan Anda telah kami terima.',visible=D)
def A5(time_filter):
	J='## πŸ“ˆ 0';G=time_filter
	try:
		with V:
			if not K.path.exists(L)or K.path.getsize(L)==0:return J,I.DataFrame({F:[],R:[]})
			P=[F,Ad,Ae];A=I.read_csv(L,header=B,names=P)
			if not A.empty and A.iloc[0][F]==F:A=A.iloc[1:].reset_index(drop=D)
		if A.empty:return J,I.DataFrame({F:[],R:[]})
		A[F]=I.to_datetime(A[F],errors='coerce');A.dropna(subset=[F],inplace=D)
		if A.empty:return J,I.DataFrame({F:[],R:[]})
		Q=Z(A);M=f"## πŸ“ˆ {Q:,}";A[R]=z.arange(1,Z(A)+1);H=n.now()
		if G==Ag:C=A[A[F]>=H-A1(weeks=1)]
		elif G==Ah:C=A[A[F]>=H-A1(weeks=2)]
		elif G==Ai:C=A[A[F]>=H-A1(days=90)]
		else:C=A
		if C.empty:return M,I.DataFrame({F:[],R:[]})
		return M,C
	except h as N:O=f"Error saat memperbarui monitor: {N}";E(f"❌ {O}");return f"## ⚠️ Error: {N}",I.DataFrame({'Error':[O]})
def A_(simple_prompt):
	B=simple_prompt
	if not B:A.Warning('Tolong masukkan ide Anda terlebih dahulu.');return N
	if not s.is_configured:A.Error('Fitur Prompt Enhancer tidak aktif karena API Key Gemini tidak diatur.');return'Fitur tidak aktif.'
	C='Anda adalah seorang ahli prompt engineering untuk model AI text-to-image seperti Stable Diffusion. Tugas Anda adalah mengubah ide sederhana dari pengguna menjadi prompt yang kaya, deskriptif, dan artistik. Fokus pada detail visual: subjek, setting, pencahayaan, gaya seni, komposisi, dan kualitas. Hasilkan HANYA prompt-nya saja dalam format teks panjang, tanpa penjelasan atau kalimat pembuka/penutup.';yield'🧠 AI sedang meracik prompt ajaib untuk Anda...';D=s.chat(B,[],system_prompt=C);yield D
def B0(image_to_upscale,clarity_strength):
	G=image_to_upscale;F=clarity_strength
	if G is B:raise A.Error('Silakan unggah gambar terlebih dahulu.')
	if A3 is B or A4 is B:raise A.Error('Fitur Upscaler tidak aktif karena model gagal dimuat.')
	yield(B,'πŸš€ Memproses peningkatan resolusi 4x oleh AI...')
	try:
		with H.no_grad():J=A4(G,return_tensors='pt').to(Q);K=A3(**J);D=K.reconstruction.data.squeeze().float().cpu().clamp_(0,1).numpy();D=z.moveaxis(D,source=0,destination=-1);D=(D*255.).round().astype(z.uint8);C=AL.fromarray(D)
		if F>S:yield(C,f"✨ Menerapkan peningkatan kejernihan (Strength: {F:.2f})...");L=c.Sharpness(C);C=L.enhance(F)
		yield(C,f"βœ… Gambar berhasil ditingkatkan! Resolusi akhir: {C.width}x{C.height}px.")
	except h as I:E(f"❌ Error saat upscaling: {I}");yield(B,f"⚠️ Terjadi error saat upscaling: {I}")
def AO():
	if not p or not q:return'Informasi sistem tidak tersedia (library psutil tidak ditemukan).'
	D=p.cpu_percent(interval=B);A=p.virtual_memory();C='Tidak terdeteksi (PyTorch tidak menemukan CUDA)'
	if H.cuda.is_available():E=H.cuda.get_device_name(0);F=H.cuda.memory_allocated(0)/1024**3;G=H.cuda.get_device_properties(0).total_memory/1024**3;C=f"GPU: {E}\nVRAM Terpakai: {F:.2f} GB / {G:.2f} GB"
	I=f"**Platform:** `{q.system()} {q.release()}`";return f"**CPU Terpakai:** `{D:.1f}%`\n**RAM Terpakai:** `{A.percent:.1f}% ({A.used/1024**3:.2f} GB / {A.total/1024**3:.2f} GB)`\n{C}\n---\n{I}"
def AP():
	G='### πŸ“‚ Riwayat Kosong\nBelum ada gambar yang dihasilkan.'
	try:
		with V:
			if not K.path.exists(P):return[],I.DataFrame(),G
			A=I.read_csv(P)
		if A.empty:return[],A,G
		B=A.sort_values(by=F,ascending=C);H=[i(U/A)for A in B[w]if(U/A).exists()];return H,B,Aj
	except h as D:E(f"❌ Error memuat riwayat: {D}");return[],I.DataFrame(),f"### ⚠️ Error\nTidak dapat memuat riwayat: {D}"
def B1(evt,history_df):
	G=history_df
	if not evt.selected or G.empty:return'### β“˜ Detail Gambar\nKlik gambar untuk melihat detailnya.',A.update(visible=C),A.update(visible=C),B
	H=evt.index;E=G.iloc[H];I=f"""
    **Prompt:** `{E[a]}`
    **Negative Prompt:** `{E.get(k,x)}`
    ---
    **Seed:** `{E[b]}` | **Steps:** `{E[l]}`
    **File:** `{E[w]}` | **Dibuat:** `{E[F]}`
    """;return I,A.update(visible=D),A.update(visible=C),H
def B2(selected_index,history_df):
	E=history_df;D=selected_index
	if D is B or E.empty:return A.update(),A.update(),A.update(),A.update(),A.update()
	C=E.iloc[D];return C[a],C.get(k,N),C[b],C[l],A.Tabs(selected=0)
def B3(selected_index,history_df):
	D=history_df;C=selected_index
	if C is B or D.empty:return A.update(),A.update()
	E=D.iloc[C];F=i(U/E[w]);return AL.open(F),A.Tabs(selected=5)
def A6(image,brightness,contrast,saturation,sharpness,filter_choice):
	H=filter_choice;G=image
	if G is B:return
	A=G.copy()
	if H==Ak:A=A.convert('L').convert('RGB')
	elif H=='Sepia':
		K=A.load();L,N=A.size
		for I in range(N):
			for J in range(L):D,E,F=A.getpixel((J,I));O,P,Q=M(.393*D+.769*E+.189*F),M(.349*D+.686*E+.168*F),M(.272*D+.534*E+.131*F);K[J,I]=min(255,O),min(255,P),min(255,Q)
	C=c.Brightness(A);A=C.enhance(brightness);C=c.Contrast(A);A=C.enhance(contrast);C=c.Color(A);A=C.enhance(saturation);C=c.Sharpness(A);A=C.enhance(sharpness);return A
def B4(selected_index,history_df,request):
	H=history_df;G=selected_index;F=request
	if G is B or H.empty:A.Warning('Pilih gambar terlebih dahulu sebelum membagikan.');return A.update(visible=C)
	E=H.iloc[G];I=i(F.url).split('?')[0]if F and hasattr(F,'url')else Al;J={'prompt':E[a],'neg':E.get(k,N),'seed':E[b],'steps':E[l]};K=urllib.parse.urlencode(J);L=f"{I}?__theme=dark&{K}";M=f"""
    **URL untuk Berbagi & Isi Ulang Generator:**
    `{L}`
    ---
    **Detail untuk Disalin:**
    - **Prompt:** {E[a]}
    - **Negative:** {E.get(k,x)}
    - **Seed:** {E[b]}
    - **Steps:** {E[l]}
    """;return A.update(value=M,visible=D)
def B5(chat_id,all_chats_history,request):
	G=request;F=all_chats_history;B=chat_id
	if not B or B not in F:return A.update(visible=C)
	H=F[B][T]
	if not H:return A.update(visible=C)
	I=i(G.url).split('?')[0]if G and hasattr(G,'url')else Al;L=F[B][O];M=f"{I}chat/{B}?__theme=dark";E=f"### Riwayat Chat: {L}\n";E+=f"**URL Sesi:** `{I}`\n---\n"
	for(J,K)in H:
		if J:E+=f"\n**πŸ‘€ Anda:**\n{J}\n"
		if K:E+=f"\n**πŸ€– AI:**\n{K}\n"
	return A.update(value=E,visible=D)
def A7(all_chats_history):C=all_chats_history;D=i(uuid.uuid4());C[D]={O:'Percakapan Baru',T:[(B,'Halo! Saya Flood, asisten AI dari RenXploit. Ada yang bisa saya bantu?')]};E=[A[O]for A in C.values()];return C,D,C[D][T],A.update(choices=E,value=C[D][O])
def AQ(user_message,chat_id,all_chats_history):
	H=user_message;G=chat_id;F=all_chats_history
	if not G or G not in F:F,G,E,L=A7({})
	E=F[G][T]
	if Z(E)==1 and E[0][0]is B:E=[]
	E.append((H,B));F[G][T]=E
	if Z(E)==1:I=H[:30]+'...'if Z(H)>30 else H;F[G][O]=I
	J=[A[O]for A in F.values()];yield(F,E,A.update(choices=J,value=F[G][O]),A.update(value=N),A.update(visible=C));K=s.chat(H,[A for A in E if A[0]is not B]);E[-1]=H,K;F[G][T]=E;yield(F,E,A.update(),A.update(),A.update(visible=D))
def B6(selected_title,all_chats_history):
	G=all_chats_history;F=selected_title
	if not F:return B,[],A.update(visible=C)
	E=B
	for(H,I)in G.items():
		if I[O]==F:E=H;break
	if E:return E,G[E][T],A.update(visible=D)
	return B,[],A.update(visible=C)
with A.Blocks(theme=A.themes.Base(),head=As)as d:
	A.Markdown("# πŸš€ RenXploit's Creative AI Suite 🌌",elem_id='main-title');A.Markdown('Sebuah platform lengkap untuk kreativitas Anda, ditenagai oleh AI.',elem_id='main-subtitle');J=A.State({});W=A.State(B);t=A.State(B)
	with A.Tabs()as A8:
		with A.TabItem('🎨 Image Generator',id=0):
			with A.Row(variant=G,equal_height=C):
				with A.Column(scale=1):
					A.Markdown('### πŸ“ **Masukan Perintah Anda**');A9=A.Textbox(label=a,placeholder='Contoh: Cinematic photo, seekor rubah merah...',lines=3,info='Jadilah sangat spesifik! Atau gunakan Prompt Enhancer.');AR=A.Textbox(label='Prompt Negatif',placeholder='Contoh: blurry, low quality, bad hands...',lines=2,info='Hal-hal yang TIDAK Anda inginkan.');B7=A.Slider(minimum=1,maximum=8,value=2,step=1,label='Jumlah Gambar');AS=A.Button('✨ Hasilkan Gambar!',variant=m)
					with A.Accordion('βš™οΈ Opsi Lanjutan',open=C):
						AT=A.Slider(minimum=1,maximum=5,value=2,step=1,label='Langkah Iterasi (Kualitas vs Kecepatan)')
						with A.Row():AA=A.Number(label=b,value=-1,precision=0,info='Gunakan -1 untuk acak.');B8=A.Button('🎲 Acak',variant=y)
				with A.Column(scale=2):A.Markdown('### πŸ–ΌοΈ **Hasil Generasi**');B9=A.Gallery(label='Hasil Gambar',show_label=C,elem_id='gallery',columns=2,object_fit=Am,height='auto');BA=A.HTML(visible=C);BB=A.Textbox(label='Informasi Generasi',visible=C,interactive=C,lines=2)
		with A.TabItem('πŸ’¬ Chat with AI',id=1):
			with A.Row(variant=G):
				with A.Column(scale=1,min_width=250)as Bc:
					A.Markdown('### πŸ—‚οΈ Riwayat Chat');BC=A.Button('βž• Obrolan Baru',variant=m)
					with A.Group(elem_id='chat-history-sidebar'):X=A.Radio(label='Pilih Obrolan',choices=[],interactive=D)
					with A.Row(visible=C)as AB:BD=A.Button('πŸ”— Bagikan Chat')
					BE=A.Textbox(label='Salin Konten Chat',lines=10,interactive=D,show_copy_button=D,visible=C)
				with A.Column(scale=3):
					A.Markdown('### πŸ€– **Asisten AI Flood**')
					if not s.is_configured:A.Warning('Fitur Chatbot dinonaktifkan. API Key Gemini tidak terkonfigurasi.')
					else:
						with A.Column(elem_id='chatbot-container'):
							e=A.Chatbot(elem_id='chatbot-display',label='Flood AI',bubble_full_width=C)
							with A.Row():f=A.Textbox(show_label=C,placeholder='Ketik pesan Anda di sini...',scale=5);BF=A.Button('Kirim',variant=y,scale=1)
		with A.TabItem('✨ Prompt Enhancer',id=2):
			with A.Row(variant=G):
				with A.Column():A.Markdown('### πŸͺ„ **Ubah Ide Jadi Prompt Ajaib**\nCukup tulis ide sederhana, dan biarkan AI menyempurnakannya menjadi prompt yang detail dan artistik.');BG=A.Textbox(label='Ide Sederhana Anda',placeholder='Contoh: seekor astronot di hutan alien',lines=3);BH=A.Button('Buat Prompt Ajaib!',variant=m);AU=A.Textbox(label='Prompt yang Disempurnakan',lines=5,interactive=D,show_copy_button=D);BI=A.Button('➑️ Kirim & Pindah ke Generator')
		with A.TabItem('πŸš€ AI Image Upscaler',id=3):
			with A.Row(variant=G,equal_height=C):
				with A.Column():A.Markdown('### **Tingkatkan Resolusi Gambar**\nUnggah gambar untuk meningkatkan kualitas dan ukurannya hingga 4x lipat menggunakan AI.');BJ=A.Image(type='pil',label='Unggah Gambar Anda di Sini');BK=A.Slider(minimum=S,maximum=3.,value=S,step=.1,label='Tingkat Peningkatan Kejernihan',info='Setelah di-upscale 4x, atur kejernihan gambar di sini. 1.0 = Tanpa efek.');BL=A.Button('Tingkatkan Resolusi!',variant=m)
				with A.Column():A.Markdown('### **Hasil Peningkatan Resolusi**');BM=A.Image(label='Gambar Hasil Upscale',interactive=C,show_download_button=D);BN=A.Markdown('Status: Menunggu gambar...')
		with A.TabItem('πŸ–ΌοΈ Galeri & Riwayat',id=4)as BO:
			with A.Row(variant=G):
				with A.Column(scale=2):A.Markdown('### **Galeri Hasil Generasi Anda**');AC=A.Gallery(label='Riwayat Gambar',show_label=C,columns=4,object_fit=Am,height='auto',elem_id='history_gallery');Y=A.State()
				with A.Column(scale=1):
					A.Markdown('### **Detail & Aksi**');AD=A.Markdown(Aj);BP=A.Button('πŸ”„ Segarkan Galeri',variant=y)
					with A.Row(visible=C)as BQ:BR=A.Button('Kirim ke Generator');BS=A.Button('Kirim ke Editor');BT=A.Button('πŸ”— Bagikan Detail')
					AV=A.Textbox(label='URL & Detail untuk Dibagikan',lines=8,interactive=D,show_copy_button=D,visible=C)
		with A.TabItem('🎨 Image Editor',id=5):
			with A.Row(variant=G):
				with A.Column(scale=1):
					A.Markdown('### **Toolkit Pasca-Produksi**');AE=A.Image(type='pil',label='Unggah Gambar atau Kirim dari Riwayat')
					with A.Accordion('Penyesuaian',open=D):AW=A.Slider(minimum=.5,maximum=1.5,value=S,step=.05,label='Kecerahan');AX=A.Slider(minimum=.5,maximum=1.5,value=S,step=.05,label='Kontras');AY=A.Slider(minimum=.0,maximum=2.,value=S,step=.05,label='Saturasi Warna');AZ=A.Slider(minimum=.0,maximum=3.,value=S,step=.1,label='Ketajaman')
					with A.Accordion('Filter Cepat',open=D):Aa=A.Radio(['None',Ak,'Sepia'],label='Pilih Filter',value='None')
				with A.Column(scale=1):A.Markdown('### **Hasil Editing**');AF=A.Image(label='Hasil Akhir',interactive=C,show_download_button=D)
		with A.TabItem('πŸ“Š Visitor Monitor',id=6):
			with A.Row(variant=G):
				with A.Column():
					A.Markdown('### πŸ“ˆ **Live Visitor Monitor**\nPantau jumlah total pengunjung aplikasi Anda secara real-time.')
					with A.Row():
						with A.Column(scale=3):AG=A.Markdown('## πŸ“ˆ Memuat data...')
						with A.Column(scale=2):u=A.Radio([An,Ag,Ah,Ai],label='Tampilkan data untuk',value=An);BU=A.Button('πŸ”„ Segarkan Manual',variant=y)
					AH=A.LinePlot(x=F,y=R,title='Grafik Pertumbuhan Pengunjung',tooltip=[F,R],height=500,interactive=D)
		with A.TabItem('βš™οΈ System & Settings',id=7):
			with A.Row(variant=G):
				with A.Column():A.Markdown('### **Live System Monitor**');Ab=A.Markdown('Memuat info sistem...');BV=A.Button('Trigger System Info',visible=C,elem_id='system-info-trigger-btn')
				with A.Column():
					A.Markdown('### **Pengaturan Aplikasi**')
					with A.Accordion('Kualitas Model',open=D):A.Radio([Ao,Ap],value=Ao if Q==v else Ap,label='Presisi Model Generator',interactive=C,info='Terkunci. Ditentukan saat aplikasi dimulai.')
		with A.TabItem('πŸ’‘ Panduan Prompting',id=8):
			with A.Row(variant=G):A.Markdown('## Cara Menjadi "Art Director" yang Hebat untuk AI...\n (Konten panduan Anda di sini)')
		with A.TabItem('πŸ“– Blog & Updates',id=9):
			with A.Row(variant=G):A.Markdown("### Perkembangan Terbaru dari RenXploit's AI Suite\nv3.0 (Perbaikan Kritis): Memperbaiki bug pada fitur Share URL dan Share Detail Galeri yang disebabkan oleh perbedaan versi Gradio dan logika event yang salah.\nv2.8: Mengganti komponen `gr.Box` dengan `gr.Group` untuk kompatibilitas.\nv2.7: Perombakan total UI Chatbot dengan fitur riwayat, new chat, dan share.\nRencana Berikutnya: Menjajaki model generator gambar yang berbeda dan fitur Inpainting/Outpainting.")
		with A.TabItem('ℹ️ About & Support',id=10):
			with A.Row(variant=G):
				with A.Column():
					A.Markdown('### Tentang Proyek dan Dukungan')
					with A.Accordion("Tentang RenXploit's Creative AI Suite",open=D):A.Markdown("\n                        RenXploit's Creative AI Suite adalah proyek pribadi untuk mengeksplorasi AI generatif.\n                        Hubungi saya melalui: ngoprek.xyz/contact\n                        ")
					with A.Accordion('Laporkan Masalah atau Beri Masukan'):BW=A.Textbox(label='Nama Anda');BX=A.Textbox(label='Email Anda (Opsional)');BY=A.Textbox(label='Pesan Anda',lines=5,placeholder='Jelaskan masalah atau ide Anda...');BZ=A.Button('Kirim Laporan',variant=m);Ba=A.Markdown(visible=C)
	A.Markdown("---\n<div class='footer'><p>Dibuat dengan ❀️ oleh <b>RenXploit</b>.</p></div>",elem_classes='footer');d.load(Aw,inputs=B,outputs=B);d.load(fn=A7,inputs=[J],outputs=[J,W,e,X]);B8.click(lambda:-1,outputs=AA);AS.click(fn=Ay,inputs=[A9,AR,AT,AA,B7],outputs=[B9,BA,AS,BB]);BC.click(fn=A7,inputs=[J],outputs=[J,W,e,X]);BF.click(fn=AQ,inputs=[f,W,J],outputs=[J,e,X,f,AB]);f.submit(fn=AQ,inputs=[f,W,J],outputs=[J,e,X,f,AB]);X.change(fn=B6,inputs=[X,J],outputs=[W,e,AB]);BD.click(fn=B5,inputs=[W,J],outputs=[BE]);BH.click(fn=A_,inputs=[BG],outputs=[AU]);BI.click(fn=lambda prompt:(prompt,A.Tabs(selected=0)),inputs=[AU],outputs=[A9,A8]);BL.click(fn=B0,inputs=[BJ,BK],outputs=[BM,BN]);BO.select(fn=AP,inputs=B,outputs=[AC,Y,AD]);BP.click(fn=AP,inputs=B,outputs=[AC,Y,AD]);AC.select(fn=B1,inputs=[Y],outputs=[AD,BQ,AV,t]);BR.click(fn=B2,inputs=[t,Y],outputs=[A9,AR,AA,AT,A8]);BS.click(fn=B3,inputs=[t,Y],outputs=[AE,A8]);BT.click(fn=B4,inputs=[t,Y],outputs=[AV]);AI=[AE,AW,AX,AY,AZ,Aa]
	for Bb in[AW,AX,AY,AZ]:Bb.release(fn=A6,inputs=AI,outputs=AF)
	Aa.change(fn=A6,inputs=AI,outputs=AF);AE.change(fn=A6,inputs=AI,outputs=AF);d.load(fn=A5,inputs=[u],outputs=[AG,AH]);BU.click(fn=A5,inputs=[u],outputs=[AG,AH]);u.change(fn=A5,inputs=[u],outputs=[AG,AH]);BV.click(fn=AO,inputs=B,outputs=Ab);d.load(fn=AO,inputs=B,outputs=Ab);BZ.click(fn=Az,inputs=[BW,BX,BY],outputs=[Ba])
if __name__=='__main__':d.launch(debug=D)