195 lines
8.4 KiB
JavaScript
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);
|
|
}
|
|
});
|