3 Commits

Author SHA1 Message Date
Maxetto
570eee7d7c Hack to make AutoUpdater download from the custom url 2025-10-21 10:18:37 +02:00
Maxetto
509bbb9c9b Custom download link for AutoUpdater on x86 2025-10-21 10:17:20 +02:00
Maxetto
9eb41a4a56 Hack to make AutoUpdater download from the custom url 2025-10-21 10:16:03 +02:00
15 changed files with 600 additions and 919 deletions

View File

@@ -1,63 +0,0 @@
import os
import shutil
def remove_line_block(filepath, start_phrase, lines_to_remove_after_start):
"""
Removes a starting line and a fixed number of lines immediately following it.
:param filepath: The path to the file to modify.
:param start_phrase: The unique string to identify the first line of the block.
:param lines_to_remove_after_start: The number of lines to remove after the starting line.
"""
# 1. Configuration for the removal logic
# The starting line is: const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";
# The block contains this line plus 8 following lines, so we want to skip 9 lines in total.
total_lines_to_skip = 1 + lines_to_remove_after_start # 1 (start line) + 8 (following lines) = 9
lines_to_keep = []
skip_count = 0
# 2. Read and filter the file content
try:
with open(filepath, 'r') as file:
for line in file:
# If we are currently in the process of skipping lines, decrement the counter and continue
if skip_count > 0:
skip_count -= 1
continue
# Check if the line matches the start phrase (we use .strip() to ignore indentation/whitespace)
if line.strip().startswith(start_phrase.strip()):
# Start skipping the block (including the current line)
skip_count = total_lines_to_skip - 1
# Note: We subtract 1 because the 'continue' will handle the first line removal immediately
continue
# If we are not skipping, keep the line, but change custom.txt to custom_.txt
line = line.replace("custom.txt", "custom_.txt")
lines_to_keep.append(line)
except FileNotFoundError:
print(f"Error: File not found at {filepath}")
return
# 3. Write the remaining lines back to the file
try:
with open(filepath, 'w') as file:
file.writelines(lines_to_keep)
print(f"Success! Removed the 9-line block starting with '{start_phrase.strip()}' from {filepath}.")
except IOError as e:
print(f"An error occurred while writing to the file: {e}")
def main():
file_path = 'src/common.rs'
start_phrase = 'const KEY: &str = "5Qbwsde3unUcJBtrx9ZkvUmwFNoExHzpryHuPUdqlWM=";'
lines_to_remove_after_start = 8
remove_line_block(file_path, start_phrase, lines_to_remove_after_start)
if __name__ == "__main__":
main()

View File

