Version de test. Met en évidence l'auteur (OP), les citations, les PEMT, et vos propres messages sur tous les forums JVC.
当前为
// ==UserScript==
// @name Surlignage Post
// @namespace http://tampermonkey.net/
// @version 0.8.3
// @description Version de test. Met en évidence l'auteur (OP), les citations, les PEMT, et vos propres messages sur tous les forums JVC.
// @author FaceDePet
// @match *://www.jeuxvideo.com/forums/*
// @grant GM_xmlhttpRequest
// @run-at document-end
// @license MIT
// ==/UserScript==
(function() {
'use strict';
class JVCTopicEnhancer {
constructor() {
this.CACHE_KEY_OP = 'jvcTopicEnhancerCacheOP';
this.CACHE_KEY_POSTS = 'jvcUserPostsCache';
this.MAX_CACHED_POSTS_PER_TOPIC = 20;
this.pemtColors = ['#1abc9c', '#3498db', '#9b59b6', '#e67e22', '#e74c3c'];
this.init();
}
async init() {
this.topicId = this.getTopicId();
if (!this.topicId) {
console.error("JVC Enhancer: Impossible de trouver l'ID du topic sur cette URL.");
return;
}
this.currentPage = this.getCurrentPageNumber();
this.currentUser = this.getCurrentUsername();
this.addPostListener();
try {
const [opUsername, userMessages] = await Promise.all([
this.getOpUsername(),
this.currentUser ? this.getAllUserMessageContents() : []
]);
this.opUsername = opUsername;
this.currentUserMessages = userMessages;
} catch (error) {
console.error("JVC Enhancer: Erreur lors de la récupération des données.", error);
return;
}
this.highlightRules = [
{ name: 'Original Poster', condition: (author) => author === this.opUsername },
{ name: 'User Mention', condition: (author, el) => this.isUserMentioned(author, el) },
{ name: 'Self', condition: (author) => author === this.currentUser }
];
this.injectStyles();
this.processMessages();
}
getTopicId() {
// Regex assouplie pour fonctionner sur tous les forums
const match = window.location.href.match(/\/forums\/\d+-\d+-(\d+)-/);
return match ? match[1] : null;
}
getCurrentPageNumber() {
const match = window.location.href.match(/-(\d+)-0-1-0-/);
return match ? parseInt(match[1], 10) : 1;
}
async getOpUsername() {
const cache = JSON.parse(sessionStorage.getItem(this.CACHE_KEY_OP)) || {};
if (cache[this.topicId]) return cache[this.topicId];
let newOpUsername = (this.currentPage === 1)
? this.parseOpUsernameFromDocument(document)
: await this.fetchOpUsernameFromPageOne();
if (newOpUsername) {
cache[this.topicId] = newOpUsername;
sessionStorage.setItem(this.CACHE_KEY_OP, JSON.stringify(cache));
}
return newOpUsername;
}
parseOpUsernameFromDocument(doc, isApi = false) {
const selector = isApi ? '.post .bloc-pseudo-msg' : '.bloc-message-forum .bloc-pseudo-msg';
return doc.querySelector(selector)?.textContent.trim() || null;
}
fetchOpUsernameFromPageOne() {
return this.fetchPageContent(1).then(doc => this.parseOpUsernameFromDocument(doc, true));
}
fetchPageContent(pageNumber) {
return new Promise((resolve, reject) => {
const currentPattern = `-${this.currentPage}-0-1-0-`;
const newPattern = `-${pageNumber}-0-1-0-`;
const pageUrl = window.location.href.replace(new RegExp(currentPattern), newPattern);
const apiUrl = pageUrl.replace('www.jeuxvideo.com', 'api.jeuxvideo.com');
GM_xmlhttpRequest({
method: "GET",
url: apiUrl,
onload: (res) => resolve(new DOMParser().parseFromString(res.responseText, "text/html")),
onerror: (err) => reject(err)
});
});
}
async getAllUserMessageContents() {
const cachedPosts = this.loadUserPostsFromCache();
let pagePosts = this.parseMessagesFromDocument(document);
let prevPagePosts = [];
if (this.currentPage > 1) {
try {
const prevPageDoc = await this.fetchPageContent(this.currentPage - 1);
prevPagePosts = this.parseMessagesFromDocument(prevPageDoc, true);
} catch (e) { console.error("JVC Enhancer: Impossible de charger la page N-1.", e); }
}
const allMessages = [...cachedPosts, ...pagePosts, ...prevPagePosts];
return [...new Set(allMessages)];
}
parseMessagesFromDocument(doc, isApi = false) {
const messages = [];
const sel = { msg: isApi ? '.post' : '.bloc-message-forum', pseudo: isApi ? '.bloc-pseudo-msg' : '.bloc-pseudo-msg', content: isApi ? '.message' : '.txt-msg' };
doc.querySelectorAll(sel.msg).forEach(msg => {
if (msg.querySelector(sel.pseudo)?.textContent.trim() === this.currentUser) {
const text = msg.querySelector(sel.content)?.textContent;
if (text) messages.push(this.normalizeText(text));
}
});
return messages;
}
addPostListener() {
const postButton = document.querySelector('.postMessage');
if (postButton) {
postButton.addEventListener('click', () => {
const messageTextarea = document.querySelector('#message_topic, .messageEditor__edit');
if (messageTextarea && messageTextarea.value && this.topicId) {
this.saveUserPostToCache(this.normalizeText(messageTextarea.value));
}
}, true);
}
}
saveUserPostToCache(normalizedText) {
try {
const cache = JSON.parse(localStorage.getItem(this.CACHE_KEY_POSTS)) || {};
if (!cache[this.topicId]) cache[this.topicId] = [];
cache[this.topicId].unshift(normalizedText);
cache[this.topicId] = cache[this.topicId].slice(0, this.MAX_CACHED_POSTS_PER_TOPIC);
localStorage.setItem(this.CACHE_KEY_POSTS, JSON.stringify(cache));
} catch (e) { console.error("JVC Enhancer: Erreur de sauvegarde du cache.", e); }
}
loadUserPostsFromCache() {
try {
const cache = JSON.parse(localStorage.getItem(this.CACHE_KEY_POSTS)) || {};
return cache[this.topicId] || [];
} catch (e) { console.error("JVC Enhancer: Erreur de lecture du cache.", e); return []; }
}
isUserMentioned(author, el) {
if (!this.currentUser || author === this.currentUser) return false;
const content = el.querySelector('.txt-msg');
if (!content) return false;
const normText = this.normalizeText(content.textContent);
if (normText.includes(this.normalizeText(this.currentUser))) return true;
for (const quote of el.querySelectorAll('blockquote.blockquote-jv')) {
const cleanQuote = this.normalizeText(quote.textContent.replace(/^Le .+? :/s, ''));
if (cleanQuote && this.currentUserMessages.some(msg => msg.includes(cleanQuote))) return true;
}
return false;
}
normalizeText(text) {
return text ? text.toLowerCase().replace(/\s+/g, ' ').trim() : '';
}
getCurrentUsername() {
return document.querySelector('.headerAccount__pseudo')?.textContent.trim() || null;
}
injectStyles() {
const styles = `
.jvc-enhancer-op { /*background-color: rgba(0, 123, 255, 0.05);*/ /*border-left: 3px solid #007bff;*/ }
.jvc-enhancer-mention { background-color: rgba(255, 193, 7, 0.07); border-left: 3px solid #ffc107; }
.jvc-enhancer-op-mention { background-color: rgba(138, 43, 226, 0.07); border-left: 3px solid #8a2be2; }
.jvc-enhancer-pemt { background-color: rgba(0, 0, 0, 0.03); border-left-width: 3px; border-left-style: solid; }
.jvc-enhancer-self { box-shadow: inset 0 0 0 1px rgba(128, 128, 128, 0.2); }
html:not(.theme-light) .jvc-enhancer-self { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.1); }
.bloc-avatar-msg { position: relative; }
.jvc-enhancer-avatar-badge {
position: absolute; bottom: -12px; left: 50%; transform: translateX(-50%); z-index: 2;
padding: 2px 6px; font-size: 9px; font-weight: bold; border-radius: 5px;
white-space: nowrap; text-transform: uppercase; letter-spacing: 0.5px;
backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
border: 1px solid rgba(255, 255, 255, 0.1); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
}
.badge-op { background-color: rgba(128, 128, 128, 0.6); color: rgba(255, 255, 255, 0.8); /*background-color: rgba(0, 123, 255, 0.85); color: white;*/ }
.badge-mention { background-color: rgba(255, 193, 7, 0.85); color: #212529; }
.badge-op-mention { background-color: rgba(138, 43, 226, 0.85); color: white; }
.badge-pemt { color: white; }
.badge-self { background-color: rgba(128, 128, 128, 0.6); color: rgba(255, 255, 255, 0.8); }
`;
const styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
}
processMessages() {
const messages = Array.from(document.querySelectorAll('.bloc-message-forum'));
messages.forEach(el => {
const author = el.querySelector('.bloc-pseudo-msg')?.textContent.trim();
if (!author) return;
const isOp = this.highlightRules[0].condition(author);
const isMention = this.highlightRules[1].condition(author, el);
const isSelf = this.highlightRules[2].condition(author);
let hClass = '', bText = '', bClass = '';
if (isSelf) {
hClass = 'jvc-enhancer-self'; bText = 'VOUS'; bClass = 'badge-self';
}
else if (isOp && isMention) {
hClass = 'jvc-enhancer-op-mention'; bText = 'OP (CITÉ)'; bClass = 'badge-op-mention';
} else if (isOp) {
hClass = 'jvc-enhancer-op'; bText = 'OP'; bClass = 'badge-op';
} else if (isMention) {
hClass = 'jvc-enhancer-mention'; bText = 'CITÉ'; bClass = 'badge-mention';
}
if (hClass) el.classList.add(hClass);
if (bText) this.createAvatarBadge(el, bText, bClass);
});
let pemtGroupIndex = 0;
for (let i = 0; i < messages.length - 1; i++) {
const time = messages[i].querySelector('.bloc-date-msg a')?.textContent.match(/\d{2}:\d{2}:\d{2}$/)?.[0];
if (!time) continue;
const group = [messages[i]];
for (let j = i + 1; j < messages.length; j++) {
if (messages[j].querySelector('.bloc-date-msg a')?.textContent.match(/\d{2}:\d{2}:\d{2}$/)?.[0] === time) {
group.push(messages[j]);
} else {
break;
}
}
if (group.length > 1) {
const color = this.pemtColors[pemtGroupIndex % this.pemtColors.length];
group.forEach(msg => {
msg.classList.add('jvc-enhancer-pemt');
msg.style.borderLeftColor = color;
if (!msg.querySelector('.jvc-enhancer-avatar-badge')) {
this.createAvatarBadge(msg, 'PEMT', 'badge-pemt', color);
}
});
pemtGroupIndex++;
i += group.length - 1;
}
}
}
createAvatarBadge(el, text, bClass, color = null) {
const container = el.querySelector('.bloc-avatar-msg');
if (!container) return;
const badge = document.createElement('span');
badge.className = `jvc-enhancer-avatar-badge ${bClass}`;
badge.textContent = text;
if (color) {
badge.style.backgroundColor = `${color}D9`;
}
container.appendChild(badge);
}
}
new JVCTopicEnhancer();
})();