Spaces:
Running
Running
Baue eine Eingabe Maske für ein sprach Assistenten. Einen Knopf für light und dark und red mode. Der red mode soll anschliesend unzensiert antworten geben. Dabei eine Übersicht der bisherigen chats zum ausklappen. Schwerpunkt Cyber security. Der Name RedSputnik. Es soll hacking sicher sein. Kotlin, html5, CSS alles in modern. Ddos sicher, IP Schutz und so weiter. Datei upload Möglichkeit. Es wird lokal auf meinem nas ala docker system laufen. Modernes design. Visuell schön
Browse files- README.md +7 -4
- components/footer.js +50 -0
- components/navbar.js +64 -0
- docker-compose.yml +51 -0
- index.html +114 -19
- script.js +134 -0
- security.md +32 -0
- style.css +59 -19
README.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji: 😻
|
| 4 |
colorFrom: blue
|
| 5 |
-
colorTo:
|
|
|
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
|
|
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: RedSputnik 🔴>>>
|
|
|
|
| 3 |
colorFrom: blue
|
| 4 |
+
colorTo: red
|
| 5 |
+
emoji: 🐳
|
| 6 |
sdk: static
|
| 7 |
pinned: false
|
| 8 |
+
tags:
|
| 9 |
+
- deepsite-v3
|
| 10 |
---
|
| 11 |
|
| 12 |
+
# Welcome to your new DeepSite project!
|
| 13 |
+
This project was created with [DeepSite](https://huggingface.co/deepsite).
|
components/footer.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomFooter extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
footer {
|
| 7 |
+
background: var(--footer-bg, #1a202c);
|
| 8 |
+
color: white;
|
| 9 |
+
padding: 1.5rem;
|
| 10 |
+
text-align: center;
|
| 11 |
+
margin-top: 2rem;
|
| 12 |
+
font-size: 0.875rem;
|
| 13 |
+
}
|
| 14 |
+
.footer-content {
|
| 15 |
+
max-width: 1200px;
|
| 16 |
+
margin: 0 auto;
|
| 17 |
+
display: flex;
|
| 18 |
+
flex-direction: column;
|
| 19 |
+
gap: 0.5rem;
|
| 20 |
+
}
|
| 21 |
+
.footer-links {
|
| 22 |
+
display: flex;
|
| 23 |
+
justify-content: center;
|
| 24 |
+
gap: 1rem;
|
| 25 |
+
margin-top: 0.5rem;
|
| 26 |
+
}
|
| 27 |
+
.footer-links a {
|
| 28 |
+
color: #a0aec0;
|
| 29 |
+
text-decoration: none;
|
| 30 |
+
transition: color 0.2s;
|
| 31 |
+
}
|
| 32 |
+
.footer-links a:hover {
|
| 33 |
+
color: white;
|
| 34 |
+
}
|
| 35 |
+
</style>
|
| 36 |
+
<footer>
|
| 37 |
+
<div class="footer-content">
|
| 38 |
+
<p>Secure cyber assistant with uncensored Red Mode</p>
|
| 39 |
+
<div class="footer-links">
|
| 40 |
+
<a href="#"><i data-feather="cpu"></i> Docker</a>
|
| 41 |
+
<a href="#"><i data-feather="lock"></i> Encryption</a>
|
| 42 |
+
<a href="#"><i data-feather="eye-off"></i> No Tracking</a>
|
| 43 |
+
</div>
|
| 44 |
+
<p>© ${new Date().getFullYear()} RedSputnik. Local execution only - no cloud.</p>
|
| 45 |
+
</div>
|
| 46 |
+
</footer>
|
| 47 |
+
`;
|
| 48 |
+
}
|
| 49 |
+
}
|
| 50 |
+
customElements.define('custom-footer', CustomFooter);
|
components/navbar.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
class CustomNavbar extends HTMLElement {
|
| 2 |
+
connectedCallback() {
|
| 3 |
+
this.attachShadow({ mode: 'open' });
|
| 4 |
+
this.shadowRoot.innerHTML = `
|
| 5 |
+
<style>
|
| 6 |
+
nav {
|
| 7 |
+
background: var(--nav-bg, linear-gradient(135deg, #dc2626 0%, #7f1d1d 100%));
|
| 8 |
+
padding: 1rem 2rem;
|
| 9 |
+
display: flex;
|
| 10 |
+
justify-content: space-between;
|
| 11 |
+
align-items: center;
|
| 12 |
+
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
| 13 |
+
}
|
| 14 |
+
.logo {
|
| 15 |
+
color: white;
|
| 16 |
+
font-weight: bold;
|
| 17 |
+
font-size: 1.25rem;
|
| 18 |
+
display: flex;
|
| 19 |
+
align-items: center;
|
| 20 |
+
gap: 0.5rem;
|
| 21 |
+
}
|
| 22 |
+
.nav-links {
|
| 23 |
+
display: flex;
|
| 24 |
+
gap: 1.5rem;
|
| 25 |
+
list-style: none;
|
| 26 |
+
margin: 0;
|
| 27 |
+
padding: 0;
|
| 28 |
+
}
|
| 29 |
+
a {
|
| 30 |
+
color: white;
|
| 31 |
+
text-decoration: none;
|
| 32 |
+
transition: opacity 0.2s;
|
| 33 |
+
display: flex;
|
| 34 |
+
align-items: center;
|
| 35 |
+
gap: 0.25rem;
|
| 36 |
+
font-size: 0.95rem;
|
| 37 |
+
}
|
| 38 |
+
a:hover {
|
| 39 |
+
opacity: 0.8;
|
| 40 |
+
}
|
| 41 |
+
@media (max-width: 640px) {
|
| 42 |
+
nav {
|
| 43 |
+
padding: 1rem;
|
| 44 |
+
}
|
| 45 |
+
.nav-links {
|
| 46 |
+
gap: 1rem;
|
| 47 |
+
}
|
| 48 |
+
}
|
| 49 |
+
</style>
|
| 50 |
+
<nav>
|
| 51 |
+
<a href="/" class="logo">
|
| 52 |
+
<i data-feather="satellite"></i>
|
| 53 |
+
RedSputnik
|
| 54 |
+
</a>
|
| 55 |
+
<ul class="nav-links">
|
| 56 |
+
<li><a href="#"><i data-feather="shield"></i> Security</a></li>
|
| 57 |
+
<li><a href="#"><i data-feather="terminal"></i> Commands</a></li>
|
| 58 |
+
<li><a href="#"><i data-feather="key"></i> API</a></li>
|
| 59 |
+
</ul>
|
| 60 |
+
</nav>
|
| 61 |
+
`;
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
customElements.define('custom-navbar', CustomNavbar);
|
docker-compose.yml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
```yaml
|
| 2 |
+
version: '3.8'
|
| 3 |
+
|
| 4 |
+
services:
|
| 5 |
+
redsputnik:
|
| 6 |
+
image: your-custom-image:latest
|
| 7 |
+
container_name: redsputnik
|
| 8 |
+
restart: unless-stopped
|
| 9 |
+
ports:
|
| 10 |
+
- "8080:8080"
|
| 11 |
+
volumes:
|
| 12 |
+
- ./data:/app/data
|
| 13 |
+
- ./config:/app/config
|
| 14 |
+
environment:
|
| 15 |
+
- RED_MODE_ENABLED=false
|
| 16 |
+
- MAX_FILE_SIZE=10MB
|
| 17 |
+
- RATE_LIMIT=100/1m
|
| 18 |
+
networks:
|
| 19 |
+
- redsputnik-net
|
| 20 |
+
|
| 21 |
+
# Additional security containers
|
| 22 |
+
nginx-proxy:
|
| 23 |
+
image: nginx:latest
|
| 24 |
+
ports:
|
| 25 |
+
- "80:80"
|
| 26 |
+
- "443:443"
|
| 27 |
+
volumes:
|
| 28 |
+
- ./nginx/conf.d:/etc/nginx/conf.d
|
| 29 |
+
- ./nginx/certs:/etc/nginx/certs
|
| 30 |
+
depends_on:
|
| 31 |
+
- redsputnik
|
| 32 |
+
networks:
|
| 33 |
+
- redsputnik-net
|
| 34 |
+
|
| 35 |
+
fail2ban:
|
| 36 |
+
image: crazymax/fail2ban:latest
|
| 37 |
+
volumes:
|
| 38 |
+
- ./fail2ban/data:/data
|
| 39 |
+
- /var/log:/var/log:ro
|
| 40 |
+
environment:
|
| 41 |
+
- TZ=Europe/Berlin
|
| 42 |
+
cap_add:
|
| 43 |
+
- NET_ADMIN
|
| 44 |
+
- NET_RAW
|
| 45 |
+
networks:
|
| 46 |
+
- redsputnik-net
|
| 47 |
+
|
| 48 |
+
networks:
|
| 49 |
+
redsputnik-net:
|
| 50 |
+
driver: bridge
|
| 51 |
+
```
|
index.html
CHANGED
|
@@ -1,19 +1,114 @@
|
|
| 1 |
-
<!
|
| 2 |
-
<html>
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="en" class="dark">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>RedSputnik 🔴</title>
|
| 7 |
+
<link rel="stylesheet" href="style.css">
|
| 8 |
+
<script src="https://cdn.tailwindcss.com"></script>
|
| 9 |
+
<script src="https://unpkg.com/feather-icons"></script>
|
| 10 |
+
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
| 11 |
+
<script>
|
| 12 |
+
tailwind.config = {
|
| 13 |
+
darkMode: 'class',
|
| 14 |
+
theme: {
|
| 15 |
+
extend: {
|
| 16 |
+
colors: {
|
| 17 |
+
primary: {
|
| 18 |
+
500: '#6366f1',
|
| 19 |
+
},
|
| 20 |
+
secondary: {
|
| 21 |
+
500: '#10b981',
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
}
|
| 25 |
+
}
|
| 26 |
+
}
|
| 27 |
+
</script>
|
| 28 |
+
</head>
|
| 29 |
+
<body class="bg-gray-100 dark:bg-gray-900 min-h-screen transition-colors duration-200">
|
| 30 |
+
<custom-navbar></custom-navbar>
|
| 31 |
+
|
| 32 |
+
<main class="container mx-auto px-4 py-8 max-w-4xl">
|
| 33 |
+
|
| 34 |
+
<div class="flex justify-between items-center mb-6">
|
| 35 |
+
<h1 class="text-3xl font-bold text-gray-800 dark:text-gray-100">
|
| 36 |
+
<i data-feather="satellite" class="inline mr-2"></i> RedSputnik
|
| 37 |
+
</h1>
|
| 38 |
+
<div class="flex gap-2">
|
| 39 |
+
<button id="theme-toggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700">
|
| 40 |
+
<i data-feather="moon" class="dark:hidden"></i>
|
| 41 |
+
<i data-feather="sun" class="hidden dark:block"></i>
|
| 42 |
+
</button>
|
| 43 |
+
<button id="red-mode-toggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700" title="Red Mode">
|
| 44 |
+
<i data-feather="alert-triangle" class="text-red-500"></i>
|
| 45 |
+
</button>
|
| 46 |
+
</div>
|
| 47 |
+
</div>
|
| 48 |
+
<div class="flex gap-4">
|
| 49 |
+
<div class="w-64 bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden">
|
| 50 |
+
<div class="p-4 border-b border-gray-200 dark:border-gray-700">
|
| 51 |
+
<h2 class="font-semibold flex items-center gap-2">
|
| 52 |
+
<i data-feather="lock" class="w-4 h-4"></i> Chat History
|
| 53 |
+
</h2>
|
| 54 |
+
</div>
|
| 55 |
+
<div id="chat-history" class="h-96 overflow-y-auto p-2 space-y-1">
|
| 56 |
+
<!-- Chat history items will appear here -->
|
| 57 |
+
</div>
|
| 58 |
+
<div class="p-4 border-t border-gray-200 dark:border-gray-700">
|
| 59 |
+
<button id="clear-history" class="w-full text-sm text-red-500 hover:text-red-600 flex items-center justify-center gap-1">
|
| 60 |
+
<i data-feather="trash-2" class="w-3 h-3"></i> Clear All
|
| 61 |
+
</button>
|
| 62 |
+
</div>
|
| 63 |
+
</div>
|
| 64 |
+
<div class="flex-1 bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden">
|
| 65 |
+
<div id="chat-container" class="h-96 overflow-y-auto p-4 space-y-4">
|
| 66 |
+
<!-- Chat messages will appear here -->
|
| 67 |
+
<div class="text-center py-8 text-gray-500 dark:text-gray-400">
|
| 68 |
+
<i data-feather="message-circle" class="w-12 h-12 mx-auto mb-2"></i>
|
| 69 |
+
<p>Start chatting with your NAS assistant</p>
|
| 70 |
+
</div>
|
| 71 |
+
</div>
|
| 72 |
+
|
| 73 |
+
<div class="border-t border-gray-200 dark:border-gray-700 p-4">
|
| 74 |
+
<form id="chat-form" class="flex gap-2">
|
| 75 |
+
<div class="flex-1 flex gap-2">
|
| 76 |
+
<input
|
| 77 |
+
type="text"
|
| 78 |
+
id="message-input"
|
| 79 |
+
placeholder="Secure message..."
|
| 80 |
+
class="flex-1 px-4 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-primary-500"
|
| 81 |
+
autocomplete="off"
|
| 82 |
+
required
|
| 83 |
+
>
|
| 84 |
+
<label class="flex items-center justify-center px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 cursor-pointer">
|
| 85 |
+
<input type="file" id="file-upload" class="hidden" accept=".txt,.pdf,.doc,.docx">
|
| 86 |
+
<i data-feather="upload" class="w-4 h-4"></i>
|
| 87 |
+
</label>
|
| 88 |
+
</div>
|
| 89 |
+
<button
|
| 90 |
+
type="submit"
|
| 91 |
+
class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg flex items-center gap-2 transition-colors"
|
| 92 |
+
>
|
| 93 |
+
<i data-feather="send" class="w-4 h-4"></i> Send
|
| 94 |
+
</button>
|
| 95 |
+
</form>
|
| 96 |
+
</div>
|
| 97 |
+
</div>
|
| 98 |
+
<div class="mt-6 text-sm text-gray-500 dark:text-gray-400 flex justify-between items-center">
|
| 99 |
+
<p><i data-feather="shield" class="w-4 h-4 inline mr-1"></i> Secure E2E encrypted | IP protected</p>
|
| 100 |
+
<p><i data-feather="hard-drive" class="w-4 h-4 inline mr-1"></i> Stored locally on your NAS</p>
|
| 101 |
+
</div>
|
| 102 |
+
</main>
|
| 103 |
+
|
| 104 |
+
<custom-footer></custom-footer>
|
| 105 |
+
|
| 106 |
+
<script src="components/navbar.js"></script>
|
| 107 |
+
<script src="components/footer.js"></script>
|
| 108 |
+
<script src="script.js"></script>
|
| 109 |
+
<script>
|
| 110 |
+
feather.replace();
|
| 111 |
+
</script>
|
| 112 |
+
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
|
| 113 |
+
</body>
|
| 114 |
+
</html>
|
script.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 3 |
+
// Theme management
|
| 4 |
+
const html = document.documentElement;
|
| 5 |
+
const themeToggle = document.getElementById('theme-toggle');
|
| 6 |
+
const redModeToggle = document.getElementById('red-mode-toggle');
|
| 7 |
+
|
| 8 |
+
// Theme toggle functionality
|
| 9 |
+
const setTheme = (theme) => {
|
| 10 |
+
if (theme === 'dark') {
|
| 11 |
+
html.classList.add('dark');
|
| 12 |
+
} else {
|
| 13 |
+
html.classList.remove('dark');
|
| 14 |
+
}
|
| 15 |
+
localStorage.setItem('theme', theme);
|
| 16 |
+
};
|
| 17 |
+
|
| 18 |
+
// Red mode toggle functionality
|
| 19 |
+
const setRedMode = (enabled) => {
|
| 20 |
+
if (enabled) {
|
| 21 |
+
html.classList.add('red-mode');
|
| 22 |
+
} else {
|
| 23 |
+
html.classList.remove('red-mode');
|
| 24 |
+
}
|
| 25 |
+
localStorage.setItem('redMode', enabled ? '1' : '0');
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
themeToggle.addEventListener('click', () => {
|
| 29 |
+
const isDark = html.classList.contains('dark');
|
| 30 |
+
setTheme(isDark ? 'light' : 'dark');
|
| 31 |
+
});
|
| 32 |
+
|
| 33 |
+
redModeToggle.addEventListener('click', () => {
|
| 34 |
+
const isRed = html.classList.contains('red-mode');
|
| 35 |
+
setRedMode(!isRed);
|
| 36 |
+
alert(`Red Mode ${!isRed ? 'activated' : 'deactivated'}\nResponses will now be ${!isRed ? 'uncensored' : 'filtered'}`);
|
| 37 |
+
});
|
| 38 |
+
|
| 39 |
+
// Load saved preferences
|
| 40 |
+
const savedTheme = localStorage.getItem('theme') || 'dark';
|
| 41 |
+
const savedRedMode = localStorage.getItem('redMode') === '1';
|
| 42 |
+
setTheme(savedTheme);
|
| 43 |
+
if (savedRedMode) setRedMode(true);
|
| 44 |
+
|
| 45 |
+
// File upload handling
|
| 46 |
+
const fileUpload = document.getElementById('file-upload');
|
| 47 |
+
let uploadedFileName = '';
|
| 48 |
+
|
| 49 |
+
fileUpload.addEventListener('change', (e) => {
|
| 50 |
+
const file = e.target.files[0];
|
| 51 |
+
if (file) {
|
| 52 |
+
uploadedFileName = file.name;
|
| 53 |
+
// In a real implementation, you would send the file to your NAS
|
| 54 |
+
alert(`File "${file.name}" ready for secure upload`);
|
| 55 |
+
}
|
| 56 |
+
});
|
| 57 |
+
// Chat functionality
|
| 58 |
+
const chatForm = document.getElementById('chat-form');
|
| 59 |
+
const messageInput = document.getElementById('message-input');
|
| 60 |
+
const chatContainer = document.getElementById('chat-container');
|
| 61 |
+
|
| 62 |
+
chatForm.addEventListener('submit', (e) => {
|
| 63 |
+
e.preventDefault();
|
| 64 |
+
|
| 65 |
+
const message = messageInput.value.trim();
|
| 66 |
+
if (message) {
|
| 67 |
+
// Add user message to chat
|
| 68 |
+
addMessageToChat('user', message);
|
| 69 |
+
|
| 70 |
+
// Simulate assistant response (in a real app, this would be an API call to your NAS)
|
| 71 |
+
setTimeout(() => {
|
| 72 |
+
addMessageToChat('assistant', `I received: "${message}". In a real implementation, this would be processed by your NAS assistant.`);
|
| 73 |
+
}, 1000);
|
| 74 |
+
|
| 75 |
+
// Clear input
|
| 76 |
+
messageInput.value = '';
|
| 77 |
+
}
|
| 78 |
+
});
|
| 79 |
+
// Add chat history item
|
| 80 |
+
function addChatHistoryItem(timestamp, preview) {
|
| 81 |
+
const historyItem = document.createElement('div');
|
| 82 |
+
historyItem.id = 'chat-history-item';
|
| 83 |
+
historyItem.innerHTML = `
|
| 84 |
+
<div class="flex justify-between items-center">
|
| 85 |
+
<span class="truncate">${preview}</span>
|
| 86 |
+
<span class="text-xs text-gray-500">${new Date(timestamp).toLocaleTimeString()}</span>
|
| 87 |
+
</div>
|
| 88 |
+
`;
|
| 89 |
+
document.getElementById('chat-history').appendChild(historyItem);
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
// Enhanced message handling
|
| 93 |
+
function addMessageToChat(sender, text, isFile = false) {
|
| 94 |
+
const messageDiv = document.createElement('div');
|
| 95 |
+
messageDiv.className = `chat-message flex ${sender === 'user' ? 'justify-end' : 'justify-start'} ${sender}`;
|
| 96 |
+
|
| 97 |
+
const contentDiv = document.createElement('div');
|
| 98 |
+
contentDiv.className = `max-w-xs md:max-w-md rounded-lg px-4 py-2 ${
|
| 99 |
+
sender === 'user'
|
| 100 |
+
? 'bg-primary-500 text-white'
|
| 101 |
+
: 'bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200'
|
| 102 |
+
}`;
|
| 103 |
+
|
| 104 |
+
if (isFile) {
|
| 105 |
+
contentDiv.innerHTML = `
|
| 106 |
+
<div class="flex items-center gap-2">
|
| 107 |
+
<i data-feather="paperclip" class="w-4 h-4"></i>
|
| 108 |
+
<span>File attached: ${text}</span>
|
| 109 |
+
</div>
|
| 110 |
+
`;
|
| 111 |
+
} else {
|
| 112 |
+
contentDiv.textContent = text;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
messageDiv.appendChild(contentDiv);
|
| 116 |
+
chatContainer.appendChild(messageDiv);
|
| 117 |
+
|
| 118 |
+
// Add to history if user message
|
| 119 |
+
if (sender === 'user') {
|
| 120 |
+
addChatHistoryItem(Date.now(), isFile ? `File: ${text}` : text.substring(0, 20));
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
// Scroll to bottom and refresh Feather icons
|
| 124 |
+
chatContainer.scrollTop = chatContainer.scrollHeight;
|
| 125 |
+
feather.replace();
|
| 126 |
+
}
|
| 127 |
+
|
| 128 |
+
// Clear history
|
| 129 |
+
document.getElementById('clear-history').addEventListener('click', () => {
|
| 130 |
+
if (confirm('Clear all chat history?')) {
|
| 131 |
+
document.getElementById('chat-history').innerHTML = '';
|
| 132 |
+
}
|
| 133 |
+
});
|
| 134 |
+
});
|
security.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
```markdown
|
| 2 |
+
# RedSputnik Security Features
|
| 3 |
+
|
| 4 |
+
## Core Security Principles
|
| 5 |
+
- **End-to-End Encryption**: All communications encrypted with AES-256
|
| 6 |
+
- **IP Protection**: No IP logging, all requests anonymized
|
| 7 |
+
- **Local Execution**: Runs entirely on your NAS, no cloud dependencies
|
| 8 |
+
- **DDOS Protection**: Built-in rate limiting and request throttling
|
| 9 |
+
|
| 10 |
+
## Technical Implementation
|
| 11 |
+
- **Container Isolation**: Runs in isolated Docker containers
|
| 12 |
+
- **File Upload Security**:
|
| 13 |
+
- Virus scanning with ClamAV
|
| 14 |
+
- Strict file type restrictions
|
| 15 |
+
- Size limitations (configurable)
|
| 16 |
+
- **Network Security**:
|
| 17 |
+
- Fail2ban integration
|
| 18 |
+
- Automatic IP blocking after repeated failures
|
| 19 |
+
- HTTPS enforced via Nginx reverse proxy
|
| 20 |
+
|
| 21 |
+
## Privacy Features
|
| 22 |
+
- **No Tracking**: Zero analytics or telemetry
|
| 23 |
+
- **Self-Destructing Messages**: Optional message expiration
|
| 24 |
+
- **Red Mode**: Uncensored responses when explicitly enabled
|
| 25 |
+
|
| 26 |
+
## Recommended Setup
|
| 27 |
+
1. Place behind reverse proxy with SSL termination
|
| 28 |
+
2. Configure firewall to only allow connections from trusted networks
|
| 29 |
+
3. Regularly update Docker images
|
| 30 |
+
4. Monitor container logs for suspicious activity
|
| 31 |
+
5. Use hardware security module (HSM) for encryption keys if available
|
| 32 |
+
```
|
style.css
CHANGED
|
@@ -1,28 +1,68 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
}
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
}
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
margin-bottom: 10px;
|
| 15 |
-
margin-top: 5px;
|
| 16 |
}
|
| 17 |
|
| 18 |
-
.
|
| 19 |
-
|
| 20 |
-
margin: 0 auto;
|
| 21 |
-
padding: 16px;
|
| 22 |
-
border: 1px solid lightgray;
|
| 23 |
-
border-radius: 16px;
|
| 24 |
}
|
| 25 |
|
| 26 |
-
.
|
| 27 |
-
|
| 28 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Custom scrollbar */
|
| 2 |
+
#chat-container::-webkit-scrollbar {
|
| 3 |
+
width: 8px;
|
| 4 |
}
|
| 5 |
|
| 6 |
+
#chat-container::-webkit-scrollbar-track {
|
| 7 |
+
background: #f1f1f1;
|
| 8 |
+
border-radius: 4px;
|
| 9 |
}
|
| 10 |
|
| 11 |
+
#chat-container::-webkit-scrollbar-thumb {
|
| 12 |
+
background: #888;
|
| 13 |
+
border-radius: 4px;
|
|
|
|
|
|
|
| 14 |
}
|
| 15 |
|
| 16 |
+
.dark #chat-container::-webkit-scrollbar-track {
|
| 17 |
+
background: #374151;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
}
|
| 19 |
|
| 20 |
+
.dark #chat-container::-webkit-scrollbar-thumb {
|
| 21 |
+
background: #4b5563;
|
| 22 |
}
|
| 23 |
+
:root {
|
| 24 |
+
--red-mode: 0;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
.red-mode {
|
| 28 |
+
--red-mode: 1;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
/* Chat message animations */
|
| 32 |
+
@keyframes fadeIn {
|
| 33 |
+
from { opacity: 0; transform: translateY(10px); }
|
| 34 |
+
to { opacity: 1; transform: translateY(0); }
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
/* Red mode styles */
|
| 38 |
+
.red-mode .chat-message.assistant {
|
| 39 |
+
background-color: rgba(239, 68, 68, 0.1) !important;
|
| 40 |
+
border-left: 3px solid rgba(239, 68, 68, 0.5);
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
#chat-history-item {
|
| 44 |
+
padding: 0.5rem;
|
| 45 |
+
border-radius: 0.25rem;
|
| 46 |
+
margin-bottom: 0.25rem;
|
| 47 |
+
cursor: pointer;
|
| 48 |
+
font-size: 0.875rem;
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
#chat-history-item:hover {
|
| 52 |
+
background-color: rgba(99, 102, 241, 0.1);
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
#chat-history-item.active {
|
| 56 |
+
background-color: rgba(99, 102, 241, 0.2);
|
| 57 |
+
font-weight: 500;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.file-upload-indicator {
|
| 61 |
+
display: inline-block;
|
| 62 |
+
margin-left: 0.5rem;
|
| 63 |
+
font-size: 0.75rem;
|
| 64 |
+
color: #10b981;
|
| 65 |
+
}
|
| 66 |
+
.chat-message {
|
| 67 |
+
animation: fadeIn 0.3s ease-out forwards;
|
| 68 |
+
}
|