Akwbw commited on
Commit
93db0b6
Β·
verified Β·
1 Parent(s): a49ab03

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -157
app.py CHANGED
@@ -5,16 +5,15 @@ import subprocess
5
  import shutil
6
  import requests
7
  import re
8
- import glob
9
 
10
  # --- CONFIGURATION ---
11
  API_ENDPOINT = "https://gen.pollinations.ai/v1/chat/completions"
12
  API_KEY = "sk_qDYtDvntvqzjmp23XKVzr9lBXYwYndaR"
13
  AI_MODEL = "claude"
14
 
15
- st.set_page_config(page_title="Strict AI Android Builder", layout="centered")
16
- st.title("πŸ•΅οΈβ€β™‚οΈ Strict AI Auto-Builder")
17
- st.markdown("Ye system har file ki **Jasoosi** karega aur build se pehle hi errors fix kar dega.")
18
 
19
  # --- HELPER: AI API ---
20
  def ask_claude(system_prompt, user_message):
@@ -28,17 +27,15 @@ def ask_claude(system_prompt, user_message):
28
  {"role": "system", "content": system_prompt},
29
  {"role": "user", "content": user_message}
30
  ],
31
- "temperature": 0.1 # Strictly logic, no creativity
32
  }
33
-
34
  try:
35
- response = requests.post(API_ENDPOINT, json=payload, headers=headers, timeout=90) # Increased timeout
36
  if response.status_code == 200:
37
  return True, response.json()['choices'][0]['message']['content']
38
- else:
39
- return False, f"API Error {response.status_code}"
40
- except Exception as e:
41
- return False, f"Connection Error: {str(e)}"
42
 
43
  # --- HELPER: KEYSTORE ---
44
  def generate_keystore():
@@ -52,82 +49,55 @@ def generate_keystore():
52
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
53
  return keystore_path
54
 
55
- # --- CORE LOGIC: THE JASOOS (STRICT SCANNER) ---
56
- def strict_scan_and_fix(project_root, status_box):
57
- # Hum in specific files ko target karenge jo 99% errors ki wajah banti hain
58
- critical_files = []
59
 
60
- # 1. Gradle Files dhoondo
 
61
  for root, dirs, files in os.walk(project_root):
62
- if "build.gradle" in files:
63
- critical_files.append(os.path.join(root, "build.gradle"))
64
- if "AndroidManifest.xml" in files:
65
- critical_files.append(os.path.join(root, "AndroidManifest.xml"))
66
 
67
- # 2. Main Java/Kotlin Files (Top 2 largest files utha lo - assuming wahi main logic hai)
68
- source_files = []
69
- for root, dirs, files in os.walk(project_root):
70
- for file in files:
71
- if file.endswith(".java") or file.endswith(".kt"):
72
- source_files.append(os.path.join(root, file))
73
-
74
- # Sort by size (descending) and take top 2
75
- source_files.sort(key=lambda x: os.path.getsize(x), reverse=True)
76
- critical_files.extend(source_files[:2])
77
-
78
- total_files = len(critical_files)
79
- fixed_count = 0
80
-
81
- for i, file_path in enumerate(critical_files):
82
- file_name = os.path.basename(file_path)
83
- status_box.write(f"🧐 Auditing: **{file_name}** ({i+1}/{total_files})")
84
 
85
- with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
86
- content = f.read()
 
 
 
 
87
 
88
- # --- PROMPT: STRICT ENVIRONMENT MATCHING ---
89
- system_prompt = """
90
- You are a Senior Android Architect auditing code for a CI/CD server.
91
- Server Specs: Linux, Java 17, Android SDK 33.
92
-
93
- Rules:
94
- 1. Fix any deprecated Gradle plugins (use valid versions for Java 17).
95
- 2. Ensure compileSdkVersion is 33 or 34.
96
- 3. Fix Manifest package name errors.
97
- 4. In Java/Kotlin, fix syntax errors strictly.
98
- 5. DO NOT remove main logic, only fix structure/syntax.
99
-
100
- Output:
101
- If the code is 100% PERFECT, reply exactly: "NO_CHANGES_NEEDED"
102
- If there is ANY issue, reply with the FULL CORRECTED CODE only. No markdown.
103
- """
104
 
