Project structure:

DarkVPN_server/
├── templates/
│   ├── admin_login.html
│   └── admin_panel.html
├── auth_server.py
└── requirements.txt


Project files:

auth_server.py
```py
# app.py

from flask import Flask, request, jsonify, session, render_template, redirect, url_for
from flask_socketio import SocketIO, emit
from datetime import datetime, timedelta
from werkzeug.utils import secure_filename
import uuid
import threading
from flask_cors import CORS

app = Flask(__name__)
app.secret_key = 'your_secret_key'
CORS(app)  # Enable CORS for all routes

socketio = SocketIO(app, async_mode='threading')

# In-memory storage for demonstration; replace with a database in production
users = {}  # Key: userKey, Value: user data
admin_password = 'your_admin_password'  # Set your admin password here
latest_extension_version = '1.0'

# Lock for thread-safe operations on users
users_lock = threading.Lock()

# API Endpoint for heartbeat
@app.route('/api/heartbeat', methods=['POST'])
def api_heartbeat():
    data = request.get_json()
    user_key = data.get('userKey')  # Get user key from the request
    version = data.get('version')
    current_url = data.get('currentUrl')
    client_ip = request.remote_addr

    if version != latest_extension_version:
        return jsonify({'status': 'update_required'}), 200

    with users_lock:
        # Find user by key
        user = users.get(user_key)

        if not user:
            return jsonify({'status': 'unauthorized'}), 403

        # Update user info
        user['last_seen'] = datetime.utcnow()
        user['ip'] = client_ip
        user['current_url'] = current_url

        if user['is_banned'] or user['is_stopped']:
            emit_user_update(user)
            return jsonify({'status': 'unauthorized'}), 403

        if user['subscription_expires'] < datetime.utcnow():
            emit_user_update(user)
            return jsonify({'status': 'subscription_expired'}), 403

        # User is authorized
        # Return proxy details
        proxy_details = {
            'host': '185.106.94.81',
            'port': 44590,
            'scheme': 'socks5'  # Include the scheme
        }

        emit_user_update(user)

        return jsonify({'status': 'ok', 'proxy': proxy_details}), 200

# Function to emit user updates to admin clients
def emit_user_update(user):
    socketio.emit('user_update', {
        'key': user['key'],
        'username': user['username'],
        'ip': user['ip'] or 'N/A',
        'current_url': user['current_url'] or 'N/A',
        'is_connected': True,
        'subscription_expires': user['subscription_expires'].isoformat(),
        'is_banned': user['is_banned'],
        'is_stopped': user['is_stopped']
    }, to='/', namespace='/')

# Admin Login
@app.route('/admin', methods=['GET', 'POST'])
def admin_login():
    if 'admin_logged_in' in session:
        return redirect(url_for('admin_panel'))

    if request.method == 'POST':
        password = request.form.get('password')
        if password == admin_password:
            session['admin_logged_in'] = True
            return redirect(url_for('admin_panel'))
        else:
            return render_template('admin_login.html', error='Invalid password')

    return render_template('admin_login.html')

# Admin Panel
@app.route('/admin/panel')
def admin_panel():
    if 'admin_logged_in' not in session:
        return redirect(url_for('admin_login'))

    return render_template('admin_panel.html')

# Admin route to add a new user
@app.route('/admin/add_user', methods=['POST'])
def admin_add_user():
    if 'admin_logged_in' not in session:
        return jsonify({'status': 'error', 'message': 'Unauthorized'}), 401

    data = request.get_json()
    username = data.get('username')
    days = int(data.get('days', 0))

    user_key = str(uuid.uuid4())  # Generate a unique key

    with users_lock:
        user = {
            'username': username,
            'key': user_key,
            'subscription_expires': datetime.utcnow() + timedelta(days=days),
            'is_banned': False,
            'is_stopped': False,
            'last_seen': None,
            'ip': None,
            'current_url': None
        }
        users[user_key] = user

    # Optionally, emit the new user to admin clients
    emit_user_update(user)

    return jsonify({'status': 'ok', 'userKey': user_key}), 200

# Admin Actions
@app.route('/admin/action', methods=['POST'])
def admin_action():
    if 'admin_logged_in' not in session:
        return jsonify({'status': 'error', 'message': 'Unauthorized'}), 401

    data = request.get_json()
    action = data.get('action')
    user_key = data.get('userKey')

    with users_lock:
        user = users.get(user_key)
        if not user:
            return jsonify({'status': 'error', 'message': 'User not found'}), 404

        if action == 'ban':
            user['is_banned'] = not user['is_banned']  # Toggle ban status
        elif action == 'stop':
            user['is_stopped'] = not user['is_stopped']  # Toggle stop status
        elif action == 'renew':
            days = int(data.get('days', 0))
            if user['subscription_expires'] < datetime.utcnow():
                user['subscription_expires'] = datetime.utcnow() + timedelta(days=days)
            else:
                user['subscription_expires'] += timedelta(days=days)
        else:
            return jsonify({'status': 'error', 'message': 'Invalid action'}), 400

        emit_user_update(user)
        return jsonify({'status': 'ok'}), 200

# Socket.IO event for admin panel to receive updates
@socketio.on('connect')
def handle_connect():
    if 'admin_logged_in' in session:
        with users_lock:
            for user in users.values():
                emit_user_update(user)
    else:
        emit('error', {'message': 'Unauthorized'})

# Logout Route
@app.route('/admin/logout')
def admin_logout():
    session.pop('admin_logged_in', None)
    return redirect(url_for('admin_login'))

# Templates for admin login and admin panel
# Ensure that templates/admin_login.html and templates/admin_panel.html exist

# Run the app
if __name__ == '__main__':
    socketio.run(app, host='0.0.0.0', port=5011, allow_unsafe_werkzeug=True)
```


