Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ test
*.bat
server.ico
start.py
icon.png
logo.png

# Build
build
Expand Down
67 changes: 67 additions & 0 deletions api/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,73 @@
from django import forms
from api.models import UserProfile

class GenerateForm(forms.Form):
#Platform
platform = forms.ChoiceField(choices=[('windows','Windows'),('linux','Linux (currently unavailable)'),('android','Android (testing now available)')], initial='windows')
version = forms.ChoiceField(choices=[('master','beta'),('1.3.2','1.3.2'),('1.3.1','1.3.1'),('1.3.0','1.3.0')], initial='1.3.2')
delayFix = forms.BooleanField(initial=True, required=False)

#General
exename = forms.CharField(label="Name for EXE file", required=True)
appname = forms.CharField(label="Custom App Name", required=False)
direction = forms.ChoiceField(widget=forms.RadioSelect, choices=[
('incoming', 'Incoming Only'),
('outgoing', 'Outgoing Only'),
('both', 'Bidirectional')
], initial='both')
installation = forms.ChoiceField(label="Disable Installation", choices=[
('installationY', 'No, enable installation'),
('installationN', 'Yes, DISABLE installation')
], initial='installationY')
settings = forms.ChoiceField(label="Disable Settings", choices=[
('settingsY', 'No, enable settings'),
('settingsN', 'Yes, DISABLE settings')
], initial='settingsY')

#Custom Server
serverIP = forms.CharField(label="Host", required=False)
apiServer = forms.CharField(label="API Server", required=False)
key = forms.CharField(label="Key", required=False)
urlLink = forms.CharField(label="Custom URL for links", required=False)

#Visual
iconfile = forms.FileField(label="Custom App Icon (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
logofile = forms.FileField(label="Custom App Logo (in .png format)", required=False, widget=forms.FileInput(attrs={'accept': 'image/png'}))
theme = forms.ChoiceField(choices=[
('light', 'Light'),
('dark', 'Dark'),
('system', 'Follow System')
], initial='system')
themeDorO = forms.ChoiceField(choices=[('default', 'Default'),('override', 'Override')], initial='default')

#Security
passApproveMode = forms.ChoiceField(choices=[('password','Accept sessions via password'),('click','Accept sessions via click'),('password-click','Accepts sessions via both')],initial='password-click')
permanentPassword = forms.CharField(widget=forms.PasswordInput(), required=False)
runasadmin = forms.ChoiceField(choices=[('false','No'),('true','Yes')], initial='false')
denyLan = forms.BooleanField(initial=False, required=False)
enableDirectIP = forms.BooleanField(initial=False, required=False)
#ipWhitelist = forms.BooleanField(initial=False, required=False)
autoClose = forms.BooleanField(initial=False, required=False)

#Permissions
permissionsDorO = forms.ChoiceField(choices=[('default', 'Default'),('override', 'Override')], initial='default')
permissionsType = forms.ChoiceField(choices=[('custom', 'Custom'),('full', 'Full Access'),('view','Screen share')], initial='custom')
enableKeyboard = forms.BooleanField(initial=True, required=False)
enableClipboard = forms.BooleanField(initial=True, required=False)
enableFileTransfer = forms.BooleanField(initial=True, required=False)
enableAudio = forms.BooleanField(initial=True, required=False)
enableTCP = forms.BooleanField(initial=True, required=False)
enableRemoteRestart = forms.BooleanField(initial=True, required=False)
enableRecording = forms.BooleanField(initial=True, required=False)
enableBlockingInput = forms.BooleanField(initial=True, required=False)
enableRemoteModi = forms.BooleanField(initial=False, required=False)

#Other
removeWallpaper = forms.BooleanField(initial=True, required=False)

defaultManual = forms.CharField(widget=forms.Textarea, required=False)
overrideManual = forms.CharField(widget=forms.Textarea, required=False)

class AddPeerForm(forms.Form):
clientID = forms.CharField(label="Client Rustdesk ID", required=True)
alias = forms.CharField(label="Client alias", required=True)
Expand Down
21 changes: 21 additions & 0 deletions api/migrations/0004_githubrun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 5.0.3 on 2024-11-12 19:35

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0003_rustdesdevice_ip_rustdeskpeer_ip'),
]

operations = [
migrations.CreateModel(
name='GithubRun',
fields=[
('id', models.IntegerField(primary_key=True, serialize=False, verbose_name='ID')),
('uuid', models.CharField(max_length=100, verbose_name='uuid')),
('status', models.CharField(max_length=100, verbose_name='status')),
],
),
]
5 changes: 5 additions & 0 deletions api/models_work.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,8 @@ class ShareLinkAdmin(admin.ModelAdmin):
list_display = ('shash', 'uid', 'peers', 'is_used', 'is_expired', 'create_time')
search_fields = ('peers', )
list_filter = ('is_used', 'uid', 'is_expired' )