105
- user_msg = f"Check this file content:\n\n{content}"
106
-
107
- success, response = ask_claude(system_prompt, user_msg)
108
-
109
- if success:
110
- if "NO_CHANGES_NEEDED" not in response:
111
- # AI ne changes kiye hain
112
- cleaned_code = response.replace("```gradle", "").replace("```java", "").replace("```xml", "").replace("```kotlin", "").replace("```", "").strip()
113
-
114
- # Safety check: Code empty to nahi?
115
- if len(cleaned_code) > 10:
116
- with open(file_path, 'w', encoding='utf-8') as f:
117
- f.write(cleaned_code)
118
- fixed_count += 1
119
- status_box.write(f"πŸ› οΈ **Fixed Issues in {file_name}**")
120
- else:
121
- status_box.write(f"⚠️ AI Skip ({file_name}): API Error")
122
 
123
- return fixed_count
 
124
 
125
- # --- MAIN UI ---
126
  uploaded_file = st.file_uploader("Project ZIP Upload", type=["zip"])
127
 
128
  if uploaded_file:
129
- if st.button("πŸš€ Strict Build (Guarantee Mode)"):
130
- status_box = st.status("Initializing Detective Mode...", expanded=True)
131
 
132
  # 1. EXTRACT
133
  if os.path.exists("project_extract"): shutil.rmtree("project_extract")
@@ -142,103 +112,88 @@ if uploaded_file:
142
  break
143
 
144
  if not project_root:
145
- status_box.update(label="❌ Invalid Zip", state="error")
146
  st.stop()
147
 
148
  subprocess.run(["chmod", "+x", os.path.join(project_root, "gradlew")])
149
 
150
- # 2. STRICT AI AUDIT (The Jasoos Step)
151
- status_box.write("πŸ•΅οΈβ€β™‚οΈ Starting Deep Scan (Scanning all critical files)...")
152
- fixes = strict_scan_and_fix(project_root, status_box)
153
-
154
- if fixes > 0:
155
- status_box.write(f"βœ… AI ne build se pehle **{fixes} files** fix kar di hain.")
156
- else:
157
- status_box.write("βœ… Code looks perfect. Proceeding...")
158
-
159
- # 3. BUILD
160
- status_box.write("πŸ”¨ Building APK...")
161
-
162
- # Force Clean Build
163
  cmd = ["./gradlew", "clean", "assembleRelease", "--no-daemon", "--stacktrace"]
