Ymc3013 commited on
Commit
97abfa4
·
verified ·
1 Parent(s): 1d4002d

Update serveur.js

Browse files
Files changed (1) hide show
  1. serveur.js +272 -97
serveur.js CHANGED
@@ -1,105 +1,280 @@
1
- const express = require('express');
2
- const { WebSocketServer } = require('ws');
3
- const http = require('http');
4
- const axios = require('axios');
5
- const fs = require('fs');
6
- const path = require('path');
7
-
8
- // --- INTERCONNEXION AVEC TON LOGICIEL DE MAJ ---
9
- const { gererMiseAJour } = require('./serveur_maj.js');
10
-
11
- // --- CONFIGURATION GOOGLE (ID CLIENT ENREGISTRÉ) ---
12
- const GOOGLE_CLIENT_ID = '411319004349-2dqnskihu1jf5vkptfp7n6p0i6bcifll.apps.googleusercontent.com';
13
- // /!\ PENSE À METTRE TON SECRET CLIENT GOOGLE ICI /!\
14
- const GOOGLE_CLIENT_SECRET = 'TON_SECRET_CLIENT_A_COPIER_DE_GOOGLE';
15
-
16
- const PORT = process.env.PORT || 7860;
17
- const DOSSIER_USER = path.join(__dirname, 'user');
18
-
19
- if (!fs.existsSync(DOSSIER_USER)) {
20
- fs.mkdirSync(DOSSIER_USER);
21
- }
22
-
23
- const app = express();
24
- const server = http.createServer(app);
25
-
26
- // Route HTTP appelée par Google après authentification
27
- app.get('/auth/google/callback', async (req, res) => {
28
- const code = req.query.code;
29
- if (!code) return res.status(400).send("Code de validation manquant.");
30
-
31
- try {
32
- // Échange du code temporaire contre un jeton d'accès
33
- const tokenResponse = await axios.post('https://oauth2.googleapis.com/token', {
34
- code: code,
35
- client_id: GOOGLE_CLIENT_ID,
36
- client_secret: GOOGLE_CLIENT_SECRET,
37
- redirect_uri: 'https://ymc3013-user-save.hf.space/auth/google/callback',
38
- grant_type: 'authorization_code'
39
- });
40
-
41
- const { access_token } = tokenResponse.data;
42
-
43
- // Récupération des infos du profil utilisateur
44
- const userResponse = await axios.get('https://www.googleapis.com/oauth2/v2/userinfo', {
45
- headers: { Authorization: `Bearer ${access_token}` }
46
- });
47
-
48
- const profilGoogle = userResponse.data;
49
-
50
- console.log(`[GOOGLE AUTH SUCCESS] Connexion de : ${profilGoogle.email}`);
51
-
52
- // Sauvegarde automatique dans le dossier user
53
- const contenuFichier = `id: ${profilGoogle.id}\npseudo: ${profilGoogle.name}\nemail: ${profilGoogle.email}`;
54
- const nomFichier = `${profilGoogle.email.replace(/[^a-zA-Z0-9@.]/g, "_")}.txt`;
55
- fs.writeFileSync(path.join(DOSSIER_USER, nomFichier), contenuFichier, 'utf8');
56
-
57
- // Page HTML renvoyée dans la popup
58
- res.send(`
59
- <html>
60
- <body style="font-family: sans-serif; text-align: center; padding-top: 50px; background: #1e1e2e; color: white;">
61
- <h2>Connexion Google réussie !</h2>
62
- <p>Bienvenue ${profilGoogle.name}. Tu peux fermer cette fenêtre pour retourner au jeu.</p>
63
- <script>
64
- window.opener.postMessage(${JSON.stringify({
65
- accountName: profilGoogle.email,
66
- fullName: profilGoogle.name,
67
- profilePicture: profilGoogle.picture,
68
- userId: profilGoogle.id,
69
- emailVerified: profilGoogle.verified_email
70
- })}, "*");
71
- </script>
72
- </body>
73
- </html>
74
- `);
75
-
76
- } catch (error) {
77
- console.error("Erreur Google Auth:", error.response ? error.response.data : error.message);
78
- res.status(500).send("Une erreur est survenue durant l'authentification.");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
- });
81
 
82
- // Initialisation du serveur WebSocket
83
- const wss = new WebSocketServer({ server });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
- wss.on('connection', (ws) => {
86
- console.log("[CONNEXION] Un utilisateur a rejoint le serveur.");
87
 
88
- ws.on('message', (message) => {
89
- const texteRecu = message.toString();
 
90
 
91
- const estUneMaj = gererMiseAJour(texteRecu, ws);
92
- if (estUneMaj) return;
 
 
 
93
 
94
- // Diffusion du chat standard
95
- wss.clients.forEach((client) => {
96
- if (client.readyState === 1) {
97
- client.send(texteRecu);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  }
99
- });
100
- });
101
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
- server.listen(PORT, '0.0.0.0', () => {
104
- console.log(`=== SERVEUR ACTIF SUR LE PORT ${PORT} ===`);
105
- });
 
1
+ // Name: WebSocket avec Authentification
2
+ // ID: gsaWebsocket
3
+ // Description: Connect to WebSocket servers and handle user file verification with boolean status.
4
+ // By: RedMan13 & Custom Auth
5
+ // License: MIT
6
+
7
+ (function (Scratch) {
8
+ "use strict";
9
+
10
+ if (!Scratch.extensions.unsandboxed) {
11
+ throw new Error("can not load outside unsandboxed mode");
12
+ }
13
+
14
+ const blobToDataURL = (blob) =>
15
+ new Promise((resolve, reject) => {
16
+ const fr = new FileReader();
17
+ fr.onload = () => resolve(fr.result);
18
+ fr.onerror = () =>
19
+ reject(new Error(`Failed to read as data URL: ${fr.error}`));
20
+ fr.readAsDataURL(blob);
21
+ });
22
+
23
+ /* ------- BLOCKS -------- */
24
+ const { BlockType, Cast, ArgumentType } = Scratch;
25
+ const vm = Scratch.vm;
26
+ const runtime = vm.runtime;
27
+
28
+ class WebSocketExtension {
29
+ constructor() {
30
+ /** @type {Record<string, WebSocketInfo>} */
31
+ this.instances = {};
32
+
33
+ runtime.on("targetWasRemoved", (target) => {
34
+ const instance = this.instances[target.id];
35
+ if (instance) {
36
+ instance.destroyed = true;
37
+ if (instance.websocket) {
38
+ instance.websocket.close();
39
+ }
40
+ delete this.instances[target.id];
41
+ }
42
+ });
43
+ }
44
+
45
+ getInfo() {
46
+ return {
47
+ id: "gsaWebsocket",
48
+ name: "WebSocket Auth",
49
+ color1: "#307eff",
50
+ color2: "#2c5eb0",
51
+ blocks: [
52
+ {
53
+ opcode: "newInstance",
54
+ blockType: BlockType.COMMAND,
55
+ arguments: {
56
+ URL: {
57
+ type: ArgumentType.STRING,
58
+ defaultValue: "wss://ymc3013-user-save.hf.space",
59
+ },
60
+ },
61
+ text: "connect to [URL]",
62
+ },
63
+ "---",
64
+ {
65
+ opcode: "enregistrerUtilisateur",
66
+ blockType: BlockType.COMMAND,
67
+ arguments: {
68
+ PSEUDO: { type: ArgumentType.STRING, defaultValue: "Scratcher" },
69
+ EMAIL: { type: ArgumentType.STRING, defaultValue: "exemple@gmail.com" },
70
+ },
71
+ text: "enregistrer l'utilisateur avec le pseudo [PSEUDO] et l'email [EMAIL]",
72
+ },
73
+ {
74
+ opcode: "verifierUtilisateur",
75
+ blockType: BlockType.COMMAND,
76
+ arguments: {
77
+ PSEUDO: { type: ArgumentType.STRING, defaultValue: "Scratcher" },
78
+ EMAIL: { type: ArgumentType.STRING, defaultValue: "exemple@gmail.com" },
79
+ },
80
+ text: "vérifier l'utilisateur avec le pseudo [PSEUDO] et l'email [EMAIL]",
81
+ },
82
+ "---",
83
+ // --- LES DEUX NOUVEAUX BLOCS DE STATUT ---
84
+ {
85
+ opcode: "estVerificationValide",
86
+ blockType: BlockType.BOOLEAN,
87
+ text: "dernière vérification valide ?",
88
+ disableMonitor: false,
89
+ },
90
+ {
91
+ opcode: "messageVerification",
92
+ blockType: BlockType.REPORTER,
93
+ text: "statut de la dernière vérification",
94
+ disableMonitor: false,
95
+ },
96
+ "---",
97
+ {
98
+ opcode: "onOpen",
99
+ blockType: BlockType.EVENT,
100
+ isEdgeActivated: false,
101
+ shouldRestartExistingThreads: true,
102
+ text: "when connected",
103
+ },
104
+ {
105
+ opcode: "isConnected",
106
+ blockType: BlockType.BOOLEAN,
107
+ text: "is connected?",
108
+ disableMonitor: true,
109
+ },
110
+ "---",
111
+ {
112
+ opcode: "onMessage",
113
+ blockType: BlockType.EVENT,
114
+ isEdgeActivated: false,
115
+ shouldRestartExistingThreads: true,
116
+ text: "when message received",
117
+ },
118
+ {
119
+ opcode: "messageData",
120
+ blockType: BlockType.REPORTER,
121
+ text: "received message data",
122
+ disableMonitor: true,
123
+ },
124
+ "---",
125
+ {
126
+ opcode: "closeWithoutReason",
127
+ blockType: BlockType.COMMAND,
128
+ text: "close connection",
129
+ }
130
+ ],
131
+ };
132
  }
 
133
 
134
+ // --- ENREGISTREMENT ET VÉRIFICATION ---
135
+
136
+ enregistrerUtilisateur(args, utils) {
137
+ const payload = JSON.stringify({
138
+ type: "enregistrement",
139
+ pseudo: Cast.toString(args.PSEUDO),
140
+ email: Cast.toString(args.EMAIL)
141
+ });
142
+ this.sendMessage({ PAYLOAD: payload }, utils);
143
+ }
144
+
145
+ verifierUtilisateur(args, utils) {
146
+ const payload = JSON.stringify({
147
+ type: "comparer",
148
+ pseudo: Cast.toString(args.PSEUDO),
149
+ email: Cast.toString(args.EMAIL)
150
+ });
151
+ this.sendMessage({ PAYLOAD: payload }, utils);
152
+ }
153
+
154
+ // --- FONCTIONS DES NOUVEAUX BLOCS BOULÉENS ---
155
+
156
+ estVerificationValide(_, utils) {
157
+ const instance = this.instances[utils.target.id];
158
+ if (!instance || instance.verificationValide === undefined) return false;
159
+ return instance.verificationValide; // Renvoie true ou false
160
+ }
161
+
162
+ messageVerification(_, utils) {
163
+ const instance = this.instances[utils.target.id];
164
+ if (!instance || !instance.verificationMessage) return "";
165
+ return instance.verificationMessage; // Renvoie le texte ("Infos correctes", etc.)
166
+ }
167
 
168
+ // --- MOTEUR DE L'EXTENSION ---
 
169
 
170
+ newInstance(args, util) {
171
+ const target = util.target;
172
+ let url = Cast.toString(args.URL);
173
 
174
+ const oldInstance = this.instances[util.target.id];
175
+ if (oldInstance) {
176
+ oldInstance.destroyed = true;
177
+ if (oldInstance.websocket) oldInstance.websocket.close();
178
+ }
179
 
180
+ const instance = {
181
+ destroyed: false,
182
+ errored: false,
183
+ data: "",
184
+ websocket: null,
185
+ messageThreadsRunning: false,
186
+ connectThreads: [],
187
+ messageThreads: [],
188
+ messageQueue: [],
189
+ sendOnceConnected: [],
190
+ // Variables pour mémoriser l'état de la connexion utilisateur
191
+ verificationValide: false,
192
+ verificationMessage: "Aucune vérification effectuée"
193
+ };
194
+ this.instances[util.target.id] = instance;
195
+
196
+ return Scratch.canFetch(url)
197
+ .then((allowed) => new Promise((resolve) => {
198
+ if (!allowed) throw new Error("Not allowed");
199
+ const websocket = new WebSocket(url);
200
+ instance.websocket = websocket;
201
+
202
+ const beforeExecute = () => {
203
+ if (instance.messageThreadsRunning) {
204
+ const stillRunning = instance.messageThreads.some((i) => runtime.isActiveThread(i));
205
+ if (!stillRunning) {
206
+ if (instance.messageQueue.length === 0) {
207
+ instance.messageThreadsRunning = false;
208
+ instance.messageThreads = [];
209
+ } else {
210
+ instance.data = instance.messageQueue.shift();
211
+ instance.messageThreads = runtime.startHats("gsaWebsocket_onMessage", null, target);
212
+ }
213
+ }
214
  }
215
+ };
216
+
217
+ vm.runtime.on("BEFORE_EXECUTE", beforeExecute);
218
+ websocket.onopen = () => {
219
+ for (const item of instance.sendOnceConnected) websocket.send(item);
220
+ instance.sendOnceConnected.length = 0;
221
+ instance.connectThreads = runtime.startHats("gsaWebsocket_onOpen", null, target);
222
+ resolve();
223
+ };
224
+
225
+ websocket.onmessage = async (e) => {
226
+ if (instance.destroyed) return;
227
+ let data = e.data;
228
+ if (data instanceof Blob) data = await blobToDataURL(data);
229
+
230
+ // --- INTERCEPTION DE LA RÉPONSE DE VÉRIFICATION ---
231
+ try {
232
+ const json = JSON.parse(data);
233
+ if (json.type === "reponse_comparer") {
234
+ instance.verificationValide = json.valide; // true ou false
235
+ instance.verificationMessage = json.message; // Le message texte
236
+ }
237
+ } catch (err) {}
238
+
239
+ if (instance.messageThreadsRunning) {
240
+ instance.messageQueue.push(data);
241
+ } else {
242
+ instance.data = data;
243
+ instance.messageThreads = runtime.startHats("gsaWebsocket_onMessage", null, target);
244
+ instance.messageThreadsRunning = true;
245
+ }
246
+ };
247
+ }));
248
+ }
249
+
250
+ isConnected(_, utils) {
251
+ const instance = this.instances[utils.target.id];
252
+ return !!instance && !!instance.websocket && instance.websocket.readyState === WebSocket.OPEN;
253
+ }
254
+
255
+ messageData(_, utils) {
256
+ const instance = this.instances[utils.target.id];
257
+ return instance ? instance.data : "";
258
+ }
259
+
260
+ sendMessage(args, utils) {
261
+ const PAYLOAD = Cast.toString(args.PAYLOAD);
262
+ const instance = this.instances[utils.target.id];
263
+ if (!instance) return;
264
+ if (!instance.websocket || instance.websocket.readyState === WebSocket.CONNECTING) {
265
+ instance.sendOnceConnected.push(PAYLOAD);
266
+ } else {
267
+ instance.websocket.send(PAYLOAD);
268
+ }
269
+ }
270
+
271
+ closeWithoutReason(_, utils) {
272
+ const instance = this.instances[utils.target.id];
273
+ if (!instance) return;
274
+ instance.destroyed = true;
275
+ if (instance.websocket) instance.websocket.close();
276
+ }
277
+ }
278
 
279
+ Scratch.extensions.register(new WebSocketExtension());
280
+ })(Scratch);