requirements.txt
```txt
flask
flask-socketio
passlib
pySocks
```


templates/admin_login.html
```html
<!-- templates/admin_login.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Admin Login</title>
    <style>
        /* Basic styles for the login page */
        body {
            font-family: Arial, sans-serif;
            background-color: #f0f0f0;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 100vh;
            margin: 0;
        }

        .login-container {
            background-color: white;
            padding: 20px 30px;
            border-radius: 5px;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
            text-align: center;
        }

        .login-container h2 {
            margin-top: 0;
        }

        .login-container input {
            width: 100%;
            padding: 8px;
            margin-bottom: 10px;
            box-sizing: border-box;
        }

        .login-container button {
            width: 100%;
            padding: 10px;
            background-color: #333;
            color: white;
            border: none;
            cursor: pointer;
        }

        .login-container button:hover {
            background-color: #555;
        }

        .error {
            color: red;
        }

    </style>
</head>
<body>
    <div class="login-container">
        <h2>Admin Login</h2>
        {% if error %}
        <p class="error">{{ error }}</p>
        {% endif %}
        <form method="post">
            <input type="password" name="password" placeholder="Enter secret key">
            <button type="submit">Login</button>
        </form>
    </div>
</body>
</html>
```


templates/admin_panel.html
```html
<!-- templates/admin_panel.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Admin Panel</title>
    <!-- Include Socket.IO library -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.min.js"></script>
    <!-- Include any CSS frameworks or custom styles -->
    <style>
        /* Basic styles for the admin panel */

        body {
            font-family: Arial, sans-serif;
            margin: 0;
            padding: 0;
            background-color: #f0f0f0;
        }

        /* Sidebar */
        .sidebar {
            width: 200px;
            background-color: #333;
            color: white;
            height: 100vh;
            position: fixed;
            overflow: auto;
        }

        .sidebar h2 {
            text-align: center;
            padding: 10px 0;
            margin: 0;
            background-color: #444;
        }

        .sidebar button {
            width: 100%;
            padding: 10px;
            border: none;
            background: none;
            color: white;
            text-align: left;
            cursor: pointer;
        }

        .sidebar button:hover {
            background-color: #555;
        }

        /* Main content */
        .main-content {
            margin-left: 200px;
            padding: 20px;
        }

        /* User grid */
        #user-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
            gap: 10px;
        }

        .user-tile {
            background-color: white;
            border: 1px solid #ccc;
            padding: 10px;
            position: relative;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .user-tile h3 {
            margin: 0 0 10px;
            font-size: 16px;
        }

        .user-tile p {
            margin: 5px 0;
            font-size: 14px;
        }

        /* User actions */
        .user-actions {
            display: none;
            position: absolute;
            bottom: 10px;
            left: 10px;
        }

        .user-actions button {
            margin-right: 5px;
            font-size: 12px;
        }

        .user-tile:hover .user-actions {
            display: block;
        }

        /* Modals */
        .modal {
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0,0,0,0.5);
        }

        .modal-content {
            background-color: #fefefe;
            margin: 10% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 300px;
            position: relative;
        }

        .modal h3 {
            margin-top: 0;
        }

        .modal input, .modal button {
            width: 100%;
            margin-bottom: 10px;
            padding: 8px;
            box-sizing: border-box;
        }

        .modal-close {
            position: absolute;
            top: 5px;
            right: 10px;
            background: none;
            border: none;
            font-size: 20px;
            cursor: pointer;
        }

        /* Copy button */
        #copy-user-key {
            width: auto;
            background-color: #4CAF50;
            color: white;
            cursor: pointer;
        }

        #copy-user-key:hover {
            background-color: #45a049;
        }

    </style>
</head>
<body>
    <!-- Sidebar -->
    <div class="sidebar">
        <h2>Admin Panel</h2>
        <button id="add-user-btn">Add New User</button>
        <!-- Add more sidebar buttons or links as needed -->
    </div>

    <!-- Main content -->
    <div class="main-content">
        <h2>Users</h2>
        <div id="user-grid">
            <!-- User tiles will be dynamically added here -->
        </div>
    </div>

    <!-- User Creation Modal -->
    <div id="create-user-modal" class="modal">
        <div class="modal-content">
            <button class="modal-close">&times;</button>
            <h3>Add New User</h3>
            <input type="text" id="new-username" placeholder="Username">
            <input type="number" id="new-user-days" placeholder="Subscription Duration (days)">
            <button id="create-user-confirm">Create</button>
        </div>
    </div>

    <!-- Display User Key Modal -->
    <div id="user-key-modal" class="modal">
        <div class="modal-content">
            <button class="modal-close">&times;</button>
            <h3>User Key</h3>
            <input type="text" id="user-key-display" readonly>
            <button id="copy-user-key">Copy</button>
        </div>
    </div>

    <!-- Modal for Renew Subscription -->
    <div id="renew-modal" class="modal">
        <div class="modal-content">
            <button class="modal-close">&times;</button>
            <h3>Renew Subscription</h3>
            <p id="renew-user-info"></p>
            <input type="number" id="renew-days" placeholder="Days to renew">
            <button id="renew-confirm">Renew</button>
        </div>
    </div>

    <!-- Include any required JS libraries -->
    <script>
        const socket = io();

        const userGrid = document.getElementById('user-grid');
        const addUserBtn = document.getElementById('add-user-btn');

        // Modals
        const createUserModal = document.getElementById('create-user-modal');
        const userKeyModal = document.getElementById('user-key-modal');
        const renewModal = document.getElementById('renew-modal');

        let currentUserKey = null; // For actions like renew

        // Event listener for "Add New User" button
        addUserBtn.addEventListener('click', function() {
            createUserModal.style.display = 'block';
        });

        // Event listener for creating a new user
        document.getElementById('create-user-confirm').addEventListener('click', function() {
            const username = document.getElementById('new-username').value.trim();
            const days = parseInt(document.getElementById('new-user-days').value);

            if (!username || isNaN(days) || days <= 0) {
                alert('Please enter a valid username and subscription duration.');
                return;
            }

            fetch('/admin/add_user', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ username: username, days: days })
            })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'ok') {
                    // Close the create user modal
                    createUserModal.style.display = 'none';
                    // Open the user key modal
                    document.getElementById('user-key-display').value = data.userKey;
                    userKeyModal.style.display = 'block';
                } else {
                    alert('Error creating user: ' + data.message);
                }
            });
        });

        // Event listener for copying the user key
        document.getElementById('copy-user-key').addEventListener('click', function() {
            const userKeyInput = document.getElementById('user-key-display');
            userKeyInput.select();
            userKeyInput.setSelectionRange(0, 99999); // For mobile devices

            document.execCommand('copy');
            alert('User key copied to clipboard.');
        });

        // Close modals when clicking on the close buttons
        document.querySelectorAll('.modal-close').forEach(function(btn) {
            btn.addEventListener('click', function() {
                this.parentElement.parentElement.style.display = 'none';
            });
        });

        // Handle clicks outside the modal content to close the modal
        window.onclick = function(event) {
            if (event.target === createUserModal) {
                createUserModal.style.display = 'none';
            } else if (event.target === userKeyModal) {
                userKeyModal.style.display = 'none';
            } else if (event.target === renewModal) {
                renewModal.style.display = 'none';
            }
        };

        // Socket.IO event for user updates
        socket.on('user_update', function(data) {
            let userTile = document.getElementById('user-' + data.key);
            if (!userTile) {
                userTile = document.createElement('div');
                userTile.id = 'user-' + data.key;
                userTile.className = 'user-tile';
                userTile.innerHTML = `
                    <h3>${data.username}</h3>
                    <p>IP: <span class="user-ip">${data.ip || 'N/A'}</span></p>
                    <p>Connected: <span class="user-connected">${data.is_connected || false}</span></p>
                    <p>Expires: <span class="user-expires">${formatDate(data.subscription_expires)}</span></p>
                    <p>Current URL: <span class="user-url">${data.current_url || 'N/A'}</span></p>
                    <div class="user-actions">
                        <button onclick="banUser('${data.key}')">${data.is_banned ? 'Unban' : 'Ban'}</button>
                        <button onclick="stopUser('${data.key}')">${data.is_stopped ? 'Unstop' : 'Stop'}</button>
                        <button onclick="openRenewModal('${data.key}', '${data.username}')">Renew</button>
                    </div>
                `;
                userGrid.appendChild(userTile);
            } else {
                userTile.querySelector('.user-ip').textContent = data.ip || 'N/A';
                userTile.querySelector('.user-connected').textContent = data.is_connected || false;
                userTile.querySelector('.user-expires').textContent = formatDate(data.subscription_expires);
                userTile.querySelector('.user-url').textContent = data.current_url || 'N/A';
                // Update action buttons
                userTile.querySelector('.user-actions').innerHTML = `
                    <button onclick="banUser('${data.key}')">${data.is_banned ? 'Unban' : 'Ban'}</button>
                    <button onclick="stopUser('${data.key}')">${data.is_stopped ? 'Unstop' : 'Stop'}</button>
                    <button onclick="openRenewModal('${data.key}', '${data.username}')">Renew</button>
                `;
            }
        });

        // Function to format date
        function formatDate(dateString) {
            const date = new Date(dateString);
            return date.toLocaleString();
        }

        // Functions for user actions
        function banUser(userKey) {
            fetch('/admin/action', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'ban', userKey: userKey })
            });
        }

        function stopUser(userKey) {
            fetch('/admin/action', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'stop', userKey: userKey })
            });
        }

        function openRenewModal(userKey, username) {
            currentUserKey = userKey;
            renewModal.style.display = 'block';
            document.getElementById('renew-user-info').textContent = `User: ${username}`;
            document.getElementById('renew-days').value = '';
        }

        // Renew subscription
        document.getElementById('renew-confirm').addEventListener('click', function() {
            const days = parseInt(document.getElementById('renew-days').value);
            if (isNaN(days) || days <= 0) {
                alert('Please enter a valid number of days.');
                return;
            }
            fetch('/admin/action', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ action: 'renew', userKey: currentUserKey, days: days })
            })
            .then(response => response.json())
            .then(data => {
                if (data.status === 'ok') {
                    renewModal.style.display = 'none';
                } else {
                    alert('Error renewing subscription: ' + data.message);
                }
            });
        });
    </script>
</body>
</html>
```


