Skip to content

Commit bcfb12b

Browse files
feat: native api for fetching plugins
1 parent e04f4d2 commit bcfb12b

3 files changed

Lines changed: 190 additions & 2 deletions

File tree

src/plugins/auth/plugin.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<framework src="androidx.security:security-crypto:1.1.0" />
1414

1515
<source-file src="src/android/Authenticator.java" target-dir="src/com/foxdebug/acode/rk/auth" />
16+
<source-file src="src/android/PluginRetriever.java" target-dir="src/com/foxdebug/acode/rk/auth" />
1617
<source-file src="src/android/EncryptedPreferenceManager.java" target-dir="src/com/foxdebug/acode/rk/auth" />
1718

1819

src/plugins/auth/src/android/Authenticator.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import java.util.Scanner;
1111

1212
public class Authenticator extends CordovaPlugin {
13-
// Standard practice: use a TAG for easy filtering in Logcat
1413
private static final String TAG = "AcodeAuth";
1514
private static final String PREFS_FILENAME = "acode_auth_secure";
1615
private static final String KEY_TOKEN = "auth_token";
@@ -42,6 +41,22 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
4241
prefManager.setString(KEY_TOKEN, token);
4342
callbackContext.success();
4443
return true;
44+
case "retrieveFilteredPlugins":
45+
try {
46+
JSONObject filterState = args.length() > 0 ? args.getJSONObject(0) : null;
47+
final JSONObject finalFilterState = filterState;
48+
cordova.getThreadPool().execute(() -> {
49+
try {
50+
PluginRetriever.retrieveFilteredPlugins(prefManager.getString(KEY_TOKEN, null), finalFilterState, callbackContext);
51+
} catch (Exception e) {
52+
Log.e(TAG, "retrieveFilteredPlugins error: " + e.getMessage(), e);
53+
callbackContext.error("Error: " + e.getMessage());
54+
}
55+
});
56+
} catch (JSONException e) {
57+
callbackContext.error("Invalid filter JSON: " + e.getMessage());
58+
}
59+
return true;
4560
default:
4661
Log.w(TAG, "Attempted to call unknown action: " + action);
4762
return false;
@@ -114,7 +129,7 @@ private String validateToken(String token) {
114129
HttpURLConnection conn = null;
115130
try {
116131
Log.d(TAG, "Network Request: Connecting to https://acode.app/api/login");
117-
URL url = new URL("https://acode.app/api/login"); // Changed from /api to /api/login
132+
URL url = new URL("https://acode.app/api/login");
118133
conn = (HttpURLConnection) url.openConnection();
119134
conn.setRequestProperty("x-auth-token", token);
120135
conn.setRequestMethod("GET");
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package com.foxdebug.acode.rk.auth;
2+
3+
import android.util.Log;
4+
import org.apache.cordova.CallbackContext;
5+
import org.json.JSONArray;
6+
import org.json.JSONException;
7+
import org.json.JSONObject;
8+
import java.net.HttpURLConnection;
9+
import java.net.URL;
10+
import java.util.Scanner;
11+
12+
public class PluginRetriever {
13+
private static final String TAG = "AcodePluginRetriever";
14+
private static final int LIMIT = 20;
15+
private static final String API_BASE = "https://acode.app/api";
16+
17+
public static void retrieveFilteredPlugins(String token,JSONObject filterState, CallbackContext callbackContext) throws Exception {
18+
JSONObject result = new JSONObject();
19+
20+
if (filterState == null) {
21+
result.put("items", new JSONArray());
22+
result.put("hasMore", false);
23+
callbackContext.success(result);
24+
return;
25+
}
26+
27+
String type = filterState.optString("type", "");
28+
29+
if ("orderBy".equals(type)) {
30+
int page = filterState.optInt("nextPage", 1);
31+
String value = filterState.optString("value", "");
32+
String url;
33+
34+
if ("top_rated".equals(value)) {
35+
url = API_BASE + "/plugins?explore=random&page=" + page + "&limit=" + LIMIT;
36+
} else {
37+
url = API_BASE + "/plugin?orderBy=" + value + "&page=" + page + "&limit=" + LIMIT;
38+
}
39+
40+
JSONArray items = fetchJsonArray(token,url);
41+
if (items == null) items = new JSONArray();
42+
43+
filterState.put("nextPage", page + 1);
44+
result.put("items", items);
45+
result.put("hasMore", items.length() == LIMIT);
46+
callbackContext.success(result);
47+
return;
48+
}
49+
50+
JSONArray buffer = filterState.optJSONArray("buffer");
51+
if (buffer == null) {
52+
buffer = new JSONArray();
53+
filterState.put("buffer", buffer);
54+
}
55+
56+
boolean hasMoreSource = !filterState.has("hasMoreSource") || filterState.getBoolean("hasMoreSource");
57+
int nextPage = filterState.optInt("nextPage", 1);
58+
if (!filterState.has("nextPage")) {
59+
filterState.put("nextPage", 1);
60+
}
61+
62+
JSONArray items = new JSONArray();
63+
64+
while (items.length() < LIMIT) {
65+
if (buffer.length() > 0) {
66+
items.put(buffer.get(0));
67+
JSONArray newBuffer = new JSONArray();
68+
for (int i = 1; i < buffer.length(); i++) newBuffer.put(buffer.get(i));
69+
buffer = newBuffer;
70+
filterState.put("buffer", buffer);
71+
continue;
72+
}
73+
74+
if (!hasMoreSource) break;
75+
76+
String url = API_BASE + "/plugins?page=" + nextPage + "&limit=" + LIMIT;
77+
JSONArray data = fetchJsonArray(token,url);
78+
nextPage++;
79+
filterState.put("nextPage", nextPage);
80+
81+
if (data == null || data.length() == 0) {
82+
hasMoreSource = false;
83+
filterState.put("hasMoreSource", false);
84+
break;
85+
}
86+
87+
if (data.length() < LIMIT) {
88+
hasMoreSource = false;
89+
filterState.put("hasMoreSource", false);
90+
}
91+
92+
for (int i = 0; i < data.length(); i++) {
93+
JSONObject plugin = data.getJSONObject(i);
94+
if (matchesFilter(plugin, filterState)) {
95+
buffer.put(plugin);
96+
}
97+
}
98+
filterState.put("buffer", buffer);
99+
}
100+
101+
while (items.length() < LIMIT && buffer.length() > 0) {
102+
items.put(buffer.get(0));
103+
JSONArray newBuffer = new JSONArray();
104+
for (int i = 1; i < buffer.length(); i++) newBuffer.put(buffer.get(i));
105+
buffer = newBuffer;
106+
filterState.put("buffer", buffer);
107+
}
108+
109+
boolean hasMore = (hasMoreSource && filterState.has("nextPage")) || buffer.length() > 0;
110+
111+
result.put("items", items);
112+
result.put("hasMore", hasMore);
113+
callbackContext.success(result);
114+
}
115+
116+
// Change fetchJsonArray signature to accept token
117+
private static JSONArray fetchJsonArray(String urlString, String token) {
118+
HttpURLConnection conn = null;
119+
try {
120+
Log.d(TAG, "Fetching: " + urlString);
121+
URL url = new URL(urlString);
122+
conn = (HttpURLConnection) url.openConnection();
123+
conn.setRequestMethod("GET");
124+
conn.setConnectTimeout(5000);
125+
conn.setReadTimeout(5000);
126+
127+
// Add auth header if token is present
128+
if (token != null && !token.isEmpty()) {
129+
conn.setRequestProperty("x-auth-token", token);
130+
}
131+
132+
int code = conn.getResponseCode();
133+
if (code != 200) {
134+
Log.w(TAG, "Non-200 response (" + code + ") for: " + urlString);
135+
return null;
136+
}
137+
138+
Scanner s = new Scanner(conn.getInputStream(), "UTF-8").useDelimiter("\\A");
139+
String body = s.hasNext() ? s.next() : "[]";
140+
return new JSONArray(body);
141+
} catch (Exception e) {
142+
Log.e(TAG, "fetchJsonArray error: " + e.getMessage(), e);
143+
return null;
144+
} finally {
145+
if (conn != null) conn.disconnect();
146+
}
147+
}
148+
149+
private static boolean matchesFilter(JSONObject plugin, JSONObject filterState) {
150+
try {
151+
String type = filterState.optString("type", "");
152+
String value = filterState.optString("value", "").toLowerCase();
153+
154+
if (value.isEmpty()) return true;
155+
156+
switch (type) {
157+
case "search":
158+
String name = plugin.optString("name", "").toLowerCase();
159+
String desc = plugin.optString("description", "").toLowerCase();
160+
return name.contains(value) || desc.contains(value);
161+
case "author":
162+
String author = plugin.optString("author", "").toLowerCase();
163+
return author.contains(value);
164+
default:
165+
return true;
166+
}
167+
} catch (Exception e) {
168+
Log.e(TAG, "matchesFilter error: " + e.getMessage(), e);
169+
return false;
170+
}
171+
}
172+
}

0 commit comments

Comments
 (0)