@@ -1,8 +1,8 @@
diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart diff --git a/flutter/lib/desktop/widgets/remote_toolbar.dart b/flutter/lib/desktop/widgets/remote_toolbar.dart
index bc3757f1e..ba6509802 100644 index 839ea1a81..9cee52263 100644
--- a/flutter/lib/desktop/widgets/remote_toolbar.dart --- a/flutter/lib/desktop/widgets/remote_toolbar.dart
+++ b/flutter/lib/desktop/widgets/remote_toolbar.dart +++ b/flutter/lib/desktop/widgets/remote_toolbar.dart
@@ -317,6 +317,7 @@ class _RemoteToolbarState extends State<RemoteToolbar> { @@ -437,6 +437,7 @@ class _RemoteToolbarState extends State<RemoteToolbar> {
borderRadius: borderRadius, borderRadius: borderRadius,
child: _DraggableShowHide( child: _DraggableShowHide(
id: widget.id, id: widget.id,
@@ -10,7 +10,7 @@ index bc3757f1e..ba6509802 100644
sessionId: widget.ffi.sessionId, sessionId: widget.ffi.sessionId,
dragging: _dragging, dragging: _dragging,
fractionX: _fractionX, fractionX: _fractionX,
@@ -2460,6 +2461,7 @@ class RdoMenuButton<T> extends StatelessWidget { @@ -2234,6 +2235,7 @@ class RdoMenuButton<T> extends StatelessWidget {
class _DraggableShowHide extends StatefulWidget { class _DraggableShowHide extends StatefulWidget {
final String id; final String id;
@@ -18,7 +18,7 @@ index bc3757f1e..ba6509802 100644
final SessionID sessionId; final SessionID sessionId;
final RxDouble fractionX; final RxDouble fractionX;
final RxBool dragging; final RxBool dragging;
@@ -2472,6 +2474,7 @@ class _DraggableShowHide extends StatefulWidget { @@ -2246,6 +2248,7 @@ class _DraggableShowHide extends StatefulWidget {
const _DraggableShowHide({ const _DraggableShowHide({
Key? key, Key? key,
required this.id, required this.id,
@@ -26,7 +26,7 @@ index bc3757f1e..ba6509802 100644
required this.sessionId, required this.sessionId,
required this.fractionX, required this.fractionX,
required this.dragging, required this.dragging,
@@ -2583,6 +2586,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> { @@ -2357,6 +2360,7 @@ class _DraggableShowHideState extends State<_DraggableShowHide> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
_buildDraggable(context), _buildDraggable(context),
@@ -34,9 +34,9 @@ index bc3757f1e..ba6509802 100644
Obx(() => buttonWrapper( Obx(() => buttonWrapper(
() { () {
widget.setFullscreen(!isFullscreen.value); widget.setFullscreen(!isFullscreen.value);
@@ -2742,3 +2746,50 @@ class EdgeThicknessControl extends StatelessWidget { @@ -2463,3 +2467,50 @@ Widget _buildPointerTrackWidget(Widget child, FFI? ffi) {
return slider; ),
} );
} }
+ +
+class _CycleMonitorMenu extends StatelessWidget { +class _CycleMonitorMenu extends StatelessWidget {

View File

@@ -3,16 +3,56 @@ run-name: Custom Android Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: server:
description: 'version to buld' description: 'Rendezvous Server'
required: true required: true
default: '' default: ''
type: string type: string
zip_url: key:
description: 'url to zip of json' description: 'Public Key'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
@@ -31,7 +71,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ inputs.version }}" VERSION: "${{ fromJson(inputs.extras).version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -44,7 +84,7 @@ jobs:
generate-bridge-linux: generate-bridge-linux:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ inputs.version }} version: ${{ fromJson(inputs.extras).version }}
build-rustdesk-android: build-rustdesk-android:
needs: [generate-bridge-linux] needs: [generate-bridge-linux]
@@ -76,46 +116,6 @@ jobs:
suffix: "", suffix: "",
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}')
r.raise_for_status()
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Free Disk Space (Ubuntu) - name: Free Disk Space (Ubuntu)
uses: jlumbroso/free-disk-space@main uses: jlumbroso/free-disk-space@main
with: with:
@@ -135,14 +135,14 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -151,7 +151,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
- name: Install dependencies - name: Install dependencies
run: | run: |
@@ -190,11 +190,6 @@ jobs:
tree \ tree \
wget wget
- name: Install dependencies
continue-on-error: true
run: |
sudo apt-get install -y potrace
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -281,16 +276,16 @@ jobs:
prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated prefix-key: rustdesk-lib-cache-android # TODO: drop '-android' part after caches are invalidated
key: ${{ matrix.job.target }} key: ${{ matrix.job.target }}
###########################################################echo "${{ env.iconbase64 }}" | base64 -d > ./res/icon.png ###########################################################echo "${{ inputs.iconbase64 }}" | base64 -d > ./res/icon.png
- name: icon stuff - name: icon stuff
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
mv ./res/icon.ico ./res/icon.ico.bak mv ./res/icon.ico ./res/icon.ico.bak
mv ./res/icon.png ./res/icon.png.bak mv ./res/icon.png ./res/icon.png.bak
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
wget -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }} wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }}
mv ./res/32x32.png ./res/32x32.png.bak mv ./res/32x32.png ./res/32x32.png.bak
mv ./res/64x64.png ./res/64x64.png.bak mv ./res/64x64.png ./res/64x64.png.bak
mv ./res/128x128.png ./res/128x128.png.bak mv ./res/128x128.png ./res/128x128.png.bak
@@ -315,74 +310,67 @@ jobs:
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
# ./flutter/pubspec.yaml # ./flutter/pubspec.yaml
#sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml #sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
- name: change appname to custom - name: change appname to custom
if: env.appname != 'rustdesk' if: inputs.appname != 'rustdesk'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml
sed -i 's|name = "RustDesk"|name = "${{ env.appname }}"|' ./Cargo.toml sed -i 's|name = "RustDesk"|name = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml
sed -i -e 's|"RustDesk Remote Desktop"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk Remote Desktop"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ env.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|VALUE "InternalName", "rustdesk" "\0"|VALUE "InternalName", "${{ inputs.appname }}" "\0"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"Copyright © 2025 Purslane Ltd. All rights reserved."|"Copyright © 2025"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"rustdesk.exe"|"${{ env.filename }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"rustdesk.exe"|"${{ inputs.filename }}"|' ./flutter/windows/runner/Runner.rc
sed -i -e 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/windows/runner/Runner.rc sed -i -e 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/windows/runner/Runner.rc
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \;
sed -i -e 's|RustDesk|${{ env.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml sed -i -e 's|RustDesk|${{ inputs.appname }}|' ./flutter/android/app/src/main/res/values/strings.xml
sed -i -e "s|title: 'RustDesk'|title: '${{ env.appname }}'|" ./flutter/lib/main.dart sed -i -e "s|title: 'RustDesk'|title: '${{ inputs.appname }}'|" ./flutter/lib/main.dart
sed -i -e "s|return 'RustDesk';|return '${{ env.appname }}';|" ./flutter/lib/web/bridge.dart sed -i -e "s|return 'RustDesk';|return '${{ inputs.appname }}';|" ./flutter/lib/web/bridge.dart
sed -i 's|android:label="RustDesk"|android:label="${{ env.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml sed -i 's|android:label="RustDesk"|android:label="${{ inputs.appname }}"|' ./flutter/android/app/src/main/AndroidManifest.xml
sed -i 's|android:label="RustDesk Input"|android:label="${{ env.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml sed -i 's|android:label="RustDesk Input"|android:label="${{ inputs.appname }} Input"|' ./flutter/android/app/src/main/AndroidManifest.xml
sed -i 's|RustDesk is Open|${{ env.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt sed -i 's|RustDesk is Open|${{ inputs.appname }} is Open|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/BootReceiver.kt
sed -i 's|Show Rustdesk|Show ${{ env.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt sed -i 's|Show Rustdesk|Show ${{ inputs.appname }}|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/FloatingWindowService.kt
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
sed -i 's|"RustDesk Service|"${{ env.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt sed -i 's|"RustDesk Service|"${{ inputs.appname }} Service|' ./flutter/android/app/src/main/kotlin/com/carriez/flutter_hbb/MainService.kt
sed -i 's|RustDesk|${{ env.appname }}|' ./flutter/lib/main.dart sed -i 's|RustDesk|${{ inputs.appname }}|' ./flutter/lib/main.dart
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./flutter/lib/desktop/widgets/tabbar_widget.dart
sed -i 's|"RustDesk"|"${{ env.appname }}"|' ./libs/hbb_common/src/config.rs sed -i 's|"RustDesk"|"${{ inputs.appname }}"|' ./libs/hbb_common/src/config.rs
- name: change url to custom - name: change url to custom
if: env.urlLink != 'https://rustdesk.com' if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ env.urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|child: Text('rustdesk.com',|child: Text('${{ fromJson(inputs.extras).urlLink }}',|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change app id to custom
if: env.androidappid != 'com.carriez.flutter_hbb'
continue-on-error: true
shell: bash
run: |
sed -i -e 's|com.carriez.flutter_hbb|${{ env.androidappid }}|' ./flutter/android/app/build.gradle
- name: change download link to custom - name: change download link to custom
if: env.downloadLink != 'https://rustdesk.com/download' if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
- name: allow custom.txt - name: allow custom.txt
continue-on-error: true continue-on-error: true
@@ -394,35 +382,35 @@ jobs:
- name: fix connection delay - name: fix connection delay
continue-on-error: true continue-on-error: true
if: ${{ env.delayFix == 'true' }} if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: env.cycleMonitor == 'true' if: fromJson(inputs.extras).cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: env.xOffline == 'true' if: fromJson(inputs.extras).xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: env.hidecm == 'true' if: fromJson(inputs.extras).hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: env.removeNewVersionNotif == 'true' if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -434,10 +422,10 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "35% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "35% complete"}'
- name: replace flutter icons - name: replace flutter icons
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
run: | run: |
pushd ./flutter pushd ./flutter
flutter pub get flutter pub get
@@ -489,10 +477,10 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "45% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "45% complete"}'
- name: icons - name: icons
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: true continue-on-error: true
run: | run: |
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
@@ -506,8 +494,6 @@ jobs:
JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64 JAVA_HOME: /usr/lib/jvm/java-17-openjdk-amd64
run: | run: |
export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH
# Increase Gradle JVM memory for CI builds
sed -i "s/org.gradle.jvmargs=-Xmx1024M/org.gradle.jvmargs=-Xmx2g/g" ./flutter/android/gradle.properties
# temporary use debug sign config # temporary use debug sign config
sed -i "s/signingConfigs.release/signingConfigs.debug/g" ./flutter/android/app/build.gradle sed -i "s/signingConfigs.release/signingConfigs.debug/g" ./flutter/android/app/build.gradle
case ${{ matrix.job.target }} in case ${{ matrix.job.target }} in
@@ -515,8 +501,8 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a mkdir -p ./flutter/android/app/src/main/jniLibs/arm64-v8a
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/arm64-v8a/librustdesk.so
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm64 --split-per-abi flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm64 --split-per-abi
@@ -526,8 +512,8 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a mkdir -p ./flutter/android/app/src/main/jniLibs/armeabi-v7a
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/armeabi-v7a/librustdesk.so
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm --split-per-abi flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-arm --split-per-abi
@@ -537,8 +523,8 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64 mkdir -p ./flutter/android/app/src/main/jniLibs/x86_64
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86_64/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86_64/librustdesk.so
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x64 --split-per-abi flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x64 --split-per-abi
@@ -548,8 +534,8 @@ jobs:
mkdir -p ./flutter/android/app/src/main/jniLibs/x86 mkdir -p ./flutter/android/app/src/main/jniLibs/x86
cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/ cp ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so ./flutter/android/app/src/main/jniLibs/x86/
cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so cp ./target/${{ matrix.job.target }}/release/liblibrustdesk.so ./flutter/android/app/src/main/jniLibs/x86/librustdesk.so
echo -n "${{ env.custom }}" | cat > ./flutter/assets/custom_.txt echo -n "${{ inputs.custom }}" | cat > ./flutter/assets/custom.txt
#sed -i '/^ - assets\//a\ - assets/custom_.txt' ./flutter/pubspec.yaml #sed -i '/^ - assets\//a\ - assets/custom.txt' ./flutter/pubspec.yaml
# build flutter # build flutter
pushd flutter pushd flutter
flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x86 --split-per-abi flutter build apk "--${{ matrix.job.reltype }}" --target-platform android-x86 --split-per-abi
@@ -558,7 +544,7 @@ jobs:
esac esac
popd popd
mkdir -p signed-apk; pushd signed-apk mkdir -p signed-apk; pushd signed-apk
mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ env.filename }}-${{ matrix.job.arch }}.apk mv ../rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}${{ matrix.job.suffix }}.apk ./${{ inputs.filename }}-${{ matrix.job.arch }}.apk
popd popd
- name: Report Status - name: Report Status
@@ -568,7 +554,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "75% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "75% complete"}'
- uses: r0adkll/sign-android-release@v1 - uses: r0adkll/sign-android-release@v1
name: Sign app APK name: Sign app APK
@@ -586,16 +572,16 @@ jobs:
BUILD_TOOLS_VERSION: "30.0.2" BUILD_TOOLS_VERSION: "30.0.2"
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./signed-apk/${{ env.filename }}-${{ matrix.job.arch }}.apk" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./signed-apk/${{ inputs.filename }}-${{ matrix.job.arch }}.apk" ${{ inputs.apiServer }}/api/save_custom_client
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -604,7 +590,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Success"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -613,7 +599,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -622,4 +608,4 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'

View File

@@ -3,16 +3,56 @@ run-name: Custom Linux Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: server:
description: 'version to buld' description: 'Rendezvous Server'
required: true required: true
default: '' default: ''
type: string type: string
zip_url: key:
description: 'url to zip of json' description: 'Public Key'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
@@ -31,7 +71,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ inputs.version }}" VERSION: "${{ fromJson(inputs.extras).version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -44,7 +84,7 @@ jobs:
generate-bridge-linux: generate-bridge-linux:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ inputs.version }} version: ${{ fromJson(inputs.extras).version }}
build-rustdesk-linux: build-rustdesk-linux:
needs: [generate-bridge-linux] needs: [generate-bridge-linux]
@@ -72,48 +112,6 @@ jobs:
vcpkg-triplet: arm64-linux, vcpkg-triplet: arm64-linux,
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Export GitHub Actions cache environment variables - name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6 uses: actions/github-script@v6
with: with:
@@ -122,14 +120,14 @@ jobs:
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || ''); core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -138,7 +136,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
- name: Maximize build space - name: Maximize build space
run: | run: |
@@ -207,7 +205,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "15% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "15% complete"}'
- name: Restore bridge files - name: Restore bridge files
if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true' if: matrix.job.arch == 'x86_64' || env.UPLOAD_ARTIFACT == 'true'
@@ -245,14 +243,14 @@ jobs:
shell: bash shell: bash
- name: icon stuff - name: icon stuff
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
mv ./res/icon.ico ./res/icon.ico.bak mv ./res/icon.ico ./res/icon.ico.bak
mv ./res/icon.png ./res/icon.png.bak mv ./res/icon.png ./res/icon.png.bak
mv ./res/tray-icon.ico ./res/tray-icon.ico.bak mv ./res/tray-icon.ico ./res/tray-icon.ico.bak
wget -O ./res/icon.png ${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}"&"uuid=${{ env.iconlink_uuid }} wget -O ./res/icon.png ${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}"&"uuid=${{ fromJson(inputs.iconlink).uuid }}
mv ./res/32x32.png ./res/32x32.png.bak mv ./res/32x32.png ./res/32x32.png.bak
mv ./res/64x64.png ./res/64x64.png.bak mv ./res/64x64.png ./res/64x64.png.bak
mv ./res/128x128.png ./res/128x128.png.bak mv ./res/128x128.png ./res/128x128.png.bak
@@ -270,97 +268,97 @@ jobs:
b64="" b64=""
- name: change appname to custom - name: change appname to custom
if: env.appname != 'rustdesk' if: inputs.appname != 'rustdesk'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./Cargo.toml
sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|description = "RustDesk Remote Desktop"|description = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|ProductName = "RustDesk"|ProductName = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ env.appname }}"|' ./libs/portable/Cargo.toml sed -i -e 's|FileDescription = "RustDesk Remote Desktop"|FileDescription = "${{ inputs.appname }}"|' ./libs/portable/Cargo.toml
sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ env.appname }}.exe"|' ./libs/portable/Cargo.toml sed -i -e 's|OriginalFilename = "rustdesk.exe"|OriginalFilename = "${{ inputs.appname }}.exe"|' ./libs/portable/Cargo.toml
find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ env.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i -e 's|RustDesk|${{ inputs.appname }}|' {} \;
sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py sed -i -e '/-p tmpdeb\/usr\/lib\/rustdesk/d' ./build.py
- name: change company name - name: change company name
if: env.compname != 'Purslane Ltd' if: fromJson(inputs.extras).compname != 'Purslane Ltd'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./Cargo.toml sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./Cargo.toml
sed -i -e 's|Purslane Ltd|${{ env.compname }}|' ./libs/portable/Cargo.toml sed -i -e 's|Purslane Ltd|${{ fromJson(inputs.extras).compname }}|' ./libs/portable/Cargo.toml
- name: allow custom.txt - name: allow custom.txt
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
git apply allowCustom.diff git apply allowCustom.diff
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/removeSetupServerTip.diff
git apply removeSetupServerTip.diff git apply removeSetupServerTip.diff
echo -n "${{ env.custom }}" | cat > ./custom_.txt echo -n "${{ inputs.custom }}" | cat > ./custom.txt
# sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml # sed -i '/intl:/a \ \ archive: ^3.6.1' ./flutter/pubspec.yaml
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
- name: change url to custom - name: change url to custom
if: env.urlLink != 'https://rustdesk.com' if: fromJson(inputs.extras).urlLink != 'https://rustdesk.com'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ env.urlLink }}|' ./build.py sed -i -e 's|Homepage: https://rustdesk.com|Homepage: ${{ fromJson(inputs.extras).urlLink }}|' ./build.py
sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart sed -i -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change download link to custom - name: change download link to custom
if: env.downloadLink != 'https://rustdesk.com/download' if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
- name: fix connection delay - name: fix connection delay
continue-on-error: true continue-on-error: true
if: ${{ env.delayFix == 'true' }} if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: env.cycleMonitor == 'true' if: fromJson(inputs.extras).cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: env.xOffline == 'true' if: fromJson(inputs.extras).xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: env.hidecm == 'true' if: fromJson(inputs.extras).hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: env.removeNewVersionNotif == 'true' if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -379,7 +377,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "65% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "65% complete"}'
- uses: rustdesk-org/run-on-arch-action@amd64-support - uses: rustdesk-org/run-on-arch-action@amd64-support
name: Build rustdesk name: Build rustdesk
@@ -431,8 +429,7 @@ jobs:
rpm \ rpm \
unzip \ unzip \
wget \ wget \
xz-utils \ xz-utils
libssl-dev
# we have libopus compiled by us. # we have libopus compiled by us.
apt-get remove -y libopus-dev || true apt-get remove -y libopus-dev || true
# output devs # output devs
@@ -524,11 +521,11 @@ jobs:
export CARGO_INCREMENTAL=0 export CARGO_INCREMENTAL=0
export DEB_ARCH=${{ matrix.job.deb_arch }} export DEB_ARCH=${{ matrix.job.deb_arch }}
mkdir -p flutter/tmpdeb/usr/share/rustdesk mkdir -p flutter/tmpdeb/usr/share/rustdesk
cp ./custom_.txt ./flutter/tmpdeb/usr/share/rustdesk/custom_.txt cp ./custom.txt ./flutter/tmpdeb/usr/share/rustdesk/custom.txt
if [[ "${{ env.logolink_url }}" != "false" ]]; then if [[ "${{ inputs.logolink }}" != "false" ]]; then
wget -O ./flutter/assets/logo.png ${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}"&"uuid=${{ env.logolink_uuid }} wget -O ./flutter/assets/logo.png ${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}"&"uuid=${{ fromJson(inputs.logolink).uuid }}
fi fi
if [[ "${{ env.iconlink_url }}" != "false" ]]; then if [[ "${{ inputs.iconlink }}" != "false" ]]; then
mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak mv ./flutter/assets/icon.svg ./flutter/assets/icon.svg.bak
convert ./res/icon.png ./flutter/assets/icon.svg convert ./res/icon.png ./flutter/assets/icon.svg
convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true convert ./res/128x128.png -resize 200% ./flutter/assets/128x128@2x.png || true
@@ -543,7 +540,7 @@ jobs:
fi fi
python3 ./build.py --flutter --skip-cargo python3 ./build.py --flutter --skip-cargo
for name in rustdesk*??.deb; do for name in rustdesk*??.deb; do
mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.deb" mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.deb"
done done
# rpm package # rpm package
@@ -557,7 +554,7 @@ jobs:
HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb HBB=`pwd` rpmbuild ./res/rpm-flutter.spec -bb
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }} pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
for name in rustdesk*??.rpm; do for name in rustdesk*??.rpm; do
mv "$name" /workspace/output/"${{ env.filename }}-${{ matrix.job.arch }}.rpm" mv "$name" /workspace/output/"${{ inputs.filename }}-${{ matrix.job.arch }}.rpm"
done done
# rpm suse package # rpm suse package
@@ -571,7 +568,7 @@ jobs:
HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb HBB=`pwd` rpmbuild ./res/rpm-flutter-suse.spec -bb
pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }} pushd ~/rpmbuild/RPMS/${{ matrix.job.arch }}
for name in rustdesk*??.rpm; do for name in rustdesk*??.rpm; do
mv "$name" /workspace/output/"${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" mv "$name" /workspace/output/"${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm"
done done
# only x86_64 for arch since we can not find newest arm64 docker image to build # only x86_64 for arch since we can not find newest arm64 docker image to build
@@ -599,32 +596,32 @@ jobs:
continue-on-error: true continue-on-error: true
if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master' if: matrix.job.arch == 'x86_64' && env.UPLOAD_ARTIFACT == 'true' && env.VERSION != 'master'
run: | run: |
cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst cp ./res/rustdesk-${{ env.VERSION }}-0-x86_64.pkg.tar.zst ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client || true
- name: send file to api server - name: send file to api server
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.deb" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb" ${{ inputs.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-suse-${{ matrix.job.arch }}.rpm" ${{ inputs.apiServer }}/api/save_custom_client
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./output/${{ env.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ env.apiServer }}/api/save_custom_client || true curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./output/${{ inputs.filename }}-${{ matrix.job.arch }}.pkg.tar.zst" ${{ inputs.apiServer }}/api/save_custom_client || true
- name: Upload deb - name: Upload deb
uses: actions/upload-artifact@master uses: actions/upload-artifact@master
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
with: with:
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
path: ./output/${{ env.filename }}-${{ matrix.job.arch }}.deb path: ./output/${{ inputs.filename }}-${{ matrix.job.arch }}.deb
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -633,7 +630,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Finished ${{ matrix.job.arch }}"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Finished ${{ matrix.job.arch }}"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -642,7 +639,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -651,7 +648,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'
build-appimage: build-appimage:
name: Build appimage ${{ matrix.job.target }} name: Build appimage ${{ matrix.job.target }}
@@ -664,48 +661,6 @@ jobs:
- { target: x86_64-unknown-linux-gnu, arch: x86_64 } - { target: x86_64-unknown-linux-gnu, arch: x86_64 }
- { target: aarch64-unknown-linux-gnu, arch: aarch64 } - { target: aarch64-unknown-linux-gnu, arch: aarch64 }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -724,12 +679,12 @@ jobs:
- name: Download Binary - name: Download Binary
uses: actions/download-artifact@master uses: actions/download-artifact@master
with: with:
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
path: . path: .
- name: Rename Binary - name: Rename Binary
run: | run: |
mv ${{ env.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb appimage/rustdesk.deb
- name: Build appimage package - name: Build appimage package
shell: bash shell: bash
@@ -742,19 +697,19 @@ jobs:
# run appimage-builder # run appimage-builder
pushd appimage pushd appimage
sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml sudo appimage-builder --skip-tests --recipe ./AppImageBuilder-${{ matrix.job.arch }}.yml
sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ env.filename }}-${{ matrix.job.arch }}.AppImage sudo mv ./rustdesk-${{ env.VERSION }}-${{ matrix.job.arch }}.AppImage ./${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./appimage/${{ env.filename }}-${{ matrix.job.arch }}.AppImage" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./appimage/${{ inputs.filename }}-${{ matrix.job.arch }}.AppImage" ${{ inputs.apiServer }}/api/save_custom_client
build-flatpak: build-flatpak:
name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }} name: Build flatpak ${{ matrix.job.target }}${{ matrix.job.suffix }}
@@ -781,48 +736,6 @@ jobs:
suffix: "", suffix: "",
} }
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -841,12 +754,12 @@ jobs:
- name: Download Binary - name: Download Binary
uses: actions/download-artifact@master uses: actions/download-artifact@master
with: with:
name: ${{ env.filename }}-${{ matrix.job.arch }}.deb name: ${{ inputs.filename }}-${{ matrix.job.arch }}.deb
path: . path: .
- name: Rename Binary - name: Rename Binary
run: | run: |
mv ${{ env.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb mv ${{ inputs.filename }}-${{ matrix.job.arch }}.deb flatpak/rustdesk.deb
- uses: rustdesk-org/run-on-arch-action@amd64-support - uses: rustdesk-org/run-on-arch-action@amd64-support
name: Build rustdesk flatpak package for ${{ matrix.job.arch }} name: Build rustdesk flatpak package for ${{ matrix.job.arch }}
@@ -875,21 +788,21 @@ jobs:
pushd flatpak pushd flatpak
git clone https://github.com/flathub/shared-modules.git --depth=1 git clone https://github.com/flathub/shared-modules.git --depth=1
flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json flatpak-builder --user --install-deps-from=flathub -y --force-clean --repo=repo ./build ./rustdesk.json
flatpak build-bundle ./repo ${{ env.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk flatpak build-bundle ./repo ${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak com.rustdesk.RustDesk
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ env.uuid }}" ${{ secrets.GENURL }}/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" -F "uuid=${{ inputs.uuid }}" ${{ secrets.GENURL }}/save_custom_client
- name: send file to api server - name: send file to api server
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ env.token }}" -F "file=@./flatpak/${{ env.filename }}-${{ matrix.job.arch }}.flatpak" ${{ env.apiServer }}/api/save_custom_client curl -i -X POST -H "Content-Type: multipart/form-data" -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" -F "file=@./flatpak/${{ inputs.filename }}-${{ matrix.job.arch }}.flatpak" ${{ inputs.apiServer }}/api/save_custom_client
@@ -897,66 +810,16 @@ jobs:
needs: [build-rustdesk-linux,build-flatpak,build-appimage] needs: [build-rustdesk-linux,build-flatpak,build-appimage]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
for attempt in range(5):
try:
print(f"Downloading secrets (Attempt {attempt + 1})...")
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}', timeout=60)
r.raise_for_status()
break
except (requests.exceptions.RequestException, requests.exceptions.Timeout) as e:
if attempt < 4:
print(f"Timeout/Error occurred: {e}. Retrying in 5 seconds...")
time.sleep(5)
else:
print("Max retries reached. Failing.")
raise e
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
run: | run: |
echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ secrets.GENURL }}/updategh" >> $GITHUB_ENV
- name: Set rdgen value - name: Set rdgen value
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
run: | run: |
echo "STATUS_URL=${{ env.apiServer }}/api/updategh" >> $GITHUB_ENV echo "STATUS_URL=${{ inputs.apiServer }}/api/updategh" >> $GITHUB_ENV
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -964,9 +827,9 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Success"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
- uses: geekyeggo/delete-artifact@v5 - uses: geekyeggo/delete-artifact@v5
continue-on-error: true continue-on-error: true
with: with:
name: ${{ env.filename }}-*.deb name: ${{ inputs.filename }}-*.deb