---------------------------------------------------------------------------------------------


Project structure:

extension_SSSSS/
├── css/
│   └── styles.css
├── icons/
│   ├── icon128.png
│   ├── icon16.png
│   ├── icon32.png
│   └── icon48.png
├── images/
│   ├── icons/
│   │   ├── DarkVPN_icon_bars2.png
│   │   └── DarkVPN_icon_house3.png
│   └── DarkVPN_LOGO.png
├── js/
│   ├── background.js
│   ├── jquery-3.7.1.min.js
│   ├── menu.js
│   └── popup.js
├── GenerateProjectShort.py
├── ProjectOneFile.txt
├── manifest.json
└── popup.html


Project files:

manifest.json
```json
{
  "manifest_version": 2,
  "name": "DarkVPN",
  "version": "1.0",
  "description": "Fastest DarkVPN",
  "permissions": [
    "proxy",
    "storage",
    "webRequest",
    "webRequestBlocking",
    "tabs",
    "<all_urls>"
  ],
  "browser_action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon16.png",
      "32": "icons/icon32.png",
      "48": "icons/icon48.png",
      "128": "icons/icon128.png"
    }
  },
  "icons": {
    "16": "icons/icon16.png",
    "32": "icons/icon32.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  "background": {
    "scripts": "js/background.js"
  }
}
```


