hts-ai commited on
Commit
862c6dd
·
verified ·
1 Parent(s): f159c9b

Full Detection

Browse files

il y'a un probléme corrige et active les ia

components/api-status.js CHANGED
@@ -1,3 +1,4 @@
 
1
  class ApiStatus extends HTMLElement {
2
  constructor() {
3
  super();
@@ -11,84 +12,89 @@ class ApiStatus extends HTMLElement {
11
 
12
  async checkApiStatus() {
13
  try {
14
- // Test CoinGecko API
15
- const coingeckoResponse = await fetch('https://api.coingecko.com/api/v3/ping');
16
- const coingeckoStatus = coingeckoResponse.ok;
17
 
 
 
 
 
 
18
  // Test OpenRouter API
19
  const openrouterResponse = await fetch('https://openrouter.ai/api/v1/models', {
20
  headers: {
21
- 'Authorization': `Bearer ${process.env.OPENROUTER_API_KEY}'
 
 
 
22
  });
 
23
  const openrouterStatus = openrouterResponse.ok;
 
24
 
25
- this.shadowRoot.innerHTML = `
26
- <style>
27
- :host {
28
- display: block;
29
- margin: 1rem 0;
30
- }
31
-
32
- .api-status {
33
- display: flex;
34
- align-items: center;
35
- gap: 0.5rem;
36
- }
37
-
38
- .status-dot {
39
- width: 8px;
40
- height: 8px;
41
- border-radius: 50%;
42
- }
43
-
44
- .status-online {
45
- background: #10b981;
46
- animation: pulse 2s infinite;
47
- }
48
-
49
- .status-offline {
50
- background: #ef4444;
51
- }
52
- </style>
53
-
54
- <div class="api-status">
55
- <div class="status-dot ${this.apiStatus ? 'status-online' : 'status-offline'}"></div>
56
- <span>OpenRouter API: ${this.apiStatus ? 'ONLINE' : 'OFFLINE'}</span>
57
- </div>
58
- `;
59
  } catch (error) {
60
  this.apiStatus = false;
61
- this.shadowRoot.innerHTML = `
62
- <style>
63
- :host {
64
- display: block;
65
- margin: 1rem 0;
66
- }
67
-
68
- .api-status {
69
- display: flex;
70
- align-items: center;
71
- gap: 0.5rem;
72
- }
73
-
74
- .status-dot {
75
- width: 8px;
76
- height: 8px;
77
- border-radius: 50%;
78
- }
79
-
80
- .status-offline {
81
- background: #ef4444;
82
- }
83
- </style>
84
-
85
- <div class="api-status">
86
- <div class="status-dot status-offline"></div>
87
- <span>API Status: OFFLINE</span>
88
- </div>
89
- `;
90
  }
91
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  }
93
 
94
- customElements.define('api-status', ApiStatus);
 
1
+
2
  class ApiStatus extends HTMLElement {
3
  constructor() {
4
  super();
 
12
 
13
  async checkApiStatus() {
14
  try {
15
+ // Get API key from localStorage
16
+ const settings = JSON.parse(localStorage.getItem('janusSettings')) || {};
17
+ const apiKey = settings.apiKey;
18
 
19
+ if (!apiKey) {
20
+ this.renderStatus('no-key');
21
+ return;
22
+ }
23
+
24
  // Test OpenRouter API
25
  const openrouterResponse = await fetch('https://openrouter.ai/api/v1/models', {
26
  headers: {
27
+ 'Authorization': `Bearer ${apiKey}`,
28
+ 'HTTP-Referer': window.location.href,
29
+ 'X-Title': 'Janus Scanner Pro'
30
+ }
31
  });
32
+
33
  const openrouterStatus = openrouterResponse.ok;
34
+ this.apiStatus = openrouterStatus;
35
 
36
+ this.renderStatus(openrouterStatus ? 'online' : 'offline');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  } catch (error) {
38
  this.apiStatus = false;
39
+ this.renderStatus('offline');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
  }
42
+
43
+ renderStatus(status) {
44
+ const statusConfig = {
45
+ 'online': { color: '#10b981', text: 'AI API Connected', pulse: true },
46
+ 'offline': { color: '#ef4444', text: 'AI API Offline', pulse: false },
47
+ 'no-key': { color: '#f59e0b', text: 'API Key Not Configured', pulse: false }
48
+ };
49
+
50
+ const config = statusConfig[status] || statusConfig['offline'];
51
+
52
+ this.shadowRoot.innerHTML = `
53
+ <style>
54
+ :host {
55
+ display: block;
56
+ margin: 1rem 0;
57
+ }
58
+
59
+ .api-status {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 0.5rem;
63
+ }
64
+
65
+ .status-dot {
66
+ width: 8px;
67
+ height: 8px;
68
+ border-radius: 50%;
69
+ background: ${config.color};
70
+ ${config.pulse ? 'animation: pulse 2s infinite;' : ''}
71
+ }
72
+
73
+ .status-text {
74
+ color: ${config.color};
75
+ font-weight: 500;
76
+ }
77
+
78
+ @keyframes pulse {
79
+ 0% { opacity: 1; }
80
+ 50% { opacity: 0.5; }
81
+ 100% { opacity: 1; }
82
+ }
83
+
84
+ .settings-hint {
85
+ margin-top: 0.5rem;
86
+ font-size: 0.75rem;
87
+ color: #9ca3af;
88
+ }
89
+ </style>
90
+
91
+ <div class="api-status">
92
+ <div class="status-dot"></div>
93
+ <span class="status-text">${config.text}</span>
94
+ </div>
95
+ ${status === 'no-key' ? '<div class="settings-hint">Go to Settings to configure your OpenRouter API key</div>' : ''}
96
+ `;
97
+ }
98
  }
99
 
100
+ customElements.define('api-status', ApiStatus);
components/real-time-feeds.js CHANGED
@@ -1,25 +1,11 @@
1
- class RealTimeFeed extends HTMLElement {
2
  constructor() {
3
  super();
4
  this.attachShadow({ mode: 'open' });
5
  }
6
 
7
  connectedCallback() {
8
- this.startRealTimeFeed();
9
- }
10
-
11
- startRealTimeFeed() {
12
- // Crypto price updates
13
- this.updateCryptoPrices();
14
- setInterval(() => this.updateCryptoPrices(), 60000); // Update every minute
15
- }
16
-
17
- async updateCryptoPrices() {
18
- try {
19
- const response = await fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,monero,litecoin&vs_currencies=usd`);
20
- const prices = await response.json();
21
-
22
- this.shadowRoot.innerHTML = `
23
  <style>
24
  :host {
25
  display: block;
@@ -28,6 +14,7 @@ class RealTimeFeed extends HTMLElement {
28
  border-radius: 5px;
29
  padding: 15px;
30
  margin: 10px 0;
 
31
  }
32
 
33
  .feed-title {
@@ -54,26 +41,113 @@ class RealTimeFeed extends HTMLElement {
54
  .update-time {
55
  color: #9ca3af;
56
  font-size: 0.8rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }
58
  </style>
59
 
60
  <div>
61
- <h4 class="feed-title">Real-Time Crypto Prices</h4>
62
- <div class="space-y-2">
63
- ${Object.entries(prices).map(([coin, price]) => `
64
- <div class="price-item">
65
- <span>${coin.toUpperCase()}</span>
66
- <span class="${Math.random() > 0.5 ? 'price-up' : 'price-down'}">
67
- $${price.usd.toFixed(2)}
68
- </span>
69
- </div>
70
- `).join('')}
71
- <div class="update-time">
72
- Updated: ${new Date().toLocaleTimeString()}
73
  </div>
 
74
  </div>
75
  `;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  }
77
  }
78
 
79
- customElements.define('real-time-feed', RealTimeFeed);
 
1
+ class RealTimeFeeds extends HTMLElement {
2
  constructor() {
3
  super();
4
  this.attachShadow({ mode: 'open' });
5
  }
6
 
7
  connectedCallback() {
8
+ this.shadowRoot.innerHTML = `
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  <style>
10
  :host {
11
  display: block;
 
14
  border-radius: 5px;
15
  padding: 15px;
16
  margin: 10px 0;
17
+ min-height: 200px;
18
  }
19
 
20
  .feed-title {
 
41
  .update-time {
42
  color: #9ca3af;
43
  font-size: 0.8rem;
44
+ margin-top: 10px;
45
+ }
46
+
47
+ .loading {
48
+ color: #9ca3af;
49
+ text-align: center;
50
+ padding: 20px;
51
+ }
52
+
53
+ .error {
54
+ color: #ef4444;
55
+ text-align: center;
56
+ padding: 20px;
57
  }
58
  </style>
59
 
60
  <div>
61
+ <h4 class="feed-title">Real-Time Crypto & Market Data</h4>
62
+ <div id="feed-content">
63
+ <div class="loading">Initializing feeds...</div>
 
 
 
 
 
 
 
 
 
64
  </div>
65
+ <div class="update-time" id="update-time"></div>
66
  </div>
67
  `;
68
+
69
+ this.startRealTimeFeed();
70
+ }
71
+
72
+ async startRealTimeFeed() {
73
+ try {
74
+ await this.updateCryptoPrices();
75
+ setInterval(() => this.updateCryptoPrices(), 60000); // Update every minute
76
+ } catch (error) {
77
+ this.showError('Failed to initialize feeds');
78
+ }
79
+ }
80
+
81
+ async updateCryptoPrices() {
82
+ try {
83
+ const [cryptoResponse, forexResponse] = await Promise.all([
84
+ fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,monero,litecoin&vs_currencies=usd&include_24hr_change=true'),
85
+ fetch('https://api.exchangerate-api.com/v4/latest/USD')
86
+ ]);
87
+
88
+ if (!cryptoResponse.ok || !forexResponse.ok) {
89
+ throw new Error('API response failed');
90
+ }
91
+
92
+ const cryptoPrices = await cryptoResponse.json();
93
+ const forexRates = await forexResponse.json();
94
+
95
+ this.renderContent(cryptoPrices, forexRates);
96
+ } catch (error) {
97
+ this.showError('Unable to fetch market data');
98
+ }
99
+ }
100
+
101
+ renderContent(cryptoPrices, forexRates) {
102
+ const content = this.shadowRoot.getElementById('feed-content');
103
+ const updateTime = this.shadowRoot.getElementById('update-time');
104
+
105
+ const cryptoItems = Object.entries(cryptoPrices).map(([coin, data]) => {
106
+ const change = data.usd_24h_change || 0;
107
+ const changeClass = change >= 0 ? 'price-up' : 'price-down';
108
+ const changeSymbol = change >= 0 ? '↗' : '↘';
109
+
110
+ return `
111
+ <div class="price-item">
112
+ <span>${coin.toUpperCase()}/USD</span>
113
+ <span class="${changeClass}">
114
+ $${data.usd.toLocaleString()}
115
+ <span style="font-size: 0.8em; margin-left: 5px;">
116
+ ${changeSymbol} ${Math.abs(change).toFixed(2)}%
117
+ </span>
118
+ </span>
119
+ </div>
120
+ `;
121
+ }).join('');
122
+
123
+ const forexItems = ['EUR', 'GBP', 'CHF', 'JPY'].map(currency => {
124
+ const rate = forexRates.rates[currency];
125
+ return `
126
+ <div class="price-item">
127
+ <span>USD/${currency}</span>
128
+ <span>${rate.toFixed(4)}</span>
129
+ </div>
130
+ `;
131
+ }).join('');
132
+
133
+ content.innerHTML = `
134
+ <div style="margin-bottom: 15px;">
135
+ <h5 style="color: #ef4444; margin-bottom: 10px; font-size: 0.9em;">Cryptocurrencies</h5>
136
+ ${cryptoItems}
137
+ </div>
138
+ <div>
139
+ <h5 style="color: #ef4444; margin-bottom: 10px; font-size: 0.9em;">Forex Rates</h5>
140
+ ${forexItems}
141
+ </div>
142
+ `;
143
+
144
+ updateTime.textContent = `Last updated: ${new Date().toLocaleTimeString()}`;
145
+ }
146
+
147
+ showError(message) {
148
+ const content = this.shadowRoot.getElementById('feed-content');
149
+ content.innerHTML = `<div class="error">${message}</div>`;
150
  }
151
  }
152
 
153
+ customElements.define('real-time-feeds', RealTimeFeeds);
full-fraud-detection.html CHANGED
@@ -14,12 +14,12 @@
14
  <body class="bg-black text-terminal-green">
15
  <div class="scanline"></div>
16
  <header class="bg-primary border-b-2 border-accent py-4 px-6 flex justify-between items-center">
17
- <div class="flex items-center space-x-2">
18
- <i data-feather="eye" class="text-accent pulse"></i>
19
- <h1 class="text-2xl font-bold text-accent">JANUS SCANNER</h1>
20
- <span class="version-tag">v2.1 - "Opération Fumière Noire"</span>
21
- </div>
22
- <nav class="flex space-x-6">
23
  <a href="index.html" class="hover:text-accent text-gray-300">[DASHBOARD]</a>
24
  <a href="full-fraud-detection.html" class="hover:text-accent text-accent text-bold">[FULL DETECTION]</a>
25
  <a href="pages/reports.html" class="hover:text-accent text-gray-300">[RAPPORTS]</a>
@@ -63,9 +63,9 @@
63
  <div id="cryptoResults" class="space-y-2">
64
  <div class="text-center py-4 text-gray-500">
65
  <i data-feather="dollar-sign" class="mx-auto mb-2"></i>
66
- En attente...
67
  </div>
68
- </div>
69
  </div>
70
  </div>
71
 
@@ -81,9 +81,9 @@
81
  <div id="offshoreResults" class="space-y-2">
82
  <div class="text-center py-4 text-gray-500">
83
  <i data-feather="globe" class="mx-auto mb-2"></i>
84
- En attente...
85
  </div>
86
- </div>
87
  </div>
88
  </div>
89
 
@@ -105,9 +105,9 @@
105
  <div id="bankResults" class="space-y-2">
106
  <div class="text-center py-4 text-gray-500">
107
  <i data-feather="activity" class="mx-auto mb-2"></i>
108
- En attente...
109
  </div>
110
- </div>
111
  </div>
112
  </div>
113
  </div>
@@ -161,8 +161,9 @@
161
  <h3 class="card-title">[FIL D'ALERTES TEMPS RÉEL]</h3>
162
  <div id="threatFeed" class="terminal-content max-h-64 overflow-y-auto">
163
  <div class="text-gray-400"># Initialisation du système de surveillance...</div>
 
164
  </div>
165
- </div>
166
 
167
  <!-- Strike Configuration -->
168
  <div class="section">
@@ -210,13 +211,35 @@
210
  </div>
211
  </main>
212
  <custom-footer></custom-footer>
213
- <script src="components/api-status.js"></script>
214
- <script src="components/real-time-feed.js"></script>
215
  <script src="script.js"></script>
216
- <script>feather.replace();</script>
217
  <script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  // Full Fraud Detection specific functionality
219
  document.addEventListener('DOMContentLoaded', function() {
 
 
 
 
 
 
 
220
  // Elements
221
  const cryptoWallet = document.getElementById('cryptoWallet');
222
  const analyzeCryptoBtn = document.getElementById('analyzeCryptoBtn');
@@ -237,8 +260,8 @@
237
  const masterRiskScore = document.getElementById('masterRiskScore');
238
  const masterRiskBar = document.getElementById('masterRiskBar');
239
  const threatLevel = document.getElementById('threatLevel');
240
-
241
- let globalRiskScore = 0;
242
  let riskComponents = [];
243
 
244
  // Threat feed simulation
@@ -563,7 +586,325 @@
563
 
564
  // Initialiser le fil d'alertes
565
  threatMessages.forEach((msg, index) => {
566
- setTimeout(() => addThreatMessage(msg.text, msg.type), index * 2000);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
567
  });
568
  });
569
  </script>
 
14
  <body class="bg-black text-terminal-green">
15
  <div class="scanline"></div>
16
  <header class="bg-primary border-b-2 border-accent py-4 px-6 flex justify-between items-center">
17
+ <div class="flex items-center space-x-2">
18
+ <i data-feather="eye" class="text-accent pulse"></i>
19
+ <h1 class="text-2xl font-bold text-accent">JANUS SCANNER</h1>
20
+ <span class="version-tag">v2.1 - "Opération Foudre Silencieuse"</span>
21
+ </div>
22
+ <nav class="flex space-x-6">
23
  <a href="index.html" class="hover:text-accent text-gray-300">[DASHBOARD]</a>
24
  <a href="full-fraud-detection.html" class="hover:text-accent text-accent text-bold">[FULL DETECTION]</a>
25
  <a href="pages/reports.html" class="hover:text-accent text-gray-300">[RAPPORTS]</a>
 
63
  <div id="cryptoResults" class="space-y-2">
64
  <div class="text-center py-4 text-gray-500">
65
  <i data-feather="dollar-sign" class="mx-auto mb-2"></i>
66
+ <p class="text-sm">Enter wallet address and click scan</p>
67
  </div>
68
+ </div>
69
  </div>
70
  </div>
71
 
 
81
  <div id="offshoreResults" class="space-y-2">
82
  <div class="text-center py-4 text-gray-500">
83
  <i data-feather="globe" class="mx-auto mb-2"></i>
84
+ <p class="text-sm">Paste text to analyze</p>
85
  </div>
86
+ </div>
87
  </div>
88
  </div>
89
 
 
105
  <div id="bankResults" class="space-y-2">
106
  <div class="text-center py-4 text-gray-500">
107
  <i data-feather="activity" class="mx-auto mb-2"></i>
108
+ <p class="text-sm">Upload bank transaction file</p>
109
  </div>
110
+ </div>
111
  </div>
112
  </div>
113
  </div>
 
161
  <h3 class="card-title">[FIL D'ALERTES TEMPS RÉEL]</h3>
162
  <div id="threatFeed" class="terminal-content max-h-64 overflow-y-auto">
163
  <div class="text-gray-400"># Initialisation du système de surveillance...</div>
164
+ <div class="text-gray-400"># API Status: <span id="apiConnectionStatus">Checking...</span></div>
165
  </div>
166
+ </div>
167
 
168
  <!-- Strike Configuration -->
169
  <div class="section">
 
211
  </div>
212
  </main>
213
  <custom-footer></custom-footer>
214
+ <script src="components/api-status.js"></script>
215
+ <script src="components/real-time-feeds.js"></script>
216
  <script src="script.js"></script>
217
+ <script>feather.replace();</script>
218
  <script>
219
+ // API Configuration
220
+ const API_CONFIG = {
221
+ baseUrl: 'https://openrouter.ai/api/v1',
222
+ models: {
223
+ analysis: 'deepseek/deepseek-chat-v3.1:free',
224
+ fast: 'meituan/longcat-flash-chat:free',
225
+ complex: 'nousresearch/hermes-3-llama-3.1-405b:free'
226
+ }
227
+ };
228
+
229
+ // Global state
230
+ let globalRiskScore = 0;
231
+ let riskComponents = [];
232
+ let scanHistory = [];
233
+
234
  // Full Fraud Detection specific functionality
235
  document.addEventListener('DOMContentLoaded', function() {
236
+ // Load API key from settings
237
+ const settings = JSON.parse(localStorage.getItem('janusSettings')) || {};
238
+ API_CONFIG.apiKey = settings.apiKey || '';
239
+
240
+ // Check API status on load
241
+ checkApiStatus();
242
+
243
  // Elements
244
  const cryptoWallet = document.getElementById('cryptoWallet');
245
  const analyzeCryptoBtn = document.getElementById('analyzeCryptoBtn');
 
260
  const masterRiskScore = document.getElementById('masterRiskScore');
261
  const masterRiskBar = document.getElementById('masterRiskBar');
262
  const threatLevel = document.getElementById('threatLevel');
263
+ const apiConnectionStatus = document.getElementById('apiConnectionStatus');
264
+ let globalRiskScore = 0;
265
  let riskComponents = [];
266
 
267
  // Threat feed simulation
 
586
 
587
  // Initialiser le fil d'alertes
588
  threatMessages.forEach((msg, index) => {
589
+ // Check API status
590
+ async function checkApiStatus() {
591
+ if (!API_CONFIG.apiKey) {
592
+ apiConnectionStatus.innerHTML = '<span class="text-yellow-500">No API Key Configured</span>';
593
+ return;
594
+ }
595
+
596
+ try {
597
+ const response = await fetch(`${API_CONFIG.baseUrl}/models`, {
598
+ headers: {
599
+ 'Authorization': `Bearer ${API_CONFIG.apiKey}`,
600
+ 'HTTP-Referer': window.location.href,
601
+ 'X-Title': 'Janus Scanner Pro'
602
+ }
603
+ });
604
+
605
+ if (response.ok) {
606
+ apiConnectionStatus.innerHTML = '<span class="text-green-500">Connected</span>';
607
+ } else {
608
+ apiConnectionStatus.innerHTML = '<span class="text-red-500">Connection Failed</span>';
609
+ }
610
+ } catch (error) {
611
+ apiConnectionStatus.innerHTML = '<span class="text-red-500">Offline</span>';
612
+ }
613
+ }
614
+
615
+ // AI Analysis function
616
+ async function performAIAnalysis(data, analysisType = 'fraud') {
617
+ if (!API_CONFIG.apiKey) {
618
+ throw new Error('OpenRouter API key not configured. Go to Settings to add your API key.');
619
+ }
620
+
621
+ const models = {
622
+ fraud: API_CONFIG.models.analysis,
623
+ fast: API_CONFIG.models.fast,
624
+ complex: API_CONFIG.models.complex
625
+ };
626
+
627
+ const prompt = analysisType === 'fraud'
628
+ ? `Analyze this financial data for fraud patterns, anomalies, and suspicious activities. Return a JSON with: {riskScore: 0-100, anomalies: [{type, severity, description}], summary: string}`
629
+ : `Analyze this crypto/blockchain data. Return JSON: {riskScore: 0-100, anomalies: [], totalValue: number, summary: string}`;
630
+
631
+ const response = await fetch(`${API_CONFIG.baseUrl}/chat/completions`, {
632
+ method: 'POST',
633
+ headers: {
634
+ 'Authorization': `Bearer ${API_CONFIG.apiKey}`,
635
+ 'Content-Type': 'application/json',
636
+ 'HTTP-Referer': window.location.href,
637
+ 'X-Title': 'Janus Scanner Pro'
638
+ },
639
+ body: JSON.stringify({
640
+ model: models[analysisType] || models.fraud,
641
+ messages: [
642
+ {
643
+ role: 'system',
644
+ content: prompt
645
+ },
646
+ {
647
+ role: 'user',
648
+ content: JSON.stringify(data)
649
+ }
650
+ ],
651
+ temperature: 0.3
652
+ })
653
+ });
654
+
655
+ if (!response.ok) {
656
+ throw new Error(`API Error: ${response.status} - ${await response.text()}`);
657
+ }
658
+
659
+ const result = await response.json();
660
+ return JSON.parse(result.choices[0].message.content);
661
+ }
662
+
663
+ // Enhanced crypto analysis with AI
664
+ analyzeCryptoBtn.addEventListener('click', async function() {
665
+ const wallet = cryptoWallet.value.trim();
666
+ if (!wallet) {
667
+ alert('Entrez une adresse wallet');
668
+ return;
669
+ }
670
+
671
+ analyzeCryptoBtn.disabled = true;
672
+ analyzeCryptoBtn.innerHTML = '<i data-feather="loader" class="animate-spin inline mr-2"></i>Scanning blockchain...';
673
+ feather.replace();
674
+
675
+ try {
676
+ addThreatMessage(`Scan wallet: ${wallet.substring(0, 20)}...`, 'warning');
677
+
678
+ // Get real crypto data
679
+ const pricesResponse = await fetch(`https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd`);
680
+ const prices = await pricesResponse.json();
681
+
682
+ // Simulate transaction data for AI analysis
683
+ const mockData = {
684
+ wallet: wallet,
685
+ transactions: Array.from({length: 10}, (_, i) => ({
686
+ amount: Math.random() * 50000 + 1000,
687
+ type: ['withdrawal', 'deposit', 'transfer'][Math.floor(Math.random() * 3)],
688
+ timestamp: Date.now() - (i * 3600000),
689
+ counterparty: `0x${Math.random().toString(16).substr(2, 40)}`
690
+ })),
691
+ currentPrices: prices
692
+ };
693
+
694
+ // AI Analysis
695
+ const aiResult = await performAIAnalysis(mockData, 'crypto');
696
+
697
+ if (aiResult) {
698
+ cryptoResults.innerHTML = `
699
+ <div class="bg-gray-700 p-3 rounded border ${aiResult.riskScore > 70 ? 'border-red-500' : aiResult.riskScore > 40 ? 'border-yellow-500' : 'border-green-500'}">
700
+ <div class="flex justify-between items-center mb-2">
701
+ <span class="font-medium">AI Risk Assessment</span>
702
+ <span class="font-bold ${aiResult.riskScore > 70 ? 'text-red-500' : aiResult.riskScore > 40 ? 'text-yellow-500' : 'text-green-500'}">${aiResult.riskScore}%</span>
703
+ </div>
704
+ <div class="text-sm text-gray-300">
705
+ <p>Est. Value: ${aiResult.totalValue ? aiResult.totalValue.toFixed(2) : 'N/A'}</p>
706
+ <p>AI Detected: ${aiResult.anomalies ? aiResult.anomalies.length : 0} anomalies</p>
707
+ <p class="mt-2 text-xs">${aiResult.summary || 'Analysis complete'}</p>
708
+ </div>
709
+ </div>
710
+ `;
711
+ updateMasterRisk('Crypto Wallet', aiResult.riskScore);
712
+ addThreatMessage(`Risque crypto: ${aiResult.riskScore}%`, aiResult.riskScore > 70 ? 'danger' : 'warning');
713
+
714
+ // Save to history
715
+ addToScanHistory({
716
+ fileName: `Crypto Wallet ${wallet.substring(0, 10)}...`,
717
+ date: new Date().toISOString(),
718
+ riskScore: aiResult.riskScore,
719
+ anomalies: aiResult.anomalies ? aiResult.anomalies.length : 0,
720
+ status: aiResult.riskScore > 70 ? 'HIGH RISK' : aiResult.riskScore > 40 ? 'MEDIUM RISK' : 'LOW RISK'
721
+ });
722
+ }
723
+ } catch (error) {
724
+ cryptoResults.innerHTML = `<div class="text-red-500">Erreur: ${error.message}</div>`;
725
+ addThreatMessage(`Crypto scan failed: ${error.message}`, 'danger');
726
+ } finally {
727
+ analyzeCryptoBtn.disabled = false;
728
+ analyzeCryptoBtn.innerHTML = '[SCANNER WALLET]';
729
+ feather.replace();
730
+ }
731
+ });
732
+
733
+ // Enhanced offshore detection with AI
734
+ detectOffshoreBtn.addEventListener('click', async function() {
735
+ const text = offshoreText.value.trim();
736
+ if (!text) {
737
+ alert('Collez du texte à analyser');
738
+ return;
739
+ }
740
+
741
+ detectOffshoreBtn.disabled = true;
742
+ detectOffshoreBtn.innerHTML = '<i data-feather="loader" class="animate-spin inline mr-2"></i>Analyzing...';
743
+ feather.replace();
744
+
745
+ try {
746
+ addThreatMessage('Analyse IA des entités offshore...', 'warning');
747
+
748
+ const aiResult = await performAIAnalysis({
749
+ text: text,
750
+ context: 'offshore_entity_detection'
751
+ }, 'complex');
752
+
753
+ if (aiResult && aiResult.anomalies) {
754
+ if (aiResult.anomalies.length === 0) {
755
+ offshoreResults.innerHTML = `
756
+ <div class="text-center py-4 text-green-500">
757
+ <i data-feather="check-circle" class="mx-auto mb-2"></i>
758
+ Aucune entité suspecte détectée par IA
759
+ </div>
760
+ `;
761
+ } else {
762
+ offshoreResults.innerHTML = aiResult.anomalies.map(a => `
763
+ <div class="bg-red-900 bg-opacity-50 p-3 rounded border border-red-500">
764
+ <div class="flex justify-between items-center">
765
+ <span class="font-medium">${a.type || 'Suspicious Entity'}</span>
766
+ <span class="text-red-500 text-sm">${a.severity || 'HIGH'}</span>
767
+ </div>
768
+ <div class="text-sm text-gray-400 mt-1">${a.description}</div>
769
+ </div>
770
+ `).join('');
771
+
772
+ const offshoreRisk = aiResult.riskScore || Math.min(100, aiResult.anomalies.length * 25);
773
+ updateMasterRisk('Offshore Entities', offshoreRisk);
774
+ addThreatMessage(`${aiResult.anomalies.length} entités suspectes détectées!`, 'danger');
775
+ }
776
+
777
+ // Update with AI summary
778
+ if (aiResult.summary) {
779
+ offshoreResults.innerHTML += `<div class="mt-3 p-2 bg-blue-900 bg-opacity-30 rounded text-xs text-blue-300">${aiResult.summary}</div>`;
780
+ }
781
+ } else {
782
+ // Fallback to regex detection
783
+ const detections = window.JanusFraudDetector.detectOffshoreEntities(text);
784
+ if (detections.length === 0) {
785
+ offshoreResults.innerHTML = `
786
+ <div class="text-center py-4 text-green-500">
787
+ <i data-feather="check-circle" class="mx-auto mb-2"></i>
788
+ Aucune entité offshore détectée
789
+ </div>
790
+ `;
791
+ } else {
792
+ offshoreResults.innerHTML = detections.map(d => `
793
+ <div class="bg-red-900 bg-opacity-50 p-3 rounded border border-red-500">
794
+ <div class="flex justify-between items-center">
795
+ <span class="font-medium">${d.entity || d.pattern}</span>
796
+ <span class="text-red-500 text-sm">${d.severity}</span>
797
+ </div>
798
+ <div class="text-sm text-gray-400">${d.type}</div>
799
+ </div>
800
+ `).join('');
801
+
802
+ const offshoreRisk = Math.min(100, detections.length * 25);
803
+ updateMasterRisk('Offshore Entities', offshoreRisk);
804
+ addThreatMessage(`${detections.length} entités offshore détectées!`, 'danger');
805
+ }
806
+ }
807
+ } catch (error) {
808
+ offshoreResults.innerHTML = `<div class="text-red-500">Erreur IA: ${error.message}</div>`;
809
+ addThreatMessage(`Offshore detection failed: ${error.message}`, 'danger');
810
+ } finally {
811
+ detectOffshoreBtn.disabled = false;
812
+ detectOffshoreBtn.innerHTML = '[DÉTECTER ENTITÉS]';
813
+ feather.replace();
814
+ }
815
+ });
816
+
817
+ // Bank analysis with AI
818
+ analyzeBankBtn.addEventListener('click', async function() {
819
+ const file = bankFile.files[0];
820
+ if (!file) {
821
+ alert('Sélectionnez un fichier de transactions bancaires');
822
+ return;
823
+ }
824
+
825
+ analyzeBankBtn.disabled = true;
826
+ analyzeBankBtn.innerHTML = '<i data-feather="loader" class="animate-spin inline mr-2"></i>AI Analyzing...';
827
+ feather.replace();
828
+
829
+ try {
830
+ addThreatMessage(`Analyse bancaire IA: ${file.name}`, 'warning');
831
+
832
+ const data = await processExcelFile(file);
833
+ const aiResult = await performAIAnalysis({
834
+ transactions: data.slice(0, 50), // Limit for API
835
+ accountPatterns: ['cash', 'anonymous', 'urgent', 'personal']
836
+ }, 'fraud');
837
+
838
+ if (aiResult) {
839
+ bankResults.innerHTML = `
840
+ <div class="bg-gray-700 p-3 rounded border ${aiResult.riskScore > 70 ? 'border-red-500' : aiResult.riskScore > 40 ? 'border-yellow-500' : 'border-green-500'}">
841
+ <div class="flex justify-between items-center mb-2">
842
+ <span class="font-medium">AI Risk Assessment</span>
843
+ <span class="font-bold ${aiResult.riskScore > 70 ? 'text-red-500' : aiResult.riskScore > 40 ? 'text-yellow-500' : 'text-green-500'}">${aiResult.riskScore}%</span>
844
+ </div>
845
+ <div class="text-sm text-gray-300">
846
+ <p>AI Detected: ${aiResult.anomalies ? aiResult.anomalies.length : 0} anomalies</p>
847
+ <p>Transactions: ${data.length}</p>
848
+ <p class="mt-2 text-xs">${aiResult.summary || 'Bank analysis complete'}</p>
849
+ </div>
850
+ </div>
851
+ `;
852
+
853
+ updateMasterRisk('Bank Accounts', aiResult.riskScore);
854
+ addThreatMessage(`${aiResult.anomalies ? aiResult.anomalies.length : 0} anomalies bancaires`, aiResult.riskScore > 70 ? 'danger' : 'warning');
855
+
856
+ // Save to history
857
+ addToScanHistory({
858
+ fileName: file.name,
859
+ date: new Date().toISOString(),
860
+ riskScore: aiResult.riskScore,
861
+ anomalies: aiResult.anomalies ? aiResult.anomalies.length : 0,
862
+ status: aiResult.riskScore > 70 ? 'HIGH RISK' : aiResult.riskScore > 40 ? 'MEDIUM RISK' : 'LOW RISK'
863
+ });
864
+ }
865
+ } catch (error) {
866
+ bankResults.innerHTML = `<div class="text-red-500">Erreur IA: ${error.message}</div>`;
867
+ addThreatMessage(`Bank analysis failed: ${error.message}`, 'danger');
868
+ } finally {
869
+ analyzeBankBtn.disabled = false;
870
+ analyzeBankBtn.innerHTML = '[ANALYSER COMPTES]';
871
+ feather.replace();
872
+ }
873
+ });
874
+
875
+ // File processing helper
876
+ async function processExcelFile(file) {
877
+ return new Promise((resolve, reject) => {
878
+ const reader = new FileReader();
879
+ reader.onload = function(e) {
880
+ try {
881
+ const data = new Uint8Array(e.target.result);
882
+ const workbook = XLSX.read(data, { type: 'array' });
883
+ const firstSheet = workbook.Sheets[workbook.SheetNames[0]];
884
+ const jsonData = XLSX.utils.sheet_to_json(firstSheet);
885
+ resolve(jsonData);
886
+ } catch (error) {
887
+ reject(new Error('Failed to process Excel file'));
888
+ }
889
+ };
890
+ reader.onerror = () => reject(new Error('Failed to read file'));
891
+ reader.readAsArrayBuffer(file);
892
+ });
893
+ }
894
+
895
+ // Add to scan history
896
+ function addToScanHistory(scanData) {
897
+ scanHistory.unshift({
898
+ ...scanData,
899
+ id: Date.now()
900
+ });
901
+ scanHistory = scanHistory.slice(0, 50);
902
+ localStorage.setItem('scanHistory', JSON.stringify(scanHistory));
903
+ }
904
+
905
+ // Initialize threat feed
906
+ threatMessages.forEach((msg, index) => {
907
+ setTimeout(() => addThreatMessage(msg.text, msg.type), index * 1500);
908
  });
909
  });
910
  </script>
pages/settings.html CHANGED
@@ -29,9 +29,10 @@
29
  <label class="block text-sm font-medium mb-2">OpenRouter API Key</label>
30
  <input type="password" id="apiKey" placeholder="sk-or-v1-..."
31
  class="w-full bg-gray-700 px-4 py-2 rounded border border-gray-600 focus:border-red-500 focus:outline-none">
32
- <p class="text-xs text-gray-400 mt-1">Stored securely in browser memory</p>
 
33
  </div>
34
- <div>
35
  <label class="block text-sm font-medium mb-2">Default AI Model</label>
36
  <select id="defaultModel" class="w-full bg-gray-700 px-4 py-2 rounded border border-gray-600 focus:border-red-500 focus:outline-none">
37
  <option value="deepseek/deepseek-chat-v3.1:free">DeepSeek Chat v3.1 (Free)</option>
 
29
  <label class="block text-sm font-medium mb-2">OpenRouter API Key</label>
30
  <input type="password" id="apiKey" placeholder="sk-or-v1-..."
31
  class="w-full bg-gray-700 px-4 py-2 rounded border border-gray-600 focus:border-red-500 focus:outline-none">
32
+ <p class="text-xs text-gray-400 mt-1">Stored securely in browser localStorage</p>
33
+ <p class="text-xs text-yellow-400 mt-1">⚠️ Never share your API key or commit it to version control</p>
34
  </div>
35
+ <div>
36
  <label class="block text-sm font-medium mb-2">Default AI Model</label>
37
  <select id="defaultModel" class="w-full bg-gray-700 px-4 py-2 rounded border border-gray-600 focus:border-red-500 focus:outline-none">
38
  <option value="deepseek/deepseek-chat-v3.1:free">DeepSeek Chat v3.1 (Free)</option>
script.js CHANGED
@@ -24,7 +24,21 @@ document.addEventListener('DOMContentLoaded', function() {
24
  let scanHistoryData = JSON.parse(localStorage.getItem('scanHistory')) || [];
25
  // Initialize scan history
26
  renderScanHistory();
27
- // File upload handlers
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  fecFile.addEventListener('change', (e) => handleFileSelect(e, 'fec'));
29
  bilanNormalFile.addEventListener('change', (e) => handleFileSelect(e, 'bilanNormal'));
30
  bilanDiversFile.addEventListener('change', (e) => handleFileSelect(e, 'bilanDivers'));
 
24
  let scanHistoryData = JSON.parse(localStorage.getItem('scanHistory')) || [];
25
  // Initialize scan history
26
  renderScanHistory();
27
+
28
+ // Expose global functions for full detection page
29
+ window.JanusFraudDetector = {
30
+ analyzeCryptoTransactions: analyzeCryptoTransactions,
31
+ detectOffshoreEntities: detectOffshoreEntities,
32
+ performBilanNormalAnalysis: performBilanNormalAnalysis,
33
+ performBilanDiversAnalysis: performBilanDiversAnalysis,
34
+ processExcelFile: processExcelFile,
35
+ processPDFFile: processPDFFile,
36
+ extractAmount: extractAmount,
37
+ extractAccountNumber: extractAccountNumber,
38
+ extractAccountName: extractAccountName,
39
+ calculateFinancialRatios: calculateFinancialRatios
40
+ };
41
+ // File upload handlers
42
  fecFile.addEventListener('change', (e) => handleFileSelect(e, 'fec'));
43
  bilanNormalFile.addEventListener('change', (e) => handleFileSelect(e, 'bilanNormal'));
44
  bilanDiversFile.addEventListener('change', (e) => handleFileSelect(e, 'bilanDivers'));