class GithubRun(models.Model):
id = models.IntegerField(verbose_name="ID",primary_key=True)
uuid = models.CharField(verbose_name="uuid", max_length=100)
status = models.CharField(verbose_name="status", max_length=100)
2 changes: 1 addition & 1 deletion api/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
<li class="layui-nav-item"><a href="/">Home</a></li>
<li class="layui-nav-item"><a href="/api/share">Share</a></li>
<li class="layui-nav-item"><a href="/api/installers">Installers</a></li>

<li class="layui-nav-item"><a href="/api/generator">Client Generator</a></li>
{% if u.is_admin %}
<li class="layui-nav-item"><a href="/admin" target="_blank">Admin Panel</a>
</li>
Expand Down
248 changes: 248 additions & 0 deletions api/templates/generator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
{% extends "base.html" %}
{% block title %}RustDesk WebUI{% endblock %}
{% block legend_name %}Client Generator{% endblock %}
{% block content %}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
<style>
.platform {
display: grid;
grid-template-columns: 1fr;
grid-gap: 20px;
margin: 0 auto;
padding: 20px;
max-width: 1200px;
}
.container {
display: grid;
grid-template-columns: 1fr 1fr; /* Adjust as needed */
grid-gap: 20px;
margin: 0 auto; /* Center the container horizontally */
padding: 20px;
max-width: 1200px;
}
.column {
flex: 50%;
}
h1 {
color: #000000;
text-align: center;
grid-column: 1 / -1;
}
h2 {
color: #000000;
margin-top: 0;
}
.section {
background-color: #111;
border-radius: 8px;
padding: 20px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
flex: 50%;
}
label {
display: block;
margin-bottom: 5px;
color: #bbb;
}
.out {
color: #000000;
}
.in {
color: #bbb;
}
input[type="text"], input[type="password"], select, textarea {
width: 100%;
padding: 8px;
margin-bottom: 10px;
background-color: #222;
border: 1px solid #444;
border-radius: 4px;
color: #fff;
}
input[type="radio"], input[type="checkbox"] {
margin-right: 5px;
}
button {
background-color: #bbb;
color: #000000;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0066cc;
}
.platform-icons {
display: flex;
justify-content: space-around;
margin-bottom: 20px;
}
.platform-icon {
font-size: 32px;
color: #bbb;
cursor: pointer;
transition: color 0.3s ease;
}
.platform-icon:hover, .platform-icon.active {
color: #000000;
}
.checkbox-group {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
}
.checkbox-group label {
display: flex;
align-items: center;
}
.preview-image {
max-width: 100%;
max-height: 100px;
margin-top: 10px;
}
</style>

<h1><i class="fas fa-cogs"></i> RustDesk Custom Client Builder</h1>
<form action="/api/generator" method="post" enctype="multipart/form-data">
<div class="platform">
<h2><i class="fas fa-desktop"></i> Select Platform</h2>
<div class="platform-icons">
<i class="fab fa-windows platform-icon active" data-platform="windows"></i>
<i class="fab fa-linux platform-icon" data-platform="linux"></i>
<i class="fab fa-android platform-icon" data-platform="android"></i>
</div>
<select name="platform" id="id_platform">
<option value="windows" selected>Windows</option>
<option value="linux">Linux</option>
<option value="android">Android</option>
</select>
<label class="out" for="{{ form.version.id_for_label }}">Rustdesk Version:</label>
{{ form.version }}
<label class="out" for="{{ form.delayFix.id_for_label }}">{{ form.delayFix }} Fix connection delay when using third-party API</label>
</div>
</div>
<div class="container">
<div class="section">
<h2 class="in"><i class="fas fa-sliders-h"></i> General</h2>
<label for="{{ form.exename.id_for_label }}">Name of the configuration:</label>
{{ form.exename }}<br><br>
<label for="{{ form.appname.id_for_label }}">Custom Application Name:</label>
{{ form.appname }}<br><br>
<label for="{{ form.direction.id_for_label }}">Connection Type:</label>
{{ form.direction }}<br><br>
<label for="{{ form.installation.id_for_label }}">Disable Installation:</label>
{{ form.installation }}<br><br>
<label for="{{ form.settings.id_for_label }}">Disable Settings:</label>
{{ form.settings }}<br><br>
</div>