popup.html
```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>DarkVPN</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Ubuntu:ital,wght@0,300;0,400;0,500;0,700;1,300;1,400;1,500;1,700&display=swap" rel="stylesheet">
  <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <div class="container">
    <div class="dark-vpn-title">DarkVPN</div>
    <div class="version-text">V-0.6.1</div>
    <div class="toggle-container">
      <button id="toggleButton">
        <img src="images/DarkVPN_LOGO.png" class="button-logo">
        <div class="b-title">Connect</div>
      </button>
    </div>
    <div class="menu-container">
      <div class="setting-bar" id="autoConnectSetting">
        <div class="setting-tile">Автоподключение</div>
        <div class="setting-switcher">
          <div class="switcher-ball"></div>
        </div>
      </div>
      <div class="setting-bar" id="adBlockSetting">
        <div class="setting-tile">Блокировка рекламы</div>
        <div class="setting-switcher">
          <div class="switcher-ball"></div>
        </div>
      </div>
    </div>
    <div class="info-container">
      <div class="buttons-row">
        <button class="control-btn" id="home-btn">
          <img src="images/icons/DarkVPN_icon_house3.png" class="control-btn-icon">
          <img src="images/icons/DarkVPN_icon_house3.png" class="control-btn-icon control-btn-glow">
        </button>
        <button class="control-btn" id="menu-btn">
          <img src="images/icons/DarkVPN_icon_bars2.png" class="control-btn-icon">
          <img src="images/icons/DarkVPN_icon_bars2.png" class="control-btn-icon control-btn-glow">
        </button>
      </div>
    </div>
  </div>
  <div class="gradient-point"></div>
  <script src="js/jquery-3.7.1.min.js"></script>
  <script src="js/popup.js"></script>
  <script src="js/menu.js"></script>
</body>
</html>
```


