« Fonctionnement technique de Jeuxvideo.com » : différence entre les versions
m Remplacement de texte : « {{TableauCatégories}} » par « » |
Plages réseau - à wikifier |
||
| (55 versions intermédiaires par 10 utilisateurs non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
{{Bannière Incomplet}} | |||
{{Bannière Info|Contenu=Cette page détaille le fonctionnement technique de jeuxvideo.com. L'API v4 du site est quant à elle documentée sur [[Documentation de l'API Jeuxvideo.com]].}} | |||
== Introduction == | == Introduction == | ||
[[Jeuxvideo.com]] utilise 2 serveurs frontaux qui sont depuis le 7 mai 2022 protégés par le service [https://cloudflare.com Cloudflare]. Chaque serveur frontal utilise un serveur HTTP Apache, tout ce qu'il y a de plus classique. En revanche, avant d'arriver sur le serveur Apache, on a plusieurs mailles dans la chaîne. En effet, lorsque vous faites une requête auprès de JVC, la chaîne suivante est effectuée avant d'arriver jusqu'au back-end : | [[Jeuxvideo.com]] utilise 2 serveurs frontaux qui sont depuis le 7 mai 2022 protégés par le service [https://cloudflare.com Cloudflare]. Chaque serveur frontal utilise un serveur HTTP Apache, tout ce qu'il y a de plus classique. En revanche, avant d'arriver sur le serveur Apache, on a plusieurs mailles dans la chaîne. En effet, lorsque vous faites une requête auprès de JVC, la chaîne suivante est effectuée avant d'arriver jusqu'au back-end : | ||
| Ligne 75 : | Ligne 79 : | ||
Comme dit précédemment, Respawn semble être un mélange de MVC et de code classique sans modèle particulier de respecté. Les fichiers du back-end sont également mitigés du côté de leur appellation, laissant encore droit au mélange entre Français et Anglais. Exemples de fichiers côté back-end : | Comme dit précédemment, Respawn semble être un mélange de MVC et de code classique sans modèle particulier de respecté. Les fichiers du back-end sont également mitigés du côté de leur appellation, laissant encore droit au mélange entre Français et Anglais. Exemples de fichiers côté back-end : | ||
/opt/datas/JEUXVIDEO.COM/htdocs/forums/liste_topic.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/modeles/core/OiPDOStatement.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/modeles/sso/Transaction.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/modeles/GoogleTagManager.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/modeles/sso/Compte.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/controllers/forum/liste_topic.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/modeles/sso/Session.php<br> | |||
/opt/datas/JEUXVIDEO.COM/app/vendor/... | |||
=== Nommage des fonctions === | === Nommage des fonctions === | ||
Respawn possède aussi des fonctions dont le nommage est entre le Français et l'Anglais. Exemples de fonctions côté back-end : | Respawn possède aussi des fonctions dont le nommage est entre le Français et l'Anglais. Exemples de fonctions côté back-end : | ||
getInfoFromIdForum<br> | |||
loadMenu<br> | |||
checkMenuItem<br> | |||
getSingleton<br> | |||
getHtmlJeuForum<br> | |||
blocHtmlBoutiqueRandom | |||
=== Optimisations === | === Optimisations === | ||
| Ligne 130 : | Ligne 132 : | ||
=== Recherche des forums === | === Recherche des forums === | ||
La recherche des forums utilise le moteur de recherche Sphinx qui est intégré au site. La recherche des forums est limitée à 1 mois sur les blablas, elle peut être contournée via https://jvarchive. | La recherche des forums utilise le moteur de recherche Sphinx qui est intégré au site. La recherche des forums est limitée à 1 mois sur les blablas, elle peut être contournée via https://jvarchive.net/. | ||
=== Sécurité informatique === | === Sécurité informatique === | ||
| Ligne 140 : | Ligne 142 : | ||
=== JvCare === | === JvCare === | ||
JvCare est un | JvCare est un algorithme d'obfuscation des liens externes postés sur le site. Il a été développé depuis Respawn. Il permet d'éviter la création de backlinks qui pourraient optimiser indirectement le SEO de sites externes à Jeuxvideo.com. | ||
Les codes ci-après permettent de décoder une chaîne obfusquée. | Les codes ci-après permettent de décoder une chaîne obfusquée. | ||
| Ligne 147 : | Ligne 149 : | ||
function jvCare(string $classe) : string { | function jvCare(string $classe) : string { | ||
$base16 = "0A12B34C56D78E9F"; | static $base16 = "0A12B34C56D78E9F"; | ||
$lien = ""; | $lien = ""; | ||
$s = explode(" ", $classe)[1]; | $s = explode(" ", $classe)[1]; | ||
for ($i = 0; $i < | for ($i = 0; $i < strlen($s); $i += 2) { | ||
$lien .= chr(strrpos($base16, $s[$i]) * 16 + strrpos($base16, $s[$i+1])); | $lien .= chr(strrpos($base16, $s[$i]) * 16 + strrpos($base16, $s[$i + 1])); | ||
} | } | ||
return $lien; | return $lien; | ||
| Ligne 158 : | Ligne 160 : | ||
==== JavaScript ==== | ==== JavaScript ==== | ||
function | function jvCare(classe) { | ||
const base16 = '0A12B34C56D78E9F'; | const base16 = '0A12B34C56D78E9F'; | ||
let lien = <nowiki>''</nowiki>; | let lien = <nowiki>''</nowiki>; | ||
const s = classe.split(' ')[1]; | const s = classe.split(' ')[1]; | ||
for (let i = 0; i < s.length; i += 2) { | for (let i = 0; i < s.length; i += 2) { | ||
lien += String.fromCharCode(base16.indexOf(s. | lien += String.fromCharCode(base16.indexOf(s.at(i)) * 16 + base16.indexOf(s.at(i + 1))); | ||
} | } | ||
return lien; | return lien; | ||
} | |||
===== Fonctionnel ===== | |||
function jvCake(classe) { | |||
const base16 = '0A12B34C56D78E9F'; | |||
const s = classe.split(' ')[1]; | |||
const codeUnits = s | |||
.match(/../g) | |||
.map((i) => base16.indexOf(i[0]) * 16 + base16.indexOf(i[1])); | |||
return String.fromCharCode(...codeUnits); | |||
} | } | ||
| Ligne 171 : | Ligne 184 : | ||
def jvcare(classe: str) -> str: | def jvcare(classe: str) -> str: | ||
base16 = '0A12B34C56D78E9F' | |||
s = classe.split()[1] | |||
url = <nowiki>''</nowiki> | |||
for i, j in zip(s[0::2], s[1::2]): | |||
url += chr(base16.index(i) * 16 + base16.index(j)) | |||
return url | |||
===== Liste en compréhension ===== | |||
def jvcare(classe: str) -> str: | |||
base16 = '0A12B34C56D78E9F' | |||
s = classe.split()[1] | |||
return <nowiki>''</nowiki>.join([chr(base16.index(i) * 16 + base16.index(j)) for i, j in zip(s[0::2], s[1::2])]) | |||
==== C ==== | ==== C ==== | ||
#include <stdlib.h> | |||
#include <string.h> | |||
const char *__jvcarebase16 = "0A12B34C56D78E9F"; | const char *__jvcarebase16 = "0A12B34C56D78E9F"; | ||
char *jvcare(const char *class) { | char *jvcare(const char *class) { | ||
char *s = strchr(class, ' ') + 1; | |||
int urllen = strlen(s) / 2; | |||
char *url = malloc(urllen + 1); | |||
for (int i = 0; i < urllen; i++) { | |||
char pos1 = strchr(__jvcarebase16, s[i * 2]) - __jvcarebase16; | |||
char pos2 = strchr(__jvcarebase16, s[i * 2 + 1]) - __jvcarebase16; | |||
url[i] = pos1 * 16 + pos2; | |||
} | |||
url[urllen] = '\0'; | |||
return url; | |||
} | |||
==== Awk ==== | |||
BEGIN { | |||
base16 = "0A12B34C56D78E9F" | |||
} | |||
{ | |||
s = $2 | |||
for (i = 1; i < length(s); i += 2) { | |||
pos1 = index(base16, substr(s, i, 1)) | |||
pos2 = index(base16, substr(s, i + 1, 1)) | |||
url = url sprintf("%c", (pos1 - 1) * 16 + (pos2 - 1)) | |||
} | |||
print url | |||
} | } | ||
== Phoenix == | == Phoenix == | ||
Phoenix | Phoenix était une partie de JVC développée en Node.js et utilisant React. De plus en plus abandonnée au fil du temps, elle était utilisée pour afficher la liste des jeux et des contenus de la rédaction. Phoenix utilisait une API spéciale hébergée au sous-domaine [[Documentation_de_l%27API_Jeuxvideo.com#API_jvc.gg|''api.jvc.gg'']]. Phoenix ainsi que l'API GG disparaissent en février 2025 et les pages qu'elles servaient sont basculées vers la partie principale du site <ref>https://www.jeuxvideo.com/forums/message/1297456370</ref>. | ||
== Passage en React== | |||
'''Fin mai 2025,''' jvc commence à se baser pour certaines parties du site sur la librairie [https://fr.wikipedia.org/wiki/React React] , ce qui a une grosse influence sur les [[Script|userscripts]] . | |||
Insérer du texte manuellement, ne marche plus : | |||
<s>messageTextArea.value = message;</s> | |||
Heureusement, il existe '''un astuce très utilisée''' sur le web pour contourner ce soucis.<br>Voilà une variante de cette méthode fournie dans le code de JVChat d'après ce [https://www.jeuxvideo.com/forums/message/1286139785 message] : | |||
function fonctionReact(textarea, value) { | |||
const prototype = Object.getPrototypeOf(textarea); | |||
const nativeSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set; | |||
nativeSetter.call(textarea, value); | |||
textarea.dispatchEvent(new Event('input', { bubbles: true })); | |||
} | |||
Ensuite, il suffit simplement de faire appel à cette fonction quand on doit remplir une zone de texte : | |||
fonctionReact(messageTextArea, message); | |||
En 1er on donne la zone de texte ciblée et en 2nd le texte à insérer. | |||
Pour simplifier, <code><span style="color:red;">messageTextArea</span>.value = <span style="color:green;">message</span>;</code> devient <code>fonctionReact(<span style="color:red;">messageTextArea</span>, <span style="color:green;">message</span>);</code> avec cette fonction. | |||
Fonction de '''dernier recours''' (+ bas niveau : API DOM / Simule une vrai entrée clavier) '''à éviter''' ⚠️ sauf si la première méthode est bloquée : | |||
function fonctionReact(textarea, value) { | |||
textarea.setRangeText(value, 0, textarea.value.length, "end"); | |||
textarea.dispatchEvent(new Event("input", { bubbles: true })); | |||
} | |||
=== Fonction officielle JVC=== | |||
Par ailleurs, en dehors de cette méthode, JVC a proposé une entrée native pour interagir directement avec REACT :<br> | |||
<code>jvc.getMessageEditor();</code> (C'est une entrée partielle, pour réaliser des fonctions officielles du site.) | |||
https://www.jeuxvideo.com/forums/message/1286112457 | |||
jvc.getMessageEditor(".class").insertText(`mon texte`); // Place du texte à l'endroit sur le focus | |||
jvc.getMessageEditor(".class").insertStartLine(`mon texte`); // Place du texte en début de ligne. | |||
jvc.getMessageEditor(".class").selectedText; // Récupérer la sélection utilisateur. | |||
PS : Pour garantir le bon fonctionnement, utilisez simplement <code>jvc.getMessageEditor();</code> et/ou <code>unsafeWindow.jvc.getMessageEditor();</code> <ref>Les userscripts sont exécutés dans un environnement isolé (appelé sandbox), ce qui empêche parfois l’accès direct aux objets définis dans le contexte global de la page, comme "window" .</ref>. <br> | |||
Il est nécessaire de faire appel à <code>jvc.getMessageEditor();</code> à chaque modification, sinon vous travaillerez avec une version antérieure. | |||
Cette fonction prend directement en compte des sélecteurs CSS et pas des éléments, exemple : | |||
let selector = "#message_topic"; | |||
jvc.getMessageEditor(selector).insertText('text'); //✅ Marche | |||
let selector = document.getElementById("message_topic"); | |||
jvc.getMessageEditor(selector).insertText('text'); //❌ Ne marche pas | |||
Cependant, cette fonction présente plusieurs avantages notables : elle est à la fois native à JVC et intégrée au fonctionnement de React. | |||
De plus, contrairement à une modification directe du champ texte via JavaScript, cette fonction ne nécessite aucune gestion manuelle du curseur, de la sélection ou des espaces, tout est automatiquement pris en charge par la fonction elle-même. | |||
En revanche, pour manipuler le champ entièrement (suppression, remplacement) {{fleched}} la fonction a moins d'intérêt.<br> | |||
De plus, elle ne fonctionne que sur JVC, et ce n'est pas une fonction JavaScript universelle, contrairement à la précédente. | |||
== Opps! == | |||
Jeuxvideo.com peut afficher des erreurs du type "Opps!", ce qui a valu la création d'un [[délire]] et même d'un [[smiley]] officiel. | |||
Le 7 mars 2026, un forumeur écrit avoir reçu le message ci-dessous lors d'un ''downtime'' du site : | |||
'''ERROR: PL/Proxy function public.get_nb_previous_message(3): [forums6] PQconnectPoll: connection to server at "10.142.5.26", port 5432 failed: FATAL: remaining connection slots are reserved for non-replication superuser connections''' | |||
Ce message indique plusieurs choses : | |||
* Jeuxvideo.com utilise la plage 10.0.0.0/8 côté infrastructure, ce qui est très courant dans les entreprises, | |||
* PostgreSQL est toujours le moteur de base de données utilisé pour les accès au site, | |||
* Une table nommée "get_nb_previous_message" existe. Son intérêt est pour le moment inconnu. | |||
* Les connexions à PostgreSQL ne sont pas fermées, ce qui est un usage courant sur les sites Internet, afin d'éviter de se connecter en boucle à PostgreSQL et brider les délais d'affichage des pages. | |||
En revanche, il est totalement inconnu de la façon d'où cet utilisateur a eu le pouvoir de voir ce message, réservé à l'équipe technique. Il est possible que le proxy de première instance ai confondu une IPv4 source avec celle d'un utilisateur de l'équipe technique, mais ce n'est qu'une hypothèse. | |||
== Plages réseau == | |||
= | Certains sites permettent d'afficher des informations administratives et techniques sur le fonctionnement de Webedia et de Jeuxvideo.com, notamment du côté du partitionnement des plages IP. | ||
D'après https://nextly.net/search?text=Webedia : | |||
* | * Webedia possède des plages IP très larges, partant côté IPv4, du /24, jusqu'à un grand nombre de /22. Le prix à la revente dépasse les 100 000€, au minimum. | ||
* Étrangement, Webedia possède énormément de plages IPv6, notamment des /32 et /29. Ces plages sont totalement inutiles et polluent les bases RIPE, sachant que Jeuxvideo.com désactive IPv6 de base, et utilise les plages Cloudflare pour les accès IPv4. | |||
* Des blocs IPv4 /29 (donc non routables via BGP) ont été assignés auprès de Webedia, apparemment via le transitaire/FAI Zayo. L'usage est inconnu pour le moment. | |||
D'autre part, il est à noter que Webedia migre doucement son infrastructure sur Google Cloud. De fait, les plages seront sûrement revendues à bon prix. | |||
== Liens externes == | |||
*[http://www.journaldunet.com/solutions/itws/050426_it_jeuxvideo.shtml Interview sur l’architecture de jeuxvideo.com de 1997 à 2005] ([http://web.archive.org/web/20070629165914/http://www.journaldunet.com/solutions/itws/050426_it_jeuxvideo.shtml archive.org]) | |||
== Voir aussi == | ==Voir aussi== | ||
* [[Documentation de l'API Jeuxvideo.com]] | *[[Documentation de l'API Jeuxvideo.com]] | ||
{{SectionRéférences}} | {{SectionRéférences}} | ||
{{TableauCatégorieFonctionnementJVC}} | {{TableauCatégorieFonctionnementJVC}} | ||
[[Catégorie:Fonctionnement technique de Jeuxvideo.com]] | |||
[[Catégorie:Fonctionnement de | |||
[[Catégorie:Extensions et outils]] | [[Catégorie:Extensions et outils]] | ||