Files
firefox/background.js
2026-06-04 01:43:55 +02:00

195 lines
8.4 KiB
JavaScript

/*
* Nightcord Background Service Worker
* Injecte Nightcord.js dans le MAIN world de Discord via chrome.scripting.executeScript.
* Cette méthode bypass la CSP de Discord car l'injection se fait depuis le contexte
* privilegié de l'extension, non depuis un script dans la page.
*/
const DISCORD_URLS = [
"*://discord.com/*",
"*://ptb.discord.com/*",
"*://canary.discord.com/*"
];
// Tracks tabs where Nightcord has already been injected to avoid double injection
const injectedTabs = new Set();
async function injectNightcord(tabId) {
if (injectedTabs.has(tabId)) return;
injectedTabs.add(tabId);
try {
// Inject CSS
await chrome.scripting.insertCSS({
target: { tabId },
files: ["dist/Nightcord.css"]
});
// Inject JS in MAIN world — this bypasses the page's CSP entirely
await chrome.scripting.executeScript({
target: { tabId },
files: ["dist/Nightcord.js"],
world: "MAIN"
});
console.log(`[Nightcord] Injected into tab ${tabId}`);
} catch (e) {
// Tab may have navigated away, ignore
injectedTabs.delete(tabId);
console.warn(`[Nightcord] Injection failed for tab ${tabId}:`, e.message);
}
}
// Show welcome popup overlay in Discord tab (first launch only)
async function maybeShowWelcomePopup(tabId) {
const result = await chrome.storage.local.get("nightcord_welcome_shown");
if (result.nightcord_welcome_shown) return;
await chrome.storage.local.set({ nightcord_welcome_shown: true });
// Wait 5 seconds after Discord is loaded, then inject the welcome overlay
setTimeout(async () => {
try {
await chrome.scripting.executeScript({
target: { tabId },
world: "MAIN",
func: () => {
// Avoid duplicate overlays
if (document.getElementById("nightcord-welcome-overlay")) return;
const overlay = document.createElement("div");
overlay.id = "nightcord-welcome-overlay";
overlay.style.cssText = `
position: fixed;
top: 0; left: 0; right: 0; bottom: 0;
z-index: 9999999;
background: rgba(0,0,0,0.75);
display: flex;
align-items: center;
justify-content: center;
font-family: 'gg sans', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
`;
const card = document.createElement("div");
card.style.cssText = `
background: #313338;
border-radius: 16px;
padding: 40px 48px;
display: flex;
flex-direction: column;
align-items: center;
gap: 24px;
box-shadow: 0 8px 48px rgba(0,0,0,0.5);
max-width: 420px;
width: 90%;
`;
const logo = document.createElement("img");
logo.src = "https://nightcord.online/logo.png";
logo.style.cssText = "width:72px;height:72px;border-radius:50%;object-fit:cover;";
logo.onerror = () => { logo.style.display = "none"; };
const title = document.createElement("div");
title.textContent = "Welcome to Nightcord!";
title.style.cssText = `
color: #fff;
font-size: 24px;
font-weight: 700;
text-align: center;
`;
const subtitle = document.createElement("div");
subtitle.textContent = "Join our community to get support, updates and more.";
subtitle.style.cssText = `
color: #b5bac1;
font-size: 15px;
text-align: center;
line-height: 1.5;
`;
const btn = document.createElement("a");
btn.href = "https://discord.gg/nightc";
btn.target = "_blank";
btn.rel = "noopener noreferrer";
btn.style.cssText = `
display: flex;
align-items: center;
gap: 12px;
background: #5865f2;
color: #fff;
font-size: 17px;
font-weight: 600;
padding: 14px 28px;
border-radius: 10px;
text-decoration: none;
cursor: pointer;
transition: background 0.15s;
`;
btn.onmouseover = () => { btn.style.background = "#4752c4"; };
btn.onmouseout = () => { btn.style.background = "#5865f2"; };
// Discord icon SVG
const iconWrapper = document.createElement("span");
iconWrapper.innerHTML = `<svg width="24" height="24" viewBox="0 0 24 24" fill="white" xmlns="http://www.w3.org/2000/svg"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057c.002.022.015.043.033.055a19.985 19.985 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.201 13.201 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/></svg>`;
const btnText = document.createElement("span");
btnText.textContent = "Join NightCord Community";
btn.appendChild(iconWrapper);
btn.appendChild(btnText);
const closeBtn = document.createElement("button");
closeBtn.textContent = "Maybe later";
closeBtn.style.cssText = `
background: none;
border: none;
color: #b5bac1;
font-size: 13px;
cursor: pointer;
padding: 4px 8px;
border-radius: 4px;
font-family: inherit;
`;
closeBtn.onmouseover = () => { closeBtn.style.color = "#fff"; };
closeBtn.onmouseout = () => { closeBtn.style.color = "#b5bac1"; };
closeBtn.onclick = () => overlay.remove();
card.appendChild(logo);
card.appendChild(title);
card.appendChild(subtitle);
card.appendChild(btn);
card.appendChild(closeBtn);
overlay.appendChild(card);
// Close on backdrop click
overlay.onclick = (e) => { if (e.target === overlay) overlay.remove(); };
document.body.appendChild(overlay);
}
});
} catch (e) {
console.warn("[Nightcord] Welcome popup failed:", e.message);
}
}, 5000);
}
// Listen for message from content.js signaling the page is ready
chrome.runtime.onMessage.addListener((msg, sender) => {
if (msg?.type === "NIGHTCORD_INJECT" && sender?.tab?.id) {
injectNightcord(sender.tab.id);
maybeShowWelcomePopup(sender.tab.id);
}
});
// Cleanup when tab is closed
chrome.tabs.onRemoved.addListener((tabId) => {
injectedTabs.delete(tabId);
});
// Also cleanup on navigation (SPA navigations stay in same tab)
chrome.tabs.onUpdated.addListener((tabId, changeInfo) => {
if (changeInfo.status === "loading") {
injectedTabs.delete(tabId);
}
});