css.styles.css
```css
:root {
  --violet-color: #6e41e1
}

body {
  width: 320px;
  height: 500px;
  margin: 0;
  font-family: 'Roboto', sans-serif;
  background-color: #1e1e1f;
  border: none;
  color: #ffffff;
}

.container {
  display: flex;
  flex-direction: column;
  height: 100%;
  justify-content: space-between;
}

.dark-vpn-title {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: 32px;
  font-family: "Ubuntu", sans-serif;
  font-weight: 500;
  font-size: 40px;
  color: #6a6a6a;
  padding: 1px 10px;
  /* background-color: #ffffff1f; */
  /* border-radius: 10px; */
  transition: opacity 0.2s;
}
.version-text {
  position: absolute;
  top: 10px;
  right: 10px;
  font-family: 'Roboto', sans-serif;
  color: rgb(255 255 255 / 15%);
  font-size: 10px;
}

.toggle-container {
  display: flex;
  justify-content: center;
  z-index: 2;
  height: 100%;
  align-items: center;
  transition: height 0.3s ease;
}

#toggleButton {
  display: flex;
  height: 150px;
  width: 150px;
  border-radius: 50%;
  font-size: 18px;
  font-weight: 500;
  color: #ffffff;
  background-color: #333333;
  border: none;
  cursor: pointer;
  position: relative;
  align-items: center;
  justify-content: center;
  transition: all 0.3s ease;
}

#toggleButton::before {
  content: '';
  position: absolute;
  width: 150%;
  height: 150%;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.07) 0%, rgba(255,255,255,0) 70%);
  transition: all 0.3s ease;
  transform: scale(1);
  opacity: 1;
}

#toggleButton.connected::before {
  background: radial-gradient(circle, rgba(138, 43, 226, 0.2) 0%, rgb(77 46 205 / 20%) 50%, rgba(138, 43, 226, 0) 70%);
  animation: pulse 2s infinite;
}

#toggleButton:hover {
  transform: scale(1.05);
}

#toggleButton:active {
  transition: all 0.1s;
  transform: scale(0.95);
}

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.1);
    opacity: 0.5;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.button-logo {
  width: 50%;
  height: 50%;
  transition: opacity 0.3s ease;
}

.menu-container {
  display: flex;
  padding: 0  20px 0 20px;
  position: absolute;
  z-index: 5;
  height: 350px;
  /* width: calc(100% - 40px); */
  background-color: #212121;
  border-radius: 10px;
  transform: translate(-50%, -50%) scale(0.9);
  left: 50%;
  top: 50%;
  opacity: 0;
  pointer-events: none;
  transition: transform 0.3s ease, opacity 0.1s;
  flex-direction: column;
  align-items: center;
}

.info-container {
  display: flex;
  padding: 10px;
  z-index: 2;
  flex-direction: column;
  margin-bottom: 25px;
}

.info-row {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
}

.info-label {
  font-weight: 300;
}

.info-value {
  font-weight: 500;
}

.buttons-row {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 10px;
}

.control-btn {
  display: flex;
  height: 32px;
  width: 32px;
  background: none;
  border: none;
  outline: none;
  align-items: center;
  justify-content: center;
  padding: 0;
  position: relative;
  cursor: pointer;
  transition: all 0.1s;
}

.control-btn .control-btn-icon {
  position: absolute;
  width: 100%;
  height: 100%;
}

.control-btn .control-btn-glow {
  opacity: 0;
  transition: opacity 0.2s;
  filter: blur(5px);
}

.control-btn:hover .control-btn-glow {
  opacity: 0.2;
}

.control-btn:hover {
  transform: scale(1.05);
}

.control-btn:active {
  transform: scale(0.98);
}


.hide-logo .button-logo {
  transition: opacity 0.1s ease;
  opacity: 0;
}


.shrink-button .toggle-container {
  height: 100px;
}

.shrink-button {
  #toggleButton {
    height: 35px;
    width: 130px;
    border-radius: 50px;
  }
  #toggleButton::before {
    opacity: 0;
    animation: none;
  }
  #toggleButton:hover {
    transform: scale(1);
    opacity: 0.95;
  }
  #toggleButton:active {
    transform: scale(1);
    opacity: 0.9;
  }
}
.display-tb-title {
  .b-title {
    transition: opacity 0.3s;
    opacity: 1;
  }
}

.shrink-button #toggleButton::before {
  opacity: 0;
}


.show-menu .menu-container {
  transition: transform 0.2s, opacity 0.2s ease;
  pointer-events: all;
  transform: translate(-50%, -50%) scale(1);
  opacity: 1;
}


#toggleButton.connected {
  background-color: var(--violet-color);
}

.b-title {
  transition: opacity 0.1s;
  position: absolute;
  opacity: 0;
  font-family: 'Roboto', sans-serif;
  color: rgba(255, 255, 255, 0.93);
}




.setting-bar {
  display: flex;
  width: 100%;
  gap: 20px;
  /* height: 50px; */
  /* background-color: rgb(255 255 255 / 0%); */
  align-items: center;
  justify-content: space-between;
  padding: 10px;
  cursor: pointer;
}
.setting-tile {
  font-family: 'Roboto', sans-serif;
  font-weight: 500;
  font-size: 15px;
}
.setting-switcher {
  display: flex;
  height: 30px;
  width: 54px;
  background-color: #ffffff26;
  align-items: center;
  justify-content: center;
  border-radius: 30px;
}
.switcher-ball {
  height: 24px;
  width: 24px;
  background-color: white;
  border-radius: 100%;
  transform: translateX(-50%);
  pointer-events: none;
  transition: all 0.1s;
}

.setting-bar.active .setting-switcher {
  background-color: var(--violet-color);
}

.switcher-ball-active {
  transform: translateX(50%);
}

```


