first init

This commit is contained in:
HackTips2
2026-05-31 00:19:17 +02:00
parent 1b6ebb03b4
commit 457fb6b2c4
12 changed files with 1653 additions and 0 deletions
Binary file not shown.
+60
View File
@@ -0,0 +1,60 @@
/*
* 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);
}
}
// 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);
}
});
// 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);
}
});
+20
View File
@@ -0,0 +1,20 @@
/*
* Nightcord Content Script
* Injected into discord.com — injects the main Nightcord bundle into the page.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
(function () {
// Inject Nightcord CSS
const style = document.createElement("link");
style.rel = "stylesheet";
style.href = chrome.runtime.getURL("dist/Nightcord.css");
document.documentElement.appendChild(style);
// Inject the main Nightcord JS bundle
const script = document.createElement("script");
script.src = chrome.runtime.getURL("dist/Nightcord.js");
script.type = "text/javascript";
(document.head ?? document.documentElement).appendChild(script);
})();
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

+87
View File
@@ -0,0 +1,87 @@
{
"manifest_version": 3,
"name": "Nightcord",
"description": "Everything Discord doesn't build, we create",
"version": "1.18.7",
"author": "Nightcord Contributors",
"homepage_url": "https://github.com/nightcordoff/nightcord",
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"default_title": "Nightcord"
},
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"content_scripts": [
{
"js": [
"content.js"
],
"matches": [
"*://discord.com/*",
"*://ptb.discord.com/*",
"*://canary.discord.com/*"
],
"run_at": "document_start",
"all_frames": true
}
],
"declarative_net_request": {
"rule_resources": [
{
"id": "csp-rules",
"enabled": true,
"path": "modifyResponseHeaders.json"
}
]
},
"permissions": [
"declarativeNetRequest",
"declarativeNetRequestFeedback",
"scripting",
"storage",
"notifications",
"contextMenus",
"clipboardWrite",
"clipboardRead",
"tabs"
],
"host_permissions": [
"*://discord.com/*",
"*://ptb.discord.com/*",
"*://canary.discord.com/*"
],
"web_accessible_resources": [
{
"resources": [
"dist/Nightcord.js",
"dist/Nightcord.css",
"dist/vendor/monaco/*"
],
"matches": [
"*://discord.com/*",
"*://ptb.discord.com/*",
"*://canary.discord.com/*"
]
}
],
"browser_specific_settings": {
"gecko": {
"id": "nightcord@nightcordoff.github.io",
"strict_min_version": "109.0",
"data_collection_permissions": {
"required": [
"none"
],
"optional": []
}
}
}
}
+50
View File
@@ -0,0 +1,50 @@
[
{
"id": 1,
"priority": 1,
"action": {
"type": "modifyHeaders",
"responseHeaders": [
{ "header": "content-security-policy", "operation": "remove" },
{ "header": "content-security-policy-report-only", "operation": "remove" },
{ "header": "x-frame-options", "operation": "remove" }
]
},
"condition": {
"urlFilter": "||discord.com/*",
"resourceTypes": ["main_frame", "sub_frame"]
}
},
{
"id": 2,
"priority": 1,
"action": {
"type": "modifyHeaders",
"responseHeaders": [
{ "header": "content-security-policy", "operation": "remove" },
{ "header": "content-security-policy-report-only", "operation": "remove" },
{ "header": "x-frame-options", "operation": "remove" }
]
},
"condition": {
"urlFilter": "||ptb.discord.com/*",
"resourceTypes": ["main_frame", "sub_frame"]
}
},
{
"id": 3,
"priority": 1,
"action": {
"type": "modifyHeaders",
"responseHeaders": [
{ "header": "content-security-policy", "operation": "remove" },
{ "header": "content-security-policy-report-only", "operation": "remove" },
{ "header": "x-frame-options", "operation": "remove" }
]
},
"condition": {
"urlFilter": "||canary.discord.com/*",
"resourceTypes": ["main_frame", "sub_frame"]
}
}
]
+362
View File
@@ -0,0 +1,362 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Nightcord</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
:root {
--bg: #08080f;
--bg2: #0e0e1a;
--bg3: #13131f;
--bg4: #1a1a2a;
--border: rgba(255,255,255,0.055);
--border2: rgba(255,255,255,0.10);
--purple: #8b5cf6;
--purple2: #6d28d9;
--purple3: #a78bfa;
--purple4: #c4b5fd;
--green: #4ade80;
--red: #f87171;
--text: #dde3f0;
--muted: #8892a4;
--dim: #4a5568;
--glow: rgba(139,92,246,0.18);
}
html, body {
width: 320px;
background: var(--bg);
color: var(--text);
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
overflow: hidden;
user-select: none;
}
/* ── Animated gradient bg ── */
body::before {
content: '';
position: fixed;
top: -60px; left: -60px;
width: 200px; height: 200px;
background: radial-gradient(circle, rgba(139,92,246,0.12) 0%, transparent 70%);
pointer-events: none;
animation: bgPulse 4s ease-in-out infinite alternate;
}
@keyframes bgPulse {
from { opacity: 0.5; transform: scale(1); }
to { opacity: 1; transform: scale(1.15); }
}
/* ── Header ── */
.header {
display: flex;
align-items: center;
gap: 11px;
padding: 15px 15px 13px;
background: linear-gradient(180deg, rgba(139,92,246,0.1) 0%, transparent 100%);
border-bottom: 1px solid var(--border);
position: relative;
}
.header::after {
content: '';
position: absolute;
bottom: -1px; left: 0; right: 0;
height: 1px;
background: linear-gradient(90deg, transparent 0%, rgba(139,92,246,0.5) 50%, transparent 100%);
}
.logo-wrap {
position: relative;
flex-shrink: 0;
}
.logo-ring {
position: absolute;
inset: -3px;
border-radius: 11px;
background: conic-gradient(from 0deg, transparent 60%, rgba(139,92,246,0.6) 80%, transparent 100%);
animation: logoSpin 4s linear infinite;
}
@keyframes logoSpin {
to { transform: rotate(360deg); }
}
.logo-inner {
position: relative;
z-index: 1;
border-radius: 9px;
overflow: hidden;
width: 34px; height: 34px;
}
.logo-inner img {
width: 34px; height: 34px;
display: block;
}
.logo-dot {
position: absolute;
bottom: -1px; right: -1px;
z-index: 2;
width: 10px; height: 10px;
border-radius: 50%;
background: var(--dim);
border: 2px solid var(--bg);
transition: background .4s, box-shadow .4s;
}
.logo-dot.live {
background: var(--green);
box-shadow: 0 0 8px rgba(74,222,128,0.7);
}
.header-text { flex: 1; }
.logo-name {
font-size: 15px;
font-weight: 800;
color: #fff;
letter-spacing: -0.3px;
background: linear-gradient(135deg, #fff 40%, var(--purple4) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.logo-sub {
font-size: 10px;
color: var(--dim);
margin-top: 2px;
letter-spacing: 0.2px;
}
.ver-pill {
font-size: 10px;
font-weight: 700;
padding: 4px 10px;
background: linear-gradient(135deg, rgba(139,92,246,0.18), rgba(109,40,217,0.18));
border: 1px solid rgba(139,92,246,0.35);
border-radius: 20px;
color: var(--purple4);
letter-spacing: 0.4px;
text-shadow: 0 0 10px rgba(167,139,250,0.4);
}
/* ── Panel ── */
.panel { padding: 10px 10px 4px; display: flex; flex-direction: column; gap: 6px; }
.option-row {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 12px;
padding: 12px 13px;
display: flex;
align-items: center;
gap: 12px;
transition: all .2s;
cursor: default;
position: relative;
overflow: hidden;
}
.option-row::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at 30% 50%, rgba(139,92,246,0.06) 0%, transparent 70%);
opacity: 0;
transition: opacity .2s;
pointer-events: none;
}
.option-row:hover { background: var(--bg3); border-color: var(--border2); }
.option-row:hover::before { opacity: 1; }
.option-row.on {
border-color: rgba(139,92,246,0.35);
background: rgba(139,92,246,0.07);
box-shadow: 0 0 0 1px rgba(139,92,246,0.1) inset, 0 2px 12px rgba(139,92,246,0.08);
}
.option-row.on::before { opacity: 1; }
.opt-icon {
width: 36px; height: 36px;
border-radius: 11px;
background: rgba(139,92,246,0.10);
border: 1px solid rgba(139,92,246,0.15);
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
transition: all .2s;
}
.option-row.on .opt-icon {
background: rgba(139,92,246,0.22);
border-color: rgba(139,92,246,0.4);
box-shadow: 0 0 10px rgba(139,92,246,0.25);
}
.opt-icon svg { width: 17px; height: 17px; fill: var(--purple3); }
.opt-text { flex: 1; }
.opt-name { font-size: 12px; font-weight: 700; color: var(--text); }
.opt-sub { font-size: 10px; color: var(--dim); margin-top: 2px; line-height: 1.4; }
/* Toggle */
.tog { position: relative; width: 42px; height: 23px; flex-shrink: 0; cursor: pointer; }
.tog input { position: absolute; opacity: 0; width: 0; height: 0; }
.tog-track {
position: absolute; inset: 0;
border-radius: 23px;
background: var(--bg4);
border: 1.5px solid rgba(255,255,255,0.07);
transition: background .25s, border-color .25s, box-shadow .25s;
}
.tog input:checked ~ .tog-track {
background: linear-gradient(135deg, var(--purple), var(--purple2));
border-color: rgba(139,92,246,0.55);
box-shadow: 0 0 10px rgba(139,92,246,0.4), 0 0 4px rgba(139,92,246,0.2) inset;
}
.tog-knob {
position: absolute;
top: 3px; left: 3px;
width: 15px; height: 15px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 4px rgba(0,0,0,0.5);
transition: transform .25s cubic-bezier(.34,1.4,.64,1);
pointer-events: none;
}
.tog input:checked ~ .tog-knob { transform: translateX(19px); }
/* ── Divider ── */
.divider {
height: 1px;
background: linear-gradient(90deg, transparent 0%, var(--border2) 30%, var(--border2) 70%, transparent 100%);
margin: 6px 10px;
}
/* ── Links ── */
.links {
display: flex;
gap: 6px;
padding: 0 10px 8px;
}
.link-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 5px;
padding: 8px 6px;
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 10px;
color: var(--dim);
font-size: 10px;
font-weight: 700;
cursor: pointer;
transition: all .2s;
text-decoration: none;
letter-spacing: 0.3px;
position: relative;
overflow: hidden;
}
.link-btn::after {
content: '';
position: absolute;
inset: 0;
opacity: 0;
transition: opacity .2s;
border-radius: inherit;
}
.link-btn:hover { transform: translateY(-1px); }
.link-btn svg { width: 13px; height: 13px; fill: currentColor; flex-shrink: 0; }
.link-btn.github:hover { color: #e2e8f0; border-color: rgba(226,232,240,0.25); background: rgba(226,232,240,0.05); box-shadow: 0 3px 10px rgba(0,0,0,0.3); }
.link-btn.discord:hover { color: #7289da; border-color: rgba(114,137,218,0.4); background: rgba(114,137,218,0.08); box-shadow: 0 3px 10px rgba(114,137,218,0.15); }
.link-btn.website:hover { color: var(--purple4); border-color: rgba(139,92,246,0.4); background: rgba(139,92,246,0.08); box-shadow: 0 3px 10px rgba(139,92,246,0.15); }
/* ── Footer ── */
.footer {
padding: 8px 14px 11px;
border-top: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
}
.footer-status {
font-size: 10px;
color: var(--dim);
display: flex;
align-items: center;
gap: 5px;
transition: color .3s;
}
.footer-status.active { color: var(--muted); }
.status-dot {
display: inline-block;
width: 6px; height: 6px;
border-radius: 50%;
background: var(--dim);
flex-shrink: 0;
transition: background .3s, box-shadow .3s;
}
.status-dot.active {
background: var(--green);
box-shadow: 0 0 6px rgba(74,222,128,0.6);
animation: dotPulse 2s ease-in-out infinite;
}
@keyframes dotPulse {
0%, 100% { box-shadow: 0 0 5px rgba(74,222,128,0.5); }
50% { box-shadow: 0 0 10px rgba(74,222,128,0.9); }
}
.debug { font-size: 9px; color: var(--dim); font-family: monospace; opacity: 0.4; }
</style>
</head>
<body>
<div class="header">
<div class="logo-wrap">
<div class="logo-ring"></div>
<div class="logo-inner">
<img src="icon.png" alt="Nightcord">
</div>
<span class="logo-dot" id="statusDot"></span>
</div>
<div class="header-text">
<div class="logo-name">Nightcord</div>
<div class="logo-sub">Discord Enhancement</div>
</div>
<span class="ver-pill">v1.18.7</span>
</div>
<div class="panel">
<div class="option-row" id="row">
<div class="opt-icon">
<svg viewBox="0 0 24 24"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
</div>
<div class="opt-text">
<div class="opt-name">Auto-inject</div>
<div class="opt-sub">Injecter automatiquement à l'ouverture de Discord</div>
</div>
<label class="tog">
<input type="checkbox" id="chk">
<div class="tog-track"></div>
<div class="tog-knob"></div>
</label>
</div>
</div>
<div class="divider"></div>
<div class="links">
<button class="link-btn github" id="btnGithub">
<svg viewBox="0 0 24 24"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.44 9.8 8.2 11.38.6.11.82-.26.82-.58v-2.03c-3.34.73-4.04-1.61-4.04-1.61-.54-1.38-1.33-1.75-1.33-1.75-1.09-.74.08-.73.08-.73 1.2.08 1.84 1.24 1.84 1.24 1.07 1.83 2.8 1.3 3.49 1 .1-.78.42-1.3.76-1.6-2.67-.3-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.14-.3-.54-1.52.1-3.18 0 0 1.01-.32 3.3 1.23a11.5 11.5 0 0 1 3-.4c1.02 0 2.04.13 3 .4 2.28-1.55 3.29-1.23 3.29-1.23.65 1.66.24 2.88.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.81 5.63-5.48 5.92.43.37.81 1.1.81 2.22v3.29c0 .32.22.69.83.57C20.57 21.8 24 17.3 24 12c0-6.63-5.37-12-12-12z"/></svg>
GitHub
</button>
<button class="link-btn discord" id="btnDiscord">
<svg viewBox="0 0 24 24"><path d="M20.32 4.37A19.8 19.8 0 0 0 15.33 3c-.22.4-.48.93-.65 1.35a18.3 18.3 0 0 0-5.36 0A14.6 14.6 0 0 0 8.67 3 19.9 19.9 0 0 0 3.68 4.38C.53 9.17-.32 13.84.1 18.44a20 20 0 0 0 6.07 3.04 14.9 14.9 0 0 0 1.3-2.1 13 13 0 0 1-2.05-.98l.5-.38a14.28 14.28 0 0 0 12.16 0l.5.38c-.64.38-1.33.7-2.05.98a14.8 14.8 0 0 0 1.3 2.1 19.94 19.94 0 0 0 6.07-3.05c.5-5.17-.83-9.8-3.58-13.86zM8.01 15.52c-1.18 0-2.15-1.08-2.15-2.41 0-1.33.95-2.42 2.15-2.42 1.2 0 2.17 1.09 2.15 2.42 0 1.33-.95 2.41-2.15 2.41zm7.98 0c-1.18 0-2.15-1.08-2.15-2.41 0-1.33.95-2.42 2.15-2.42 1.2 0 2.16 1.09 2.15 2.42 0 1.33-.94 2.41-2.15 2.41z"/></svg>
Discord
</button>
<button class="link-btn website" id="btnWebsite">
<svg viewBox="0 0 24 24"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></svg>
Site web
</button>
</div>
<div class="footer">
<span class="footer-status" id="ftxt">
<span class="status-dot" id="dot"></span>
Prêt
</span>
<span class="debug" id="dbg"></span>
</div>
<script src="popup.js"></script>
</body>
</html>
+85
View File
@@ -0,0 +1,85 @@
var chk = document.getElementById('chk');
var row = document.getElementById('row');
var dbg = document.getElementById('dbg');
var ftxt = document.getElementById('ftxt');
var statusDot = document.getElementById('statusDot');
/* ── Liens ── */
document.getElementById('btnGithub').addEventListener('click', function() {
chrome.tabs.create({ url: 'https://github.com/nightcordoff/nightcord' });
});
document.getElementById('btnDiscord').addEventListener('click', function() {
chrome.tabs.create({ url: 'https://discord.gg/nightcord' });
});
document.getElementById('btnWebsite').addEventListener('click', function() {
chrome.tabs.create({ url: 'https://nightcord.su' });
});
/* ── UI ── */
function setUI(val) {
chk.checked = val;
row.classList.toggle('on', val);
var dot = ftxt.querySelector('.status-dot');
if (val) {
if (dot) { dot.className = 'status-dot active'; }
ftxt.childNodes[ftxt.childNodes.length - 1].textContent = 'Auto-inject actif';
ftxt.classList.add('active');
statusDot.classList.add('live');
} else {
if (dot) { dot.className = 'status-dot'; }
ftxt.childNodes[ftxt.childNodes.length - 1].textContent = 'Désactivé';
ftxt.classList.remove('active');
statusDot.classList.remove('live');
}
}
function log(msg) { dbg.textContent = msg; }
/* ── Lecture ── */
function loadValue() {
try {
chrome.storage.local.get('nc_autoInject', function(result) {
if (chrome.runtime.lastError) { log(chrome.runtime.lastError.message); fallback(); return; }
var val = result['nc_autoInject'];
/* Si jamais défini → true par défaut */
setUI(val !== false);
if (val === undefined) saveValue(true);
});
} catch(e) { log(String(e)); fallback(); }
}
function fallback() {
try {
var v = localStorage.getItem('nc_autoInject');
setUI(v !== 'false');
if (v === null) saveValue(true);
} catch(e) { setUI(true); }
}
/* ── Sauvegarde ── */
function saveValue(val) {
try {
chrome.storage.local.set({ nc_autoInject: val }, function() {
if (chrome.runtime.lastError) log(chrome.runtime.lastError.message);
});
} catch(e) {}
try { localStorage.setItem('nc_autoInject', String(val)); } catch(e) {}
}
/* ── Toggle ── */
chk.addEventListener('change', function() {
saveValue(chk.checked);
setUI(chk.checked);
});
/* ── Texte du footer (nœuds) ── */
(function fixFooter() {
/* S'assure qu'il y a bien un TextNode après le span .status-dot */
var span = ftxt.querySelector('.status-dot');
if (span && !span.nextSibling) {
ftxt.appendChild(document.createTextNode('Prêt'));
}
})();
loadValue();
+1
View File
File diff suppressed because one or more lines are too long
+849
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long