Очистить репозиторий перед переносом продукта
@@ -106,7 +106,9 @@ ESP32/**/*.a
|
||||
deploy/backup/archive/**
|
||||
!deploy/backup/archive/.gitkeep
|
||||
|
||||
# Локальная дев-обвязка Claude (дев-сервер shine-UI, сессии, планы) — не коммитим
|
||||
# Локальная дев-обвязка AI-агентов (сессии, планы, настройки) — не коммитим
|
||||
.agents/
|
||||
.codex/
|
||||
.claude/
|
||||
# Рабочие бэкапы/превью-ассеты UI — не для репозитория
|
||||
*.bak.png
|
||||
|
||||
@@ -55,7 +55,6 @@
|
||||
- `far/` - дальнее будущее без понятного срока.
|
||||
- Если пользователь спрашивает, какие есть планы или что можно продолжить, нужно смотреть эти три папки и отвечать кратким списком по горизонтам.
|
||||
- Файлы из `TODO/` не начинать реализовывать без явной команды пользователя.
|
||||
- После реализации фичи, требующей ручной проверки, нужно добавить отдельный файл в `docs/Pending_Features/`.
|
||||
|
||||
## Центр задач и предложений
|
||||
- Сервис хранит простые задачи и предложения в `data/task_center/items.json`.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
# Third-party notices
|
||||
|
||||
This file lists third-party components and assets used by SHiNE. It is a practical attribution file for repository publication; individual dependency artifacts may include additional license text in their own packages.
|
||||
|
||||
## Twemoji
|
||||
|
||||
SHiNE UI uses Twemoji graphics for emoji rendering in the chat emoji picker and emoji-only messages.
|
||||
|
||||
- Source: https://github.com/twitter/twemoji
|
||||
- Graphics license: Creative Commons Attribution 4.0 International (CC BY 4.0)
|
||||
- Code license: MIT
|
||||
- License text: https://creativecommons.org/licenses/by/4.0/
|
||||
|
||||
Attribution:
|
||||
|
||||
Emoji graphics by Twemoji, licensed under CC BY 4.0.
|
||||
|
||||
Changes in SHiNE:
|
||||
|
||||
- Emoji are stored and sent as normal Unicode text.
|
||||
- Twemoji SVG graphics are used only as a visual rendering layer in the web UI.
|
||||
- The UI loads Twemoji SVG assets from the pinned `twitter/twemoji@14.0.2` package via jsDelivr.
|
||||
|
||||
## QR Code Generator
|
||||
|
||||
SHiNE UI includes `shine-UI/js/vendor-qrcode-generator.js`.
|
||||
|
||||
- Project: QR Code Generator for JavaScript
|
||||
- Copyright: Kazuhiko Arase
|
||||
- License: MIT
|
||||
- Source: http://www.d-project.com/
|
||||
|
||||
## SHiNE project-owned visual assets
|
||||
|
||||
SHiNE logos, icons and generated visual assets in `shine-UI/assets/` and `shine-UI/img/` are project-owned assets, unless a specific file says otherwise.
|
||||
|
||||
## Solana JavaScript libraries
|
||||
|
||||
SHiNE UI and Solana tooling use Solana JavaScript libraries, including `@solana/web3.js`.
|
||||
|
||||
- Package: `@solana/web3.js`
|
||||
- License: MIT
|
||||
- Source: https://github.com/solana-foundation/solana-web3.js
|
||||
|
||||
Some Solana JavaScript dependency trees include additional packages under permissive licenses such as MIT, Apache-2.0, BSD, ISC, 0BSD and CC0-1.0.
|
||||
|
||||
Known stricter dependency:
|
||||
|
||||
- Package: `rpc-websockets`
|
||||
- License: LGPL-3.0-only
|
||||
- Used transitively through Solana JavaScript dependencies in `shine-solana/shine` and `SHiNE-browser-plugin-wallet`.
|
||||
|
||||
## Noble cryptography libraries
|
||||
|
||||
SHiNE browser wallet/vendor bundles include Noble cryptography code.
|
||||
|
||||
- Packages: `@noble/curves`, `@noble/hashes`
|
||||
- License: MIT
|
||||
- Source: https://github.com/paulmillr/noble-curves and https://github.com/paulmillr/noble-hashes
|
||||
|
||||
## Java server dependencies
|
||||
|
||||
The SHiNE Java server uses third-party dependencies from Maven Central, including:
|
||||
|
||||
- Eclipse Jetty (`org.eclipse.jetty:*`) - EPL-2.0 / Apache-2.0 family licensing
|
||||
- Bouncy Castle (`org.bouncycastle:bcprov-jdk18on`) - Bouncy Castle permissive license
|
||||
- Jackson (`com.fasterxml.jackson.core:jackson-databind`) - Apache-2.0
|
||||
- Logback (`ch.qos.logback:logback-classic`) - EPL-1.0 / LGPL-2.1
|
||||
- SLF4J (`org.slf4j:slf4j-api`) - MIT
|
||||
- SQLite JDBC (`org.xerial:sqlite-jdbc`) - Apache-2.0
|
||||
- Web Push Java library (`nl.martijndwars:web-push`) - Apache-2.0
|
||||
- JUnit (`org.junit:*`) - EPL-2.0
|
||||
|
||||
## Gradle Wrapper
|
||||
|
||||
The repository includes Gradle wrapper scripts.
|
||||
|
||||
- License: Apache License 2.0
|
||||
- Source: https://gradle.org/
|
||||
|
||||
## Espressif code snippets
|
||||
|
||||
The ESP32 prototype area includes Espressif audio codec helper files with SPDX/license headers.
|
||||
|
||||
- Files include `ESPRESSIF MIT License` and `SPDX-License-Identifier: Apache-2.0` notices.
|
||||
- Original copyright notices are preserved in the source files.
|
||||
@@ -1,64 +0,0 @@
|
||||
# ESP32 как аппаратный кошелёк (device-сессия)
|
||||
|
||||
## Суть фичи
|
||||
|
||||
ESP32 становится аппаратным HSM (hardware security module): хранит ключи, постоянно подключён к SHiNE-серверу как device-сессия, подтверждает операции нажатием на экране. Другие устройства (браузер, телефон) взаимодействуют с ESP32 через сервер — без прямого соединения.
|
||||
|
||||
## Два ключевых сценария
|
||||
|
||||
### Сценарий 1 — Создание делегированной сессии
|
||||
1. Браузер/телефон → сервер: «хочу делегированную сессию от имени пользователя X»
|
||||
2. Сервер → ESP32 (device-сессия): «запрос на одобрение»
|
||||
3. Пользователь нажимает «Да» на сенсорном экране ESP32
|
||||
4. ESP32 → сервер: одобрено → сервер создаёт делегированную сессию для браузера
|
||||
|
||||
### Сценарий 2 — Подпись транзакции / блока
|
||||
1. Браузер (через делегированную сессию) → сервер → ESP32: «подпиши вот это»
|
||||
2. ESP32 показывает запрос на экране, пользователь подтверждает
|
||||
3. ESP32 подписывает нужным ключом → ответ через сервер → браузер
|
||||
|
||||
## Что нужно сделать
|
||||
|
||||
### ESP32 (основная работа)
|
||||
- [ ] Инициализация WiFi (SSID/пароль в NVS)
|
||||
- [ ] WebSocket-клиент (`WebSocketsClient`) — постоянное соединение с сервером
|
||||
- [ ] Авторизация на сервере: `AuthChallenge` → `CreateAuthSession` через `clientKey` (уже есть в NVS), сохранить `sessionId` в NVS
|
||||
- [ ] Обработчик входящих WebSocket-событий: JSON-парсинг, диспетчер по типу
|
||||
- [ ] Новые UI-экраны: «Разрешить сессию?» и «Подписать?» с кнопками Да/Нет
|
||||
- [ ] Расширенное хранилище ключей в NVS (произвольные именованные ключи сверх базовых трёх)
|
||||
- [ ] Переподключение при разрыве (reconnect loop)
|
||||
|
||||
### Сервер (минимальные изменения)
|
||||
- [ ] Добавить поле `sessionType` (`USER` / `DEVICE`) в таблицу `active_sessions`
|
||||
- [ ] Новая операция `DeviceApprovalRequest` — браузер запрашивает одобрение у device-сессии
|
||||
- [ ] Новая операция `DeviceApprovalResponse` — ESP32 отвечает (одобрено/отклонено)
|
||||
- [ ] Новые операции `SignRequest` / `SignResponse` — запрос подписи и ответ
|
||||
- [ ] Роутинг: при получении запроса найти device-сессию через `ActiveConnectionsRegistry.getByLogin(login)` + фильтр по `sessionType=DEVICE`, переслать туда
|
||||
|
||||
### Клиент (отдельный этап)
|
||||
- [ ] Браузерное расширение или UI: создание делегированной сессии, отправка `SignRequest`
|
||||
|
||||
## Что уже готово (переиспользуем)
|
||||
|
||||
- **Роутинг сообщений** — `SendDirectMessage` с `TARGET_ONE_SESSION` и `CallSignalToSession` уже умеют точечно доставлять в конкретный `sessionId`. Механизм готов, нужно добавить только новые op-коды поверх него.
|
||||
- **Ed25519 на ESP32** — библиотека `<Ed25519.h>` уже используется в скетче. Подписи работают.
|
||||
- **NVS** — уже хранит логин, мастер-секрет, 3 пары ключей. Расширяется легко.
|
||||
- **`ActiveConnectionsRegistry`** — поиск по `login` и `sessionId` уже есть на сервере.
|
||||
- **Аутентификация** — схема `AuthChallenge` → `CreateAuthSession` через Ed25519 уже полностью реализована.
|
||||
|
||||
## Оценка сложности
|
||||
|
||||
| Компонент | Сложность |
|
||||
|---|---|
|
||||
| ESP32: WiFi + WebSocket-клиент + авторизация | Средняя |
|
||||
| ESP32: обработчик входящих + UI подтверждений | Средняя |
|
||||
| Сервер: флаг sessionType + 4 новых op-а + роутинг | Низкая–средняя |
|
||||
| Браузерное расширение | Высокая (отдельный этап) |
|
||||
|
||||
**Итого фазы ESP32 + сервер: ~1–1.5 недели.**
|
||||
|
||||
## С чего начинать
|
||||
|
||||
1. Серверная часть проще и быстрее — начать с добавления `sessionType` и `DeviceApprovalRequest/Response`.
|
||||
2. Затем ESP32: WiFi → WebSocket → авторизация → обработчик входящих → UI.
|
||||
3. Браузерное расширение — отдельная итерация после того как ESP32 + сервер работают.
|
||||
@@ -1,41 +0,0 @@
|
||||
# TODO: Будущие доработки
|
||||
|
||||
## 1) Полный переход на `ReceiveOutcomingMessage`
|
||||
- Сейчас в UI используется `ReceiveOutcomingMessage` с fallback на `SendMessagePair`.
|
||||
- Fallback нужен только временно для совместимости со старыми серверами.
|
||||
- После обновления всех серверов:
|
||||
- убрать вызов `SendMessagePair` из UI,
|
||||
- убрать регистрацию `SendMessagePair` на сервере (оставить только `ReceiveOutcomingMessage`).
|
||||
|
||||
## 2) Реальная мультисерверная доставка
|
||||
- Сейчас фактически предполагается 1 сервер на пользователя.
|
||||
- Нужно реализовать штатную мультисерверную схему:
|
||||
- пересылка исходящих сообщений между серверами пользователя A,
|
||||
- пересылка входящих сообщений между серверами пользователя B,
|
||||
- дедупликация на уровне БД для затухания дублей.
|
||||
|
||||
## 3) Надёжная доставка при перезапуске сервера
|
||||
- Сейчас возможен сценарий: запись уже сохранена в БД, но сервер не успел переслать дальше из-за перезапуска.
|
||||
- Нужно добавить механизм «store + guaranteed forward»:
|
||||
- очередь/аутбокс для межсерверной пересылки,
|
||||
- фоновый ретрай до подтверждения отправки,
|
||||
- корректная остановка (graceful shutdown) с дожатием критичных задач.
|
||||
|
||||
## 4) Политика идемпотентности
|
||||
- Сохранить принцип: пара (`incoming`, `outgoing`) пишется одной транзакцией, либо обе, либо ни одной.
|
||||
- Не допускать частичного состояния, при котором в БД есть только один блок пары.
|
||||
|
||||
## 5) Наблюдаемость и аналитика
|
||||
- Добавить метрики по доставке:
|
||||
- количество дублей,
|
||||
- количество успешных вставок пар,
|
||||
- доля доставок в WS/push,
|
||||
- количество ретраев межсерверной пересылки.
|
||||
|
||||
## 6) Ограничение текущих звонков (важно)
|
||||
- Сейчас звонки работают только в рамках одного сигнального сервера (или единого контура, где обе стороны уже подключены).
|
||||
- Сценарий «пользователь A на своих серверах, пользователь B на других серверах» пока не поддержан.
|
||||
- TODO на будущее:
|
||||
- временная межсерверная авторизация/сессия для старта звонка,
|
||||
- отправка сигнальных сообщений между разными серверами пользователей,
|
||||
- аккуратное завершение временной сессии после установления/завершения звонка.
|
||||
@@ -1,41 +0,0 @@
|
||||
# TODO: Звонки и межсерверность
|
||||
|
||||
## Текущее ограничение
|
||||
- Текущая реализация звонков фактически работает в одном сигнальном контуре (один сервер/единый кластер, где обе стороны уже присутствуют).
|
||||
- Если пользователь A подключён к серверу A, а пользователь B к серверу B (и между ними нет общего сигнального слоя), `CallInviteBroadcast`/`CallSignalToSession` не смогут полноценно провести звонок между ними.
|
||||
|
||||
## Почему так сейчас
|
||||
- Сигналинг звонка привязан к активным сессиям и событиям на конкретном сервере.
|
||||
- Выбор целевой сессии (`sessionId`) и обмен `OFFER/ANSWER/ICE` происходит в рамках текущего сигнального контура.
|
||||
- Push решает только «разбудить/уведомить», но не заменяет межсерверный сигнальный канал.
|
||||
|
||||
## Что можно сделать дальше
|
||||
- Добавить временное межсерверное подключение именно для старта и ведения звонка:
|
||||
- инициатор получает short-lived access на сервер callee (или через доверенный межсерверный gateway),
|
||||
- в рамках короткой сессии отправляет invite/signal для конкретного `callId`,
|
||||
- после завершения звонка временная сессия закрывается автоматически.
|
||||
|
||||
## Что нужно доработать для этого
|
||||
1. Межсерверная доверенная модель:
|
||||
- подпись/верификация межсерверных вызовов,
|
||||
- allowlist доверенных серверов и ротация ключей.
|
||||
|
||||
2. Короткоживущая «call-only» авторизация:
|
||||
- отдельный тип токена/сессии с TTL (например 1–3 минуты),
|
||||
- минимальные права только на `CallInviteBroadcast/CallSignalToSession`.
|
||||
|
||||
3. Маршрутизация сессий пользователя между серверами:
|
||||
- где находится активная сессия callee,
|
||||
- как доставлять `stop_call` и terminal-сигналы на все устройства callee.
|
||||
|
||||
4. Идемпотентность и дедупликация:
|
||||
- защита от повторов межсерверных сигналов по `callId + eventId`,
|
||||
- корректная обработка out-of-order событий.
|
||||
|
||||
5. Наблюдаемость:
|
||||
- метрики межсерверной доставки сигналов,
|
||||
- диагностика по стадиям звонка и причинам срыва.
|
||||
|
||||
## Временный рабочий подход (до межсерверности)
|
||||
- Держать звонки в одном сигнальном контуре.
|
||||
- Использовать WebPush как fallback-уведомление (`incoming_call`/`stop_call`) для офлайн-сессий.
|
||||
@@ -1,2 +1,2 @@
|
||||
client.version=1.2.331
|
||||
server.version=1.2.303
|
||||
client.version=1.2.332
|
||||
server.version=1.2.304
|
||||
|
||||
@@ -1,246 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITHUB_USER="ai5590"
|
||||
TOKEN_VAR_NAME="GIT_AI5590_CLASSIC_API_KEY"
|
||||
|
||||
print_line() {
|
||||
echo "------------------------------------------------------------"
|
||||
}
|
||||
|
||||
abort() {
|
||||
echo
|
||||
echo "Ошибка: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
command -v "$1" >/dev/null 2>&1 || abort "Не найдена команда '$1'. Установи её и запусти скрипт снова."
|
||||
}
|
||||
|
||||
get_token() {
|
||||
if [[ -z "${GIT_AI5590_CLASSIC_API_KEY:-}" ]]; then
|
||||
abort "Не задана переменная окружения ${TOKEN_VAR_NAME}.
|
||||
Перед запуском выполни:
|
||||
export ${TOKEN_VAR_NAME}=\"ТВОЙ_GITHUB_TOKEN\""
|
||||
fi
|
||||
}
|
||||
|
||||
show_intro() {
|
||||
print_line
|
||||
echo "Этот скрипт создаст новый репозиторий в GitHub в аккаунте '${GITHUB_USER}',"
|
||||
echo "затем инициализирует git в текущей папке (если нужно),"
|
||||
echo "добавит файлы, кроме самого этого скрипта, создаст первый commit и отправит проект в GitHub."
|
||||
echo
|
||||
echo "Скрипт работает с содержимым ТЕКУЩЕЙ папки:"
|
||||
echo " $(pwd)"
|
||||
echo
|
||||
echo "Для авторизации используется переменная окружения:"
|
||||
echo " ${TOKEN_VAR_NAME}"
|
||||
print_line
|
||||
echo
|
||||
}
|
||||
|
||||
ask_repo_name() {
|
||||
local repo_name
|
||||
read -r -p "Введите имя нового репозитория в GitHub: " repo_name
|
||||
repo_name="$(echo "$repo_name" | xargs)"
|
||||
|
||||
[[ -n "$repo_name" ]] || abort "Имя репозитория не может быть пустым."
|
||||
|
||||
if [[ ! "$repo_name" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
||||
abort "Имя репозитория содержит недопустимые символы.
|
||||
Разрешены: буквы, цифры, точка, дефис, подчёркивание."
|
||||
fi
|
||||
|
||||
REPO_NAME="$repo_name"
|
||||
}
|
||||
|
||||
ask_visibility() {
|
||||
local answer
|
||||
echo
|
||||
read -r -p "Сделать репозиторий публичным? [y/N]: " answer
|
||||
answer="${answer:-N}"
|
||||
|
||||
case "$answer" in
|
||||
y|Y|yes|YES|да|Да|ДА)
|
||||
REPO_PRIVATE="false"
|
||||
REPO_VISIBILITY_TEXT="public"
|
||||
;;
|
||||
*)
|
||||
REPO_PRIVATE="true"
|
||||
REPO_VISIBILITY_TEXT="private"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
ask_confirmation() {
|
||||
echo
|
||||
print_line
|
||||
echo "Будет выполнено:"
|
||||
echo "1. Создание GitHub-репозитория '${GITHUB_USER}/${REPO_NAME}' (${REPO_VISIBILITY_TEXT})"
|
||||
echo "2. Подготовка git в текущей папке"
|
||||
echo "3. Commit файлов из текущей папки, кроме самого этого скрипта"
|
||||
echo "4. Push в ветку main"
|
||||
print_line
|
||||
echo
|
||||
read -r -p "Продолжить? [y/N]: " confirm
|
||||
confirm="${confirm:-N}"
|
||||
|
||||
case "$confirm" in
|
||||
y|Y|yes|YES|да|Да|ДА) ;;
|
||||
*) echo "Отменено пользователем."; exit 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
check_not_inside_wrong_git_repo() {
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
local top
|
||||
top="$(git rev-parse --show-toplevel)"
|
||||
if [[ "$top" != "$(pwd)" ]]; then
|
||||
abort "Ты запустил скрипт внутри уже существующего git-репозитория, но не в его корне.
|
||||
Корень репозитория:
|
||||
$top
|
||||
|
||||
Либо перейди в корень этого репозитория, либо запусти скрипт в папке, которая не вложена в другой git-репозиторий."
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
create_github_repo() {
|
||||
echo
|
||||
echo "Создаю репозиторий в GitHub..."
|
||||
|
||||
local http_code
|
||||
local response_body_file
|
||||
|
||||
response_body_file="$(mktemp)"
|
||||
|
||||
http_code="$(
|
||||
curl -sS \
|
||||
-o "$response_body_file" \
|
||||
-w "%{http_code}" \
|
||||
-X POST "https://api.github.com/user/repos" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer ${GIT_AI5590_CLASSIC_API_KEY}" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
-d "$(cat <<JSON
|
||||
{
|
||||
"name": "${REPO_NAME}",
|
||||
"private": ${REPO_PRIVATE},
|
||||
"auto_init": false
|
||||
}
|
||||
JSON
|
||||
)"
|
||||
)"
|
||||
|
||||
if [[ "$http_code" != "201" ]]; then
|
||||
echo
|
||||
echo "GitHub API вернул ошибку. HTTP code: $http_code"
|
||||
echo "Ответ сервера:"
|
||||
cat "$response_body_file"
|
||||
rm -f "$response_body_file"
|
||||
abort "Не удалось создать репозиторий '${GITHUB_USER}/${REPO_NAME}'."
|
||||
fi
|
||||
|
||||
rm -f "$response_body_file"
|
||||
echo "Репозиторий успешно создан: https://github.com/${GITHUB_USER}/${REPO_NAME}"
|
||||
}
|
||||
|
||||
get_script_paths() {
|
||||
SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")"
|
||||
PROJECT_PATH="$(pwd -P)"
|
||||
|
||||
SCRIPT_INSIDE_PROJECT="false"
|
||||
SCRIPT_RELATIVE_PATH=""
|
||||
|
||||
case "$SCRIPT_PATH" in
|
||||
"$PROJECT_PATH"/*)
|
||||
SCRIPT_INSIDE_PROJECT="true"
|
||||
SCRIPT_RELATIVE_PATH="${SCRIPT_PATH#$PROJECT_PATH/}"
|
||||
;;
|
||||
*)
|
||||
SCRIPT_INSIDE_PROJECT="false"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
prepare_git_repo() {
|
||||
echo
|
||||
echo "Подготавливаю git в текущей папке..."
|
||||
|
||||
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
echo "Git уже инициализирован."
|
||||
else
|
||||
git init
|
||||
echo "Git инициализирован."
|
||||
fi
|
||||
|
||||
get_script_paths
|
||||
|
||||
if [[ "$SCRIPT_INSIDE_PROJECT" == "true" ]]; then
|
||||
echo "Скрипт находится внутри проекта и будет исключён из commit:"
|
||||
echo " $SCRIPT_RELATIVE_PATH"
|
||||
git add . ":!$SCRIPT_RELATIVE_PATH"
|
||||
else
|
||||
git add .
|
||||
fi
|
||||
|
||||
if git diff --cached --quiet; then
|
||||
echo "В staged нет изменений. Возможно, файлы уже были закоммичены ранее."
|
||||
else
|
||||
git commit -m "Initial commit"
|
||||
echo "Создан commit: Initial commit"
|
||||
fi
|
||||
|
||||
git branch -M main
|
||||
|
||||
local remote_url="https://${GITHUB_USER}:${GIT_AI5590_CLASSIC_API_KEY}@github.com/${GITHUB_USER}/${REPO_NAME}.git"
|
||||
|
||||
if git remote get-url origin >/dev/null 2>&1; then
|
||||
echo "Remote 'origin' уже существует. Обновляю URL..."
|
||||
git remote set-url origin "$remote_url"
|
||||
else
|
||||
git remote add origin "$remote_url"
|
||||
fi
|
||||
}
|
||||
|
||||
push_to_github() {
|
||||
echo
|
||||
echo "Отправляю проект в GitHub..."
|
||||
|
||||
git push -u origin main
|
||||
|
||||
echo
|
||||
echo "Готово."
|
||||
echo "Репозиторий: https://github.com/${GITHUB_USER}/${REPO_NAME}"
|
||||
}
|
||||
|
||||
cleanup_remote_url() {
|
||||
echo
|
||||
echo "Убираю токен из remote URL, чтобы он не светился в git config..."
|
||||
|
||||
local safe_url="https://github.com/${GITHUB_USER}/${REPO_NAME}.git"
|
||||
git remote set-url origin "$safe_url"
|
||||
|
||||
echo "Теперь origin = ${safe_url}"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_command git
|
||||
require_command curl
|
||||
require_command realpath
|
||||
get_token
|
||||
check_not_inside_wrong_git_repo
|
||||
show_intro
|
||||
ask_repo_name
|
||||
ask_visibility
|
||||
ask_confirmation
|
||||
create_github_repo
|
||||
prepare_git_repo
|
||||
push_to_github
|
||||
cleanup_remote_url
|
||||
}
|
||||
|
||||
main "$@"
|
||||
@@ -1,17 +0,0 @@
|
||||
# SHiNE TURN Server
|
||||
|
||||
This directory stores TURN setup scripts and operational instructions.
|
||||
|
||||
## Purpose
|
||||
- Install and configure coturn for SHiNE calls.
|
||||
- Keep repeatable setup scripts for new TURN nodes.
|
||||
- Keep TURN-related config templates.
|
||||
|
||||
## Current production model
|
||||
- Multiple TURN servers are supported by backend config section:
|
||||
- `call.ice.turn.servers.1.*`
|
||||
- `call.ice.turn.servers.2.*`
|
||||
- ...
|
||||
- Each server can use:
|
||||
- REST auth (`sharedSecret`) for temporary credentials, or
|
||||
- static `username`/`password` (fallback).
|
||||
@@ -1,9 +0,0 @@
|
||||
# Third-party notices
|
||||
|
||||
## Telegram Animated Emojis
|
||||
|
||||
Animated emoji previews in SHiNE use the public catalog from Tarikul-Islam-Anik.
|
||||
|
||||
Source: https://github.com/Tarikul-Islam-Anik/Telegram-Animated-Emojis
|
||||
|
||||
The repository README states that the media files are sourced from Emojipedia and that rights to the Telegram media belong to Telegram.org. Review those rights before public distribution.
|
||||
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 8.4 KiB |
|
Before Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 8.5 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 11 KiB |