<div class="section">
<h2 class="in"><i class="fas fa-server"></i> Custom Server</h2>
<label for="{{ form.serverIP.id_for_label }}">Host:</label>
{{ form.serverIP }}<br><br>
<label for="{{ form.key.id_for_label }}">Key:</label>
{{ form.key }}<br><br>
<label for="{{ form.apiServer.id_for_label }}">API:</label>
{{ form.apiServer }}<br><br>
<label for="{{ form.urlLink.id_for_label }}">Custom URL for links (replaces https://rustdesk.com):</label>
{{ form.urlLink }}<br><br>
</div>
</div>
<div class="container">
<div class="section">
<h2 class="in"><i class="fas fa-shield-alt"></i> Security</h2>
<label for="{{ form.runasadmin.id_for_label }}">Always run as Administrator?</label>
{{ form.runasadmin }}<br><br>
<label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
{{ form.passApproveMode }}<br><br>
<label for="{{ form.permanentPassword.id_for_label }}">Set Permanent Password:</label>
{{ form.permanentPassword }} <div class="in">*The password is used as default, but can be changed by the client</div><br><br>


<label for="{{ form.denyLan.id_for_label }}">{{ form.denyLan }} Deny LAN discovery</label><br>

<label for="{{ form.enableDirectIP.id_for_label }}">{{ form.enableDirectIP }} Enable direct IP access</label><br>

<label for="{{ form.autoClose.id_for_label }}">{{ form.autoClose }} Automatically close incoming sessions on user inactivity</label><br>
</div>

<div class="section">
<h2 class="in"><i class="fas fa-paint-brush"></i> Visual</h2>
<label for="{{ form.iconfile.id_for_label }}">Custom App Icon (in .png format)</label>
<div class="in">{{ form.iconfile }}</div><br><br>
<div id="icon-preview"></div><br><br>
<label for="{{ form.logofile.id_for_label }}">Custom App Logo (in .png format)</label>
<div class="in">{{ form.logofile }}</div><br><br>
<div id="logo-preview"></div><br><br>
<label for="{{ form.theme.id_for_label }}">Theme:</label>
{{ form.theme }} {{ form.themeDorO }} <div class="in">*Default sets the theme but allows the client to change it, Override sets the theme permanently.</div><br><br>
</div>
</div>
<div class="container">
<div class="section">
<h2 class="in"><i class="fas fa-lock"></i> Permissions</h2>
<div class="in">The following Permissions can be set as default (the user can change the settins) or override (the settings cannot be changed).</div><br>
{{ form.permissionsDorO }}
<label for="{{ form.permissionsType.id_for_label }}">Permission type:</label>
{{ form.permissionsType }}<br><br>
<div class="checkbox-group">
<label for="{{ form.enableKeyboard.id_for_label }}">{{ form.enableKeyboard }} Enable keyboard/mouse</label>
<label for="{{ form.enableClipboard.id_for_label }}">{{ form.enableClipboard }} Enable clipboard</label>
<label for="{{ form.enableFileTransfer.id_for_label }}">{{ form.enableFileTransfer }} Enable file transfer</label>
<label for="{{ form.enableAudio.id_for_label }}">{{ form.enableAudio }} Enable audio</label>
<label for="{{ form.enableTCP.id_for_label }}">{{ form.enableTCP }} Enable TCP tunneling</label>
<label for="{{ form.enableRemoteRestart.id_for_label }}">{{ form.enableRemoteRestart }} Enable remote restart</label>
<label for="{{ form.enableRecording.id_for_label }}">{{ form.enableRecording }} Enable recording session</label>
<label for="{{ form.enableBlockingInput.id_for_label }}">{{ form.enableBlockingInput }} Enable blocking user input</label>
<label for="{{ form.enableRemoteModi.id_for_label }}">{{ form.enableRemoteModi }} Enable remote configuration modification</label>
</div>
</div>

<div class="section">
<h2 class="in"><i class="fas fa-cog"></i> Other</h2>
<label for="{{ form.removeWallpaper.id_for_label }}">{{ form.removeWallpaper }} Remove wallpaper during incoming sessions</label><br>
<label for="{{ form.defaultManual.id_for_label }}">Default settings</label><br>
{{ form.defaultManual }}<br><br>
<label for="{{ form.overrideManual.id_for_label }}">Override settings</label><br>
{{ form.overrideManual }}<br><br>
</div>
</div>
<div class="platform">
<div class="section">
<button type="submit"><i class="fas fa-rocket"></i> Generate Custom Client</button>
</div>
</div>
</form>
<script>
document.querySelectorAll('.platform-icon').forEach(icon => {
icon.addEventListener('click', function() {
document.querySelectorAll('.platform-icon').forEach(i => i.classList.remove('active'));
this.classList.add('active');
document.getElementById('id_platform').value = this.dataset.platform;
});
});
document.getElementById("{{ form.iconfile.id_for_label }}").addEventListener('change', function(event) {
previewImage(event.target, 'icon-preview');
});
document.getElementById("{{ form.logofile.id_for_label }}").addEventListener('change', function(event) {
previewImage(event.target, 'logo-preview');
});
function previewImage(input, previewContainerId) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
var img = document.createElement('img');
img.src = e.target.result;  
img.style.maxWidth = '300px';
img.style.maxHeight = '60px';
document.getElementById(previewContainerId).innerHTML = '';
document.getElementById(previewContainerId).appendChild(img);
};
reader.readAsDataURL(input.files[0]);
}
}
</script>
{% endblock %}
Loading