View File

@@ -3,16 +3,56 @@ run-name: Custom macOS Client Generator
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: server:
description: 'version to buld' description: 'Rendezvous Server'
required: true required: true
default: '' default: ''
type: string type: string
zip_url: key:
description: 'url to zip of json' description: 'Public Key'
required: true required: true
default: '' default: ''
type: string type: string
apiServer:
description: 'API Server'
required: true
default: ''
type: string
custom:
description: "Custom JSON"
required: true
default: ''
type: string
uuid:
description: "uuid of request"
required: true
default: ''
type: string
iconlink:
description: "icon link"
required: false
default: 'false'
type: string
logolink:
description: "logo link"
required: false
default: 'false'
type: string
appname:
description: "app name"
required: true
default: 'rustdesk'
type: string
filename:
description: "Filename"
required: true
default: 'rustdesk'
type: string
extras:
description: "extra inputs in json"
required: true
default: '{}'
type: string
env: env:
SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html SCITER_RUST_VERSION: "1.75" # https://github.com/rustdesk/rustdesk/discussions/7503, also 1.78 has ABI change which causes our sciter version not working, https://blog.rust-lang.org/2024/03/30/i128-layout-update.html
@@ -31,7 +71,7 @@ env:
# vcpkg version: 2024.07.12 # vcpkg version: 2024.07.12
VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b" VCPKG_COMMIT_ID: "120deac3062162151622ca4860575a33844ba10b"
ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836" ARMV7_VCPKG_COMMIT_ID: "6f29f12e82a8293156836ad81cc9bf5af41fe836"
VERSION: "${{ inputs.version }}" VERSION: "${{ fromJson(inputs.extras).version }}"
NDK_VERSION: "r27c" NDK_VERSION: "r27c"
#signing keys env variable checks #signing keys env variable checks
ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}" ANDROID_SIGNING_KEY: "${{ secrets.ANDROID_SIGNING_KEY }}"
@@ -43,7 +83,7 @@ jobs:
generate-bridge: generate-bridge:
uses: ./.github/workflows/bridge.yml uses: ./.github/workflows/bridge.yml
with: with:
version: ${{ inputs.version }} version: ${{ fromJson(inputs.extras).version }}
build-for-macos: build-for-macos:
name: ${{ matrix.job.target }} name: ${{ matrix.job.target }}
@@ -55,7 +95,7 @@ jobs:
job: job:
- { - {
target: x86_64-apple-darwin, target: x86_64-apple-darwin,
os: macos-15-intel, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel os: macos-13, #macos-latest or macos-14 use M1 now, https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#:~:text=14%20GB-,macos%2Dlatest%20or%20macos%2D14,-The%20macos%2Dlatestlabel
extra-build-args: "", extra-build-args: "",
arch: x86_64, arch: x86_64,
vcpkg-triplet: x64-osx, vcpkg-triplet: x64-osx,
@@ -69,59 +109,9 @@ jobs:
vcpkg-triplet: arm64-osx, vcpkg-triplet: arm64-osx,
} }
env: env:
STATUS_URL: "${{ secrets.GENURL }}/updategh" STATUS_URL: ${{ fromJson(inputs.extras).rdgen == 'true' && format('{0}/updategh', secrets.GENURL) || format('{0}/api/updategh', inputs.apiServer) }}
steps: steps:
- name: install python deps
run: |
pip install requests pyzipper
- name: Download, Decrypt, and Mask
shell: python
run: |
import requests
import pyzipper
import io
import os
import json
r = requests.get('${{ fromJson(inputs.zip_url).url }}/get_zip?filename=${{ fromJson(inputs.zip_url).file }}')
r.raise_for_status()
try:
with pyzipper.AESZipFile(io.BytesIO(r.content)) as zf:
zf.setpassword('${{ secrets.ZIP_PASSWORD }}'.encode())
with zf.open('secrets.json') as f:
secrets = json.load(f)
except Exception as e:
print(f"Error: Could not decrypt ZIP. Check if password matches. {e}")
exit(1)
with open(os.environ['GITHUB_ENV'], 'a') as env_file:
for key, value in secrets.items():
print(f"::add-mask::{value}")
env_file.write(f"{key}={value}\n")
api_server = secrets.get('apiServer', '').strip()
api_server = api_server.rstrip('/')
rdgen_value = str(secrets.get('rdgen', 'false')).lower()
if rdgen_value == "true":
status_url = "${{ secrets.GENURL }}/updategh"
else:
status_url = f"{api_server}/api/updategh"
env_file.write(f"STATUS_URL={status_url}\n")
print("Secrets loaded into environment.")
- name: Finalize and Cleanup zip/json
if: always() # Run even if previous steps fail
uses: fjogeleit/http-request-action@v1
with:
url: ${{ env.STATUS_URL }}
method: 'POST'
customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}"}'
- name: Export GitHub Actions cache environment variables - name: Export GitHub Actions cache environment variables
uses: actions/github-script@v6 uses: actions/github-script@v6
with: with:
@@ -135,7 +125,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "5% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "5% complete"}'
- name: Checkout source code - name: Checkout source code
if: ${{ env.VERSION != 'master' }} if: ${{ env.VERSION != 'master' }}
@@ -168,73 +158,76 @@ jobs:
cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak cp ./flutter/macos/Runner/Configs/AppInfo.xcconfig ./flutter/macos/Runner/Configs/AppInfo.xcconfig.bak
# MACSTUFF Update Info.plist # MACSTUFF Update Info.plist
sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleName</key>.*<string>.*</string>|<key>CFBundleName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist
sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ env.appname }}</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleDisplayName</key>.*<string>.*</string>|<key>CFBundleDisplayName</key>\n\t<string>${{ inputs.appname }}</string>|' ./flutter/macos/Runner/Info.plist
sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ env.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist sed -i '' -e 's|<key>CFBundleIdentifier</key>.*<string>.*</string>|<key>CFBundleIdentifier</key>\n\t<string>com.${{ inputs.appname }}.app</string>|' ./flutter/macos/Runner/Info.plist
# sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist # sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
# MACSTUFF Update AppInfo.xcconfig # MACSTUFF Update AppInfo.xcconfig
sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|PRODUCT_NAME = .*|PRODUCT_NAME = ${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ env.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|PRODUCT_BUNDLE_IDENTIFIER = .*|PRODUCT_BUNDLE_IDENTIFIER = com.${{ inputs.appname }}.app|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
sed -i '' -e 's|Purslane Ltd.|${{ env.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig sed -i '' -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./flutter/macos/Runner/Configs/AppInfo.xcconfig
# Keep DEVELOPMENT_TEAM if it exists, don't blank it out # Keep DEVELOPMENT_TEAM if it exists, don't blank it out
sed -i -e 's|Purslane Ltd.|${{ env.appname }}|' ./Cargo.toml sed -i -e 's|Purslane Ltd.|${{ inputs.appname }}|' ./Cargo.toml
sed -i -e 's|Purslane Ltd|${{ env.appname }}|' ./libs/portable/Cargo.toml sed -i -e 's|Purslane Ltd|${{ inputs.appname }}|' ./libs/portable/Cargo.toml
# Update Xcode project settings # Update Xcode project settings
sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ env.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj sed -i '' -e 's/PRODUCT_NAME = "RustDesk"/PRODUCT_NAME = "${{ inputs.appname }}"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ env.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj sed -i '' -e 's/PRODUCT_BUNDLE_IDENTIFIER = ".*"/PRODUCT_BUNDLE_IDENTIFIER = "com.${{ inputs.appname }}.app"/' ./flutter/macos/Runner.xcodeproj/project.pbxproj
# Don't modify DEVELOPMENT_TEAM in project.pbxproj # Don't modify DEVELOPMENT_TEAM in project.pbxproj
# Update CMake settings # Update CMake settings
if [ -f "./flutter/macos/CMakeLists.txt" ]; then if [ -f "./flutter/macos/CMakeLists.txt" ]; then
sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ env.appname }}")/' ./flutter/macos/CMakeLists.txt sed -i '' -e 's/set(BINARY_NAME ".*")/set(BINARY_NAME "${{ inputs.appname }}")/' ./flutter/macos/CMakeLists.txt
fi fi
# Update Podfile - keep the target as 'Runner' # Update Podfile - keep the target as 'Runner'
# sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ env.appname }}'"'"' do/' ./flutter/macos/Podfile # sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'${{ inputs.appname }}'"'"' do/' ./flutter/macos/Podfile
sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile sed -i '' -e 's/target '"'"'Runner'"'"' do/target '"'"'Runner'"'"' do/' ./flutter/macos/Podfile
cp ./src/lang/en.rs ./src/lang/en.rs.bak cp ./src/lang/en.rs ./src/lang/en.rs.bak
cp ./src/lang/nl.rs ./src/lang/nl.rs.bak cp ./src/lang/nl.rs ./src/lang/nl.rs.bak
find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ env.appname }}|' {} \; find ./src/lang -name "*.rs" -exec sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' {} \;
sed -i '' -e 's|RustDesk|${{ env.appname }}|' ./src/lang/nl.rs sed -i '' -e 's|RustDesk|${{ inputs.appname }}|' ./src/lang/nl.rs
sed -i '' -e 's|https://rustdesk.com|${{ env.urlLink }}|' ./build.py sed -i '' -e 's|https://rustdesk.com|${{ fromJson(inputs.extras).urlLink }}|' ./build.py
sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ env.urlLink }}'));|" ./flutter/lib/common.dart sed -i '' -e "s|launchUrl(Uri.parse('https://rustdesk.com'));|launchUrl(Uri.parse('${{ fromJson(inputs.extras).urlLink }}'));|" ./flutter/lib/common.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ env.urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com');|launchUrlString('${{ fromJson(inputs.extras).urlLink }}');|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/desktop/pages/desktop_setting_page.dart
sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ env.urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart sed -i '' -e "s|const url = 'https://rustdesk.com/';|const url = '${{ fromJson(inputs.extras).urlLink }}';|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ env.urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart sed -i '' -e "s|launchUrlString('https://rustdesk.com/privacy.html')|launchUrlString('${{ fromJson(inputs.extras).urlLink }}/privacy.html')|" ./flutter/lib/mobile/pages/settings_page.dart
sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ env.urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart sed -i '' -e "s|https://rustdesk.com/privacy.html|${{ fromJson(inputs.extras).urlLink }}/privacy.html|" ./flutter/lib/desktop/pages/install_page.dart
- name: change download link to custom - name: change download link to custom
if: env.downloadLink != 'https://rustdesk.com/download' if: fromJson(inputs.extras).downloadLink != 'https://rustdesk.com/download'
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./flutter/lib/mobile/pages/connection_page.dart
sed -i -e 's|https://rustdesk.com/download|${{ env.downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
sed -i -e 's|&download_url|"${{ fromJson(inputs.extras).downloadLink }}"|' ./src/updater.rs
sed -i -e 's|get_download_file_from_url(.*)|get_download_file_from_url("${{ fromJson(inputs.extras).downloadLink }}")|g' ./src/flutter_ffi.rs
sed -i -e 's|let download_url = _value.clone()|let download_url = "${{ fromJson(inputs.extras).downloadLink }}".to_string()|' ./src/flutter_ffi.rs
# Update slogan # Update slogan
#sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ env.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist #sed -i '' '/<key>NSHumanReadableCopyright<\/key>/{n;s/<string>.*<\/string>/<string>Copyright 2025 ${{ inputs.appname }}. All rights reserved.<\/string>/;}' ./flutter/macos/Runner/Info.plist
# Update slogan - About in en.rs # Update slogan - About in en.rs
sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/en.rs sed -i '' -e 's/("Slogan_tip", "Made with heart in this chaotic world!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/en.rs
sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ env.appname }}")/' ./src/lang/en.rs sed -i '' -e 's/("About RustDesk", "")/("About RustDesk", "About ${{ inputs.appname }}")/' ./src/lang/en.rs
# Update slogan - About in nl.rs # Update slogan - About in nl.rs
sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ env.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("Slogan_tip", "Ontwikkeld met het hart voor deze chaotische wereld!")/("Slogan_tip", "Powered by ${{ inputs.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ env.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("Your Desktop", "Uw Bureaublad")/("Your Desktop", "Uw ${{ inputs.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ env.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("About RustDesk", "Over RustDesk")/("About RustDesk", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs
sed -i '' -e 's/("About", "Over")/("About", "Over ${{ env.appname }}")/' ./src/lang/nl.rs sed -i '' -e 's/("About", "Over")/("About", "Over ${{ inputs.appname }}")/' ./src/lang/nl.rs
sed -i -e 's|rs-ny.rustdesk.com|${{ env.server }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|rs-ny.rustdesk.com|${{ inputs.server }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ env.key }}|' ./libs/hbb_common/src/config.rs sed -i -e 's|OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=|${{ inputs.key }}|' ./libs/hbb_common/src/config.rs
sed -i -e 's|https://admin.rustdesk.com|${{ env.apiServer }}|' ./src/common.rs sed -i -e 's|https://admin.rustdesk.com|${{ inputs.apiServer }}|' ./src/common.rs
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/allowCustom.diff
git apply allowCustom.diff git apply allowCustom.diff
@@ -254,11 +247,11 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "10% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "10% complete"}'
- name: Install build runtime - name: Install build runtime
run: | run: |
brew install llvm create-dmg brew install llvm create-dmg nasm
# pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner # pkg-config is handled in a separate step, because it may be already installed by `macos-latest`(14.7.1) runner
if command -v pkg-config &>/dev/null; then if command -v pkg-config &>/dev/null; then
echo "pkg-config is already installed" echo "pkg-config is already installed"
@@ -266,17 +259,6 @@ jobs:
brew install pkg-config brew install pkg-config
fi fi
- name: Install NASM
run: |
# Install NASM 2.16.x from official release.
# Do NOT use `brew install nasm` which installs NASM 3.x.
# NASM 3.x is a complete rewrite with incompatible CLI options and removed features.
# aom and other multimedia libraries require NASM 2.x for x86/x86_64 assembly.
wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/macosx/nasm-2.16.03-macosx.zip
unzip nasm-2.16.03-macosx.zip
sudo cp nasm-2.16.03/nasm /usr/local/bin/nasm
nasm --version
- name: Install flutter - name: Install flutter
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
@@ -309,7 +291,7 @@ jobs:
prefix-key: ${{ matrix.job.os }} prefix-key: ${{ matrix.job.os }}
- name: Magick stuff for macOS - name: Magick stuff for macOS
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -323,8 +305,8 @@ jobs:
# Download icon using curl with additional SSL options # Download icon using curl with additional SSL options
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \ curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
-H "User-Agent: Mozilla/5.0" \ -H "User-Agent: Mozilla/5.0" \
"${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}" \ "${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}" \
-o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ env.iconlink_url }}/get_png?filename=${{ env.iconlink_file }}&uuid=${{ env.iconlink_uuid }}" -o ./res/icon.png || wget --no-check-certificate -O ./res/icon.png "${{ fromJson(inputs.iconlink).url }}/get_png?filename=${{ fromJson(inputs.iconlink).file }}&uuid=${{ fromJson(inputs.iconlink).uuid }}"
# Backup existing files (if they exist) # Backup existing files (if they exist)
[ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak [ -f "./res/32x32.png" ] && mv ./res/32x32.png ./res/32x32.png.bak
@@ -419,7 +401,7 @@ jobs:
ls -lh rustdesk/data/flutter_assets/assets/ ls -lh rustdesk/data/flutter_assets/assets/
- name: replace flutter icons - name: replace flutter icons
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -427,8 +409,8 @@ jobs:
# Create required directories and files # Create required directories and files
mkdir -p web mkdir -p web
mkdir -p assets mkdir -p assets
echo '{"name":"${{ env.appname }}","short_name":"${{ env.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json echo '{"name":"${{ inputs.appname }}","short_name":"${{ inputs.appname }}","start_url":"/","display":"standalone","background_color":"#ffffff","theme_color":"#ffffff","description":"A remote desktop software."}' > web/manifest.json
echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ env.appname }}</title></head><body></body></html>' > web/index.html echo '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>${{ inputs.appname }}</title></head><body></body></html>' > web/index.html
# Ensure the AppIcon.appiconset directory exists # Ensure the AppIcon.appiconset directory exists
mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset mkdir -p macos/Runner/Assets.xcassets/AppIcon.appiconset
@@ -443,7 +425,7 @@ jobs:
cd .. cd ..
- name: ui.rs - name: ui.rs
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: true continue-on-error: true
shell: bash shell: bash
run: | run: |
@@ -456,35 +438,35 @@ jobs:
- name: fix connection delay - name: fix connection delay
continue-on-error: false continue-on-error: false
if: ${{ env.delayFix == 'true' }} if: ${{ fromJson(inputs.extras).delayFix == 'true' }}
shell: bash shell: bash
run: | run: |
sed -i -e 's|!key.is_empty()|false|' ./src/client.rs sed -i -e 's|!key.is_empty()|false|' ./src/client.rs
- name: add cycle monitors to toolbar - name: add cycle monitors to toolbar
continue-on-error: true continue-on-error: true
if: env.cycleMonitor == 'true' if: fromJson(inputs.extras).cycleMonitor == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/cycle_monitor.diff
git apply cycle_monitor.diff git apply cycle_monitor.diff
- name: use X for offline display instead of orange circle - name: use X for offline display instead of orange circle
continue-on-error: true continue-on-error: true
if: env.xOffline == 'true' if: fromJson(inputs.extras).xOffline == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/xoffline.diff
git apply xoffline.diff git apply xoffline.diff
- name: hide-cm - name: hide-cm
continue-on-error: true continue-on-error: true
if: env.hidecm == 'true' if: fromJson(inputs.extras).hidecm == 'true'
run: | run: |
wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff wget https://raw.githubusercontent.com/bryangerlach/rdgen/refs/heads/master/.github/patches/hidecm.diff
git apply hidecm.diff git apply hidecm.diff
- name: removeNewVersionNotif - name: removeNewVersionNotif
continue-on-error: true continue-on-error: true
if: env.removeNewVersionNotif == 'true' if: fromJson(inputs.extras).removeNewVersionNotif == 'true'
run: | run: |
sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart sed -i -e 's|updateUrl.isNotEmpty|false|' ./flutter/lib/desktop/pages/desktop_home_page.dart
sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs sed -i '/let (request, url) =/,/Ok(())/{/Ok(())/!d}' ./src/common.rs
@@ -495,7 +477,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "20% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "20% complete"}'
- name: Restore bridge files - name: Restore bridge files
uses: actions/download-artifact@master uses: actions/download-artifact@master
@@ -531,7 +513,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "25% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "25% complete"}'
- name: Create MacOS directory structure - name: Create MacOS directory structure
run: | run: |
@@ -546,7 +528,7 @@ jobs:
sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml sed -i -e "s/osx_minimum_system_version = \"[0-9]*.[0-9]*\"/osx_minimum_system_version = \"${MIN_MACOS_VERSION}\"/" Cargo.toml
sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj sed -i -e "s/MACOSX_DEPLOYMENT_TARGET = [0-9]*.[0-9]*;/MACOSX_DEPLOYMENT_TARGET = ${MIN_MACOS_VERSION};/" flutter/macos/Runner.xcodeproj/project.pbxproj
fi fi
sed -i -e "s/RustDesk.app/\"${{ env.appname }}.app\"/" build.py sed -i -e "s/RustDesk.app/\"${{ inputs.appname }}.app\"/" build.py
./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }} ./build.py --flutter --hwcodec --unix-file-copy-paste ${{ matrix.job.extra-build-args }}
# - name: Copy service file # - name: Copy service file
@@ -559,7 +541,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ inputs.uuid }}", "status": "50% complete, this step takes about 5 minutes, be patient."}'
- name: Install rcodesign tool - name: Install rcodesign tool
if: env.MACOS_P12_BASE64 != null if: env.MACOS_P12_BASE64 != null
@@ -587,7 +569,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}' data: '{"uuid": "${{ inputs.uuid }}", "status": "70% complete, this step takes about 5 minutes, be patient."}'
- name: Show version information (Rust, cargo, Clang) - name: Show version information (Rust, cargo, Clang)
shell: bash shell: bash
@@ -600,7 +582,7 @@ jobs:
rustc -V rustc -V
- name: icon svg handling - name: icon svg handling
if: ${{ env.iconlink_url != 'false' }} if: ${{ inputs.iconlink != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -616,7 +598,7 @@ jobs:
rm ./temp_icon.pbm rm ./temp_icon.pbm
- name: logo handling - name: logo handling
if: ${{ env.logolink_url != 'false' }} if: ${{ inputs.logolink != 'false' }}
continue-on-error: false continue-on-error: false
shell: bash shell: bash
run: | run: |
@@ -624,11 +606,11 @@ jobs:
mkdir -p "$ASSETS_DIR" mkdir -p "$ASSETS_DIR"
curl -k -L --tlsv1.2 --proto =https --ssl-reqd \ curl -k -L --tlsv1.2 --proto =https --ssl-reqd \
-H "User-Agent: Mozilla/5.0" \ -H "User-Agent: Mozilla/5.0" \
"${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}" \ "${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}" \
-o "$ASSETS_DIR/logo.png" || \ -o "$ASSETS_DIR/logo.png" || \
wget --no-check-certificate \ wget --no-check-certificate \
-O "$ASSETS_DIR/logo.png" \ -O "$ASSETS_DIR/logo.png" \
"${{ env.logolink_url }}/get_png?filename=${{ env.logolink_file }}&uuid=${{ env.logolink_uuid }}" "${{ fromJson(inputs.logolink).url }}/get_png?filename=${{ fromJson(inputs.logolink).file }}&uuid=${{ fromJson(inputs.logolink).uuid }}"
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -636,7 +618,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "85% complete"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "85% complete"}'
- name: Sign macOS app bundle - name: Sign macOS app bundle
if: env.MACOS_P12_BASE64 != '' if: env.MACOS_P12_BASE64 != ''
@@ -649,21 +631,21 @@ jobs:
# Rename RustDesk.app to the custom app name first # Rename RustDesk.app to the custom app name first
if [ -d "RustDesk.app" ]; then if [ -d "RustDesk.app" ]; then
# First rename the app if it's still called RustDesk.app # First rename the app if it's still called RustDesk.app
mv "RustDesk.app" "${{ env.appname }}.app" mv "RustDesk.app" "${{ inputs.appname }}.app"
echo "Renamed RustDesk.app to ${{ env.appname }}.app" echo "Renamed RustDesk.app to ${{ inputs.appname }}.app"
fi fi
echo "App bundle contents after rename:" echo "App bundle contents after rename:"
ls -la "${{ env.appname }}.app" || echo "App not found" ls -la "${{ inputs.appname }}.app" || echo "App not found"
ls -la "${{ env.appname }}.app/Contents" || echo "Contents not found" ls -la "${{ inputs.appname }}.app/Contents" || echo "Contents not found"
# Decode the certificate # Decode the certificate
echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12 echo "${{ secrets.MACOS_P12_BASE64 }}" | base64 --decode > certificate.p12
# Sign the app bundle and its contents # Sign the app bundle and its contents
if [ -d "${{ env.appname }}.app/Contents/MacOS" ]; then if [ -d "${{ inputs.appname }}.app/Contents/MacOS" ]; then
echo "Signing main executable..." echo "Signing main executable..."
MAIN_EXECUTABLE="${{ env.appname }}.app/Contents/MacOS/${{ env.appname }}" MAIN_EXECUTABLE="${{ inputs.appname }}.app/Contents/MacOS/${{ inputs.appname }}"
if [ -f "$MAIN_EXECUTABLE" ]; then if [ -f "$MAIN_EXECUTABLE" ]; then
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "$MAIN_EXECUTABLE" --code-signature-flags runtime "$MAIN_EXECUTABLE"
@@ -671,23 +653,23 @@ jobs:
echo "Main executable not found at expected path: $MAIN_EXECUTABLE" echo "Main executable not found at expected path: $MAIN_EXECUTABLE"
# Try to find the actual executable # Try to find the actual executable
echo "Available executables in MacOS directory:" echo "Available executables in MacOS directory:"
ls -la "${{ env.appname }}.app/Contents/MacOS/" ls -la "${{ inputs.appname }}.app/Contents/MacOS/"
ACTUAL_EXECUTABLE=$(ls "${{ env.appname }}.app/Contents/MacOS/" | head -n 1) ACTUAL_EXECUTABLE=$(ls "${{ inputs.appname }}.app/Contents/MacOS/" | head -n 1)
if [ -n "$ACTUAL_EXECUTABLE" ]; then if [ -n "$ACTUAL_EXECUTABLE" ]; then
echo "Found executable: $ACTUAL_EXECUTABLE" echo "Found executable: $ACTUAL_EXECUTABLE"
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "${{ env.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE" --code-signature-flags runtime "${{ inputs.appname }}.app/Contents/MacOS/$ACTUAL_EXECUTABLE"
fi fi
fi fi
echo "Signing frameworks..." echo "Signing frameworks..."
find "${{ env.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \ find "${{ inputs.appname }}.app/Contents/Frameworks" -type f -not -name ".*" -exec \
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime {} \; --code-signature-flags runtime {} \;
echo "Signing main bundle..." echo "Signing main bundle..."
rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \ rcodesign sign --p12-file certificate.p12 --p12-password "${{ secrets.MACOS_P12_PASSWORD }}" \
--code-signature-flags runtime "${{ env.appname }}.app" --code-signature-flags runtime "${{ inputs.appname }}.app"
else else
echo "Error: Invalid app bundle structure" echo "Error: Invalid app bundle structure"
exit 1 exit 1
@@ -705,24 +687,24 @@ jobs:
# Find the actual .app bundle # Find the actual .app bundle
if [ -d "RustDesk.app" ]; then if [ -d "RustDesk.app" ]; then
# First rename the app if it's still called RustDesk.app # First rename the app if it's still called RustDesk.app
mv "RustDesk.app" "${{ env.appname }}.app" mv "RustDesk.app" "${{ inputs.appname }}.app"
fi fi
if [ ! -d "${{ env.appname }}.app" ]; then if [ ! -d "${{ inputs.appname }}.app" ]; then
echo "Could not find .app bundle!" echo "Could not find .app bundle!"
exit 1 exit 1
fi fi
echo "Creating DMG for ${{ env.appname }}.app" echo "Creating DMG for ${{ inputs.appname }}.app"
create-dmg \ create-dmg \
--volname "${{ env.appname }}" \ --volname "${{ inputs.appname }}" \
--window-pos 200 120 \ --window-pos 200 120 \
--window-size 800 400 \ --window-size 800 400 \
--icon-size 100 \ --icon-size 100 \
--icon "${{ env.appname }}.app" 200 190 \ --icon "${{ inputs.appname }}.app" 200 190 \
--hide-extension "${{ env.appname }}.app" \ --hide-extension "${{ inputs.appname }}.app" \
--app-drop-link 600 185 \ --app-drop-link 600 185 \
"${{ env.appname }}-${{ matrix.job.arch }}.dmg" \ "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" \
"${{ env.appname }}.app" "${{ inputs.appname }}.app"
mv "${{ env.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/ mv "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg" $GITHUB_WORKSPACE/
- name: Rename rustdesk - name: Rename rustdesk
if: env.UPLOAD_ARTIFACT == 'true' if: env.UPLOAD_ARTIFACT == 'true'
@@ -732,38 +714,38 @@ jobs:
ls -la ls -la
# Find the DMG file dynamically # Find the DMG file dynamically
DMG_FILE=$(find . -name "${{ env.appname }}-${{ matrix.job.arch }}.dmg") DMG_FILE=$(find . -name "${{ inputs.appname }}-${{ matrix.job.arch }}.dmg")
if [ -n "$DMG_FILE" ]; then if [ -n "$DMG_FILE" ]; then
echo "Found DMG file: $DMG_FILE" echo "Found DMG file: $DMG_FILE"
mv "$DMG_FILE" "${{ env.filename }}-${{ matrix.job.arch }}.dmg" mv "$DMG_FILE" "${{ inputs.filename }}-${{ matrix.job.arch }}.dmg"
echo "Renamed to ${{ env.filename }}-${{ matrix.job.arch }}.dmg" echo "Renamed to ${{ inputs.filename }}-${{ matrix.job.arch }}.dmg"
else else
echo "No DMG file found matching the pattern" echo "No DMG file found matching the pattern"
exit 1 exit 1
fi fi
- name: send file to rdgen server - name: send file to rdgen server
if: ${{ env.rdgen == 'true' }} if: ${{ fromJson(inputs.extras).rdgen == 'true' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST \ curl -i -X POST \
-H "Content-Type: multipart/form-data" \ -H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer ${{ env.token }}" \ -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \
-F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \ -F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \
-F "uuid=${{ env.uuid }}" \ -F "uuid=${{ inputs.uuid }}" \
"${{ secrets.GENURL }}/save_custom_client" "${{ secrets.GENURL }}/save_custom_client"
- name: send file to api server - name: send file to api server
if: ${{ env.rdgen == 'false' }} if: ${{ fromJson(inputs.extras).rdgen == 'false' }}
shell: bash shell: bash
run: | run: |
curl -i -X POST \ curl -i -X POST \
-H "Content-Type: multipart/form-data" \ -H "Content-Type: multipart/form-data" \
-H "Authorization: Bearer ${{ env.token }}" \ -H "Authorization: Bearer ${{ fromJson(inputs.extras).token }}" \
-F "file=@$GITHUB_WORKSPACE/${{ env.filename }}-${{ matrix.job.arch }}.dmg" \ -F "file=@$GITHUB_WORKSPACE/${{ inputs.filename }}-${{ matrix.job.arch }}.dmg" \
"${{ env.apiServer }}/api/save_custom_client" "${{ inputs.apiServer }}/api/save_custom_client"
- name: Report Status - name: Report Status
uses: fjogeleit/http-request-action@v1 uses: fjogeleit/http-request-action@v1
@@ -771,7 +753,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Success"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Success"}'
- name: failed - name: failed
if: failure() if: failure()
@@ -780,7 +762,7 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation failed, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation failed, try again"}'
- name: failed - name: failed
if: cancelled() if: cancelled()
@@ -789,4 +771,4 @@ jobs:
url: ${{ env.STATUS_URL }} url: ${{ env.STATUS_URL }}
method: 'POST' method: 'POST'
customHeaders: '{"Content-Type": "application/json"}' customHeaders: '{"Content-Type": "application/json"}'
data: '{"uuid": "${{ env.uuid }}", "status": "Generation cancelled, try again"}' data: '{"uuid": "${{ inputs.uuid }}", "status": "Generation cancelled, try again"}'

View File

@@ -217,6 +217,7 @@ jobs:
shell: bash shell: bash
run: | run: |
sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis sed -i -e 's|https://rustdesk.com/download|${{ fromJson(inputs.extras).downloadLink }}|' ./src/ui/index.tis
sed -i -e 's|&download_url|"${{ fromJson(inputs.extras).downloadLink }}"|' ./src/updater.rs
- name: set server, key, and apiserver - name: set server, key, and apiserver
continue-on-error: true continue-on-error: true

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,6 @@
services: services:
rdgen: rdgen:
# use bryangerlach/rdgen:latest for the latest build # use bryangerlach/rdgen:latest for the latest build
#build: .
image: bryangerlach/rdgen:latest image: bryangerlach/rdgen:latest
restart: unless-stopped restart: unless-stopped
environment: environment:
@@ -9,8 +8,6 @@ services:
GHUSER: "github_username" GHUSER: "github_username"
GHBEARER: "github_access_token" GHBEARER: "github_access_token"
GENURL: "accessible_url_of_server" GENURL: "accessible_url_of_server"
ZIP_PASSWORD: ""
GHBRANCH: "master"
PROTOCOL: "https" PROTOCOL: "https"
REPONAME: "rdgen" REPONAME: "rdgen"
ports: ports:

View File

@@ -24,8 +24,6 @@ SECRET_KEY = os.environ.get('SECRET_KEY','django-insecure-!(t-!f#6g#sr%yfded9(xh
GHUSER = os.environ.get("GHUSER", '') GHUSER = os.environ.get("GHUSER", '')
GHBEARER = os.environ.get("GHBEARER", '') GHBEARER = os.environ.get("GHBEARER", '')
GENURL = os.environ.get("GENURL", '') GENURL = os.environ.get("GENURL", '')
GHBRANCH = os.environ.get("GHBRANCH",'master')
ZIP_PASSWORD = os.environ.get("ZIP_PASSWORD",'insecure')
PROTOCOL = os.environ.get("PROTOCOL", 'https') PROTOCOL = os.environ.get("PROTOCOL", 'https')
REPONAME = os.environ.get("REPONAME", 'rdgen') REPONAME = os.environ.get("REPONAME", 'rdgen')

View File

@@ -32,5 +32,4 @@ urlpatterns = [
url(r'^startgh',views.startgh), url(r'^startgh',views.startgh),
url(r'^get_png',views.get_png), url(r'^get_png',views.get_png),
url(r'^save_custom_client',views.save_custom_client), url(r'^save_custom_client',views.save_custom_client),
url(r'^get_zip',views.get_zip),
] ]

View File

@@ -4,7 +4,7 @@ from PIL import Image
class GenerateForm(forms.Form): class GenerateForm(forms.Form):
#Platform #Platform
platform = forms.ChoiceField(choices=[('windows','Windows 64Bit'),('windows-x86','Windows 32Bit'),('linux','Linux'),('android','Android'),('macos','macOS')], initial='windows') platform = forms.ChoiceField(choices=[('windows','Windows 64Bit'),('windows-x86','Windows 32Bit'),('linux','Linux'),('android','Android'),('macos','macOS')], initial='windows')
version = forms.ChoiceField(choices=[('master','nightly'),('1.4.5','1.4.5'),('1.4.4','1.4.4'),('1.4.3','1.4.3'),('1.4.2','1.4.2'),('1.4.1','1.4.1'),('1.4.0','1.4.0'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.4.5') version = forms.ChoiceField(choices=[('master','nightly'),('1.4.3','1.4.3'),('1.4.2','1.4.2'),('1.4.1','1.4.1'),('1.4.0','1.4.0'),('1.3.9','1.3.9'),('1.3.8','1.3.8'),('1.3.7','1.3.7'),('1.3.6','1.3.6'),('1.3.5','1.3.5'),('1.3.4','1.3.4'),('1.3.3','1.3.3')], initial='1.4.3')
help_text="'master' is the development version (nightly build) with the latest features but may be less stable" help_text="'master' is the development version (nightly build) with the latest features but may be less stable"
delayFix = forms.BooleanField(initial=True, required=False) delayFix = forms.BooleanField(initial=True, required=False)
@@ -24,7 +24,6 @@ class GenerateForm(forms.Form):
('settingsY', 'No, enable settings'), ('settingsY', 'No, enable settings'),
('settingsN', 'Yes, DISABLE settings') ('settingsN', 'Yes, DISABLE settings')
], initial='settingsY') ], initial='settingsY')
androidappid = forms.CharField(label="Custom Android App ID (replaces 'com.carriez.flutter_hbb')", required=False)
#Custom Server #Custom Server
serverIP = forms.CharField(label="Host", required=False) serverIP = forms.CharField(label="Host", required=False)
@@ -49,7 +48,7 @@ class GenerateForm(forms.Form):
#Security #Security
passApproveMode = forms.ChoiceField(choices=[('password','Accept sessions via password'),('click','Accept sessions via click'),('password-click','Accepts sessions via both')],initial='password-click') 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) permanentPassword = forms.CharField(widget=forms.PasswordInput(), required=False)
#runasadmin = forms.ChoiceField(choices=[('false','No'),('true','Yes')], initial='false') runasadmin = forms.ChoiceField(choices=[('false','No'),('true','Yes')], initial='false')
denyLan = forms.BooleanField(initial=False, required=False) denyLan = forms.BooleanField(initial=False, required=False)
enableDirectIP = forms.BooleanField(initial=False, required=False) enableDirectIP = forms.BooleanField(initial=False, required=False)
#ipWhitelist = forms.BooleanField(initial=False, required=False) #ipWhitelist = forms.BooleanField(initial=False, required=False)

