diff --git a/apps/chromium/Dockerfile b/apps/chromium/Dockerfile
index 4a3171f5e..02fce70d7 100644
--- a/apps/chromium/Dockerfile
+++ b/apps/chromium/Dockerfile
@@ -1,6 +1,8 @@
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/base:latest
FROM $BASE_IMAGE
+COPY ./widevinecdm.sh /widevine.sh
+
#
# install neko chromium
RUN set -eux; \
@@ -12,19 +14,10 @@ RUN set -eux; \
CHROMIUM_DIR="/usr/lib/chromium"; \
ARCH=$(dpkg --print-architecture); \
if [ "${ARCH}" = "amd64" ]; then \
- # https://commondatastorage.googleapis.com/chromeos-localmirror/distfiles/chromeos-lacros-arm64-squash-zstd-120.0.6098.0
- apt-get install -y --no-install-recommends unzip; \
- WIDEVINE_ARCH="x64"; \
- WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | tail -n 1); \
- wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-${WIDEVINE_ARCH}.zip"; \
- mkdir -p "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_${WIDEVINE_ARCH}"; \
- unzip -p /tmp/widevine.zip LICENSE.txt > "${CHROMIUM_DIR}/WidevineCdm/LICENSE"; \
- unzip -p /tmp/widevine.zip manifest.json > "${CHROMIUM_DIR}/WidevineCdm/manifest.json"; \
- unzip -p /tmp/widevine.zip libwidevinecdm.so > "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_${WIDEVINE_ARCH}/libwidevinecdm.so"; \
- find "${CHROMIUM_DIR}/WidevineCdm" -type d -exec chmod 0755 '{}' \;; \
- find "${CHROMIUM_DIR}/WidevineCdm" -type f -exec chmod 0644 '{}' \;; \
- rm /tmp/widevine.zip; \
- apt-get --purge autoremove -y unzip; \
+ apt-get install -y --no-install-recommends xz-utils; \
+ ./widevine.sh "${CHROMIUM_DIR}/WidevineCdm"; \
+ rm -f /widevine.sh; \
+ apt-get --purge autoremove -y xz-utils; \
else \
echo "Widevine is not supported on ${ARCH}"; \
fi; \
diff --git a/apps/chromium/Dockerfile.nvidia b/apps/chromium/Dockerfile.nvidia
index 8af30e5ef..14560b23a 100644
--- a/apps/chromium/Dockerfile.nvidia
+++ b/apps/chromium/Dockerfile.nvidia
@@ -1,6 +1,8 @@
ARG BASE_IMAGE=ghcr.io/m1k1o/neko/nvidia-base:latest
FROM $BASE_IMAGE
+COPY ./widevinecdm.sh /widevine.sh
+
#
# install neko chromium
RUN set -eux; \
@@ -10,22 +12,15 @@ RUN set -eux; \
# and nvidia base is ubuntu not debian
add-apt-repository ppa:system76/pop; \
apt-get update; \
- apt-get install -y --no-install-recommends unzip chromium openbox; \
+ apt-get install -y --no-install-recommends xz-utils chromium openbox; \
#
# install widevine module
CHROMIUM_DIR="/usr/lib/chromium"; \
- WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | tail -n 1); \
- wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-x64.zip"; \
- mkdir -p "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_x64"; \
- unzip -p /tmp/widevine.zip LICENSE.txt > "${CHROMIUM_DIR}/WidevineCdm/LICENSE"; \
- unzip -p /tmp/widevine.zip manifest.json > "${CHROMIUM_DIR}/WidevineCdm/manifest.json"; \
- unzip -p /tmp/widevine.zip libwidevinecdm.so > "${CHROMIUM_DIR}/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"; \
- find "${CHROMIUM_DIR}/WidevineCdm" -type d -exec chmod 0755 '{}' \;; \
- find "${CHROMIUM_DIR}/WidevineCdm" -type f -exec chmod 0644 '{}' \;; \
- rm /tmp/widevine.zip; \
+ ./widevine.sh "${CHROMIUM_DIR}/WidevineCdm"; \
+ rm -f /widevine.sh; \
#
# clean up
- apt-get --purge autoremove -y unzip; \
+ apt-get --purge autoremove -y xz-utils; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
diff --git a/apps/chromium/widevinecdm.sh b/apps/chromium/widevinecdm.sh
new file mode 100755
index 000000000..bededfbad
--- /dev/null
+++ b/apps/chromium/widevinecdm.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+set -e
+
+TARGET_DIR="$(realpath "$1")"
+if [ -z "$TARGET_DIR" ]; then
+ echo "Usage: $0 /path/to/install/WidevineCdm"
+ exit 1
+fi
+
+TMPDIR=$(mktemp -d)
+cd "$TMPDIR"
+
+function cleanup {
+ rm -rf "$TMPDIR"
+}
+trap cleanup EXIT
+
+# Fetch manifest and extract URL
+URL=$(python3 -c "
+import json, urllib.request
+data = json.load(urllib.request.urlopen('https://raw.githubusercontent.com/mozilla/gecko-dev/master/toolkit/content/gmp-sources/widevinecdm.json'))
+for v in data['vendors'].values():
+ for k, p in v['platforms'].items():
+ if 'Linux_x86_64-gcc3' in k:
+ print(p['fileUrl'])
+ break
+")
+
+# Download CRX
+curl -L -o widevinecdm.crx "$URL"
+
+# Install go-crx3
+echo "Fetching latest go-crx3 version..."
+VERSION=$(curl -s https://api.github.com/repos/m1k1o/go-crx3/releases/latest | grep 'tag_name' | cut -d '"' -f4)
+ARTIFACT="go-crx3_${VERSION#v}_linux_amd64.tar.gz"
+URL="https://github.com/m1k1o/go-crx3/releases/download/${VERSION}/${ARTIFACT}"
+echo "Downloading $URL"
+curl -L -o "$ARTIFACT" "$URL"
+tar -xzf "$ARTIFACT"
+
+# Unpack with go-crx3
+./go-crx3 unpack widevinecdm.crx
+mkdir -p "$TARGET_DIR"
+cp -ar widevinecdm/* "$TARGET_DIR"
diff --git a/apps/ungoogled-chromium/Dockerfile b/apps/ungoogled-chromium/Dockerfile
index d7ab45a30..709e66721 100644
--- a/apps/ungoogled-chromium/Dockerfile
+++ b/apps/ungoogled-chromium/Dockerfile
@@ -3,6 +3,8 @@ FROM $BASE_IMAGE
ARG API_URL="https://api.github.com/repos/macchrome/linchrome/releases/latest"
+COPY ./widevinecdm.sh /widevine.sh
+
#
# install custom chromium build from woolyss with support for hevc/x265
SHELL ["/bin/bash", "-c"]
@@ -21,11 +23,9 @@ RUN set -eux; apt-get update; \
chmod 4755 /usr/lib/chromium/chrome-sandbox; \
#
# install widevine module
- WIDEVINE_VERSION=$(wget --quiet -O - https://dl.google.com/widevine-cdm/versions.txt | sort --version-sort | tail -n 1); \
- wget -O /tmp/widevine.zip "https://dl.google.com/widevine-cdm/${WIDEVINE_VERSION}-linux-x64.zip"; \
- unzip -p /tmp/widevine.zip libwidevinecdm.so > /usr/lib/chromium/libwidevinecdm.so; \
- chmod 644 /usr/lib/chromium/libwidevinecdm.so; \
- rm /tmp/widevine.zip; \
+ CHROMIUM_DIR="/usr/lib/chromium"; \
+ ./widevine.sh "${CHROMIUM_DIR}/WidevineCdm"; \
+ rm -f /widevine.sh; \
#
# install latest version of uBlock Origin and SponsorBlock for YouTube
CHROMIUM_VERSION="$(wget -O - "${API_URL}" 2>/dev/null | jq -r ".tag_name" | sed -e 's/v//' -e 's/-.*//')"; \
diff --git a/apps/ungoogled-chromium/preferences.json b/apps/ungoogled-chromium/preferences.json
index 31cd367a0..b4cf90621 100644
--- a/apps/ungoogled-chromium/preferences.json
+++ b/apps/ungoogled-chromium/preferences.json
@@ -1,8 +1,8 @@
{
- "homepage": "http://www.google.com",
+ "homepage": "https://duckduckgo.com/",
"homepage_is_newtabpage": false,
"first_run_tabs": [
- "https://www.google.com/_/chrome/newtab?ie=UTF-8"
+ "https://duckduckgo.com/"
],
"custom_links": {
"initialized": true,
diff --git a/apps/ungoogled-chromium/widevinecdm.sh b/apps/ungoogled-chromium/widevinecdm.sh
new file mode 100755
index 000000000..bededfbad
--- /dev/null
+++ b/apps/ungoogled-chromium/widevinecdm.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+set -e
+
+TARGET_DIR="$(realpath "$1")"
+if [ -z "$TARGET_DIR" ]; then
+ echo "Usage: $0 /path/to/install/WidevineCdm"
+ exit 1
+fi
+
+TMPDIR=$(mktemp -d)
+cd "$TMPDIR"
+
+function cleanup {
+ rm -rf "$TMPDIR"
+}
+trap cleanup EXIT
+
+# Fetch manifest and extract URL
+URL=$(python3 -c "
+import json, urllib.request
+data = json.load(urllib.request.urlopen('https://raw.githubusercontent.com/mozilla/gecko-dev/master/toolkit/content/gmp-sources/widevinecdm.json'))
+for v in data['vendors'].values():
+ for k, p in v['platforms'].items():
+ if 'Linux_x86_64-gcc3' in k:
+ print(p['fileUrl'])
+ break
+")
+
+# Download CRX
+curl -L -o widevinecdm.crx "$URL"
+
+# Install go-crx3
+echo "Fetching latest go-crx3 version..."
+VERSION=$(curl -s https://api.github.com/repos/m1k1o/go-crx3/releases/latest | grep 'tag_name' | cut -d '"' -f4)
+ARTIFACT="go-crx3_${VERSION#v}_linux_amd64.tar.gz"
+URL="https://github.com/m1k1o/go-crx3/releases/download/${VERSION}/${ARTIFACT}"
+echo "Downloading $URL"
+curl -L -o "$ARTIFACT" "$URL"
+tar -xzf "$ARTIFACT"
+
+# Unpack with go-crx3
+./go-crx3 unpack widevinecdm.crx
+mkdir -p "$TARGET_DIR"
+cp -ar widevinecdm/* "$TARGET_DIR"
diff --git a/client/src/components/video.vue b/client/src/components/video.vue
index 7ee578647..051493e1b 100644
--- a/client/src/components/video.vue
+++ b/client/src/components/video.vue
@@ -26,6 +26,8 @@
@touchmove.stop.prevent="onTouchHandler"
@touchstart.stop.prevent="onTouchHandler"
@touchend.stop.prevent="onTouchHandler"
+ @compositionstart="onCompositionStartHandler"
+ @compositionend="onCompositionEndHandler"
/>
@@ -250,6 +252,7 @@
private focused = false
private fullscreen = false
private mutedOverlay = true
+ private lastTextAreaValue = ''
get admin() {
return this.$accessor.user.admin
@@ -756,6 +759,14 @@
first.target.dispatchEvent(simulatedEvent)
}
+ onCompositionStartHandler() {
+ this.lastTextAreaValue = this._overlay.value
+ }
+
+ onCompositionEndHandler() {
+ this._overlay.value = this.lastTextAreaValue
+ }
+
isMouseDown = false
onMouseDown(e: MouseEvent) {
diff --git a/client/src/locale/index.ts b/client/src/locale/index.ts
index 9743c0b8e..2bc323616 100644
--- a/client/src/locale/index.ts
+++ b/client/src/locale/index.ts
@@ -12,6 +12,7 @@ import * as cn from './zh-cn'
import * as tw from './zh-tw'
import * as ja from './ja-jp'
import * as id from './id-id'
+import * as pl from './pl-pl'
export const messages = {
en,
@@ -28,4 +29,5 @@ export const messages = {
tw,
ja,
id,
+ pl,
}
diff --git a/client/src/locale/pl-pl.ts b/client/src/locale/pl-pl.ts
new file mode 100644
index 000000000..ccad05e7e
--- /dev/null
+++ b/client/src/locale/pl-pl.ts
@@ -0,0 +1,127 @@
+export const logout = 'Wyloguj się'
+export const unsupported = 'Ta przeglądarka nie obsługuje WebRTC'
+export const admin_loggedin = 'Jesteś zalogowany jako administrator'
+export const you = 'Ty'
+export const somebody = 'Ktoś'
+export const send_a_message = 'Wyślij wiadomość'
+
+export const side = {
+ chat: 'Czat',
+ files: 'Pliki',
+ settings: 'Ustawienia',
+}
+
+export const connect = {
+ login_title: 'Zaloguj się',
+ invitation_title: 'Otrzymałeś zaproszenie do tego pokoju',
+ displayname: 'Podaj swoją nazwę',
+ password: 'Hasło',
+ connect: 'Połącz',
+ error: 'Błąd logowania',
+ empty_displayname: 'Pole nazwy użytkownika nie może być puste.',
+}
+
+export const context = {
+ ignore: 'Ignoruj',
+ unignore: 'Przestań ignorować',
+ mute: 'Wycisz',
+ unmute: 'Cofnij wyciszenie',
+ release: 'Wymuś zwolnienie sterowania',
+ take: 'Wymuś przejęcie sterowania',
+ give: 'Przekaż sterowanie',
+ kick: 'Wyrzuć',
+ ban: 'Zbanuj IP',
+ confirm: {
+ kick_title: 'Wyrzucić {name}?',
+ kick_text: 'Czy na pewno chcesz wyrzucić {name}?',
+ ban_title: 'Zbanować {name}?',
+ ban_text: 'Czy chcesz zbanować {name}? Aby cofnąć, musisz zrestartować serwer.',
+ mute_title: 'Wyciszyć {name}?',
+ mute_text: 'Czy na pewno chcesz wyciszyć {name}?',
+ unmute_title: 'Cofnąć wyciszenie {name}?',
+ unmute_text: 'Czy chcesz cofnąć wyciszenie {name}?',
+ button_yes: 'Tak',
+ button_cancel: 'Anuluj',
+ },
+}
+
+export const controls = {
+ release: 'Zwolnij sterowanie',
+ request: 'Poproś o sterowanie',
+ lock: 'Zablokuj sterowanie',
+ unlock: 'Odblokuj sterowanie',
+ has: 'Masz sterowanie',
+ hasnot: 'Nie masz sterowania',
+}
+
+export const locks = {
+ control: {
+ lock: 'Zablokuj sterowanie (dla użytkowników)',
+ unlock: 'Odblokuj sterowanie (dla użytkowników)',
+ locked: 'Sterowanie zablokowane (dla użytkowników)',
+ unlocked: 'Sterowanie odblokowane (dla użytkowników)',
+ notif_locked: 'zablokował sterowanie dla użytkowników',
+ notif_unlocked: 'odblokował sterowanie dla użytkowników',
+ },
+ login: {
+ lock: 'Zablokuj pokój (dla użytkowników)',
+ unlock: 'Odblokuj pokój (dla użytkowników)',
+ locked: 'Pokój zablokowany (dla użytkowników)',
+ unlocked: 'Pokój odblokowany (dla użytkowników)',
+ notif_locked: 'zablokował pokój',
+ notif_unlocked: 'odblokował pokój',
+ },
+ file_transfer: {
+ lock: 'Zablokuj transfer plików (dla użytkowników)',
+ unlock: 'Odblokuj transfer plików (dla użytkowników)',
+ locked: 'Transfer plików zablokowany (dla użytkowników)',
+ unlocked: 'Transfer plików odblokowany (dla użytkowników)',
+ notif_locked: 'zablokował transfer plików',
+ notif_unlocked: 'odblokował transfer plików',
+ },
+}
+
+export const setting = {
+ scroll: 'Czułość przewijania',
+ scroll_invert: 'Odwróć przewijanie',
+ autoplay: 'Autoodtwarzanie wideo',
+ ignore_emotes: 'Ignoruj emotki',
+ chat_sound: 'Odtwarzaj dźwięk czatu',
+ keyboard_layout: 'Układ klawiatury',
+ broadcast_title: 'Transmisja na żywo',
+}
+
+export const connection = {
+ logged_out: 'Zostałeś wylogowany.',
+ reconnecting: 'Ponowne łączenie...',
+ connected: 'Połączono',
+ disconnected: 'Rozłączono',
+ kicked: 'Zostałeś usunięty z pokoju.',
+ button_confirm: 'OK',
+}
+
+export const notifications = {
+ connected: '{name} dołączył',
+ disconnected: '{name} opuścił',
+ controls_taken: '{name} przejął sterowanie',
+ controls_taken_force: 'przejął sterowanie siłą',
+ controls_taken_steal: 'przejął sterowanie od {name}',
+ controls_released: '{name} zwolnił sterowanie',
+ controls_released_force: 'zwolnił sterowanie siłą',
+ controls_released_steal: 'zwolnił sterowanie od {name}',
+ controls_given: 'przekazał sterowanie {name}',
+ controls_has: '{name} ma sterowanie',
+ controls_has_alt: 'Ale poinformowałem osobę, że chciałeś je otrzymać',
+ controls_requesting: '{name} prosi o sterowanie',
+ resolution: 'zmienił rozdzielczość na {width}x{height}@{rate}',
+ banned: 'zbanował {name}',
+ kicked: 'wyrzucił {name}',
+ muted: 'wyciszył {name}',
+ unmuted: 'cofnął wyciszenie {name}',
+}
+
+export const files = {
+ downloads: 'Pobrane pliki',
+ uploads: 'Wysyłane pliki',
+ upload_here: 'Kliknij lub przeciągnij pliki tutaj, aby przesłać',
+}
diff --git a/client/src/utils/guacamole-keyboard.js b/client/src/utils/guacamole-keyboard.js
index df0b93cf5..d450c3b88 100644
--- a/client/src/utils/guacamole-keyboard.js
+++ b/client/src/utils/guacamole-keyboard.js
@@ -111,12 +111,12 @@ Guacamole.Keyboard = function Keyboard(element) {
altIsTypableOnly: false,
/**
- * Whether we can rely on receiving a keyup event for the Caps Lock
- * key.
+ * Whether we can rely on receiving a keyup or keydown event for the
+ * Caps Lock key.
*
* @type {!boolean}
*/
- capsLockKeyupUnreliable: false
+ capsLockKeyEventUnreliable: false
};
@@ -129,10 +129,11 @@ Guacamole.Keyboard = function Keyboard(element) {
quirks.keyupUnreliable = true;
// The Alt key on Mac is never used for keyboard shortcuts, and the
- // Caps Lock key never dispatches keyup events
+ // Caps Lock key never dispatches keyup events in firefox, and it
+ // dispatches either keydown or keyup events in chrome, but never both
else if (navigator.platform.match(/^mac/i)) {
quirks.altIsTypableOnly = true;
- quirks.capsLockKeyupUnreliable = true;
+ quirks.capsLockKeyEventUnreliable = true;
}
}
@@ -291,12 +292,16 @@ Guacamole.Keyboard = function Keyboard(element) {
this.keyupReliable = false;
// We cannot rely on receiving keyup for Caps Lock on certain platforms
- else if (this.keysym === 0xFFE5 && quirks.capsLockKeyupUnreliable)
+ else if (this.keysym === 0xFFE5 && quirks.capsLockKeyEventUnreliable)
this.keyupReliable = false;
// Determine whether default action for Alt+combinations must be prevented
var prevent_alt = !this.modifiers.ctrl && !quirks.altIsTypableOnly;
+ // If alt is typeable only, and this is actually an alt key event, treat as AltGr instead
+ if (quirks.altIsTypableOnly && (this.keysym === 0xFFE9 || this.keysym === 0xFFEA))
+ this.keysym = 0xFE03;
+
// Determine whether default action for Ctrl+combinations must be prevented
var prevent_ctrl = !this.modifiers.alt;
@@ -357,6 +362,14 @@ Guacamole.Keyboard = function Keyboard(element) {
// We extend KeyEvent
KeyEvent.call(this, orig);
+ // If unreliable caps lock was pressed and event was not marked, then
+ // we need to pretend that this is a keydown event because we obviously
+ // did not receive it (issue on macos with chrome)
+ if (this.keyCode == 20 && quirks.capsLockKeyEventUnreliable) {
+ eventLog.push(new KeydownEvent(this));
+ return;
+ }
+
// If key is known from keyCode or DOM3 alone, use that (keyCode is
// still more reliable for keyup when dead keys are in use)
this.keysym = keysym_from_keycode(this.keyCode, this.location)
@@ -397,7 +410,7 @@ Guacamole.Keyboard = function Keyboard(element) {
13: [0xFF0D], // enter
16: [0xFFE1, 0xFFE1, 0xFFE2], // shift
17: [0xFFE3, 0xFFE3, 0xFFE4], // ctrl
- 18: [0xFFE9, 0xFFE9, 0xFE03], // alt
+ 18: [0xFFE9, 0xFFE9, 0xFFEA], // alt
19: [0xFF13], // pause/break
20: [0xFFE5], // caps lock
27: [0xFF1B], // escape
@@ -458,7 +471,7 @@ Guacamole.Keyboard = function Keyboard(element) {
"Again": [0xFF66],
"AllCandidates": [0xFF3D],
"Alphanumeric": [0xFF30],
- "Alt": [0xFFE9, 0xFFE9, 0xFE03],
+ "Alt": [0xFFE9, 0xFFE9, 0xFFEA],
"Attn": [0xFD0E],
"AltGraph": [0xFE03],
"ArrowDown": [0xFF54],
@@ -469,7 +482,7 @@ Guacamole.Keyboard = function Keyboard(element) {
"CapsLock": [0xFFE5],
"Cancel": [0xFF69],
"Clear": [0xFF0B],
- "Convert": [0xFF21],
+ "Convert": [0xFF23],
"Copy": [0xFD15],
"Crsel": [0xFD1C],
"CrSel": [0xFD1C],
@@ -536,6 +549,7 @@ Guacamole.Keyboard = function Keyboard(element) {
"Left": [0xFF51],
"Meta": [0xFFE7, 0xFFE7, 0xFFE8],
"ModeChange": [0xFF7E],
+ "NonConvert": [0xFF22],
"NumLock": [0xFF7F],
"PageDown": [0xFF56],
"PageUp": [0xFF55],
@@ -545,6 +559,7 @@ Guacamole.Keyboard = function Keyboard(element) {
"PrintScreen": [0xFF61],
"Redo": [0xFF66],
"Right": [0xFF53],
+ "Romaji": [0xFF24],
"RomanCharacters": null,
"Scroll": [0xFF14],
"Select": [0xFF60],
@@ -1316,9 +1331,10 @@ Guacamole.Keyboard = function Keyboard(element) {
var keydownEvent = new KeydownEvent(e);
- // Ignore (but do not prevent) the "composition" keycode sent by some
- // browsers when an IME is in use (see: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html)
- if (keydownEvent.keyCode === 229)
+ // Ignore (but do not prevent) the event if explicitly marked as composing,
+ // or when the "composition" keycode sent by some browsers when an IME is in use
+ // (see: http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html)
+ if (e.isComposing || keydownEvent.keyCode === 229)
return;
// Log event
@@ -1365,7 +1381,70 @@ Guacamole.Keyboard = function Keyboard(element) {
}, true);
- // NEKO: Do not automatically type text entered into the wrapped field
+ /**
+ * Handles the given "input" event, typing the data within the input text.
+ *
+ * @private
+ * @param {!InputEvent} e
+ * The "input" event to handle.
+ */
+ var handleInput = function handleInput(e) {
+
+ // Only intercept if handler set
+ if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
+
+ // Ignore events which have already been handled
+ if (!markEvent(e)) return;
+
+ // Type all content written
+ if (e.data && !e.isComposing)
+ guac_keyboard.type(e.data);
+
+ };
+
+ /**
+ * Handles the given "compositionstart" event, automatically removing
+ * the "input" event handler, as "input" events should only be handled
+ * if composition events are not provided by the browser.
+ *
+ * @private
+ * @param {!CompositionEvent} e
+ * The "compositionstart" event to handle.
+ */
+ var handleCompositionStart = function handleCompositionStart(e) {
+
+ // Remove the "input" event handler now that the browser is known
+ // to send composition events
+ element.removeEventListener("input", handleInput, false);
+
+ };
+
+ /**
+ * Handles the given "compositionend" event, typing the data within the
+ * composed text.
+ *
+ * @private
+ * @param {!CompositionEvent} e
+ * The "compositionend" event to handle.
+ */
+ var handleCompositionEnd = function handleCompositionEnd(e) {
+
+ // Only intercept if handler set
+ if (!guac_keyboard.onkeydown && !guac_keyboard.onkeyup) return;
+
+ // Ignore events which have already been handled
+ if (!markEvent(e)) return;
+
+ // Type all content written
+ if (e.data)
+ guac_keyboard.type(e.data);
+
+ };
+
+ // Automatically type text entered into the wrapped field
+ element.addEventListener("input", handleInput, false);
+ element.addEventListener("compositionend", handleCompositionEnd, false);
+ element.addEventListener("compositionstart", handleCompositionStart, false);
};
diff --git a/runtime/Dockerfile.bookworm b/runtime/Dockerfile.bookworm
index b53e1ad06..ea3c7954a 100644
--- a/runtime/Dockerfile.bookworm
+++ b/runtime/Dockerfile.bookworm
@@ -14,8 +14,8 @@ RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
wget ca-certificates supervisor \
- pulseaudio xserver-xorg-video-dummy \
- libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 libxcvt0 \
+ pulseaudio dbus-x11 xserver-xorg-video-dummy \
+ libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 libx264-164 libvo-aacenc0 librtmp1 libxcvt0 \
#
# needed for profile upload preStop hook
zip curl \
@@ -46,6 +46,7 @@ RUN set -eux; \
/home/$USERNAME/.config/pulse \
/home/$USERNAME/.local/share/xorg; \
chmod 1777 /var/log/neko; \
+ chmod 0700 /tmp/runtime-$USERNAME; \
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
#
@@ -72,8 +73,10 @@ RUN set -eux; \
#
# copy runtime configs
COPY --chown=neko:neko .Xresources /home/$USERNAME/.Xresources
+COPY dbus /usr/bin/dbus
COPY default.pa /etc/pulse/default.pa
COPY supervisord.conf /etc/neko/supervisord.conf
+COPY supervisord.dbus.conf /etc/neko/supervisord.dbus.conf
COPY xorg.conf /etc/neko/xorg.conf
#
@@ -98,6 +101,7 @@ HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
CMD wget -O - http://localhost:${NEKO_SERVER_BIND#*:}/health || \
wget --no-check-certificate -O - https://localhost:${NEKO_SERVER_BIND#*:}/health || \
exit 1
+
#
# run neko
CMD ["/usr/bin/supervisord", "-c", "/etc/neko/supervisord.conf"]
diff --git a/runtime/Dockerfile.intel.bookworm b/runtime/Dockerfile.intel.bookworm
new file mode 100644
index 000000000..dd5519c7d
--- /dev/null
+++ b/runtime/Dockerfile.intel.bookworm
@@ -0,0 +1,119 @@
+ARG BASE_IMAGE=debian:bookworm-slim
+FROM $BASE_IMAGE AS runtime
+
+#
+# set custom user
+ARG USERNAME=neko
+ARG USER_UID=1000
+ARG USER_GID=$USER_UID
+
+#
+# install dependencies
+ENV DEBIAN_FRONTEND=noninteractive
+RUN set -eux; \
+ #
+ # add non-free repo for intel drivers
+ echo deb http://deb.debian.org/debian bookworm main contrib non-free > /etc/apt/sources.list; \
+ echo deb http://deb.debian.org/debian-security/ bookworm-security main contrib non-free >> /etc/apt/sources.list; \
+ echo deb http://deb.debian.org/debian bookworm-updates main contrib non-free >> /etc/apt/sources.list; \
+ apt-get update; \
+ apt-get install -y --no-install-recommends \
+ wget ca-certificates supervisor \
+ pulseaudio dbus-x11 xserver-xorg-video-dummy \
+ libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 libx264-164 libvo-aacenc0 librtmp1 libxcvt0 \
+ #
+ # intel driver + vaapi
+ intel-media-va-driver-non-free libva2 vainfo \
+ #
+ # needed for profile upload preStop hook
+ zip curl \
+ #
+ # file chooser handler, clipboard, drop
+ xdotool xclip libgtk-3-0 \
+ #
+ # gst
+ gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
+ gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
+ gstreamer1.0-pulseaudio gstreamer1.0-vaapi; \
+ #
+ # create a non-root user
+ groupadd --gid $USER_GID $USERNAME; \
+ useradd --uid $USER_UID --gid $USERNAME --shell /bin/bash --create-home $USERNAME; \
+ adduser $USERNAME audio; \
+ adduser $USERNAME video; \
+ adduser $USERNAME pulse; \
+ #
+ # workaround for an X11 problem: http://blog.tigerteufel.de/?p=476
+ mkdir /tmp/.X11-unix; \
+ chmod 1777 /tmp/.X11-unix; \
+ chown $USERNAME /tmp/.X11-unix/; \
+ #
+ # make directories for neko
+ mkdir -p /etc/neko /var/www /var/log/neko \
+ /tmp/runtime-$USERNAME \
+ /home/$USERNAME/.config/pulse \
+ /home/$USERNAME/.local/share/xorg; \
+ chmod 1777 /var/log/neko; \
+ chmod 0700 /tmp/runtime-$USERNAME; \
+ chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
+ chown -R $USERNAME:$USERNAME /home/$USERNAME; \
+ #
+ # install fonts
+ apt-get install -y --no-install-recommends \
+ # Emojis
+ fonts-noto-color-emoji \
+ # Chinese fonts
+ fonts-arphic-ukai fonts-arphic-uming \
+ fonts-wqy-zenhei xfonts-intl-chinese xfonts-wqy \
+ # Japanese fonts
+ fonts-ipafont-mincho fonts-ipafont-gothic \
+ fonts-takao-mincho \
+ # Korean fonts
+ fonts-unfonts-core \
+ fonts-wqy-microhei \
+ # Indian fonts
+ fonts-indic; \
+ #
+ # clean up
+ apt-get clean -y; \
+ rm -rf /var/lib/apt/lists/* /var/cache/apt/*
+
+#
+# copy runtime configs
+COPY --chown=neko:neko .Xresources /home/$USERNAME/.Xresources
+COPY dbus /usr/bin/dbus
+COPY default.pa /etc/pulse/default.pa
+COPY supervisord.conf /etc/neko/supervisord.conf
+COPY supervisord.dbus.conf /etc/neko/supervisord.dbus.conf
+COPY xorg.conf /etc/neko/xorg.conf
+COPY intel/add-render-group.sh /usr/bin/add-render-group.sh
+COPY intel/supervisord.rendergroup.conf /etc/neko/supervisord/supervisord.rendergroup.conf
+
+#
+# copy runtime folders
+COPY --chown=neko:neko icon-theme /home/$USERNAME/.icons/default
+COPY fontconfig/* /etc/fonts/conf.d/
+COPY fonts /usr/local/share/fonts
+
+#
+# set default envs
+ENV USER=$USERNAME
+ENV DISPLAY=:99.0
+ENV PULSE_SERVER=unix:/tmp/pulseaudio.socket
+ENV XDG_RUNTIME_DIR=/tmp/runtime-$USERNAME
+ENV NEKO_SERVER_BIND=:8080
+ENV NEKO_PLUGINS_ENABLED=true
+ENV NEKO_PLUGINS_DIR=/etc/neko/plugins/
+ENV NEKO_HWENC=VAAPI
+ENV RENDER_GID=
+
+#
+# add healthcheck
+HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
+ CMD wget -O - http://localhost:${NEKO_SERVER_BIND#*:}/health || \
+ wget --no-check-certificate -O - https://localhost:${NEKO_SERVER_BIND#*:}/health || \
+ exit 1
+
+#
+# run neko
+CMD ["/usr/bin/supervisord", "-c", "/etc/neko/supervisord.conf"]
diff --git a/runtime/Dockerfile.nvidia.bookworm b/runtime/Dockerfile.nvidia.bookworm
index 0e3c3c1d0..ff223e83e 100644
--- a/runtime/Dockerfile.nvidia.bookworm
+++ b/runtime/Dockerfile.nvidia.bookworm
@@ -1,116 +1,71 @@
ARG UBUNTU_RELEASE=22.04
ARG CUDA_VERSION=12.2.0
ARG VIRTUALGL_VERSION=3.1.3-20250409
-ARG GSTREAMER_VERSION=1.22
-#
-# Stage 1: Build gstreamer with nvidia plugins.
-#
-FROM ubuntu:${UBUNTU_RELEASE} AS gstreamer
-ARG GSTREAMER_VERSION
-
-#
-# install dependencies
-ENV DEBIAN_FRONTEND=noninteractive
-RUN set -eux; \
- apt-get update; \
- apt-get install -y --no-install-recommends \
- # Install essentials
- curl build-essential ca-certificates git \
- # Install pip and ninja
- python3-pip python-gi-dev ninja-build \
- # Install build deps
- autopoint autoconf automake autotools-dev libtool gettext bison flex gtk-doc-tools \
- # Install libraries
- librtmp-dev \
- libvo-aacenc-dev \
- libtool-bin \
- libgtk2.0-dev \
- libgl1-mesa-dev \
- libopus-dev \
- libpulse-dev \
- libssl-dev \
- libx264-dev \
- libvpx-dev; \
- # Install meson
- pip3 install meson; \
- #
- # clean up
- apt-get clean -y; \
- rm -rf /var/lib/apt/lists/* /var/cache/apt/*
-
-#
-# build gstreamer
-RUN set -eux; \
- git clone --depth 1 --branch $GSTREAMER_VERSION https://gitlab.freedesktop.org/gstreamer/gstreamer.git /gstreamer/src; \
- cd /gstreamer/src; \
- mkdir -p /usr/share/gstreamer; \
- meson --prefix /usr/share/gstreamer \
- -Dgpl=enabled \
- -Dugly=enabled \
- -Dgst-plugins-ugly:x264=enabled \
- build; \
- ninja -C build; \
- meson install -C build;
-
-#
-# Stage 2: Runtime.
-#
FROM nvidia/cuda:${CUDA_VERSION}-runtime-ubuntu${UBUNTU_RELEASE} AS runtime
-ARG UBUNTU_RELEASE
ARG VIRTUALGL_VERSION
# Make all NVIDIA GPUs visible by default
ENV NVIDIA_VISIBLE_DEVICES=all
# All NVIDIA driver capabilities should preferably be used, check `NVIDIA_DRIVER_CAPABILITIES` inside the container if things do not work
ENV NVIDIA_DRIVER_CAPABILITIES=all
-
-#
-# set vgl-display to headless 3d gpu card/// correct values are egl[n] or /dev/dri/card0:if this is passed into container
+# Set vgl-display to headless 3d gpu card/// correct values are egl[n] or /dev/dri/card0:if this is passed into container
ENV VGL_DISPLAY=egl
-#
-# set custom user
-ARG USERNAME=neko
-ARG USER_UID=1000
-ARG USER_GID=$USER_UID
-
#
# install hardware accleration dependencies
ENV DEBIAN_FRONTEND=noninteractive
RUN set -eux; \
- dpkg --add-architecture i386; \
apt-get update; \
apt-get install -y --no-install-recommends \
+ wget gpg ca-certificates \
# opengl base: https://gitlab.com/nvidia/container-images/opengl/-/blob/ubuntu20.04/base/Dockerfile
- libxau6 libxau6:i386 \
- libxdmcp6 libxdmcp6:i386 \
- libxcb1 libxcb1:i386 \
- libxext6 libxext6:i386 \
- libx11-6 libx11-6:i386 \
+ libxau6 libxdmcp6 libxcb1 libxext6 libx11-6 \
# opengl runtime: https://gitlab.com/nvidia/container-images/opengl/-/blob/ubuntu20.04/glvnd/runtime/Dockerfile
- libglvnd0 libglvnd0:i386 \
- libgl1 libgl1:i386 \
- libglx0 libglx0:i386 \
- libegl1 libegl1:i386 \
- libgles2 libgles2:i386 \
+ libglvnd0 libgl1 libglx0 libegl1 libgles2 \
# hardware accleration utilities
- libglu1 libglu1:i386 \
- libvulkan-dev libvulkan-dev:i386 \
- mesa-utils mesa-utils-extra \
- mesa-va-drivers mesa-vulkan-drivers \
- vainfo vdpauinfo; \
+ libglu1 libvulkan-dev vainfo vdpauinfo vulkan-tools \
+ mesa-utils mesa-utils-extra mesa-va-drivers mesa-vulkan-drivers; \
#
- # install vulkan-utils or vulkan-tools depending on ubuntu release
- if [ "${UBUNTU_RELEASE}" = "18.04" ]; then \
- apt-get install -y --no-install-recommends vulkan-utils; \
- else \
- apt-get install -y --no-install-recommends vulkan-tools; \
+ # install an up-to-date version of VirtualGL
+ if [ -n "${VIRTUALGL_VERSION}" ]; then \
+ #
+ # add VirtualGL GPG key
+ wget -q -O- https://packagecloud.io/dcommander/virtualgl/gpgkey | \
+ gpg --dearmor >/etc/apt/trusted.gpg.d/VirtualGL.gpg; \
+ #
+ # download the official VirtualGL.list file
+ wget -q -O /etc/apt/sources.list.d/VirtualGL.list \
+ https://raw.githubusercontent.com/VirtualGL/repo/main/VirtualGL.list; \
+ #
+ # install packages
+ apt-get update; \
+ apt-get install -y --no-install-recommends virtualgl=${VIRTUALGL_VERSION}; \
fi; \
#
# create symlink for libnvrtc.so (needed for cudaconvert)
find /usr/local/cuda/lib64/ -maxdepth 1 -type l -name "*libnvrtc.so.*" -exec sh -c 'ln -sf {} /usr/local/cuda/lib64/libnvrtc.so' \;; \
#
+ # configure EGL manually
+ mkdir -p /usr/share/glvnd/egl_vendor.d/; \
+ echo "{\n\
+ \"file_format_version\" : \"1.0.0\",\n\
+ \"ICD\": {\n\
+ \"library_path\": \"libEGL_nvidia.so.0\"\n\
+ }\n\
+ }" > /usr/share/glvnd/egl_vendor.d/10_nvidia.json; \
+ #
+ # configure Vulkan manually
+ VULKAN_API_VERSION=$(dpkg -s libvulkan1 | grep -oP 'Version: [0-9|\.]+' | grep -oP '[0-9]+(\.[0-9]+)(\.[0-9]+)'); \
+ mkdir -p /etc/vulkan/icd.d/; \
+ echo "{\n\
+ \"file_format_version\" : \"1.0.0\",\n\
+ \"ICD\": {\n\
+ \"library_path\": \"libGLX_nvidia.so.0\",\n\
+ \"api_version\" : \"${VULKAN_API_VERSION}\"\n\
+ }\n\
+ }" > /etc/vulkan/icd.d/nvidia_icd.json; \
+ #
# clean up
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
@@ -119,6 +74,16 @@ RUN set -eux; \
# add cuda to ld path, for gstreamer cuda plugins
ENV LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:/usr/lib/i386-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}:/usr/local/cuda/lib:/usr/local/cuda/lib64"
+#
+# entrypoint script that sets up VirtualGL and runs commands
+COPY nvidia/entrypoint.sh /bin/entrypoint.sh
+
+#
+# set custom user
+ARG USERNAME=neko
+ARG USER_UID=1000
+ARG USER_GID=$USER_UID
+
#
# install dependencies
ENV DEBIAN_FRONTEND=noninteractive
@@ -126,15 +91,19 @@ RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
wget ca-certificates supervisor \
- pulseaudio xserver-xorg-video-dummy \
+ pulseaudio dbus-x11 xserver-xorg-video-dummy \
libcairo2 libxcb1 libxrandr2 libxv1 libopus0 libvpx7 libx264-163 libvo-aacenc0 librtmp1 libxcvt0 \
- libgtk-3-bin software-properties-common cabextract aptitude vim curl \
#
# needed for profile upload preStop hook
zip curl \
#
# file chooser handler, clipboard, drop
- xdotool xclip libgtk-3-0; \
+ xdotool xclip libgtk-3-0 \
+ #
+ # gst
+ gstreamer1.0-plugins-base gstreamer1.0-plugins-good \
+ gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
+ gstreamer1.0-pulseaudio; \
#
# create a non-root user
groupadd --gid $USER_GID $USERNAME; \
@@ -154,6 +123,7 @@ RUN set -eux; \
/home/$USERNAME/.config/pulse \
/home/$USERNAME/.local/share/xorg; \
chmod 1777 /var/log/neko; \
+ chmod 0700 /tmp/runtime-$USERNAME; \
chown $USERNAME /var/log/neko/ /tmp/runtime-$USERNAME; \
chown -R $USERNAME:$USERNAME /home/$USERNAME; \
#
@@ -177,52 +147,14 @@ RUN set -eux; \
apt-get clean -y; \
rm -rf /var/lib/apt/lists/* /var/cache/apt/*
-#
-# configure EGL and Vulkan manually
-RUN VULKAN_API_VERSION=$(dpkg -s libvulkan1 | grep -oP 'Version: [0-9|\.]+' | grep -oP '[0-9]+(\.[0-9]+)(\.[0-9]+)') && \
- # Configure EGL manually
- mkdir -p /usr/share/glvnd/egl_vendor.d/ && \
- echo "{\n\
- \"file_format_version\" : \"1.0.0\",\n\
- \"ICD\": {\n\
- \"library_path\": \"libEGL_nvidia.so.0\"\n\
- }\n\
-}" > /usr/share/glvnd/egl_vendor.d/10_nvidia.json && \
- # Configure Vulkan manually
- mkdir -p /etc/vulkan/icd.d/ && \
- echo "{\n\
- \"file_format_version\" : \"1.0.0\",\n\
- \"ICD\": {\n\
- \"library_path\": \"libGLX_nvidia.so.0\",\n\
- \"api_version\" : \"${VULKAN_API_VERSION}\"\n\
- }\n\
-}" > /etc/vulkan/icd.d/nvidia_icd.json
-
-#
-# install an up-to-date version of VirtualGL
-RUN apt-get update; \
- apt-get install -y --no-install-recommends wget gpg ca-certificates; \
- # Add VirtualGL GPG key
- wget -q -O- https://packagecloud.io/dcommander/virtualgl/gpgkey | \
- gpg --dearmor >/etc/apt/trusted.gpg.d/VirtualGL.gpg; \
- # Download the official VirtualGL.list file
- wget -q -O /etc/apt/sources.list.d/VirtualGL.list \
- https://raw.githubusercontent.com/VirtualGL/repo/main/VirtualGL.list; \
- # Install packages
- apt-get update; \
- apt-get install -y --no-install-recommends virtualgl=${VIRTUALGL_VERSION}; \
- #
- # clean up
- apt-get clean -y; \
- rm -rf /var/lib/apt/lists/* /var/cache/apt/*
-
#
# copy runtime configs
COPY --chown=neko:neko .Xresources /home/$USERNAME/.Xresources
+COPY dbus /usr/bin/dbus
COPY default.pa /etc/pulse/default.pa
COPY supervisord.conf /etc/neko/supervisord.conf
+COPY supervisord.dbus.conf /etc/neko/supervisord.dbus.conf
COPY xorg.conf /etc/neko/xorg.conf
-COPY nvidia/entrypoint.sh /bin/entrypoint.sh
#
# copy runtime folders
@@ -240,16 +172,6 @@ ENV NEKO_SERVER_BIND=:8080
ENV NEKO_PLUGINS_ENABLED=true
ENV NEKO_PLUGINS_DIR=/etc/neko/plugins/
-#
-# set gstreamer envs
-ENV PATH="/usr/share/gstreamer/bin:${PATH}"
-ENV LD_LIBRARY_PATH="/usr/share/gstreamer/lib/x86_64-linux-gnu${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
-ENV PKG_CONFIG_PATH="/usr/share/gstreamer/lib/x86_64-linux-gnu/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}"
-
-#
-# copy artifacts from previous stages
-COPY --from=gstreamer /usr/share/gstreamer /usr/share/gstreamer
-
#
# add healthcheck
HEALTHCHECK --interval=10s --timeout=5s --retries=8 \
diff --git a/scripts/sync-upstream.sh b/scripts/sync-upstream.sh
new file mode 100755
index 000000000..9667d27d2
--- /dev/null
+++ b/scripts/sync-upstream.sh
@@ -0,0 +1,78 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# Usage/help
+usage() {
+ cat <<'EOF'
+Usage: scripts/sync-upstream-manual.sh [options]
+
+Options:
+ -u, --upstream-branch BRANCH Upstream branch to merge (default: master)
+ --no-new-branch Merge into current branch instead of creating a new one
+ -h, --help Show this help and exit
+EOF
+}
+
+# Defaults
+UPSTREAM_BRANCH="master"
+CREATE_NEW_BRANCH="true"
+
+# Parse args
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ -u|--upstream-branch)
+ if [[ $# -lt 2 ]]; then
+ echo "Missing value for $1" >&2
+ usage
+ exit 1
+ fi
+ UPSTREAM_BRANCH="$2"
+ shift 2
+ ;;
+ --no-new-branch)
+ CREATE_NEW_BRANCH="false"
+ shift
+ ;;
+ -h|--help)
+ usage
+ exit 0
+ ;;
+ *)
+ echo "Unknown option: $1" >&2
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+# Check if upstream remote exists, add if not
+if ! git remote get-url upstream >/dev/null 2>&1; then
+ echo "Adding upstream remote..."
+ git remote add upstream https://github.com/m1k1o/neko.git
+else
+ echo "Upstream remote already exists"
+fi
+
+if [[ "${CREATE_NEW_BRANCH}" == "true" ]]; then
+ branch="sync/upstream-$(date +%Y%m%d)"
+ git checkout -b "$branch" # work on a throw-away branch
+else
+ echo "Merging into existing branch: $(git rev-parse --abbrev-ref HEAD)"
+fi
+
+# merge selected upstream branch into this branch
+git fetch upstream
+git merge --no-edit "upstream/${UPSTREAM_BRANCH}" || true
+echo "there are now likely conflicts to resolve. Go forth and resolve them!"
+
+# For each stop:
+# - run git status to see the conflicted files
+# - open each file, remove the conflict markers (<<<<<<<, =======, >>>>>>>) and keep the version you want,
+# OR, if you simply want the upstream copy: git checkout --theirs path/to/file.
+# If you want to keep your fork's version: git checkout --ours path/to/file.
+# - git add
(or git rm if you really mean to delete it).
+# - git merge --continue.
+
+
+# When git merge is completed, push the branch back to GitHub:
+# git push --force-with-lease -u origin HEAD
diff --git a/server/Dockerfile b/server/Dockerfile
index aba6a3121..356096518 100644
--- a/server/Dockerfile
+++ b/server/Dockerfile
@@ -1,4 +1,4 @@
-ARG BASE_IMAGE=golang:1.21-bullseye
+ARG BASE_IMAGE=golang:1.24-bullseye
FROM $BASE_IMAGE AS server
WORKDIR /src
diff --git a/server/Dockerfile.bookworm b/server/Dockerfile.bookworm
index 1f0cbfa94..e3f67371c 100644
--- a/server/Dockerfile.bookworm
+++ b/server/Dockerfile.bookworm
@@ -1,4 +1,4 @@
-ARG BASE_IMAGE=golang:1.21-bookworm
+ARG BASE_IMAGE=golang:1.24-bookworm
FROM $BASE_IMAGE AS server
WORKDIR /src
diff --git a/server/go.mod b/server/go.mod
index 58ced2488..2b74dd7d5 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -1,68 +1,68 @@
module github.com/m1k1o/neko/server
-go 1.21
+go 1.24.0
+
+toolchain go1.24.5
require (
- github.com/PaesslerAG/gval v1.2.2
+ github.com/PaesslerAG/gval v1.2.4
+ github.com/fsnotify/fsnotify v1.9.0
github.com/go-chi/chi v1.5.5
- github.com/go-chi/cors v1.2.1
- github.com/gorilla/websocket v1.5.1
+ github.com/go-chi/cors v1.2.2
+ github.com/gorilla/websocket v1.5.3
github.com/kataras/go-events v0.0.3
- github.com/pion/ice/v2 v2.3.12
- github.com/pion/interceptor v0.1.25
- github.com/pion/logging v0.2.2
- github.com/pion/rtcp v1.2.13
- github.com/pion/webrtc/v3 v3.2.24
- github.com/prometheus/client_golang v1.18.0
- github.com/rs/zerolog v1.31.0
- github.com/spf13/cobra v1.8.0
- github.com/spf13/viper v1.18.2
+ github.com/mitchellh/mapstructure v1.5.0
+ github.com/pion/ice/v2 v2.3.38
+ github.com/pion/interceptor v0.1.40
+ github.com/pion/logging v0.2.4
+ github.com/pion/rtcp v1.2.15
+ github.com/pion/webrtc/v3 v3.3.6
+ github.com/prometheus/client_golang v1.23.0
+ github.com/rs/zerolog v1.34.0
+ github.com/spf13/cobra v1.9.1
+ github.com/spf13/viper v1.20.1
)
require (
github.com/beorn7/perks v1.0.1 // indirect
- github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
- github.com/fsnotify/fsnotify v1.7.0 // indirect
+ github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/magiconair/properties v1.8.7 // indirect
- github.com/mattn/go-colorable v0.1.13 // indirect
+ github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
- github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/pelletier/go-toml/v2 v2.1.1 // indirect
- github.com/pion/datachannel v1.5.5 // indirect
- github.com/pion/dtls/v2 v2.2.9 // indirect
- github.com/pion/mdns v0.0.9 // indirect
+ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/pelletier/go-toml/v2 v2.2.4 // indirect
+ github.com/pion/datachannel v1.5.10 // indirect
+ github.com/pion/dtls/v2 v2.2.12 // indirect
+ github.com/pion/mdns v0.0.12 // indirect
github.com/pion/randutil v0.1.0 // indirect
- github.com/pion/rtp v1.8.3 // indirect
- github.com/pion/sctp v1.8.9 // indirect
- github.com/pion/sdp/v3 v3.0.6 // indirect
- github.com/pion/srtp/v2 v2.0.18 // indirect
+ github.com/pion/rtp v1.8.21 // indirect
+ github.com/pion/sctp v1.8.39 // indirect
+ github.com/pion/sdp/v3 v3.0.15 // indirect
+ github.com/pion/srtp/v2 v2.0.20 // indirect
github.com/pion/stun v0.6.1 // indirect
- github.com/pion/transport/v2 v2.2.4 // indirect
- github.com/pion/turn/v2 v2.1.4 // indirect
+ github.com/pion/transport/v2 v2.2.10 // indirect
+ github.com/pion/transport/v3 v3.0.7 // indirect
+ github.com/pion/turn/v2 v2.1.6 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
- github.com/prometheus/client_model v0.5.0 // indirect
- github.com/prometheus/common v0.46.0 // indirect
- github.com/prometheus/procfs v0.12.0 // indirect
- github.com/sagikazarmark/locafero v0.4.0 // indirect
- github.com/sagikazarmark/slog-shim v0.1.0 // indirect
- github.com/shopspring/decimal v1.3.1 // indirect
- github.com/sourcegraph/conc v0.3.0 // indirect
- github.com/spf13/afero v1.11.0 // indirect
- github.com/spf13/cast v1.6.0 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/stretchr/testify v1.8.4 // indirect
+ github.com/prometheus/client_model v0.6.2 // indirect
+ github.com/prometheus/common v0.65.0 // indirect
+ github.com/prometheus/procfs v0.17.0 // indirect
+ github.com/sagikazarmark/locafero v0.10.0 // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
+ github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
+ github.com/spf13/afero v1.14.0 // indirect
+ github.com/spf13/cast v1.9.2 // indirect
+ github.com/spf13/pflag v1.0.7 // indirect
+ github.com/stretchr/testify v1.10.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
- go.uber.org/multierr v1.11.0 // indirect
- golang.org/x/crypto v0.18.0 // indirect
- golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
- golang.org/x/net v0.20.0 // indirect
- golang.org/x/sys v0.16.0 // indirect
- golang.org/x/text v0.14.0 // indirect
- google.golang.org/protobuf v1.32.0 // indirect
- gopkg.in/ini.v1 v1.67.0 // indirect
+ github.com/wlynxg/anet v0.0.5 // indirect
+ golang.org/x/crypto v0.40.0 // indirect
+ golang.org/x/net v0.42.0 // indirect
+ golang.org/x/sys v0.34.0 // indirect
+ golang.org/x/text v0.27.0 // indirect
+ google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
diff --git a/server/go.sum b/server/go.sum
index 84008d03d..4889a2418 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -1,56 +1,41 @@
-github.com/PaesslerAG/gval v1.2.2 h1:Y7iBzhgE09IGTt5QgGQ2IdaYYYOU134YGHBThD+wm9E=
-github.com/PaesslerAG/gval v1.2.2/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac=
+github.com/PaesslerAG/gval v1.2.4 h1:rhX7MpjJlcxYwL2eTTYIOBUyEKZ+A96T9vQySWkVUiU=
+github.com/PaesslerAG/gval v1.2.4/go.mod h1:XRFLwvmkTEdYziLdaCeCa5ImcGVrfQbeNUbVR+C6xac=
github.com/PaesslerAG/jsonpath v0.1.0 h1:gADYeifvlqK3R3i2cR5B4DGgxLXIPb3TRTH1mGi0jPI=
github.com/PaesslerAG/jsonpath v0.1.0/go.mod h1:4BzmtoM/PI8fPO4aQGIusjGxGir2BzcV0grWtFzq1Y8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
-github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
+github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
-github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
+github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
+github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
-github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
-github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
-github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
+github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
+github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
+github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
-github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
-github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
-github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
+github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kataras/go-events v0.0.3 h1:o5YK53uURXtrlg7qE/vovxd/yKOJcLuFtPQbf1rYMC4=
github.com/kataras/go-events v0.0.3/go.mod h1:bFBgtzwwzrag7kQmGuU1ZaVxhK2qseYPQomXoVEMsj4=
+github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
+github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -58,248 +43,182 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
-github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
+github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
-github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
-github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
-github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
-github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
-github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
-github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
-github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
-github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
-github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
-github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
+github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
+github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
+github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
+github.com/pion/datachannel v1.5.10 h1:ly0Q26K1i6ZkGf42W7D4hQYR90pZwzFOjTq5AuCKk4o=
+github.com/pion/datachannel v1.5.10/go.mod h1:p/jJfC9arb29W7WrxyKbepTU20CFgyx5oLo8Rs4Py/M=
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
-github.com/pion/dtls/v2 v2.2.9 h1:K+D/aVf9/REahQvqk6G5JavdrD8W1PWDKC11UlwN7ts=
-github.com/pion/dtls/v2 v2.2.9/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
-github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
-github.com/pion/ice/v2 v2.3.12 h1:NWKW2b3+oSZS3klbQMIEWQ0i52Kuo0KBg505a5kQv4s=
-github.com/pion/ice/v2 v2.3.12/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
-github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc=
-github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
-github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
+github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk=
+github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE=
+github.com/pion/ice/v2 v2.3.38 h1:DEpt13igPfvkE2+1Q+6e8mP30dtWnQD3CtMIKoRDRmA=
+github.com/pion/ice/v2 v2.3.38/go.mod h1:mBF7lnigdqgtB+YHkaY/Y6s6tsyRyo4u4rPGRuOjUBQ=
+github.com/pion/interceptor v0.1.40 h1:e0BjnPcGpr2CFQgKhrQisBU7V3GXK6wrfYrGYaU6Jq4=
+github.com/pion/interceptor v0.1.40/go.mod h1:Z6kqH7M/FYirg3frjGJ21VLSRJGBXB/KqaTIrdqnOic=
github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms=
-github.com/pion/mdns v0.0.8/go.mod h1:hYE72WX8WDveIhg7fmXgMKivD3Puklk0Ymzog0lSyaI=
-github.com/pion/mdns v0.0.9 h1:7Ue5KZsqq8EuqStnpPWV33vYYEH0+skdDN5L7EiEsI4=
-github.com/pion/mdns v0.0.9/go.mod h1:2JA5exfxwzXiCihmxpTKgFUpiQws2MnipoPK09vecIc=
+github.com/pion/logging v0.2.4 h1:tTew+7cmQ+Mc1pTBLKH2puKsOvhm32dROumOZ655zB8=
+github.com/pion/logging v0.2.4/go.mod h1:DffhXTKYdNZU+KtJ5pyQDjvOAh/GsNSyv1lbkFbe3so=
+github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8=
+github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk=
github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA=
github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8=
-github.com/pion/rtcp v1.2.10/go.mod h1:ztfEwXZNLGyF1oQDttz/ZKIBaeeg/oWbRYqzBM9TL1I=
github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
-github.com/pion/rtcp v1.2.13 h1:+EQijuisKwm/8VBs8nWllr0bIndR7Lf7cZG200mpbNo=
-github.com/pion/rtcp v1.2.13/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4=
-github.com/pion/rtp v1.8.2/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
-github.com/pion/rtp v1.8.3 h1:VEHxqzSVQxCkKDSHro5/4IUUG1ea+MFdqR2R3xSpNU8=
+github.com/pion/rtcp v1.2.15 h1:LZQi2JbdipLOj4eBjK4wlVoQWfrZbh3Q6eHtWtJBZBo=
+github.com/pion/rtcp v1.2.15/go.mod h1:jlGuAjHMEXwMUHK78RgX0UmEJFV4zUKOFHR7OP+D3D0=
github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU=
-github.com/pion/sctp v1.8.5/go.mod h1:SUFFfDpViyKejTAdwD1d/HQsCu+V/40cCs2nZIvC3s0=
-github.com/pion/sctp v1.8.8/go.mod h1:igF9nZBrjh5AtmKc7U30jXltsFHicFCXSmWA2GWRaWs=
-github.com/pion/sctp v1.8.9 h1:TP5ZVxV5J7rz7uZmbyvnUvsn7EJ2x/5q9uhsTtXbI3g=
-github.com/pion/sctp v1.8.9/go.mod h1:cMLT45jqw3+jiJCrtHVwfQLnfR0MGZ4rgOJwUOIqLkI=
-github.com/pion/sdp/v3 v3.0.6 h1:WuDLhtuFUUVpTfus9ILC4HRyHsW6TdugjEX/QY9OiUw=
-github.com/pion/sdp/v3 v3.0.6/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw=
-github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo=
-github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
+github.com/pion/rtp v1.8.21 h1:3yrOwmZFyUpcIosNcWRpQaU+UXIJ6yxLuJ8Bx0mw37Y=
+github.com/pion/rtp v1.8.21/go.mod h1:bAu2UFKScgzyFqvUKmbvzSdPr+NGbZtv6UB2hesqXBk=
+github.com/pion/sctp v1.8.39 h1:PJma40vRHa3UTO3C4MyeJDQ+KIobVYRZQZ0Nt7SjQnE=
+github.com/pion/sctp v1.8.39/go.mod h1:cNiLdchXra8fHQwmIoqw0MbLLMs+f7uQ+dGMG2gWebE=
+github.com/pion/sdp/v3 v3.0.15 h1:F0I1zds+K/+37ZrzdADmx2Q44OFDOPRLhPnNTaUX9hk=
+github.com/pion/sdp/v3 v3.0.15/go.mod h1:88GMahN5xnScv1hIMTqLdu/cOcUkj6a9ytbncwMCq2E=
+github.com/pion/srtp/v2 v2.0.20 h1:HNNny4s+OUmG280ETrCdgFndp4ufx3/uy85EawYEhTk=
+github.com/pion/srtp/v2 v2.0.20/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA=
github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4=
github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8=
-github.com/pion/transport v0.14.1 h1:XSM6olwW+o8J4SCmOBb/BpwZypkHeyM0PGFCxNQBr40=
-github.com/pion/transport v0.14.1/go.mod h1:4tGmbk00NeYA3rUa9+n+dzCCoKkcy3YlYb99Jn2fNnI=
github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g=
-github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc=
github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
-github.com/pion/transport/v2 v2.2.4 h1:41JJK6DZQYSeVLxILA2+F4ZkKb4Xd/tFJZRFZQ9QAlo=
github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0=
-github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM=
+github.com/pion/transport/v2 v2.2.10 h1:ucLBLE8nuxiHfvkFKnkDQRYWYfp8ejf4YBOPfaQpw6Q=
+github.com/pion/transport/v2 v2.2.10/go.mod h1:sq1kSLWs+cHW9E+2fJP95QudkzbK7wscs8yYgQToO5E=
github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0=
+github.com/pion/transport/v3 v3.0.7 h1:iRbMH05BzSNwhILHoBoAPxoB9xQgOaJk+591KC9P1o0=
+github.com/pion/transport/v3 v3.0.7/go.mod h1:YleKiTZ4vqNxVwh77Z0zytYi7rXHl7j6uPLGhhz9rwo=
github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
-github.com/pion/turn/v2 v2.1.4 h1:2xn8rduI5W6sCZQkEnIUDAkrBQNl2eYIBCHMZ3QMmP8=
-github.com/pion/turn/v2 v2.1.4/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
-github.com/pion/webrtc/v3 v3.2.24 h1:MiFL5DMo2bDaaIFWr0DDpwiV/L4EGbLZb+xoRvfEo1Y=
-github.com/pion/webrtc/v3 v3.2.24/go.mod h1:1CaT2fcZzZ6VZA+O1i9yK2DU4EOcXVvSbWG9pr5jefs=
+github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc=
+github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY=
+github.com/pion/webrtc/v3 v3.3.6 h1:7XAh4RPtlY1Vul6/GmZrv7z+NnxKA6If0KStXBI2ZLE=
+github.com/pion/webrtc/v3 v3.3.6/go.mod h1:zyN7th4mZpV27eXybfR/cnUf3J2DRy8zw/mdjD9JTNM=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
-github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
-github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
-github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
-github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
-github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
-github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
-github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
+github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
+github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
+github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
+github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
+github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
+github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
+github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0=
+github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
-github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
-github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
+github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
+github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
-github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
-github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
-github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
-github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw=
-github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
+github.com/sagikazarmark/locafero v0.10.0 h1:FM8Cv6j2KqIhM2ZK7HZjm4mpj9NBktLgowT1aN9q5Cc=
+github.com/sagikazarmark/locafero v0.10.0/go.mod h1:Ieo3EUsjifvQu4NZwV5sPd4dwvu0OCgEQV7vjc9yDjw=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
-github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
-github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
-github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
-github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
-github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
-github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
-github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
-github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
+github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
+github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
+github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
+github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
+github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.7 h1:vN6T9TfwStFPFM5XzjsvmzZkLuaLX+HS+0SeFLRgU6M=
+github.com/spf13/pflag v1.0.7/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
+github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
+github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
+github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
-go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
-golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
-golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
-golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
-golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
-golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
+golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
-golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
-golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
-golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
+golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
+golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
-golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
-golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
+golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
+golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
-google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
+google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
-gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/server/internal/capture/manager.go b/server/internal/capture/manager.go
index 0758f935e..d16919e9f 100644
--- a/server/internal/capture/manager.go
+++ b/server/internal/capture/manager.go
@@ -3,6 +3,7 @@ package capture
import (
"errors"
"fmt"
+ "os"
"strings"
"github.com/rs/zerolog"
@@ -80,6 +81,10 @@ func New(desktop types.DesktopManager, config *config.Capture) *CaptureManagerCt
broadcast: broadcastNew(func(url string) (string, error) {
if config.BroadcastPipeline != "" {
var pipeline = config.BroadcastPipeline
+ if hostname, err := os.Hostname(); err == nil {
+ // replace {hostname} with valid hostname
+ pipeline = strings.Replace(pipeline, "{hostname}", hostname, 1)
+ }
// replace {display} with valid display
pipeline = strings.Replace(pipeline, "{display}", config.Display, 1)
// replace {device} with valid device
diff --git a/server/internal/config/capture.go b/server/internal/config/capture.go
index 298e69cd0..6bf568974 100644
--- a/server/internal/config/capture.go
+++ b/server/internal/config/capture.go
@@ -298,7 +298,7 @@ func (Capture) InitV2(cmd *cobra.Command) error {
// broadcast
//
- cmd.PersistentFlags().String("broadcast_pipeline", "", "V2: custom gst pipeline used for broadcasting, strings {url} {device} {display} will be replaced")
+ cmd.PersistentFlags().String("broadcast_pipeline", "", "V2: custom gst pipeline used for broadcasting, strings {hostname} {url} {device} {display} will be replaced")
if err := viper.BindPFlag("broadcast_pipeline", cmd.PersistentFlags().Lookup("broadcast_pipeline")); err != nil {
return err
}
diff --git a/server/internal/config/capture_pipeline.go b/server/internal/config/capture_pipeline.go
index 12019747e..07cece223 100644
--- a/server/internal/config/capture_pipeline.go
+++ b/server/internal/config/capture_pipeline.go
@@ -3,6 +3,7 @@ package config
import (
"fmt"
+ "os"
"strings"
"github.com/m1k1o/neko/server/pkg/gst"
@@ -40,12 +41,17 @@ func NewBroadcastPipeline(device string, display string, pipelineSrc string, url
var pipelineStr string
if pipelineSrc != "" {
+ pipelineStr = pipelineSrc
+ // replace {hostname} with valid hostname
+ if hostname, err := os.Hostname(); err == nil {
+ pipelineStr = strings.ReplaceAll(pipelineStr, "{hostname}", hostname)
+ }
// replace RTMP url
- pipelineStr = strings.Replace(pipelineSrc, "{url}", url, -1)
+ pipelineStr = strings.ReplaceAll(pipelineStr, "{url}", url)
// replace audio device
- pipelineStr = strings.Replace(pipelineStr, "{device}", device, -1)
+ pipelineStr = strings.ReplaceAll(pipelineStr, "{device}", device)
// replace display
- pipelineStr = strings.Replace(pipelineStr, "{display}", display, -1)
+ pipelineStr = strings.ReplaceAll(pipelineStr, "{display}", display)
} else {
pipelineStr = fmt.Sprintf("flvmux name=mux ! rtmpsink location='%s live=1' %s audio/x-raw,channels=2 ! audioconvert ! voaacenc ! mux. %s x264enc bframes=0 key-int-max=60 byte-stream=true tune=zerolatency speed-preset=veryfast ! mux.", url, audio, video)
}
diff --git a/webpage/docs/configuration/capture.md b/webpage/docs/configuration/capture.md
index be998e710..6349943ea 100644
--- a/webpage/docs/configuration/capture.md
+++ b/webpage/docs/configuration/capture.md
@@ -279,6 +279,33 @@ See documentation for [ximagesrc](https://gstreamer.freedesktop.org/documentatio
This configuration requires [Nvidia GPU](https://developer.nvidia.com/cuda-gpus) with [NVENC](https://developer.nvidia.com/nvidia-video-codec-sdk) support.
+ ```yaml title="config.yaml"
+ capture:
+ video:
+ codec: h264
+ ids: [ main ]
+ pipelines:
+ main:
+ gst_pipeline: |
+ ximagesrc display-name={display} show-pointer=true use-damage=false
+ ! cudaupload ! cudaconvert ! queue
+ ! video/x-raw(memory:CUDAMemory),format=NV12
+ ! nvh264enc
+ name=encoder
+ preset=2
+ gop-size=25
+ spatial-aq=true
+ temporal-aq=true
+ bitrate=4096
+ vbv-buffer-size=4096
+ rc-mode=6
+ ! h264parse config-interval=-1
+ ! video/x-h264,stream-format=byte-stream
+ ! appsink name=appsink
+ ```
+
+ This configuration requires [Nvidia GPU](https://developer.nvidia.com/cuda-gpus) with [NVENC](https://developer.nvidia.com/nvidia-video-codec-sdk) support and [Cuda](https://developer.nvidia.com/cuda-zone) support.
+
@@ -347,7 +374,7 @@ The default encoder uses `h264` for video and `aac` for audio, muxed in the `flv
- and are the bitrate settings for the default audio and video encoders expressed in kilobits per second.
- is the encoding speed preset for the default video encoder. See available presets [here](https://gstreamer.freedesktop.org/documentation/x264/index.html?gi-language=c#GstX264EncPreset).
-- when set, encoder settings above are ignored and the custom Gstreamer pipeline description is used. In the pipeline, you can use `{display}`, `{device}` and `{url}` as placeholders for the X display name, pulseaudio audio device name, and broadcast URL respectively.
+- when set, encoder settings above are ignored and the custom Gstreamer pipeline description is used. In the pipeline, you can use `{hostname}`, `{display}`, `{device}` and `{url}` as placeholders for the X display name, pulseaudio audio device name, and broadcast URL respectively.
- is the URL of the RTMP server where the broadcast will be sent e.g. `rtmp:////`. This can be set later using the API if the URL is not known at the time of configuration or is expected to change.
- is a boolean value that determines whether the broadcast should start automatically when neko starts, works only if the URL is set.
diff --git a/webpage/docs/installation/docker-images.md b/webpage/docs/installation/docker-images.md
index 44b4d903b..e27a056b9 100644
--- a/webpage/docs/installation/docker-images.md
+++ b/webpage/docs/installation/docker-images.md
@@ -241,7 +241,7 @@ For images with Nvidia GPU hardware acceleration using EGL use:
- [`ghcr.io/m1k1o/neko/nvidia-microsoft-edge`](https://ghcr.io/m1k1o/neko/nvidia-microsoft-edge)
- [`ghcr.io/m1k1o/neko/nvidia-brave`](https://ghcr.io/m1k1o/neko/nvidia-brave)
-The base image is available at [`ghcr.io/m1k1o/neko/nvidia-base`](https://ghcr.io/m1k1o/neko/nvidia-base).
+The base image is available at [`ghcr.io/m1k1o/neko/nvidia-base`](https://ghcr.io/m1k1o/neko/nvidia-base). See [Examples](/docs/v3/installation/examples#nvidia) for more information and usage.
## Supported Architectures {#arch}
diff --git a/webpage/docs/installation/examples.md b/webpage/docs/installation/examples.md
index ee229cae3..6bb57ed22 100644
--- a/webpage/docs/installation/examples.md
+++ b/webpage/docs/installation/examples.md
@@ -113,9 +113,9 @@ services:
## Nvidia GPU Acceleration {#nvidia}
-Neko supports hardware acceleration using Nvidia GPUs. To use this feature, you need to have the Nvidia Container Toolkit installed on your system. You can find the installation instructions [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html).
+Neko supports hardware acceleration using Nvidia GPUs. To use this feature, you need to have the Nvidia Container Toolkit installed on your system. You can find the installation instructions [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). Check if your GPU supports hardware encoding with [this list](https://developer.nvidia.com/video-encode-decode-gpu-support-matrix).
-This example shows how to accelerate video encoding and as well the browser rendering using the GPU. You can test if the GPU is used by running `nvidia-smi`, which should show the GPU usage of both the browser and neko. In the browser, you can run the [WebGL Aquarium Demo](https://webglsamples.org/aquarium/aquarium.html) to test the GPU usage.
+This example shows how to accelerate video encoding and as well the browser rendering using the GPU. You can test if the GPU is used by running `nvtop` or `nvidia-smi`, which should show the GPU usage of both the browser and neko. In the browser, you can run the [WebGL Aquarium Demo](https://webglsamples.org/aquarium/aquarium.html) to test the GPU usage.
```yaml title="docker-compose.yaml"
services:
@@ -130,8 +130,8 @@ services:
NEKO_CAPTURE_VIDEO_PIPELINE: |
ximagesrc display-name={display} show-pointer=true use-damage=false
! video/x-raw,framerate=25/1
- ! videoconvert ! queue
- ! video/x-raw,format=NV12
+ ! cudaupload ! cudaconvert ! queue
+ ! video/x-raw(memory:CUDAMemory),format=NV12
! nvh264enc
name=encoder
preset=2
@@ -161,7 +161,11 @@ services:
See available [Nvidia Docker Images](/docs/v3/installation/docker-images#nvidia).
-If you only want to accelerate the encoding, **not the browser rendering**, you can use the default image with additional environment variables:
+:::note
+If your Nvidia GPU does not support CUDA, you can use the pipeline below without `cudaupload` and `cudaconvert`. This should work with older GPUs, but the performance might be lower.
+:::
+
+If you only want to accelerate the encoding, **not the browser rendering**, and you do not need [Cuda library](https://gstreamer.freedesktop.org/documentation/cuda/index.html?gi-language=c), you can use the default image with additional environment variables:
```yaml title="docker-compose.yaml"
services:
@@ -181,8 +185,10 @@ services:
NEKO_CAPTURE_VIDEO_PIPELINE: |
ximagesrc display-name={display} show-pointer=true use-damage=false
! video/x-raw,framerate=25/1
+ # highlight-start
! videoconvert ! queue
! video/x-raw,format=NV12
+ # highlight-end
! nvh264enc
name=encoder
preset=2
diff --git a/webpage/docs/migration-from-v2/help.json b/webpage/docs/migration-from-v2/help.json
index 0110d40fa..3e2b728a5 100644
--- a/webpage/docs/migration-from-v2/help.json
+++ b/webpage/docs/migration-from-v2/help.json
@@ -250,7 +250,7 @@
"broadcast_pipeline"
],
"type": "string",
- "description": "custom gst pipeline used for broadcasting, strings {url} {device} {display} will be replaced"
+ "description": "custom gst pipeline used for broadcasting, strings {hostname} {url} {device} {display} will be replaced"
},
{
"key": [
diff --git a/webpage/docs/migration-from-v2/help.txt b/webpage/docs/migration-from-v2/help.txt
index 097f114fb..e530e8568 100644
--- a/webpage/docs/migration-from-v2/help.txt
+++ b/webpage/docs/migration-from-v2/help.txt
@@ -37,7 +37,7 @@
--audio string audio codec parameters to use for streaming
--audio_bitrate int audio bitrate in kbit/s
- --broadcast_pipeline string custom gst pipeline used for broadcasting, strings {url} {device} {display} will be replaced
+ --broadcast_pipeline string custom gst pipeline used for broadcasting, strings {hostname} {url} {device} {display} will be replaced
--broadcast_url string a default default URL for broadcast streams, can be disabled/changed later by admins in the GUI
--broadcast_autostart automatically start broadcasting when neko starts and broadcast_url is set