js.background.js
```js
// background.js

const SERVER_URL = 'https://85.236.189.41:5011';  // Replace with your Flask server URL
const EXTENSION_VERSION = '1.0';

let isConnected = false;
let heartbeatInterval = null;
let userKey = null;

// Function to store the user key persistently
function setUserKey(key) {
  userKey = key;
  // Store it in sync storage for persistence across devices
  chrome.storage.sync.set({ userKey: key });
}

// Function to get the user key
function getUserKey(callback) {
  if (userKey) {
    callback(userKey);
  } else {
    chrome.storage.sync.get('userKey', function(data) {
      if (data.userKey) {
        userKey = data.userKey;
        callback(userKey);
      } else {
        // No user key found, prompt the user to input it
        promptForUserKey(callback);
      }
    });
  }
}

// Function to prompt the user to input their user key
function promptForUserKey(callback) {
  // Send a message to the popup to display a prompt
  chrome.runtime.sendMessage({ action: 'promptUserKey' }, function(response) {
    if (response && response.userKey) {
      setUserKey(response.userKey);
      callback(response.userKey);
    } else {
      // Handle the case where the user didn't provide a key
      console.error('User key is required.');
    }
  });
}

// Function to connect to VPN with proxy details from the server
function connectVPN(proxyConfig) {
  chrome.proxy.settings.set({ value: proxyConfig, scope: 'regular' }, function() {
    isConnected = true;
    chrome.storage.local.set({ isConnected: true });
  });
}

// Function to disconnect from VPN
function disconnectVPN() {
  chrome.proxy.settings.clear({ scope: 'regular' }, function() {
    isConnected = false;
    chrome.storage.local.set({ isConnected: false });
  });
}

// Function to send heartbeat to the server every 10 seconds
function startHeartbeat() {
  if (heartbeatInterval) {
    clearInterval(heartbeatInterval);
  }

  heartbeatInterval = setInterval(function() {
    sendHeartbeat();
  }, 10000);

  // Send immediately on startup
  sendHeartbeat();
}

// Function to send heartbeat and get proxy details
function sendHeartbeat() {
  getUserKey(function(userKey) {
    // Get the current tab's URL
    chrome.tabs.query({ active: true, lastFocusedWindow: true }, function(tabs) {
      const currentUrl = tabs[0]?.url || 'unknown';

      fetch(`${SERVER_URL}/api/heartbeat`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          userKey: userKey,
          version: EXTENSION_VERSION,
          currentUrl: currentUrl
        })
      })
      .then(response => response.json())
      .then(data => {
        if (data.status === 'ok') {
          // Received proxy details from the server
          const newProxyConfig = {
            mode: "fixed_servers",
            rules: {
              singleProxy: {
                scheme: data.proxy.scheme,
                host: data.proxy.host,
                port: data.proxy.port
              },
              bypassList: ["localhost"]
            }
          };

          connectVPN(newProxyConfig);
        } else if (data.status === 'update_required') {
          // Notify user to update the extension
          chrome.notifications.create({
            type: 'basic',
            iconUrl: 'icons/icon128.png',
            title: 'DarkVPN Update Required',
            message: 'Please update your DarkVPN extension to the latest version.'
          });
          disconnectVPN();
        } else {
          // Unauthorized or subscription expired
          disconnectVPN();
        }
      })
      .catch(error => {
        console.error('Error communicating with server:', error);
        disconnectVPN();
      });
    });
  });
}

// On startup
startHeartbeat();

// Listen for changes in active tab to update current URL
chrome.tabs.onActivated.addListener(function(activeInfo) {
  sendHeartbeat();
});

// Listen for updates to the tab's URL
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
  if (changeInfo.url) {
    sendHeartbeat();
  }
});

// Listen for messages from popup.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  if (request.action === 'promptUserKey') {
    // Handle prompt if needed
  } else if (request.action === 'toggleConnection') {
    // Optional: Handle manual connect/disconnect if needed
  }
});
```