View File

@@ -287,8 +287,6 @@
{{ form.installation }}<br><br> {{ form.installation }}<br><br>
<label for="{{ form.settings.id_for_label }}">Disable Settings:</label> <label for="{{ form.settings.id_for_label }}">Disable Settings:</label>
{{ form.settings }}<br><br> {{ form.settings }}<br><br>
<label for="{{ form.androidappid.id_for_label }}">Custom Android App ID (replaces 'com.carriez.flutter_hbb', leave blank to use default):</label>
{{ form.androidappid }}<br><br>
</div> </div>
<div class="section"> <div class="section">
@@ -310,6 +308,8 @@
<div class="container"> <div class="container">
<div class="section"> <div class="section">
<h2><i class="fas fa-shield-alt"></i> Security</h2> <h2><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> <label for="{{ form.passApproveMode.id_for_label }}">Password Approve mode:</label>
{{ form.passApproveMode }}<br><br> {{ form.passApproveMode }}<br><br>
<div id="passwordRequirement" class="password-requirement">To use the hide connection window feature, please set a permanent password.</div> <div id="passwordRequirement" class="password-requirement">To use the hide connection window feature, please set a permanent password.</div>

View File

@@ -9,7 +9,6 @@ import requests
import base64 import base64
import json import json
import uuid import uuid
import pyzipper
from django.conf import settings as _settings from django.conf import settings as _settings
from django.db.models import Q from django.db.models import Q
from .forms import GenerateForm from .forms import GenerateForm
@@ -47,20 +46,15 @@ def generator_view(request):
installation = form.cleaned_data['installation'] installation = form.cleaned_data['installation']
settings = form.cleaned_data['settings'] settings = form.cleaned_data['settings']
appname = form.cleaned_data['appname'] appname = form.cleaned_data['appname']
if not appname:
appname = "rustdesk"
filename = form.cleaned_data['exename'] filename = form.cleaned_data['exename']
compname = form.cleaned_data['compname'] compname = form.cleaned_data['compname']
if not compname: if not compname:
compname = "Purslane Ltd" compname = "Purslane Ltd"
androidappid = form.cleaned_data['androidappid']
if not androidappid:
androidappid = "com.carriez.flutter_hbb"
compname = compname.replace("&","\\&") compname = compname.replace("&","\\&")
permPass = form.cleaned_data['permanentPassword'] permPass = form.cleaned_data['permanentPassword']
theme = form.cleaned_data['theme'] theme = form.cleaned_data['theme']
themeDorO = form.cleaned_data['themeDorO'] themeDorO = form.cleaned_data['themeDorO']
#runasadmin = form.cleaned_data['runasadmin'] runasadmin = form.cleaned_data['runasadmin']
passApproveMode = form.cleaned_data['passApproveMode'] passApproveMode = form.cleaned_data['passApproveMode']
denyLan = form.cleaned_data['denyLan'] denyLan = form.cleaned_data['denyLan']
enableDirectIP = form.cleaned_data['enableDirectIP'] enableDirectIP = form.cleaned_data['enableDirectIP']
@@ -99,22 +93,18 @@ def generator_view(request):
iconfile = form.cleaned_data.get('iconfile') iconfile = form.cleaned_data.get('iconfile')
if not iconfile: if not iconfile:
iconfile = form.cleaned_data.get('iconbase64') iconfile = form.cleaned_data.get('iconbase64')
iconlink_url, iconlink_uuid, iconlink_file = save_png(iconfile,myuuid,full_url,"icon.png") iconlink = save_png(iconfile,myuuid,full_url,"icon.png")
except: except:
print("failed to get icon, using default") print("failed to get icon, using default")
iconlink_url = "false" iconlink = "false"
iconlink_uuid = "false"
iconlink_file = "false"
try: try:
logofile = form.cleaned_data.get('logofile') logofile = form.cleaned_data.get('logofile')
if not logofile: if not logofile:
logofile = form.cleaned_data.get('logobase64') logofile = form.cleaned_data.get('logobase64')
logolink_url, logolink_uuid, logolink_file = save_png(logofile,myuuid,full_url,"logo.png") logolink = save_png(logofile,myuuid,full_url,"logo.png")
except: except:
print("failed to get logo") print("failed to get logo")
logolink_url = "false" logolink = "false"
logolink_uuid = "false"
logolink_file = "false"
###create the custom.txt json here and send in as inputs below ###create the custom.txt json here and send in as inputs below
decodedCustom = {} decodedCustom = {}
@@ -197,20 +187,20 @@ def generator_view(request):
base64_bytes = base64.b64encode(string_bytes) base64_bytes = base64.b64encode(string_bytes)
encodedCustom = base64_bytes.decode("ascii") encodedCustom = base64_bytes.decode("ascii")
# #github limits inputs to 10, so lump extras into one with json #github limits inputs to 10, so lump extras into one with json
# extras = {} extras = {}
# extras['genurl'] = _settings.GENURL extras['genurl'] = _settings.GENURL
# #extras['runasadmin'] = runasadmin extras['runasadmin'] = runasadmin
# extras['urlLink'] = urlLink extras['urlLink'] = urlLink
# extras['downloadLink'] = downloadLink extras['downloadLink'] = downloadLink
# extras['delayFix'] = 'true' if delayFix else 'false' extras['delayFix'] = 'true' if delayFix else 'false'
# extras['rdgen'] = 'true' extras['version'] = version
# extras['cycleMonitor'] = 'true' if cycleMonitor else 'false' extras['rdgen'] = 'true'
# extras['xOffline'] = 'true' if xOffline else 'false' extras['cycleMonitor'] = 'true' if cycleMonitor else 'false'
# extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false' extras['xOffline'] = 'true' if xOffline else 'false'
# extras['compname'] = compname extras['removeNewVersionNotif'] = 'true' if removeNewVersionNotif else 'false'
# extras['androidappid'] = androidappid extras['compname'] = compname
# extra_input = json.dumps(extras) extra_input = json.dumps(extras)
####from here run the github action, we need user, repo, access token. ####from here run the github action, we need user, repo, access token.
if platform == 'windows': if platform == 'windows':
@@ -227,59 +217,21 @@ def generator_view(request):
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches' url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-windows.yml/dispatches'
#url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches' #url = 'https://api.github.com/repos/'+_settings.GHUSER+'/rustdesk/actions/workflows/test.yml/dispatches'
inputs_raw = {
"server":server,
"key":key,
"apiServer":apiServer,
"custom":encodedCustom,
"uuid":myuuid,
"iconlink_url":iconlink_url,
"iconlink_uuid":iconlink_uuid,
"iconlink_file":iconlink_file,
"logolink_url":logolink_url,
"logolink_uuid":logolink_uuid,
"logolink_file":logolink_file,
"appname":appname,
"genurl":_settings.GENURL,
"urlLink":urlLink,
"downloadLink":downloadLink,
"delayFix": 'true' if delayFix else 'false',
"rdgen":'true',
"cycleMonitor": 'true' if cycleMonitor else 'false',
"xOffline": 'true' if xOffline else 'false',
"removeNewVersionNotif": 'true' if removeNewVersionNotif else 'false',
"compname": compname,
"androidappid":androidappid,
"filename":filename
}
temp_json_path = f"data_{uuid.uuid4()}.json"
zip_filename = f"secrets_{uuid.uuid4()}.zip"
zip_path = "temp_zips/%s" % (zip_filename)
Path("temp_zips").mkdir(parents=True, exist_ok=True)
with open(temp_json_path, "w") as f:
json.dump(inputs_raw, f)
with pyzipper.AESZipFile(zip_path, 'w', compression=pyzipper.ZIP_LZMA, encryption=pyzipper.WZ_AES) as zf:
zf.setpassword(_settings.ZIP_PASSWORD.encode())
zf.write(temp_json_path, arcname="secrets.json")
# 4. Cleanup the plain JSON file immediately
if os.path.exists(temp_json_path):
os.remove(temp_json_path)
zipJson = {}
zipJson['url'] = full_url
zipJson['file'] = zip_filename
zip_url = json.dumps(zipJson)
data = { data = {
"ref":_settings.GHBRANCH, "ref":"master",
"inputs":{ "inputs":{
"version":version, "server":server,
"zip_url":zip_url "key":key,
"apiServer":apiServer,
"custom":encodedCustom,
"uuid":myuuid,
#"iconbase64":iconbase64.decode("utf-8"),
#"logobase64":logobase64.decode("utf-8") if logobase64 else "",
"iconlink":iconlink,
"logolink":logolink,
"appname":appname,
"extras":extra_input,
"filename":filename
} }
} }
#print(data) #print(data)
@@ -292,7 +244,7 @@ def generator_view(request):
create_github_run(myuuid) create_github_run(myuuid)
response = requests.post(url, json=data, headers=headers) response = requests.post(url, json=data, headers=headers)
print(response) print(response)
if response.status_code == 204 or response.status_code == 200: if response.status_code == 204:
return render(request, 'waiting.html', {'filename':filename, 'uuid':myuuid, 'status':"Starting generator...please wait", 'platform':platform}) return render(request, 'waiting.html', {'filename':filename, 'uuid':myuuid, 'status':"Starting generator...please wait", 'platform':platform})
else: else:
return JsonResponse({"error": "Something went wrong"}) return JsonResponse({"error": "Something went wrong"})
@@ -401,7 +353,7 @@ def startgh(request):
####from here run the github action, we need user, repo, access token. ####from here run the github action, we need user, repo, access token.
url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches' url = 'https://api.github.com/repos/'+_settings.GHUSER+'/'+_settings.REPONAME+'/actions/workflows/generator-'+data_.get('platform')+'.yml/dispatches'
data = { data = {
"ref": _settings.GHBRANCH, "ref":"master",
"inputs":{ "inputs":{
"server":data_.get('server'), "server":data_.get('server'),
"key":data_.get('key'), "key":data_.get('key'),
@@ -444,12 +396,12 @@ def save_png(file, uuid, domain, name):
with open(file_save_path, "wb+") as f: with open(file_save_path, "wb+") as f:
for chunk in file.chunks(): for chunk in file.chunks():
f.write(chunk) f.write(chunk)
# imageJson = {} imageJson = {}
# imageJson['url'] = domain imageJson['url'] = domain
# imageJson['uuid'] = uuid imageJson['uuid'] = uuid
# imageJson['file'] = name imageJson['file'] = name
#return "%s/%s" % (domain, file_save_path) #return "%s/%s" % (domain, file_save_path)
return domain, uuid, name return json.dumps(imageJson)
def save_custom_client(request): def save_custom_client(request):
file = request.FILES['file'] file = request.FILES['file']
@@ -461,37 +413,3 @@ def save_custom_client(request):
f.write(chunk) f.write(chunk)
return HttpResponse("File saved successfully!") return HttpResponse("File saved successfully!")
def cleanup_secrets(request):
# Pass the UUID as a query param or in JSON body
my_uuid = request.GET.get('uuid')
if not my_uuid:
return HttpResponse("Missing UUID", status=400)
# 1. Find the files in your temp directory matching the UUID
temp_dir = os.path.join('temp_zips')
# We look for any file starting with 'secrets_' and containing the uuid
for filename in os.listdir(temp_dir):
if my_uuid in filename and filename.endswith('.zip'):
file_path = os.path.join(temp_dir, filename)
try:
os.remove(file_path)
print(f"Successfully deleted {file_path}")
except OSError as e:
print(f"Error deleting file: {e}")
return HttpResponse("Cleanup successful", status=200)
def get_zip(request):
filename = request.GET['filename']
#filename = filename+".exe"
file_path = os.path.join('temp_zips',filename)
with open(file_path, 'rb') as file:
response = HttpResponse(file, headers={
'Content-Type': 'application/vnd.microsoft.portable-executable',
'Content-Disposition': f'attachment; filename="{filename}"'
})
return response

View File

@@ -1,5 +1,4 @@
django django
requests requests
pillow pillow
gunicorn gunicorn
pyzipper

View File

@@ -20,14 +20,10 @@
* Now click New repository secret * Now click New repository secret
* Set the Name to GENURL * Set the Name to GENURL
* Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from) * Set the Secret to https://rdgen.hostname.com (or whatever your server will be accessed from)
* Now click New repository secret again
* Set the Name to ZIP_PASSWORD
* Set the Secret to any password you want (use this in the next step as well) - generate a password by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
4. Now download the docker-compose.yml file and fill in the environment variables: 4. Now download the docker-compose.yml file and fill in the environment variables:
* SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'``` * SECRET_KEY="your secret key" - generate a secret key by running: ```python3 -c 'import secrets; print(secrets.token_hex(100))'```
* GHUSER="your github username" * GHUSER="your github username"
* GHBEARER="your fine-grained access token" * GHBEARER="your fine-grained access token"
* ZIP_PASSWORD="the same password that you entered as a github secret"
* PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to * PROTOCOL="https" *optional - defaults to "https", change to "http" if you need to
* REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it * REPONAME="rdgen" *optional - defaults to "rdgen", change this if you renamed the repo when you forked it
5. Now just run ```docker compose up -d``` 5. Now just run ```docker compose up -d```