Hiren122 commited on
Commit
cbed94a
·
verified ·
1 Parent(s): 4704976

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +211 -0
app.py ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, Response, jsonify
2
+ import requests
3
+ import json
4
+ import uuid
5
+ import time
6
+ import os
7
+ import re
8
+ import base64
9
+ import mimetypes
10
+ import random
11
+ from datetime import datetime, timedelta
12
+
13
+ app = Flask(__name__)
14
+
15
+ # ================= CONFIGURATION =================
16
+ COGNIX_BASE_URL = "https://www.cognixai.co"
17
+ DEFAULT_SESSION_ID = "f351d7e7-a0ba-4888-86a4-76aab9a7a661"
18
+
19
+ # Development Users Plan - 1 Month Validity
20
+ PLAN_NAME = "Development Users Plan"
21
+ # Set expiration to 1 month from now (current date: 2026-02-13)
22
+ # Expiration: 2026-03-13
23
+ EXPIRATION_DATE = datetime(2026, 3, 13)
24
+
25
+ # API Keys with "sk-rudraksh" like prefixes
26
+ # Format: { "api_key": { "name": "...", "expiry": datetime } }
27
+ AUTHORIZED_KEYS = {
28
+ "sk-rudraksh": {"name": "Rudraksh"},
29
+ "sk-fardin-aslam": {"name": "Fardin Aslam"},
30
+ "sk-at41rv": {"name": "At41rv"},
31
+ "sk-wivodetok": {"name": "Wivodetok"},
32
+ "sk-fx-uk": {"name": "Fx uk"},
33
+ "sk-g-man": {"name": "G-Man"},
34
+ "sk-aakash-singh": {"name": "Aakash Singh"},
35
+ "sk-redollaz": {"name": "Redollaz"}
36
+ }
37
+
38
+ # Rate Limit Settings
39
+ RPM_LIMIT = 60
40
+ RPD_LIMITS = {
41
+ "claude opus-4.6": 20,
42
+ "3-pro": 20,
43
+ "gpt-5.3 codex": 20
44
+ }
45
+
46
+ # Tracking Data (In-memory)
47
+ rpm_tracking = {}
48
+ rpd_tracking = {}
49
+
50
+ # Use USER'S provided cookies from cognix_proxy.py/demo.py
51
+ COGNIX_COOKIES = [
52
+ "ext_name=ojplmecpdpgccookcobabopnaifgidhf; cf_clearance=j_nYaeNI0RwDRG1Qyd.bRf0R5YCGgIgAEzEgaQEjCCU-1770908625-1.2.1.1-RMchxpAE5hSG0Xl4XY3BShfT4aXGHCqNiBxN6iyTGkrv8azqzeTMuCOKZZ1lHjBZ5kdtj4.F_hmpP2legrsaaSe16gMqtqa5.FrM7yNuGQczvf1ep45loNu5MhI151HAk0k9T5UKDHdHXHcidlUt_ajlE64FUTSj26Rf6WwTg55n.xeliVOzxYygojzifx7hywAXmXMAqCpKADeDnSuEWqahc2_zDnpJxwy4444gh_o; __Secure-better-auth.state=FOj7ymeub1GeD3s4fiEbm9Hrd-hE0slR.oM0kHle4Je9FhUDPisXmPSHQvH4nkqldTe3kRBrTHJk%3D; __Secure-better-auth.session_token=5npdnyCa90buJBq2qW2wopL6nC3HjO4R.5v3gNhODuU7F0hbVXAJ%2BPFgMPsCPM0j8J%2BHk%2FrqsNdc%3D; __Secure-better-auth.session_data=eyJzZXNzaW9uIjp7InNlc3Npb24iOnsiZXhwaXJlc0F0IjoiMjAyNi0wMi0xOVQxNTowMzo0OC44MjNaIiwidG9rZW4iOiI1bnBkbnlDYTkwYnVKQnEycVcyd29wTDZuQzNIak80UiIsImNyZWF0ZWRBdCI6IjIwMjYtMDItMTJUMTU6MDM6NDguODIzWiIsInVwZGF0ZWRBdCI6IjIwMjYtMDItMTJUMTU6MDM6NDguODIzWiIsImlwQWRkcmVzcyI6IjE2Mi4xNTguNjMuMjQwIiwidXNlckFnZW50IjoiTW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzE0NC4wLjAuMCBTYWZhcmkvNTM3LjM2IiwidXNlcklkIjoiODM0YWZkYWEtOWFiYy00OGNkLTkwMzQtNzU4YTMzY2M3NTUxIiwiaW1wZXJzb25hdGVkQnkiOm51bGwsImlkIjoiNzk5ODJjMWMtZjQwOC00ODYyLWI0ZGEtMzI2ZTZkZmQ1NWU0In0sInVzZXIiOnsibmFtZSI6IkhpcmVuIEFoYWxhd2F0IiwiZW1haWwiOiJnaGc2NDI3MkBnbWFpbC5jb20iLCJlbWFpbFZlcmlmaWVkIjp0cnVlLCJpbWFnZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hL0FDZzhvY0ozTVo3MjdKYzlJU244bERCcUplS2MyU0MxYXV5djFlbkV1bWxuTDhmR01CaEp0OGNUPXM5Ni1jIiwiY3JlYXRlZEF0IjoiMjAyNi0wMS0yNlQwNTo0NzoyNC43NzNaIiwidXBkYXRlZEF0IjoiMjAyNi0wMS0yNlQwNTo0NzoyNC43NzNaIiwicm9sZSI6ImVkaXRvciIsImJhbm5lZCI6ZmFsc2UsImJhblJlYXNvbiI6bnVsbCwiYmFuRXhwaXJlcyI6bnVsbCwiaWQiOiI4MzRhZmRhYS05YWJjLTQ4Y2QtOTAzNC03NThhMzNjYzc1NTEifX0sImV4cGlyZXNBdCI6MTc3MDkxMjIyODgzNCwic2lnbmF0dXJlIjoidXpNQWloYU9Sbk1QSnZ1V2VCMDdtOGcxSHliYVVrT2hLU05PS3JKSE96byJ9"
53
+ ]
54
+
55
+ def get_headers():
56
+ return {
57
+ "accept": "*/*",
58
+ "accept-language": "en-IN,en;q=0.9",
59
+ "cookie": random.choice(COGNIX_COOKIES),
60
+ "origin": "https://www.cognixai.co",
61
+ "referer": f"https://www.cognixai.co/chat/{DEFAULT_SESSION_ID}",
62
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36"
63
+ }
64
+
65
+ # ================= AUTH & RATE LIMITING =================
66
+
67
+ @app.before_request
68
+ def validate_access():
69
+ if request.path == "/" or not request.path.startswith("/v1/"):
70
+ return
71
+
72
+ # 1. Date Check (1 Month Validity)
73
+ if datetime.now() > EXPIRATION_DATE:
74
+ return jsonify({
75
+ "error": "Plan Expired",
76
+ "message": "plan expired contact Admin",
77
+ "code": 402
78
+ }), 402
79
+
80
+ auth_header = request.headers.get("Authorization", "")
81
+ if not auth_header.startswith("Bearer "):
82
+ return jsonify({"error": "Unauthorized", "message": "Missing API key"}), 401
83
+
84
+ api_key = auth_header.replace("Bearer ", "").strip().lower()
85
+ if api_key not in AUTHORIZED_KEYS:
86
+ return jsonify({"error": "Unauthorized", "message": "Invalid API key for Development Plan"}), 401
87
+
88
+ now = time.time()
89
+ today = datetime.now().strftime("%Y-%m-%d")
90
+
91
+ # 2. RPM Check (60 RPM)
92
+ if api_key not in rpm_tracking:
93
+ rpm_tracking[api_key] = []
94
+ rpm_tracking[api_key] = [t for t in rpm_tracking[api_key] if now - t < 60]
95
+ if len(rpm_tracking[api_key]) >= RPM_LIMIT:
96
+ return jsonify({"error": "Rate limit exceeded", "message": f"Limit: {RPM_LIMIT} RPM"}), 429
97
+ rpm_tracking[api_key].append(now)
98
+
99
+ # 3. RPD Check for restricted models
100
+ if request.method == "POST" and (request.path.endswith("/chat/completions") or request.path.endswith("/messages")):
101
+ try:
102
+ body = request.get_json(silent=True) or {}
103
+ model_id = body.get("model", "").lower()
104
+
105
+ matched_model = None
106
+ for key in RPD_LIMITS:
107
+ if key in model_id:
108
+ matched_model = key
109
+ break
110
+
111
+ # Restricted models check
112
+ if matched_model:
113
+ if api_key not in rpd_tracking:
114
+ rpd_tracking[api_key] = {}
115
+ if matched_model not in rpd_tracking[api_key]:
116
+ rpd_tracking[api_key][matched_model] = {}
117
+ if today not in rpd_tracking[api_key][matched_model]:
118
+ rpd_tracking[api_key][matched_model][today] = 0
119
+
120
+ if rpd_tracking[api_key][matched_model][today] >= RPD_LIMITS[matched_model]:
121
+ return jsonify({
122
+ "error": "Daily quota reached",
123
+ "message": f"Daily limit for '{matched_model}' reached (20 RPD)."
124
+ }), 403
125
+
126
+ rpd_tracking[api_key][matched_model][today] += 1
127
+ # UNLIMITED for all other models
128
+ except Exception as e:
129
+ print(f"Error checking limits: {e}")
130
+
131
+ # ================= CORE LOGIC =================
132
+
133
+ def parse_cognix_stream_chunk(line):
134
+ if not line.strip(): return None, "content"
135
+ if line.startswith("data: "): line = line[6:]
136
+ if line.strip() == "[DONE]": return None, "stop"
137
+ try:
138
+ data = json.loads(line)
139
+ content = data.get('text') or data.get('content')
140
+ if not content:
141
+ delta = data.get('delta')
142
+ if isinstance(delta, str): content = delta
143
+ elif isinstance(delta, dict): content = delta.get('text') or delta.get('content', '')
144
+ return content or "", "content"
145
+ except:
146
+ if line.strip().startswith('{') and line.strip().endswith('}'): return "", "content"
147
+ return line, "content"
148
+
149
+ @app.route('/v1/chat/completions', methods=['POST'])
150
+ def chat_completions():
151
+ d = request.json
152
+ model = d.get('model', 'anthropic/Claude Opus 4.6')
153
+ messages = d.get('messages', [])
154
+ system_prompt = next((m.get('content', '') for m in messages if m.get('role') == 'system'), "")
155
+ filtered = [m for m in messages if m.get('role') != 'system']
156
+
157
+ prov, ver = model.split('/', 1) if '/' in model else ("anthropic", model)
158
+
159
+ payload = {
160
+ "id": str(uuid.uuid4()),
161
+ "chatModel": {"provider": prov, "model": ver},
162
+ "message": {"role": "user", "parts": [{"type": "text", "text": f"[System]\n{system_prompt}\n\n[Message]\n{filtered[-1].get('content', '') if filtered else ''}"}], "id": str(uuid.uuid4())},
163
+ "allowedAppDefaultToolkit": ["webSearch"],
164
+ "attachments": []
165
+ }
166
+
167
+ if d.get('stream'):
168
+ def gen():
169
+ cid = f"chatcmpl-{uuid.uuid4().hex[:24]}"
170
+ yield f"data: {json.dumps({'id': cid, 'object': 'chat.completion.chunk', 'choices': [{'delta': {'role': 'assistant'}}]})}\n\n"
171
+ with requests.post(f"{COGNIX_BASE_URL}/api/chat", json=payload, headers=get_headers(), stream=True) as r:
172
+ for line in r.iter_lines(decode_unicode=True):
173
+ if not line: continue
174
+ cont, pty = parse_cognix_stream_chunk(line)
175
+ if pty == "stop": break
176
+ if cont:
177
+ yield f"data: {json.dumps({'id': cid, 'object': 'chat.completion.chunk', 'choices': [{'delta': {'content': cont}}]})}\n\n"
178
+ yield "data: [DONE]\n\n"
179
+ return Response(gen(), content_type='text/event-stream')
180
+
181
+ r = requests.post(f"{COGNIX_BASE_URL}/api/chat", json=payload, headers=get_headers())
182
+ full_text = "".join([parse_cognix_stream_chunk(l)[0] or "" for l in r.text.strip().split('\n')])
183
+ return jsonify({"id": str(uuid.uuid4()), "object": "chat.completion", "choices": [{"message": {"role": "assistant", "content": full_text}, "finish_reason": "stop"}]})
184
+
185
+ @app.route('/v1/models', methods=['GET'])
186
+ def list_models():
187
+ return jsonify({
188
+ "object": "list",
189
+ "data": [
190
+ {"id": "claude opus-4.6", "object": "model"},
191
+ {"id": "3-pro", "object": "model"},
192
+ {"id": "gpt-5.3 codex", "object": "model"},
193
+ {"id": "gpt-4o", "object": "model"},
194
+ {"id": "claude-3-5-sonnet", "object": "model"}
195
+ ]
196
+ })
197
+
198
+ @app.route('/')
199
+ def index():
200
+ return jsonify({
201
+ "status": "online",
202
+ "plan": PLAN_NAME,
203
+ "expires_on": EXPIRATION_DATE.strftime("%Y-%m-%d"),
204
+ "rpm": RPM_LIMIT,
205
+ "rpd_restricted_models": list(RPD_LIMITS.keys()),
206
+ "other_models": "Unlimited"
207
+ })
208
+
209
+ if __name__ == '__main__':
210
+ print(f"🚀 {PLAN_NAME} Proxy starting on http://localhost:7860")
211
+ app.run(host='0.0.0.0', port=7860, debug=True)