diff --git a/daoip-5/scripts/API/README.md b/daoip-5/scripts/API/README.md
index ee8f384..1af6df7 100644
--- a/daoip-5/scripts/API/README.md
+++ b/daoip-5/scripts/API/README.md
@@ -16,7 +16,7 @@ GitHub repository: [DAOIP-5 JSON files](https://github.com/opensource-observer/o
1. **Clone the repository**:
```bash
git clone https://github.com/opensource-observer/oss-funding
- cd oss-funding/daoip-5
+ cd oss-funding/daoip-5/scripts/API
```
2. **Install dependencies**:
diff --git a/daoip-5/scripts/API/run.py b/daoip-5/scripts/API/run.py
index 93921ef..d0b9146 100644
--- a/daoip-5/scripts/API/run.py
+++ b/daoip-5/scripts/API/run.py
@@ -1,10 +1,12 @@
from flask import Flask, jsonify, abort, send_file
+import json
import os
+import logging
app = Flask(__name__)
# Path to the directory where the JSON files are stored (relative to the repository)
-BASE_PATH = '../../json'
+BASE_PATH = '../../json'
def get_grant_systems():
@@ -37,7 +39,7 @@ def display_help():
DAOIP-5 Datalake API Documentation
Repository: DAOIP-5 JSON Repository
-
+
Endpoint: /
Method: GET
@@ -45,7 +47,7 @@ def display_help():
Parameters: None
Response: A JSON array of grant system names.
-
+
Endpoint: /<grant_system>
Method: GET
@@ -60,7 +62,7 @@ def display_help():
Response: A JSON array of JSON file names (grant pools) in the specified folder.
-
+
Endpoint: /<grant_system>/<filename>.json
Method: GET
@@ -76,7 +78,7 @@ def display_help():
Response: The JSON content of the specified file.
-
+
Endpoint: /help
Method: GET
@@ -151,7 +153,95 @@ def proxy_json_file(grant_system, filename):
except Exception as e:
return jsonify({"error": str(e)}), 500
+@app.route('/search/', defaults={'project_name': ''})
+@app.route('/search/
')
+def search_project(project_name):
+ """
+ Endpoint to search for all applications matching a project name across all grant systems.
+ If no project name or empty string is provided, returns all applications.
+
+ Args:
+ project_name (str): The name of the project to search for (optional)
+ Returns:
+ JSON object containing matching applications and result count
+ """
+ try:
+ results = []
+ # Use existing function to get grant systems
+ grant_systems = get_grant_systems()
+
+ for system in grant_systems:
+ # Use existing function to get grant pools
+ files = get_grant_pools(system)
+ applications_files = [f for f in files if 'applications' in f]
+
+ for file in applications_files:
+ try:
+ # Use existing function to get file path and Flask's send_file
+ file_path = get_file_path(system, file)
+ with open(file_path, 'r') as f:
+ data = json.load(f)
+
+ if not isinstance(data, dict) or 'grant_pools' not in data:
+ continue
+
+ for pool in data['grant_pools']:
+ if not isinstance(pool, dict) or 'applications' not in pool:
+ continue
+
+ for app in pool['applications']:
+ # If project_name is empty or None, include all applications
+ if not project_name:
+ result = {
+ **app,
+ 'metadata': {
+ 'grantSystem': system,
+ 'sourceFile': file,
+ 'grantPoolId': app.get('grantPoolId', 'unknown'),
+ 'grantPoolName': app.get('grantPoolName', 'unknown')
+ }
+ }
+ results.append(result)
+ else:
+ # More robust project name matching for specific search
+ project_name_match = str(app.get('projectName', '')).lower()
+ project_id_match = str(app.get('projectId', '')).lower()
+ search_term = project_name.lower()
+
+ if search_term in project_name_match or search_term in project_id_match:
+ result = {
+ **app,
+ 'metadata': {
+ 'grantSystem': system,
+ 'sourceFile': file,
+ 'grantPoolId': app.get('grantPoolId', 'unknown'),
+ 'grantPoolName': app.get('grantPoolName', 'unknown')
+ }
+ }
+ results.append(result)
+
+ except (json.JSONDecodeError, Exception) as e:
+ # Log the error but continue processing other files
+ logging.error(f"Error processing {file} in {system}: {str(e)}")
+ continue
+
+ search_description = "all applications" if not project_name else f"applications for project: {project_name}"
+ response = {
+ "message": f"Found {len(results)} {search_description}",
+ "count": len(results),
+ "results": results
+ }
+ return jsonify(response), 200
+
+ except Exception as e:
+ error_description = "all applications" if not project_name else f"project: {project_name}"
+ logging.error(f"Search failed for {error_description}: {str(e)}")
+ return jsonify({
+ "error": f"Search failed for {error_description}: {str(e)}",
+ "status": "error"
+ }), 500
+
if __name__ == '__main__':
- port = int(os.environ.get("PORT", 5000))
+ port = int(os.environ.get("PORT", 3000))
app.run(debug=True, host='0.0.0.0', port=port)