rairo commited on
Commit
ac8b6fd
·
verified ·
1 Parent(s): 0dbcbd3

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +278 -0
main.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import json
4
+ from datetime import datetime
5
+ from flask import Flask, request, jsonify
6
+ from flask_cors import CORS
7
+ import google.generativeai as genai
8
+ import firebase_admin
9
+ from firebase_admin import credentials, db, storage, auth
10
+
11
+ # Initialize Flask app and CORS
12
+ app = Flask(__name__)
13
+ CORS(app)
14
+
15
+ # Firebase initialization
16
+ cred = credentials.Certificate('sozo-daac1-firebase-adminsdk-fbsvc-b5d5c23b6d.json')
17
+ firebase_admin.initialize_app(cred, {
18
+ 'databaseURL': 'https://sozo-daac1-default-rtdb.firebaseio.com',
19
+ 'storageBucket': 'sozo-daac1.firebasestorage.app'
20
+ })
21
+ bucket = storage.bucket()
22
+
23
+ # Gemini API initialization
24
+ api_key = os.environ['Gemini']
25
+ def configure_gemini():
26
+ genai.configure(api_key=api_key)
27
+ return genai.GenerativeModel('gemini-2.0-flash-thinking-exp')
28
+
29
+ # Helper functions
30
+ def verify_token(token):
31
+ try:
32
+ decoded_token = auth.verify_id_token(token)
33
+ return decoded_token['uid']
34
+ except Exception as e:
35
+ return None
36
+
37
+ def verify_admin(auth_header):
38
+ if not auth_header or not auth_header.startswith('Bearer '):
39
+ raise ValueError('Invalid token')
40
+ token = auth_header.split(' ')[1]
41
+ uid = verify_token(token)
42
+ if not uid:
43
+ raise PermissionError('Invalid user')
44
+ user_ref = db.reference(f'users/{uid}')
45
+ user_data = user_ref.get()
46
+ if not user_data or not user_data.get('is_admin', False):
47
+ raise PermissionError('Admin access required')
48
+ return uid
49
+
50
+ # ---------- Dummy Admin Creation on Startup ----------
51
+ def create_dummy_admin():
52
+ admin_email = "rairo@test.com"
53
+ admin_password = "123456"
54
+ try:
55
+ # Try to get the user if it exists
56
+ admin_user = auth.get_user_by_email(admin_email)
57
+ except firebase_admin.auth.UserNotFoundError:
58
+ # Create the dummy admin if not found
59
+ admin_user = auth.create_user(email=admin_email, password=admin_password)
60
+ # Set or update admin record in the database
61
+ admin_ref = db.reference(f'users/{admin_user.uid}')
62
+ admin_data = admin_ref.get() or {}
63
+ if not admin_data.get('is_admin', False):
64
+ admin_ref.set({
65
+ 'email': admin_email,
66
+ 'credits': 9999, # Optionally, give admin lots of credits
67
+ 'is_admin': True,
68
+ 'created_at': datetime.utcnow().isoformat()
69
+ })
70
+ print(f"Dummy admin ready: {admin_email}")
71
+
72
+ # ---------- Authentication Endpoints ----------
73
+
74
+ @app.route('/api/auth/signup', methods=['POST'])
75
+ def signup():
76
+ try:
77
+ data = request.get_json()
78
+ email = data.get('email')
79
+ password = data.get('password')
80
+ if not email or not password:
81
+ return jsonify({'error': 'Email and password are required'}), 400
82
+
83
+ # Create user in Firebase Auth
84
+ user = auth.create_user(email=email, password=password)
85
+ # Set initial user data in the realtime database with 3 starting credits
86
+ user_ref = db.reference(f'users/{user.uid}')
87
+ user_data = {
88
+ 'email': email,
89
+ 'credits': 3,
90
+ 'is_admin': False,
91
+ 'created_at': datetime.utcnow().isoformat()
92
+ }
93
+ user_ref.set(user_data)
94
+ return jsonify({
95
+ 'success': True,
96
+ 'user': {
97
+ 'uid': user.uid,
98
+ **user_data
99
+ }
100
+ }), 201
101
+ except Exception as e:
102
+ return jsonify({'error': str(e)}), 400
103
+
104
+ # ---------- User Profile ----------
105
+
106
+ @app.route('/api/user/profile', methods=['GET'])
107
+ def get_user_profile():
108
+ try:
109
+ auth_header = request.headers.get('Authorization', '')
110
+ if not auth_header.startswith('Bearer '):
111
+ return jsonify({'error': 'Authorization header missing or malformed'}), 401
112
+ token = auth_header.split(' ')[1]
113
+ uid = verify_token(token)
114
+ if not uid:
115
+ return jsonify({'error': 'Invalid token'}), 401
116
+ user_record = auth.get_user(uid)
117
+ user_data = db.reference(f'users/{uid}').get()
118
+ return jsonify({
119
+ 'uid': uid,
120
+ 'email': user_record.email,
121
+ 'credits': user_data.get('credits', 0),
122
+ 'is_admin': user_data.get('is_admin', False),
123
+ 'created_at': user_data.get('created_at')
124
+ })
125
+ except Exception as e:
126
+ return jsonify({'error': str(e)}), 500
127
+
128
+ # ---------- Video Generation Endpoint ----------
129
+
130
+ @app.route('/api/video/generate', methods=['POST'])
131
+ def generate_video():
132
+ try:
133
+ auth_header = request.headers.get('Authorization', '')
134
+ if not auth_header.startswith('Bearer '):
135
+ return jsonify({'error': 'Authorization header missing or malformed'}), 401
136
+ token = auth_header.split(' ')[1]
137
+ uid = verify_token(token)
138
+ if not uid:
139
+ return jsonify({'error': 'Invalid token'}), 401
140
+
141
+ # Get user data and check credits
142
+ user_ref = db.reference(f'users/{uid}')
143
+ user_data = user_ref.get()
144
+ if not user_data or user_data.get('credits', 0) < 1:
145
+ return jsonify({'error': 'Insufficient credits'}), 400
146
+
147
+ # Deduct one credit
148
+ new_credits = user_data.get('credits', 0) - 1
149
+ user_ref.update({'credits': new_credits})
150
+
151
+ # Get prompt and generate video (simulation using Gemini)
152
+ req_data = request.get_json()
153
+ prompt = req_data.get('prompt', '')
154
+ if not prompt:
155
+ return jsonify({'error': 'Prompt is required'}), 400
156
+
157
+ model = configure_gemini()
158
+ # Call to Gemini to generate video content (this is a simulation)
159
+ response = model.generate(prompt=prompt)
160
+ # For demonstration, we assume the response contains a 'result' field
161
+ generated_video = response.result if hasattr(response, 'result') else "Video content generated based on prompt."
162
+
163
+ return jsonify({
164
+ 'success': True,
165
+ 'video': generated_video,
166
+ 'remaining_credits': new_credits
167
+ })
168
+ except Exception as e:
169
+ return jsonify({'error': str(e)}), 500
170
+
171
+ # ---------- Credit Request Endpoints ----------
172
+
173
+ @app.route('/api/user/request-credits', methods=['POST'])
174
+ def request_credits():
175
+ try:
176
+ auth_header = request.headers.get('Authorization', '')
177
+ if not auth_header.startswith('Bearer '):
178
+ return jsonify({'error': 'Authorization header missing or malformed'}), 401
179
+ token = auth_header.split(' ')[1]
180
+ uid = verify_token(token)
181
+ if not uid:
182
+ return jsonify({'error': 'Invalid token'}), 401
183
+
184
+ data = request.get_json()
185
+ requested_credits = data.get('requested_credits')
186
+ if requested_credits is None:
187
+ return jsonify({'error': 'requested_credits is required'}), 400
188
+
189
+ # Create a credit request entry
190
+ credit_request_ref = db.reference('credit_requests').push()
191
+ credit_request_ref.set({
192
+ 'user_id': uid,
193
+ 'requested_credits': requested_credits,
194
+ 'status': 'pending',
195
+ 'requested_at': datetime.utcnow().isoformat()
196
+ })
197
+ return jsonify({'success': True, 'request_id': credit_request_ref.key})
198
+ except Exception as e:
199
+ return jsonify({'error': str(e)}), 500
200
+
201
+ # ---------- Admin Endpoints for Credit Requests ----------
202
+
203
+ @app.route('/api/admin/credit_requests', methods=['GET'])
204
+ def list_credit_requests():
205
+ try:
206
+ verify_admin(request.headers.get('Authorization', ''))
207
+ requests_ref = db.reference('credit_requests')
208
+ credit_requests = requests_ref.get() or {}
209
+ # Convert dict to list with id
210
+ requests_list = [{'id': req_id, **data} for req_id, data in credit_requests.items()]
211
+ return jsonify({'credit_requests': requests_list})
212
+ except Exception as e:
213
+ return jsonify({'error': str(e)}), 500
214
+
215
+ @app.route('/api/admin/credit_requests/<string:request_id>', methods=['PUT'])
216
+ def process_credit_request(request_id):
217
+ try:
218
+ admin_uid = verify_admin(request.headers.get('Authorization', ''))
219
+ req_ref = db.reference(f'credit_requests/{request_id}')
220
+ req_data = req_ref.get()
221
+ if not req_data:
222
+ return jsonify({'error': 'Credit request not found'}), 404
223
+
224
+ data = request.get_json()
225
+ decision = data.get('decision')
226
+ if decision not in ['approved', 'declined']:
227
+ return jsonify({'error': 'decision must be "approved" or "declined"'}), 400
228
+
229
+ # If approved, add credits to the user
230
+ if decision == 'approved':
231
+ user_ref = db.reference(f'users/{req_data["user_id"]}')
232
+ user_data = user_ref.get()
233
+ if not user_data:
234
+ return jsonify({'error': 'User not found'}), 404
235
+ new_total = user_data.get('credits', 0) + float(req_data.get('requested_credits', 0))
236
+ user_ref.update({'credits': new_total})
237
+ req_ref.update({
238
+ 'status': 'approved',
239
+ 'processed_by': admin_uid,
240
+ 'processed_at': datetime.utcnow().isoformat()
241
+ })
242
+ return jsonify({'success': True, 'new_user_credits': new_total})
243
+ else:
244
+ req_ref.update({
245
+ 'status': 'declined',
246
+ 'processed_by': admin_uid,
247
+ 'processed_at': datetime.utcnow().isoformat()
248
+ })
249
+ return jsonify({'success': True, 'message': 'Credit request declined'})
250
+ except Exception as e:
251
+ return jsonify({'error': str(e)}), 500
252
+
253
+ # ---------- Admin Endpoint to Directly Update Credits ----------
254
+ @app.route('/api/admin/users/<string:uid>/credits', methods=['PUT'])
255
+ def admin_update_credits(uid):
256
+ try:
257
+ verify_admin(request.headers.get('Authorization', ''))
258
+ data = request.get_json()
259
+ add_credits = data.get('add_credits')
260
+ if add_credits is None:
261
+ return jsonify({'error': 'add_credits is required'}), 400
262
+
263
+ user_ref = db.reference(f'users/{uid}')
264
+ user_data = user_ref.get()
265
+ if not user_data:
266
+ return jsonify({'error': 'User not found'}), 404
267
+
268
+ new_total = user_data.get('credits', 0) + float(add_credits)
269
+ user_ref.update({'credits': new_total})
270
+ return jsonify({'success': True, 'new_total_credits': new_total})
271
+ except Exception as e:
272
+ return jsonify({'error': str(e)}), 500
273
+
274
+ # ---------- Main ----------
275
+ if __name__ == '__main__':
276
+ # Create dummy admin account if it doesn't exist
277
+ create_dummy_admin()
278
+ app.run(debug=True, host="0.0.0.0", port=7860)