js.menu.js
```js
$(document).ready(function() {
  let isMenuMode = false;

  function enterMenuMode() {
    if (!isMenuMode) {
      isMenuMode = true;
      $('.dark-vpn-title').css("opacity", "0")
      $('body').addClass('hide-logo');
      $('body').addClass('shrink-button');
      setTimeout(() => {
        $('body').addClass('display-tb-title');
      }, 100);
      setTimeout(() => {
        $('body').addClass('show-menu');
      }, 200);
    }
  }

  function exitMenuMode() {
    if (isMenuMode) {
      isMenuMode = false;
      $('.dark-vpn-title').css("opacity", "1")
      $('body').removeClass('show-menu');
      $('body').removeClass('shrink-button');
      $('body').removeClass('hide-logo');
      $('body').removeClass('display-tb-title');
    }
  }

  function UpdateConnectButtonTitle() {
    if ($('#toggleButton').hasClass('connected')) {
      $('.b-title').text("Disconnect");
    } else {
      $('.b-title').text("Connect");
    }
  }

  function toggleConnection() {
    $('#toggleButton').toggleClass('connected');
    UpdateConnectButtonTitle();
  }

  $('#home-btn').click(exitMenuMode);
  $('#menu-btn').click(enterMenuMode);
  $('#toggleButton').click(toggleConnection);

  // Load saved settings
  chrome.storage.local.get(['autoConnect', 'adBlock'], function(data) {
    if (data.autoConnect) {
      $('#autoConnectSetting').addClass('active');
      $('#autoConnectSetting .switcher-ball').addClass('switcher-ball-active');
    }
    if (data.adBlock) {
      $('#adBlockSetting').addClass('active');
      $('#adBlockSetting .switcher-ball').addClass('switcher-ball-active');
    }
  });

  // Save settings when toggled
  $('.setting-bar').click(function() {
    $(this).toggleClass('active');
    $(this).find('.switcher-ball').toggleClass('switcher-ball-active');

    const settingId = $(this).attr('id');
    const isActive = $(this).hasClass('active');

    if (settingId === 'autoConnectSetting') {
      chrome.storage.local.set({autoConnect: isActive});
    } else if (settingId === 'adBlockSetting') {
      chrome.storage.local.set({adBlock: isActive});
    }
  });
});
```