164
  result = subprocess.run(cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
165
 
 
166
  if result.returncode == 0:
167
- status_box.write("βœ… Build Successful! Signing now...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- # Find & Sign
170
- unsigned_apk = None
171
  for root, dirs, files in os.walk(project_root):
172
  for file in files:
173
  if file.endswith(".apk") and "release" in file:
174
- unsigned_apk = os.path.join(root, file)
175
  break
176
 
177
- if unsigned_apk:
178
  keystore = generate_keystore()
179
- signed_name = "Pro_Signed_App.apk"
180
-
181
- # Zipalign
182
- subprocess.run(["zipalign", "-v", "-p", "4", unsigned_apk, "aligned.apk"], stdout=subprocess.DEVNULL)
183
- # Sign
184
- subprocess.run([
185
- "apksigner", "sign", "--ks", keystore, "--ks-pass", "pass:android",
186
- "--out", signed_name, "aligned.apk"
187
- ])
188
 
189
- status_box.update(label="πŸŽ‰ App Ready!", state="complete")
190
- with open(signed_name, "rb") as f:
191
- st.download_button("⬇️ Download Final APK", f, file_name=signed_name, mime="application/vnd.android.package-archive")
192
- else:
193
- status_box.error("APK file gum ho gayi.")
194
  else:
195
- # 4. EMERGENCY REPAIR (Agar Jasoos se bhi kuch bach gaya ho)
196
- status_box.write("⚠️ Build Error! Activating Emergency Repair...")
197
-
198
- # Simple Repair Logic for last attempt
199
- error_log = result.stderr
200
- match = re.search(r'(/[\w/-]+\.(java|kt|xml|gradle)):(\d+):', error_log)
201
- if match:
202
- broken_file = match.group(1)
203
- # Relative path fix
204
- if not os.path.exists(broken_file):
205
- for root, dirs, files in os.walk(project_root):
206
- if os.path.basename(broken_file) in files:
207
- broken_file = os.path.join(root, os.path.basename(broken_file))
208
- break
209
-
210
- if os.path.exists(broken_file):
211
- status_box.write(f"πŸš‘ Fixing leftover error in: {os.path.basename(broken_file)}")
212
- with open(broken_file, 'r') as f: content = f.read()
213
-
214
- # Ask AI one last time
215
- s_prompt = "Fix this specific build error in the code. Output ONLY code."
216
- u_msg = f"Error: {error_log[-500:]}\nCode: {content}"
217
- success, fixed = ask_claude(s_prompt, u_msg)
218
-
219
- if success:
220
- clean = fixed.replace("```java", "").replace("```", "").strip()
221
- with open(broken_file, 'w') as f: f.write(clean)
222
-
223
- # Last Retry
224
- status_box.write("πŸ”„ Final Retry...")
225
- subprocess.run(cmd, cwd=project_root, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
226
-
227
- # Check again
228
- final_apk = None
229
- for root, dirs, files in os.walk(project_root):
230
- for file in files:
231
- if file.endswith(".apk") and "release" in file:
232
- final_apk = os.path.join(root, file)
233
- break
234
- if final_apk:
235
- status_box.update(label="πŸŽ‰ Saved by AI!", state="complete")
236
- with open(final_apk, "rb") as f:
237
- st.download_button("⬇️ Download Rescued APK", f, file_name="rescued_app.apk")
238
- st.stop()
239
-
240
- status_box.update(label="❌ Total Failure", state="error")
241
- st.error("AI couldn't fix it automatically.")
242
- st.text_area("Logs", result.stderr[-2000:], height=300)
243
 
244
  if os.path.exists("uploaded.zip"): os.remove("uploaded.zip")
 
5
  import shutil
6
  import requests
7
  import re
 
8
 
9
  # --- CONFIGURATION ---
10
  API_ENDPOINT = "https://gen.pollinations.ai/v1/chat/completions"
11
  API_KEY = "sk_qDYtDvntvqzjmp23XKVzr9lBXYwYndaR"
12
  AI_MODEL = "claude"
13
 
14
+ st.set_page_config(page_title="Auto-Upgrade Builder", layout="centered")
15
+ st.title("πŸ›‘οΈ AI Builder + Auto-Upgrade Engine")
16
+ st.markdown("Agar project purana hua to system khud usay modernize karega.")
17
 
18
  # --- HELPER: AI API ---
19
  def ask_claude(system_prompt, user_message):
 
27
  {"role": "system", "content": system_prompt},
28
  {"role": "user", "content": user_message}
29
  ],
30
+ "temperature": 0.1
31
  }
 
32
  try:
33
+ response = requests.post(API_ENDPOINT, json=payload, headers=headers, timeout=60)
34
  if response.status_code == 200:
35
  return True, response.json()['choices'][0]['message']['content']
36
+ return False, "API Error"
37
+ except:
38
+ return False, "Connection Error"
 
39
 
40
  # --- HELPER: KEYSTORE ---
41
  def generate_keystore():
 
49
  ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
50
  return keystore_path
51
 
52
+ # --- πŸ› οΈ THE MODERNIZER (JADOO) ---
53
+ # Ye function puranay project ko zabardasti naya bana dega
54
+ def force_upgrade_engine(project_root, status_box):
55
+ status_box.write("πŸ”§ Project Engine bahut purana hai. Zabardasti Upgrade kar raha hun...")
56
 
57
+ # 1. Force Gradle Wrapper to 8.0 (Compatible with Java 17)
58
+ wrapper_props = None
59
  for root, dirs, files in os.walk(project_root):
60
+ if "gradle-wrapper.properties" in files:
61
+ wrapper_props = os.path.join(root, "gradle-wrapper.properties")
62
+ break
 
63
 
64
+ if wrapper_props:
65
+ new_props = """distributionBase=GRADLE_USER_HOME
66
+ distributionPath=wrapper/dists
67
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
68
+ zipStoreBase=GRADLE_USER_HOME
69
+ zipStorePath=wrapper/dists
70
+ """
71
+ with open(wrapper_props, "w") as f:
72
+ f.write(new_props)
73
+ status_box.write("βœ… Gradle Wrapper set to 8.0")
 
 
 
 
 
 
 
74
 
75
+ # 2. Update Classpath in build.gradle
76
+ root_gradle = None
77
+ for root, dirs, files in os.walk(project_root):
78
+ if "build.gradle" in files and "app" not in root: # Root level
79
+ root_gradle = os.path.join(root, "build.gradle")
80
+ break
81
 
82
+ if root_gradle:
83
+ with open(root_gradle, "r") as f: content = f.read()
84
+ # Regex to replace old classpath with new one
85
+ new_content = re.sub(r"classpath\s+['\"]com.android.tools.build:gradle:.*?['\"]",
86
+ "classpath 'com.android.tools.build:gradle:8.0.0'", content)
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ # Add google() if missing
89
+ if "google()" not in new_content:
90
+ new_content = new_content.replace("repositories {", "repositories {\n google()\n mavenCentral()")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ with open(root_gradle, "w") as f: f.write(new_content)
93
+ status_box.write("βœ… Build Plugin updated to 8.0.0")
94
 
95
+ # --- MAIN LOGIC ---
96
  uploaded_file = st.file_uploader("Project ZIP Upload", type=["zip"])
97
 
98
  if uploaded_file:
99
+ if st.button("πŸš€ Start Auto-Build"):
100
+ status_box = st.status("Initializing...", expanded=True)
101
 
102
  # 1. EXTRACT
103
  if os.path.exists("project_extract"): shutil.rmtree("project_extract")
 
112
  break
113
 
114
  if not project_root:
115
+ st.error("Gradlew not found.")
116
  st.stop()
117
 
118
  subprocess.run(["chmod", "+x", os.path.join(project_root, "gradlew")])
119
 
120
+ # 2. ATTEMPT 1: NORMAL BUILD
121
+ status_box.write("πŸ”¨ Attempt 1: Building with default settings...")
 
 
 
 
 
 
 
 
 
 
 
122
  cmd = ["./gradlew", "clean", "assembleRelease", "--no-daemon", "--stacktrace"]
123
  result = subprocess.run(cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
124
 
125
+ success = False
126
  if result.returncode == 0:
127
+ success = True
128
+ else:
129
+ # 3. FAILURE DETECTED -> UPGRADE ENGINE -> ATTEMPT 2
130
+ status_box.write("❌ Attempt 1 Failed. Checking if engine is old...")
131
+
132
+ # Agar 'Daemon' ya 'Java' ka error hai to Modernizer chalao
133
+ logs = result.stderr
134
+ if "Daemon" in logs or "Java" in logs or "Minimum supported Gradle" in logs:
135
+ force_upgrade_engine(project_root, status_box)
136
+
137
+ status_box.write("πŸ”„ Attempt 2: Rebuilding with NEW Engine...")
138
+ result = subprocess.run(cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
139
+
140
+ if result.returncode == 0:
141
+ success = True
142
+ else:
143
+ # 4. STILL FAILING -> USE AI FOR CODE ERRORS -> ATTEMPT 3
144
+ status_box.write("❌ Attempt 2 Failed. Now checking Code Errors with AI...")
145
+
146
+ logs = result.stderr
147
+ # Find broken file from logs
148
+ match = re.search(r'(/[\w/-]+\.(java|kt|xml|gradle)):(\d+):', logs)
149
+ if match:
150
+ broken_file = match.group(1)
151
+ # Fix path
152
+ if not os.path.exists(broken_file):
153
+ for r, d, f in os.walk(project_root):
154
+ if os.path.basename(broken_file) in f:
155
+ broken_file = os.path.join(r, os.path.basename(broken_file))
156
+ break
157
+
158
+ if os.path.exists(broken_file):
159
+ with open(broken_file, 'r') as f: code = f.read()
160
+ status_box.write(f"πŸ€– AI Fixing: {os.path.basename(broken_file)}")
161
+
162
+ prompt = "Fix this compile error strictly. Return only code."
163
+ msg = f"Error: {logs[-1000:]}\n\nCode:\n{code}"
164
+ ok, fixed_code = ask_claude(prompt, msg)
165
+
166
+ if ok:
167
+ clean_code = fixed_code.replace("```java","").replace("```","").strip()
168
+ with open(broken_file, 'w') as f: f.write(clean_code)
169
+ status_box.write("βœ… Code Fixed. Final Retry...")
170
+
171
+ result = subprocess.run(cmd, cwd=project_root, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
172
+ if result.returncode == 0: success = True
173
+
174
+ # 5. FINAL RESULT
175
+ if success:
176
+ status_box.update(label="βœ… Build Successful! Signing...", state="complete")
177
 
178
+ # Find APK
179
+ target_apk = None
180
  for root, dirs, files in os.walk(project_root):
181
  for file in files:
182
  if file.endswith(".apk") and "release" in file:
183
+ target_apk = os.path.join(root, file)
184
  break
185
 
186
+ if target_apk:
187
  keystore = generate_keystore()
188
+ signed = "Auto_Fixed_App.apk"
189
+ subprocess.run(["zipalign", "-v", "-p", "4", target_apk, "aligned.apk"], stdout=subprocess.DEVNULL)
190
+ subprocess.run(["apksigner", "sign", "--ks", keystore, "--ks-pass", "pass:android", "--out", signed, "aligned.apk"])
 
 
 
 
 
 
191
 
192
+ with open(signed, "rb") as f:
193
+ st.download_button("⬇️ Download 100% Working APK", f, file_name=signed)
 
 
 
194
  else:
195
+ status_box.update(label="❌ Fatal Error", state="error")
196
+ st.error("System could not auto-fix this project.")
197
+ st.text_area("Last Logs", result.stderr[-2000:], height=300)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  if os.path.exists("uploaded.zip"): os.remove("uploaded.zip")