js.popup.js
```js
// popup.js

document.addEventListener('DOMContentLoaded', function() {
  const toggleButton = document.getElementById('toggleButton');
  const ipElement = document.getElementById('ip');

  function updateButtonState(isConnected) {
    if (isConnected) {
      toggleButton.classList.add('connected');
      $('.b-title').text("Disconnect");
    } else {
      toggleButton.classList.remove('connected');
      $('.b-title').text("Connect");
    }
  }

  // Get connection status from storage
  chrome.storage.local.get('isConnected', function(data) {
    updateButtonState(data.isConnected);
  });

  // Update connection status when changed
  chrome.storage.onChanged.addListener(function(changes, area) {
    if (area === 'local' && changes.isConnected) {
      updateButtonState(changes.isConnected.newValue);
    }
  });

  // Manual connect/disconnect
  toggleButton.addEventListener('click', function() {
    chrome.runtime.sendMessage({ action: 'toggleConnection' }, function(response) {
      updateButtonState(response.isConnected);
    });
  });

  // Listen for message from background.js to prompt for user key
  chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.action === 'promptUserKey') {
      const userKey = prompt('Please enter your user key:');
      if (userKey) {
        // Store the key and send it back to background.js
        chrome.storage.sync.set({ userKey: userKey }, function() {
          sendResponse({ userKey: userKey });
        });
      } else {
        sendResponse({ userKey: null });
      }
      return true; // Indicate that we will send a response asynchronously
    }
  });
});
```


Можешь просмотреть мой проект VPN-расширения и сервера аутентификации.
Найди тут ошибки и исправь их.
Приведи полные обновленные файлы.