Приёмы разработки плагинов Dune HD: сеть, данные, фон и веб¶
Часть каталога о сети, хранении и фоновой работе: HTTP-клиент и разбор ответов, настройки и DATA, фоновые процессы и системные действия, CGI и внешние приложения. Это разделы 9, 10, 13 и 15 общего каталога; их нумерация сохранена.
9. Сеть и HTTP¶
Объект: HTTP-клиенты, авторизация, разбор ответов и обход блокировок в PHP-плагинах (GlobalTV, Twitch TV,
ProIPTV, altIPTV, Smart_, youtube_api/folder_cache, YouTube (Smart_), zlostnyi, MegaAnime, MegaRadio, RemTor и
др.), в Android-приложении Jellyfin Bridge и во внешнем клиенте watch-sync; уровень code (отдельные строки —
forum). Платформа и прошивка исполнения у большинства плагинов не установлены; факты о прошивке — tv188b r24
(code) и r25 (device).
Почти каждый сетевой плагин несёт свою копию HD::http_get_document поверх расширения curl PHP, и копии
расходятся в тайм-аутах, User-Agent и реакции на ошибку. Встроенный в прошивку r24 метод по умолчанию отключает
проверку TLS-сертификата, следует редиректам и применяет опции вызывающего поверх своих
(код r24)1, а при ошибке curl или любом HTTP-коде, кроме 200, бросает
DuneCurlException (код r24)2. На r25 (device) curl в PHP — 7.67.0 с
OpenSSL 1.0.1u (устройство r25)3, и части констант (CURLOPT_ACCEPT_ENCODING, CURLOPT_RESOLVE,
CURL_SSLVERSION_TLSv1_2 и др.) в нём нет (устройство r25)4; остальные сетевые грабли платформы
(падение curl_multi к httpd самого плеера, CA-бандл, HTTP_HOST) — guide/pitfalls.md, «Сеть».
Ошибки на экране — §17, хранение логинов и токенов — §10, локальный HTTP-API прошивки — §15 и
guide/ip-control.md.
9.1. HTTP-клиент: своя копия HD::http_get_document и её варианты¶
Общий приём — один хелпер на curl для всех запросов плагина, с POST-обёрткой поверх него. Различаются три вещи: тайм-ауты, проверка TLS и то, что хелпер делает при ошибке, — от этого зависит, упадёт ли вся операция плагина.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Сделать GET с тайм-аутами и редиректами | HD::http_get_document на curl; тайм-ауты 10 с (Twitch TV, Apple Trailers, Anidub.Com, pirates_), 11/10 с (Widget Ext), 25 с (altIPTV, plugtv, zlostnyi), 30/60 с (GlobalTV), 30 с с gzip и User-Agent Chrome/80 (Bazinga3), 40 с (Smart_, Online Movies rus, копии zlostnyi) |
у GlobalTV, Twitch TV, Widget Ext, altIPTV, plugtv, zlostnyi, Smart_*, Online Movies (rus), Torrent Center, ProIPTV и Bazinga3 проверка TLS отключена (CURLOPT_SSL_VERIFYPEER, у части и VERIFYHOST) — так же, как в хелпере прошивки r24 |
GlobalTV (код)5; Twitch TV (код)6; Apple Trailers (код)7; Anidub.Com (код)8; pirates_* (код)9; Widget Ext (код)10; altIPTV (код)11; plugtv (код)12; zlostnyi (код)13; Smart_* (код)14; Online Movies (rus) (код)15; Torrent Center (код)16; ProIPTV (код)17; Bazinga3 (код)18 |
| Дать вызывающему переопределить опции curl | переданные opts применяются после стандартных curl_setopt |
стандартные тайм-ауты и TLS-флаги можно случайно заменить | Widget Ext (код)19; Twitch TV (код)6; altIPTV (код)11; Smart_* (код)14 |
| POST и JSON-RPC | http_post_document = http_get_document + CURLOPT_POST/CURLOPT_POSTFIELDS; make_json_rpc_request строит jsonrpc = 2.0 с id из статического счётчика |
Polbox.tv: service_api_call → fetch_document(get_post_data()) — POST-JSON с CURLOPT_SSL_VERIFYPEER=0 и CURLOPT_SSL_VERIFYHOST=0 |
Widget Ext (код)20; Anidub.Com (код)21; Polbox.tv (код)22 |
| Реакция на ошибку | исключение при ошибке curl или коде ≠ 200 (Twitch TV, Apple Trailers, pirates_*, Widget Ext); DuneCurlException при коде вне 200/201 (GlobalTV); пустая строка вместо исключения (Anidub.Com); null на 404 и исключение на прочие (DunePlexCatalog); только запись в лог и возврат тела — throw закомментированы (altIPTV) |
при исключении операция плагина обрывается, при пустой строке вызывающий должен сам проверять результат | Twitch TV (код)6; Apple Trailers (код)7; pirates_* (код)9; Widget Ext (код)10; GlobalTV (код)23; Anidub.Com (код)8; DunePlexCatalog (код)24; altIPTV (код)25 |
| Сообщить сетевому монитору прошивки об ошибке | при ошибке curl и наличии сетевого монитора атомарно записать 1 в /tmp/run/network_monitor/force_check_on_error |
— | GlobalTV (код)26 |
| Проверить ключ доступа одним запросом | HD::check_token: curl, при ошибке или коде ≠ 200 строка nottoken, иначе тело |
возвращается строка, а не null — см. §19 |
zlostnyi (код)27 |
| Быстро проверить доступность сервера | HD::isDomainAvailible: HEAD (CURLOPT_NOBODY) с CONNECTTIMEOUT 10 с; для URL на /echo — вернуть тело |
— | MegaTorrents (код)28 |
| Обойтись без curl | file_get_contents($url) + json_decode; при FALSE — DuneException с фатальным show_error |
ошибка закрывает плагин | AceStreamSearch (код)29 |
| Качать из shell-скрипта | wget по http (OpenWeatherMap, Яндекс, rp5), curl -s --location -k по https (Gismeteo) |
у каждого сервиса свой разбор ответа | Widget Ext (код)30 |
| Взять curl под платформу в shell | выбор бинарника по platform_kind из $FS_PREFIX/tmp/run/versions.txt: android → $FS_PREFIX/firmware/bin/curl, коды 87../864./867./865. → свои сборки, иначе CURL пуст |
вложенные curl — 7.19.5 (mipsel) и 7.36.0 (ARM); curl.864x побайтно совпадает с shell_ext/bin/curl прошивки tv188b r24 |
Widget Ext (код)31 |
| Проверить, жив ли URL | перед проверкой URL отрезать суффиксы \|Referer… и \|Cookie…, затем запрос с Range: bytes=0-10000 и тайм-аутом 1 с; при ошибке источник отбрасывается |
— | Online Movies (eng) (код)32 |
Загрузить .torrent в TorrServer |
multipart file=@<путь> на /torrent/upload, hash — из JSON ответа при его наличии; ссылка — JSON action=add с link и save_to_db (сбрасывается при dontSave) |
— | Torrent Center (код)33 |
| Создать плейлист в аккаунте YouTube | POST /playlists?part=snippet,status с описанием «Created on Dune HD! Enjoy!» и privacyStatus private, затем добавить видео POST /playlistItems?part=snippet через http_get_api_v3 |
— | YouTube (Smart_*) (код)34 |
| Сходить в сеть из отдельного процесса | run.php вызывает curl с тайм-аутом 40 с и User-Agent Firefox 7.0.1 |
— | Dune HD TV (код)35 |
9.2. User-Agent и сведения об устройстве в запросе¶
User-Agent в копиях хелпера разный: от честного DuneHD/1.0 до браузерных и мобильных строк, которые сервис
принимает за своего клиента.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Назвать себя Dune с моделью и прошивкой | DuneHD/1.0 + строки product_id и firmware_version из /tmp/sysinfo.txt |
— | GlobalTV (код)36; ProIPTV (ещё и подпись плагина app_caption + app_version) (код)17 |
Просто DuneHD/1.0 |
постоянная строка в хелпере | — | Twitch TV (код)6; Apple Trailers (код)7; DunePlexCatalog (код)24 |
| Представиться браузером | Firefox 7.0.1 (pirates_*, Online Movies rus), Firefox 7 (Anidub.Com), Firefox/53 (Widget Ext), Firefox 25 + DuneHD/1.0 (plugtv), Opera Mobi (zlostnyi) |
— | pirates_* (код)9; Online Movies (rus) (код)15; Anidub.Com (код)8; Widget Ext (код)10; plugtv (код)12; zlostnyi (код)37 |
| Притвориться TV-клиентом YouTube | POST JSON-контекста TV-клиента с заголовками Origin/Referer youtube.com/tv |
зависит от разметки youtube.com/tv |
YouTube (Smart_*) (код)38 |
| UA для веб-приложения | параметр манифеста user_agent=DUNE (bonus-tv) или user_agent=dune (xsmart) |
регистр у пакетов разный | веб-плагины (код)39 |
9.3. Авторизация, токены и сессии¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Авторизоваться системной строкой устройства | содержимое /tmp/dune_auth.txt дописывается в query как есть |
— | GlobalTV (код)40 |
| Сменить учётку из настроек | сохранить логин и пароль, сбросить сессию, try_login; DuneException → post_action |
— | Юрта ТВ (код)41 |
| Разделить фатальные и обычные ошибки API | код 12 с текстом Authentification error, коды 17 и 5 → unset_login; остальные показываются с кодом и сообщением (в playback — только сообщением) |
— | Moi-Dom.tv (код)42 |
| Показать ошибки доступа сервиса | коды сервера 201–204 → «нет доступа», «пробный период окончен», «пробный период недоступен» (с кнопкой оплаты), «сервис недоступен» | — | GlobalTV (код)43 |
| Войти в аккаунт с пульта (OAuth device flow) | POST на .../oauth2/device/code → диалог с адресом активации и кодом → опрос .../oauth2/token по timer(5000), пока в ответе error |
перед диалогом обработчик ждёт interval секунд через sleep |
YouTube (Smart_*) (код)44; по сообщениям пользователей, код вводится в браузере компьютера (форум)45 |
| Обновить токен | на error.code 401 при наличии access_token — grant_type=refresh_token |
— | YouTube (Smart_*) (код)46 |
| Несколько аккаунтов | токены основного аккаунта в tokens, дополнительных — в user_plus_tokens[<имя>] |
— | YouTube (Smart_*) (код)47 |
| Протокол с session id в заголовке (Transmission RPC) | GetSessionID: GET, ожидание 409, чтение X-Transmission-Session-Id; запросы — POST JSON {method, arguments} с этим заголовком и Basic auth |
401 → E_AUTHENTICATION, 409 → E_SESSIONID; тайм-аут 10 с |
RemTor (код)48 |
| Ключи и токены API | зашиты в код (client_id Twitch, токены bazon/HDVB/Kodik, ключ Last.fm) |
— | Twitch TV (код)49; Smart_* (link_api) (код)50; MegaRadio (код)51 |
| Не логиниться повторно | если существует cookie-файл tmp_dir_path/filmix_cooki, вход считается выполненным; иначе POST login_name/login_password с заголовком x-a-key=sinatra и этим cookie-файлом |
ошибкой считается наличие form action= в ответе |
Smart_* (Filmix) (код)52 |
| Войти по коду из SMS | api_login: POST v2/auth/otp с phone (ведущая 8 заменяется на 7) и паролем из SMS, access_token — из ответа; эндпоинты сессии — v2/otps, v2/auth/otp, v2/auth/login, v2/auth/device, v2/users/self/... |
— | Dune HD TV (код)53 |
| Привязать устройство к аккаунту | POST v2/users/self/devices с vendor DUNE, моделью, версией плагина, device_type stb, серийным номером из первой строки /fconfig/dune_license.dlf (третье поле, без дефисов) и application_type dune; device_id хранится в plugin_cookies, без него используется серийный номер |
ответ 400 «Too many devices.» открывает экран списка устройств | Dune HD TV (код)54 |
| Поднять сессию по устройству | при заданном device_id POST v2/auth/device, затем v2/users/self (id, phone, username, parental_code, provider) |
— | Dune HD TV (код)55 |
| Разделить коды ответа API | api_call: JSON декодируется; коды 200, 400, 401, 403, 404 возвращаются вызывающему как данные, остальные — исключение с диалогом «Ошибка взаимодействия с сервером.» при наличии error.message |
400/401/403/404 вызывающий разбирает сам | Dune HD TV (код)56 |
| Активировать устройство по коду | при заданном selected_media_url: token_request с user_dev_* и пустым user_dev_token → адрес https://filmix.tech/console и user_code; do_slogin_action сохраняет token_request в DuneSystem::$properties["user_dev_token"] и HD::save_items('tokens'), затем запрашивает /user_profile, успех — наличие user_data |
по сообщениям пользователей, без регистрации доступно только 480p, для 720p нужна регистрация, выше — Pro-аккаунт | Smart_* (Filmix_API) (код)57; по сообщениям пользователей (форум)58 |
| Узнать версию Transmission RPC | конструктор TransmissionRPC сразу вызывает sget() и сохраняет rpc_version; get_rpc_version делает пустой запрос и возвращает версию созданного клиента |
sget() уже выполнен в конструкторе |
RemTor (код)59 |
| Переключить альтернативную скорость | use_alt_speed читает general_info['alt-speed-enabled'] из сохранённого ответа, сравнивает со строкой 'true' и вызывает sset с противоположным значением |
результат get_session_stats игнорируется; сравнение со строкой 'true' |
RemTor (код)60 |
9.4. Разбор ответов: HTML без DOM, JSON в странице, XML, большие числа¶
Плагины разбирают сайты строковыми операциями, а не DOM-парсером; такие разборы привязаны к вёрстке конкретного сайта.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Разобрать HTML-страницу | strstr/explode по текстовым маркерам блоков (newstitle, dle-content, <div class="item">, div#menu и т. п.) |
в youtube_api/folder_cache 12 уникальных версий cursor.php на 15 пакетов; у karas — 20 decoder-файлов под сайты |
Anidub.Com (код)61; youtube_api/folder_cache (код)62; MegaAnime (код)63 |
| Достать JSON из JS на странице | регулярка di.app.start\((.*})\); + json_decode |
у 101.ru результат json_decode не проверяется |
101.ru (код)64; MegaRadio (код)65 |
| Пройти страницы каталога | /page/<n>/ к URL раздела; поиск — один POST |
поиск возвращает только первую страницу | Anidub.Com (код)66 |
| Добраться до плеера через iframe | GET страницы → <iframe src> → повторный GET |
— | Smart_* (link_api) (код)67 |
| Разобрать iframe-резолверы link_api | tortuga: разбор file:'...' JSON с title/folder/file, кэш cacheLinkApiTR; videoframe: frameindex.php?kp=<id> → data-token и type → POST /loadvideo → HLS; kinoDom: переводы по data-link и pl:"...", сезоны и серии из JSON playlist, playbackUrl через sUtils::parseModStr |
у tortuga playbackUrl в ранней ветке (URL уже в static $sArr) заменяет https на http, после разбора страницы — нет; getTortugaIframe — заглушка; kinoDom использует прокси при Kinodom_Class::$proxy |
Smart_* (link_api) (код)68 |
| Выбрать декодер хостинга по ссылке | цепочка проверок подстроки в URL, иначе URL как есть; для файлообменника — скрытые поля формы, sleep 5–12 с, POST, регулярка file: "…" |
порядок проверок важен; задержка зашита в код | youtube_api/folder_cache (код)69 |
| Разобрать XML/plist | HD::parse_xml_document/simplexml_load_string, пары key/value; при неудаче — регулярка по HTML (Apple Trailers) |
ожидаемый корневой узел проверяется: при несовпадении — исключение (DunePlexCatalog) | Apple Trailers (код)70; Moi-Dom.tv (код)71; DunePlexCatalog (код)72 |
| Сохранить большие числа JSON | до json_decode переписать числа в строки регуляркой |
RemTor превращает в строки все целые; так же делает клиент TorrServer прошивки r25 для чисел от 10 цифр (API_OPT_LONG_INT_AS_STRING) |
Torrent Center (код)73; RemTor (код)74; прошивка r25 (код r25)75 |
| Подсказки поиска Google/YouTube | suggestqueries.google.com/complete/search (client=toolbar, ds=yt), разбор по <suggestion data=" |
ответ — не JSON | Widget Ext (код)76 |
| Очистить названия от «опасных» символов | HD::get_repl_mips_bug: перечисленные emoji, обратный слэш и полноширинные ASCII → *, прочие символы вне \pL\pN\pP\pS\pZ → пробел |
исходные названия искажаются | altSource (код)77 |
9.5. Блокировки, прокси, зеркала и сервисы-посредники¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Прокси по выбору сайтов | настройки proxy, proxy_akk, curlopt_proxytype (HTTP/SOCKS5) и site_proxytype; хелпер ставит CURLOPT_PROXY только для URL, подходящих под режим |
у MegaAnime в режиме 2 исключены ссылки link_api, iframe, m3u8 и адреса торрент-клиентов; у Vimeo — googleapis/zona/myshows | MegaAnime (код)78; Smart_* (код)79 |
| Прокси для одного запроса | содержимое <data_dir>/tvdb_proxy.txt → HTTP_PROXY перед get_episodes |
— | Online Movies (eng) (код)80 |
| Пустить аудиопоток через прокси | URL http://127.0.0.1/cgi-bin/plugins/MegaRadio/proxy?<поток> → CGI с http_proxy и wget -O- |
адрес прокси зашит в CGI | MegaRadio (код)81 |
| Сайт через анонимайзер | префикс CGI-прокси anonymouse.org в базовом URL |
префикс зашит во все основные URL | youtube_api/folder_cache (код)82 |
| Зеркало сайта | сохранённый domen с адресом по умолчанию; адрес из Location ответа; адрес от удалённого hdrezka_mirror.php |
без Location остаётся адрес по умолчанию |
Smart_* (код)83 |
| Сменить домен поставщика настройкой | домен по умолчанию — константа в коде (Filmix — https://filmix.ac, Rezka — https://rezka.ag, Rutracker — https://rutracker.org, Kinozal — http://kinozal.tv), переопределяется настройкой <cName>DomainName |
— | Bazinga3 (код)84 |
| Выбрать домены по региону | у подсемейства endpoints.json (antifriz, cbilling, glanz) конструктор вызывает loadEndpointsConfig() и скачивает http://zlostnyi.tech/dune/<каталог>/endpoints.json, заполняя домены api и playlist для world, ru, kz; antifriz показывает combobox «Выбор региона» (по умолчанию world) |
при каждом создании плагина — сетевой запрос | zlostnyi (код)85 |
| Подставить ключ и номер устройства в шаблон плейлиста | шаблон на сервере автора (dune/<каталог>/playlist…), в шаблонах встречаются замены -token-, -pass-, --dev-- (cookie dev, по умолчанию 1), -srv- (cookie country_server), -ott_key-; shara-club при nottoken или пустом ответе повторяет запрос к playlist_2 |
зависимость от сервера автора; у shara-club при ошибке — два запроса | zlostnyi (код)86 |
| Настроить прокси для CGI | proxy_settings читает www/cgi-bin/proxy, разбирает http_proxy, затем безусловно перезаписывает логин/пароль строкой «Login:Password»; do_proxy_action перезаписывает http_proxy, proxy_search парсит free-proxy.cz и проверяет прокси запросом к shoutcast.com |
проверка зависит от внешнего сайта | MegaRadio (код)87 |
| Сменить адрес сервиса без пересборки | читать URL сначала из /config/ktv_stats_url.txt, затем из /firmware/config/... |
— | Polbox.tv (код)88 |
| Анти-бот cookie | взять toNumbers("...") со страницы, посчитать значение на dune-club.info/tts2, кэшировать в /tmp/zonaRCPC |
зависит от внешнего сервиса | Smart_* (link_api) (код)89 |
| Подпись ссылок YouTube | запрос dune-club.info/echo?message=<s> (старые пакеты) или переименование sig= в signature= |
внешний сервис или устаревший формат | youtube_api/folder_cache (код)90; Anidub.Com (код)91 |
| Картинки через конвертер | dune-club.info/.../gif2jpg.php?url=… |
внешний сервис | 101.ru (код)92 |
| Определить страну | country_code_3 из $FS_PREFIX/tmp/location_info.properties, при пустом — https://ifconfig.co/json |
понимает только RU/UA/BY | FREE TV (код)93 |
9.6. Локальная сеть: IP Control, сетевые папки, multicast¶
Вызов IP Control из CGI плагина и из Android-приложения — §15.5.
Плагины и внешние программы обращаются к HTTP-API самой приставки (/cgi-bin/do) и к файлам сетевого менеджера.
Команды IP Control — guide/ip-control.md; здесь — как ими пользуются.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Нажать кнопку пульта из плагина | GET http://<ip>/cgi-bin/do?cmd=ir_code&ir_code=… (IP из ifconfig у Screenshoter, 127.0.0.1 у Dune BackUp) |
Screenshoter ответ игнорирует; у Dune BackUp на APK — порт 11080 | Screenshoter (код)94; Dune BackUp (код)95 |
| Читать состояние плеера снаружи | cmd=status (с result_syntax=json или разбором name="…" value="…") |
Jellyfin Bridge: ответ ≤ 65 536 символов, тайм-ауты 2 с | Jellyfin Bridge (код)96; watch-sync (код)97 |
| Перемотать на позицию | cmd=set_playback_state&position=<сек>&timeout=1; успех — command_status ok или timeout |
— | Jellyfin Bridge (код)98 |
| Выключить по таймеру | строка cron с wget …/cgi-bin/do?cmd=standby |
сброс таймеров переписывает весь crontab | служебные установщики hdtv (код)99 |
| Смонтировать сохранённую сетевую папку | найти готовое монтирование в network_mount_list.xml, иначе файл-команда mount в /tmp/run/ipc__network_manager и чтение результата |
ожидание: sleep(1) у altSource; у Dune BackUp — до 5 повторов с паузой 2 с |
Dune BackUp (код)100; altSource (код)101 |
| Список сохранённых сетевых папок | разбор network_folders.properties (type 0 — smb, 1 — nfs) |
— | Dune BackUp (код)102; altSource (код)103; Torrent Center (код)104; remote-control (код)105 |
| Обзор SMB без своей библиотеки | proc_open прошивочного smbtree с LD_LIBRARY_PATH=/tango/firmware/lib |
нужен бинарник прошивки | remote-control (код)106 |
| Обойти проверку SMB-каталога | test -d вместо is_dir для платформ 8672, 8673 и 8758; при is_smb — opendir/closedir |
— | Torrent Center (код)107 |
| Хранить пароли сетевых папок | HD::eney: base64 со сдвигом по зашитому ключу |
ключ в коде — это обфускация | altSource (код)108 |
| Объявить себя Plex-клиентом | UDP HELLO * HTTP/1.0 на 239.0.0.250:32413 |
— | DunePlexCatalog (код)109 |
| Выбрать интерфейс для UPnP | wlan0, если скрипт Wi-Fi AP check успешен, иначе eth0 |
— | DLNA Renderer (код)110 |
| Отличить плееры в сети | по сообщениям пользователей, надёжный признак — netbios name из etc/samba/smb.conf |
— | watch-sync (форум r22)111 |
9.7. Свой HTTP-эндпойнт плагина: локальные запросы и обратный прокси¶
Когда в плагин шлёт данные другое приложение на той же приставке, CGI плагина работает как маленький сервер. Веб-часть и CGI в целом — §15.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Принимать POST только с самой приставки | список адресов REMOTE_ADDR (127.0.0.1, ::1, ::ffff:127.0.0.1 в разных записях), иначе 403 local_requests_only |
GET до проверки отдаёт сведения о плагине | Lampa bridge (код)112 |
| Ограничить вход | тело ≤ 262144 байт; 1–250 элементов; позиция 0–604800 с; длины строк в байтах UTF-8; URL только http/https до 16384 байт; управляющие символы C0, кроме TAB/LF/CR, вырезаются | — | Lampa bridge (код)113 |
| Ответ JSON без кэша, ошибки машиночитаемо | Content-Type: application/json; charset=utf-8, Cache-Control: no-store; при исключении 400 и {error: …} |
— | Lampa bridge (код)114 |
| Handshake с клиентом | GET отдаёт plugin, version, protocol |
версия протокола своя | Lampa bridge (код)115 |
| Обойти CORS веб-приложения | CGI пересылает GET/POST на внешний API через curl с cookie-jar и ставит Access-Control-Allow-Origin: * |
TLS-проверка выключена; отладочный лог пишется в /D/ |
веб-плагины (код)116 |
| Запускать плагин по IP-доступу без включения ТВ | страница http://<ip>/cgi-bin/plugins/<name>/do; по сообщениям пользователей, через неё стримы SomaFM и Radiopotok.ru играют без включения ТВ |
— | surface_* (форум)117 |
9.8. Сетевые URL-обёртки для плеера¶
Часть сетевой работы плагины перекладывают на плеер, заворачивая URL в префиксы. Что эти префиксы значат для воспроизведения — §7.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| RTMP/RTSP/HDS/FLV через локальный CGI | http://ts://127.0.0.1:81/cgi-bin/<proto>.sh?…; прочий http:// → http://ts:// |
https-варианты не меняются; CGI-скрипты даёт кодекпак — install-скрипт EvolutionTV скачивает его и запускает httpd на порту 81 |
EvolutionTV (код)118; youtube_api/folder_cache (код)119 |
| Multicast через UDP-прокси | udp://@ → http://ts://<proxy_ip>:<proxy_port>/udp/ при use_proxy=yes |
нужен внешний UDP-прокси | EvolutionTV (код)120 |
| Прямой mp4 | префикс http://mp4://; Online Movies (eng) добавляет через dune_params параметр http_mp4_allow_other_formats:1, а .m3u8 не трогает |
— | youtube_api/folder_cache (код)119; Online Movies (eng) (код)121 |
| Аудиопоток радио | http://audio_stream:// + host + :8000 + path |
— | 101.ru (код)122 |
10. Настройки, хранение и кэш¶
Объект: экраны настроек, хранение настроек и данных, кэш в PHP-плагинах Dune HD (Widget Ext 1.5.6, GlobalTV
260130_1351, Screenshoter 1.0.6, ProIPTV 9.1, семейства Smart_, surface_, zlostnyi, youtube_api/folder_cache и
другие; code, отдельные факты — forum); платформа и прошивка исполнения в основном не установлены. Опора на
платформу — SDK плагинов (doc, any-documented).
Платформа даёт плагину два механизма хранения. Первый — cookies: каждый метод DunePlugin получает
&$plugin_cookies по ссылке (SDK)123, а результат операции несёт поле plugin_cookies
(SDK)124. Второй — каталоги из DuneSystem::$properties: tmp_dir_path и data_dir_path
(SDK)125. tmp_dir_path лежит под /tmp, и Dune GUI гарантирует его существование
(SDK)126; data_dir_path для постоянных данных на устройствах без System Storage и Flash Memory
Storage не задан (SDK)127. Плагины строят поверх этого три слоя: простые значения в cookies (§10.3),
свои файлы в DATA (§10.4–10.6) и кэш во временном каталоге или в DATA (§10.8). Экран настроек — control-папка,
см. guide/gui-screens.md §2.8; контролы и обработка ввода — guide/input-dialogs.md
§2.4.
10.1. Экран настроек: AbstractControlsScreen, сохранение и reset_controls¶
Фабрики контролов и каркас AbstractControlsScreen — §4.4; поля и диалоги — §5.
Схема, повторяющаяся в плагинах ниже: control-папка, обработчик ввода пишет значение и возвращает новые контролы. Различаются плагины тем, как применяют изменение к уже открытым спискам.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Построить экран настроек | папка PLUGIN_FOLDER_VIEW_CONTROLS с initial_sel_ndx = -1; в каркасах — наследник AbstractControlsScreen с ID setup |
экран без контролов: у WeburgTV код контролов закомментирован, и do_get_control_defs возвращает null |
Widget Ext (код)128; Twitch TV (код)129; Screenshoter (код)130; zlostnyi (код)131; WeburgTV (код)132 |
| Собрать экран из готовых разделов | altSource: папка DATA (выгрузить, загрузить, очистить), оформление, поиск, тема, PIN, прокси Kinopoisk, логин myShows, кнопка исправления цветов для alt:Silver; Jurt: логин, информация, буферизация 0…15000 мс, показ на главном экране, «мягкая» перезагрузка; rmfon.pl: bg_path/mode_path из файлов DATA, версия из dune_plugin.xml, IP-адрес и show_tv; MegaRadio: путь DATA и закачки, use_osk, additional_settings, pin_dialog, QR, mode_path, difm_login; Setup Wallpaper: DATA-диалог, dload_path, use_wll, use_osk, abyss_api_key, pin_dialog |
— | altSource (код)133; Юрта ТВ (код)134; surface_* (код)135; MegaRadio (код)136; Smart Apps (код)137 |
| Сделать отдельный диалог настроек | show_dialog шириной 1100 с close_by_return = false; RETURN переназначен на close_dialog с флагом close_config_dialog_kbrd_q21, закрытие вызывает screen_render_after_config |
RETURN не закрывает диалог сам; после закрытия настройки перезагружаются и вызывается change_keyboard(0) |
Widget Ext (AdvKeyboard) (код)138 |
| Вынести второстепенные настройки в отдельный экран | additional_settings: timer_osd 1–29 с, use_osd 0–3, video_quality 360/480/720/1080, плюс переход в proxy_settings |
— | MegaRadio (код)139 |
| Дать выбрать качество видео | MoviesTape: комбобокс video_quality закомментирован, обработчик всё равно сохраняет значение; Filmix_API: 360/480/720/1080, при HD::get_dash_platform_kind()==true ещё 1440p и 2160p; Vimeo: 360/480/720/1080 |
— | Smart_* (код)140 |
| Применить набор настроек списка | apply_sections декодирует checked_idset/initial_checked_idset, обновляет и записывает sections_on_off; CFG_TS/EPF и reread_all_epfs(true) — только при результате записи 1 |
при результате записи ≠ 1 обновление EPF не выполняется | GlobalTV (код)141 |
| Сохранить изменение и перерисовать экран | handle_user_input по action_type (confirm/apply) и control_id пишет значение в cookie и возвращает reset_controls с заново собранными defs |
Widget Ext возвращает reset_controls после каждого ввода; pirates_* — при любом action_type, в том числе не confirm; Twitch TV сохраняет только по apply на кнопке btnSave |
Widget Ext (код)142; Anidub.Com (код)143; pirates_* (код)144; 101.ru (код)145; Twitch TV (код)146 |
| Применить настройку к открытому списку | после записи cookie вернуть invalidate_folders нужных папок (и затем reset_controls) |
plugtv: Трофей HD при смене epg_server инвалидирует tv_channel_list, «Новый Мир» — нет, только сохраняет |
altIPTV (код)147; 101.ru (код)145; AceStreamSearch (код)148; rain_* (код)149; plugtv (код)150 |
| Ввести ключ доступа с проверкой | кнопка открывает диалог с text_field; обработчик сохраняет cookie, проверяет плейлист, перезагружает каналы и возвращает close_dialog_and_run(invalidate_folders(…, reset_controls)) |
при ответе nottoken или пустом — сообщение «Неправильный ключ доступа» |
zlostnyi (код)151 |
| Разбить большую форму | страницы: page_num 1–4 и reset_controls; или взаимоисключающие разделы: при выборе одного остальные сбрасываются в no |
— | altIPTV (код)152; EvolutionTV (код)153 |
| Показывать поля по условию | поле строится, только если выбран режим: m3u_dir при m3u_type=2, proxy_ip/proxy_port при use_proxy=yes; набор полей по поставщику погоды |
— | EvolutionTV (код)153; Kaban.tv (код)154; AceStreamSearch (код)155; Widget Ext (код)156 |
| Вводить значение в удобных единицах | в UI секунды, при сохранении *= 1000 (buffering_ms); epg_shift подписан в часах, хранится как $i*3600 секунд |
— | AceStreamSearch (код)157; pirates_* (код)158 |
Грабли switch: в «Новом Мире» (plugtv) у case 'buf_time' нет break, и после сохранения буферизации открывается
диалог перезагрузки (код)159.
10.2. Что ещё кладут на экран настроек: версия, «что нового», QR, лог, перезагрузка, пароль¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Показать версию плагина | HD::ver() или разбор dune_plugin.xml из install_dir_path, версия — в подписи или метке |
это версия плагина, а не прошивки | Screenshoter (код)160; surface_* (код)161; 101.ru (код)162; FREE TV (код)163 |
| Показать «что нового» | кнопка whats_new загружает http://dune-club.info/plugins/update/<plugin_name>/info.txt и показывает текст в диалоге; DI.FM — по B_GREEN на списке групп, текст в multiline-label и диалоге %tr%t5 |
URL собран из имени плагина; HD::http_get_document отключает проверку SSL |
Screenshoter (код)164; 101.ru (DI.FM) (код)165 |
| Показать адрес веб-интерфейса и QR-код | адрес — по IP из ifconfig (первый не 127.0.0.1) и HD_HTTP_LOCAL_PORT; QR скачивается с api.qrserver.com в tmp_dir_path/img.jpeg и показывается тегом <icon> в диалоге; MegaRadio строит QR через api.qrserver.com по http://<IP-плеера>/cgi-bin/plugins/MegaRadio/do |
внешний сервис QR; на не-Android вместо адреса — надпись «Plugin for Dune Android» | Screenshoter (код)166; surface_* (код)167; MegaRadio (код)168 |
| Показать лог и статус фоновых задач | диалог с логом из tmp/run/*.log; статус cron — по наличию update_weather.sh/meminfo.sh в выводе bin/crontask.sh |
статус — по строке в cron, а не по живому процессу | Widget Ext (код)169 |
| Кнопки обслуживания | кнопки запускают shell-скрипты (bin/meminfo.sh x, bin/update_weather.sh, bin/clean_old_fix.sh) |
— | Widget Ext (код)170 |
| «Мягкая» перезагрузка плеера | кнопка выполняет shell_exec('killall shell') |
— | AllTV (код)171; Юрта ТВ (код)172; кнопка restart — Anidub.Com (код)173, youtube_api/folder_cache (код)174 |
| Закрыть настройки паролем | при непустом PARAM_SETTINGS_PASSWORD перед экранами настроек — диалог с полем pass; неверный → err_bad_pass |
— | ProIPTV (код)175 |
| Сменить PIN | старый PIN должен совпасть с cookie pin (по умолчанию 0000), новый вводится в отдельное поле; MegaRadio меняет pin, только когда pin1 и pin2 непусты и pin1 совпадает с текущим |
— | liteIPTV (код)176; Smart_* (код)177; MegaRadio (код)178 |
| Настройки на стороне сервиса | экран показывает данные подписки из account, а изменения отправляет запросом settings_set.php |
код закрытых каналов (pcode) уходит в URL |
Moi-Dom.tv (код)179 |
| Применить настройки, присланные сервером | ActionFactory::change_settings($settings_to_apply, false, false, $post_action): stats_on, timeshift, buffering, bitrate, stream_server, server_address, login, password; upgrade_url пишется в /config/fw_online_upgrade_url.txt через временный файл и rename |
применяется только при непустом ответе; пустой URL удаляет файл и /tmp/fw_online_upgrade_last_autocheck_time, только если отличается от прежнего |
Polbox.tv (код)180 |
10.3. Простые настройки в plugin_cookies¶
Cookies — первый способ хранить настройки: SDK передаёт их в каждый метод (SDK)123 и прямо предлагает как постоянное хранилище для избранного ТВ (SDK)181.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Хранить параметры с умолчаниями | значение из cookie, а при его отсутствии — умолчание из кода (AceSearchConfig::item(), check_cookies) |
значения нормализуют: ext_torrserver без порта дополняется :8090 |
AceStreamSearch (код)182; RemTor (код)183; Online Movies (TV Series) (код)184; AllTV (код)185; liteIPTV (код)186; youtube_api/folder_cache (код)187; Anidub.Com (код)188 |
| Отличать «не настроено» | умолчание-маркер: token = '0' → вместо плейлиста группа-заглушка «Ключ доступа не найден!» |
— | zlostnyi (код)189 |
| Хранить список | id через запятую (favorite_channels, favorite_categories, exclude_channels) |
FREE TV при загрузке удаляет из списков id, которых нет в плейлисте, а без cookie записывает 19 стартовых каналов | GlobalTV (код)190; FREE TV (код)191 |
| Накапливать значения | новое значение дописывается к cookie через разделитель *** |
— | Novosib-iptv (код)192 |
| Спрятать значок плагина из главного меню | show_cookie_name = main_icon и show_by_default = yes в манифесте + combobox, пишущий yes/no в main_icon; SDK допускает и lang(…) |
влияет на точку входа в root://applications; вторая точка в setup://applications без show_cookie_name остаётся; surface_* объявляет show_application, но этот cookie никто не пишет |
SDK (SDK)193; Screenshoter (код, SDK)194; служебные установщики hdtv (код)195; surface_* (код)196 |
| Прочитать cookies вне PHP | shell-скрипт разбирает /config/twitch_tv_plugin_cookies.properties строками ключ значение |
пустой auth_token даёт SHIC_PASS="oauth:" и проходит проверку |
Twitch TV (код)197 |
| Задать показ на главном экране | Jurt: show_in_main_screen=auto/yes/no; при auto пишется show_tv=lang(russian), иначе — выбранное значение |
— | Юрта ТВ (код)198 |
Мёртвые cookies — частая находка: Anidub.Com пишет три cookie, которые нигде не читает
(код)199, а Peers.TV и pirates_* читают show_vod, для которого нет контрола
(код)200. Kohana-канал объявляет Cookie::init со ссылкой на
$plugin_cookies, но get/set не вызывает и собственных настроек не читает (код)201.
10.4. Свои файлы в DATA: serialize, properties, INI, SQLite, XML¶
Когда настроек много или это массивы (избранное, история, токены), плагины пишут свои файлы в data_dir_path.
Повторяющийся приём — хелперы HD::get_items/save_items, которые плагин несёт в своём lib/utils.php
(код)202.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Хранить массивы | HD::get_items/save_items: PHP serialize/unserialize в файл под DATA; строки — get_item/save_item (пустая строка, если файла нет); Bazinga3: HD::saveItemsArr/getItemsArr — serialize-файлы в HD::get_data_path(), saveItemStr/getItemStr — строки отдельными файлами |
у Bazinga3 при macAdr=true к имени добавляется MAC без двоеточий |
Smart_* (код)203; служебные установщики hdtv (код)204; Widget Ext (код)205, языки и цвета AdvKeyboard (код)206; altIPTV (код)207; Torrent Center (код)208; YouTube (Smart_*) (код)209; MegaAnime (код)210; youtube_api/folder_cache (код)211; Bazinga3 (код)212; MegaRadio (repl_arr, строка DELETE очищает список) (код)213 |
| Временные массивы | get_items_tmp/save_items_tmp — те же файлы под tmp_dir_path; Bazinga3: saveItemTmpStr/saveItemsTmpArr пишут в DuneSystem tmp_dir_path |
— | Smart_* (код)214; служебные установщики hdtv (код)204; MegaTorrents (код)215; Bazinga3 (код)216 |
| Удалить файл и его кэш | после подтверждения — shell_exec("rm -rf \"<path>\""); для video_file и папок дополнительно удаляются items/<series_id\|basename>.jpg и .json |
— | altSource (код)217 |
| Несколько плееров на одной DATA | к имени файла добавляется MAC без двоеточий (macAdr) |
MAC берётся командой ifconfig eth0; youtube_api/folder_cache пишет избранное с MAC, а main_menu:fav читает legacy cookie — рассинхронизация |
Torrent Center (код)218; Widget Ext (код)219; MegaAnime (код)210; MegaTorrents (код)220; youtube_api/folder_cache (код)211 |
| Свой файл «ключ = значение» | settings.properties в data_dir_path, читается один раз при init(), при изменении перезаписывается целиком; INI plugin_settings_<name> через parse_ini_file |
запись Widget Ext — полная перезапись файла; load_settings возвращает false, если нет файла или ключа |
Widget Ext (код)221; служебные установщики hdtv (код)222 |
| База настроек с типами | SQLite: глобальное — common.db, по плейлисту — <playlist_id>.db (settings, cookies); в settings хранится gettype значения, при чтении — settype по типу умолчания |
для старых SQLite: page_size до первой страницы, cache_size до 3.7.10 в страницах, mmap_size с 3.7.17 |
ProIPTV (код)223 |
| Конфиг редактора списков | /config/lcfg_<config_id>.txt: до строки --- — +id/-id, после — порядок; нет файла → пустой конфиг |
— | GlobalTV (код)224 |
| Справочники в пакете | список станций — локальный XML, категории — data/feed.xml: читаются из пакета, без сети; Kaban.tv грузит таблицы с удалённого DATA_PATH с запасным data/ в пакете (кроме файла 01), формат — gzip + XOR + unserialize |
— | pirates_* (код)225; youtube_api/folder_cache (код)226; Kaban.tv (код)227 |
| Править конфиг стороннего пакета | str_replace строки в файле (START_TRANSMISSION=…, пути в settings.json/core.conf), пишется config.json с перезапуском сервера |
при переустановке LTU сначала задаёт умолчания, затем подгружает старый configure и пишет файл заново — значения пользователя сохраняются |
служебные установщики hdtv (код)228; Entware/Wallpaper (код)229; PeerflixServer (код)230 |
| Слои конфигурации в каркасе | файлы config из всех путей сливаются Arr::merge, более поздний (APPPATH) перекрывает модульные |
— | Kohana-канал (код)231 |
Вне PHP: JS-плагин Lampa хранит сессию прогресса в localStorage под ключом dune_local_progress_v1, а вместо URL
кладёт дайджест — по комментарию, URL и токены туда не попадают (код)232; при восстановлении
отбрасываются сессии старше 12 часов и неверные элементы (код)233.
10.5. Где лежат данные: data_dir_path, перенос DATA, накопители и системные файлы¶
Штатный каталог — data_dir_path (SDK)125; на части устройств его нет (SDK)127.
Плагины ниже дают пользователю перенести DATA на накопитель или в сетевую папку и читают системные файлы прошивки.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Найти каталог данных вне PHP | первый существующий из /persistfs/plugins_data/<name>, /flashdata/plugins_data/<name>, иначе /config/plugins_data/<name> |
— | Online Movies (eng) (код)234 |
| Перенести DATA в другое место | в data_dir_path кладётся файл-дескриптор data_dir_path с выбранным путём; get_data_path() при его наличии берёт путь через smbtree::get_folder_info и кэширует; сброс — удалить дескриптор; Bazinga3 берёт путь так же: DuneSystem data_dir_path, а при наличии одноимённого файла — через smbtree::get_folder_info('data_dir_path') |
Smart_*: эталонный get_data_path значение не возвращает, а в YouTube — возвращает; TorrServe вызывает SmartConfig::get_data_path, которого в классе нет |
Torrent Center (код)235; Widget Ext (код)236; MegaTorrents (код)237; altSource (код)238; Smart_* (код)239; YouTube (Smart_*) (код)240; TorrServe (код)241; Bazinga3 (код)242 |
| Выбрать хранилище из списка | каталог плагина, /D, SMB или свой путь; несуществующий выбор → каталог плагина; для SMB — mount -t cifs с логином и паролем из cookies |
— | altIPTV (код)243 |
| Выбрать папку или файл | экран file_list с save_data/save_file и фильтром extension; импорт конфига проверяет первую секцию на поле type |
rclone: файл без type даёт ошибку импорта; по сообщению пользователя, такая ошибка встречалась, и автор ответил примером секций с type |
DunePlexServer (код)244; surface_* (код)245; liteIPTV (код)246; Torrent Center (код)247; rclone (код, форум)248 |
| Подключить сохранённые сетевые папки | smbtree монтирует отсутствующие в df ресурсы: mount -t cifs в фоне, mount -t nfs с сохранённым протоколом |
surface_* хранит SMB-логины и пароли в сериализованных файлах DATA и передаёт их в mount -o username=…,password=…; для платформ 8672/8673/8758 liteIPTV проверяет SMB-каталог через test -d |
Smart_* (код)249; surface_* (код)250; liteIPTV (код)251 |
| Сменить каталог кэша | к выбранному каталогу добавляется /<plugin_name> (кроме data_dir_path), старый удаляется rm -rf |
— | rclone (код)252 |
| Сохранить файл пользователя на накопитель | внешний /tmp/mnt/D (если есть /system/dunehd/init) или /D, затем внутренняя /sdcard; нужно больше 15000 байт свободно |
— | Screenshoter (код)253 |
| Общие данные нескольких плагинов | search_items вычисляется в родительском каталоге data_dir_path: из пути убирается имя плагина |
имя файла добавляется без слэша | Smart_* (код)254 |
| Читать настройки прошивки | /config/settings.properties («ключ = значение»): interface_language, widget_country, show_builtin_memory_item; country_code_2 — из /tmp/location_info.properties, иначе /config/…; tv_4k — из /tmp/run/tv_4k.txt |
— | GlobalTV (код)255; Screenshoter (код)256; Online Movies (TV Series) (код)257 |
| Писать настройки прошивки | power_on_action в /config/settings.properties через INI::write |
INI::write выводит все секции и ключи заново, с сортировкой ksort |
remote-control (код)258 |
| Хранить EPF во флеш-памяти | GlobalTV: /flashdata/plugins_epfs/<имя плагина>, временные — в /tmp/plugins/<имя плагина>/epfs; id section_fav для избранного, section_<section_id> для остальных разделов |
— | GlobalTV (код)259 |
| Свои иконки библиотек | иконки берутся из /D/dpc_custom_icons (только .png), выбранная копируется в /persistfs/plugins_data/<каталог плагина>/lib_icons/cust_icon_<lib>.png и в icons/ пакета; в диалоге Icons экрана Design доступны plex_standard, plex_composite и custom_icon, если иконка уже сохранена |
— | DunePlexCatalog (код)260 |
Сохранить .torrent в папку закачки |
save_torrent: при пустой или несуществующей dload_dir_path открывается выбор папки dload_path, иначе get_torrent(series_id, <папка>/<имя>.torrent) и диалог «<имя> сохранен!» |
— | MegaAnime (код)261 |
| Загрузить ключ API с накопителя | ищется /D/apikey.txt, затем первый /tmp/mnt/storage/*/apikey.txt; UTF-8 BOM в начале отбрасывается и значение обрезается trim |
берётся первый найденный файл | Widget Ext (код)262 |
| Понять метку времени истории просмотра | по сообщениям пользователей, watch-sync на Solo 8K и Pro 8K Plus (Android-прошивка r22): timestamp — 16 цифр, unix-время в микросекундах; совпадает с mtime файла timestamp |
— | watch-sync (форум r22)263 |
Прочитать отметки watched_*.txt |
по сообщениям пользователей, watch-sync на Solo 8K и Pro 8K Plus (Android-прошивка r22): строки «процент |
файл почти не используется: у Pro одна строка 104 B, у Solo пустой | watch-sync (форум r22)264 |
История просмотра Android-прошивки, по сообщениям пользователей, хранится только в приватном каталоге
/data/data/com.dunehd.app/ (позиции — в config/watch_history/) (форум r22)265; внешний сервис watch-sync работает с ней через adb
(код)266.
10.6. Выгрузка, загрузка и очистка DATA, восстановление¶
Бэкап как отдельная функция плагина (архивы настроек и системы) — §13.10.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Выгрузить и загрузить DATA | рекурсивное копирование HD::pCopyFolders (RecursiveDirectoryIterator + copy) между data_dir_path и выбранной папкой (altSource, liteIPTV — <папка>/<plugin_name>); MegaRadio: экспорт data_dir_path, импорт папки или файла и очистка DATA |
— | Torrent Center (код)267; altSource (код)268; liteIPTV (код)269; MegaAnime (код)270; MegaRadio (код)271 |
| То же в фоне | cp -rf в фоне, у surface_* — через shell_exec(… > /dev/null &) |
— | Smart_* (код)272; surface_* (код)273; altIPTV (код)274 |
| Выгрузить и загрузить свои скрипты и иконки | пункты «Выгрузить скрипты»/«Загрузить скрипты» копируют .sh и .png между plugins_data и выбранной папкой (при выгрузке — папка накопителя); при загрузке — chmod -R 777 и возврат !update_list! |
— | Dune BackUp (код)275 |
| Выгрузить на накопитель с проверками | копирование data_dir_path в /D/YTV_data и обратно; без /D — сообщение подключить накопитель, нет /D/YTV_data — каталог создаётся при выгрузке, при загрузке — сообщение |
— | youtube_api/folder_cache (код)276 |
| Очистить DATA | rm -rf <data_dir_path> и mkdir заново |
altSource при очистке сохраняет дескриптор data_dir_path |
liteIPTV (код)277; MegaAnime (код)270; surface_* (код)245; altSource (код)268 |
| Вернуть стандартные данные | удалить свой каталог данных и скопировать data из install_dir_path в фоне |
— | altIPTV (код)278 |
| Пережить порчу файла | сравнить число элементов с копией .bak: больше — обновить .bak; текущий пуст, а .bak не пуст — диалог «восстановить» |
— | MegaAnime (код)279 |
| Перенести настройки старой версии | install.sh/update.sh переносят старые файлы настроек в каталог данных |
миграция в комментарии описана для 1.0.0 и 1.0.1 | Widget Ext (код)280 |
| Очистить историю | combobox clear_history: при confirm со значением yes история очищается и показывается диалог history_cleared |
— | AceStreamSearch (код)281 |
| Назвать папку и файл бэкапа | Dune BackUp: папка <накопитель>/dune_bcp/bcp_ГГГГ_ММ_ДД (при файле settings/BackUp-separate-minute — с -ЧЧ.ММ), в конец имени — ID/модель с пробелами → _; файл <тип>-<число_элементов>_(<ID или модель>)_ГГГГ.ММ.ДД-ЧЧ.ММ_<флаг>.dbcp |
флаг присваивается последовательно s → S → A → N, каждое следующее перекрывает предыдущее: S при /persistfs/plugins, A при interface_language_synchronized, N при apk_interface_language_changed; при ключе A флаг A даже с /persistfs/plugins, при обоих ключах — N |
Dune BackUp (код)282 |
| Переключить режим сохранения | пункт «Выбор режима сохранения Бэкапов в папки» вызывает script save.sh change и возвращает !return_start! для перезапуска пункта |
режим — наличие файла BackUp-separate-minute |
Dune BackUp (код)283 |
| Проверить, что бэкапить | перед каждым бэкапом save.sh проверяет накопитель, непустоту списка и наличие каждого элемента; при пустом списке, отсутствии накопителя или элемента пишет ошибку в .sms и завершается; отдельно предупреждает о встроенной памяти Android и неверной дате раньше 2026-08-01 |
бэкап не блокируется, только предупреждает о дате и носителе | Dune BackUp (код)284 |
| Составить разделы бэкапа | отдельные списки: «Моя коллекция» (config/movie_index_config.xml, fb_cache, movie_index, dunemdb_cache, image_cache, custom_mdb, my_collection.properties, lcfg_mc_categories.txt, mc/mdb/search_timestamp, mdb_image_state.json), «Сетевые папки» (network_folders.properties, lcfg_sources.txt), «Плагины» (flashdata/plugins*, D/dune_plugins, cookies, lcfg_*), «Избранное, Последнее» (main_screen_items, watch_history, lcfg_favorites.txt), «Настройки Dune Shell» (settings.properties, скины, сервисы, lcfg_*.txt и др.) |
epg_cache плагина proiptv исключается; без type в network_folders.properties базовый список очищается, но lcfg_sources.txt добавляется после; без movie_index_config.xml с id= список «Моей коллекции» очищается |
Dune BackUp (код)285 |
| Обновить файлы перед записью | удалить из папки всё, чьё имя начинается с того же типа (find ... -name "<тип>-*" -exec rm); при сохранении скачать свежий dune_plugin_Dune_backup.zip с dune-club.info (если файла нет в tmp и пинг домена успешен) и при изменении md5 скопировать архив в dune_bcp |
zip качается только при успешном пинге домена | Dune BackUp (код)286 |
| Восстановить из файла | upload.sh: если передан каталог — искать ровно один файл <тип>-* (ноль или несколько — ошибка); если файл — тип из имени; число элементов — из имени после <тип>-, непустое целое, ноль отвергается |
— | Dune BackUp (код)287 |
| Нормализовать восстановленные данные | для «Моей коллекции» и «Настроек» при флаге платформы не 1: пересобрать lcfg_mc_categories.txt (оставить folder: только с id из movie_index_config.xml, остальные строки сохранить), обновить mc_timestamp; для Bazinga3 заменить старый MAC в именах plugins_data/Bazinga3 на текущий из tmp/plugins/Dune_backup/mac_addr; for_php-cgi.sh заменить php-cgi в восстановленных плагинах (кроме test_php-cgi и каталогов с 86/87) на копию из test_php-cgi; for_common.setting.sh заменить в plugins_data файлах common.settings с ключом channels_list_path путь /persistfs/plugins или /flashdata/plugins на фактический с FS_PREFIX |
php-cgi меняется, только если размер, md5 или ссылка отличаются; нестандартный каталог DATA Bazinga3 — предупреждение | Dune BackUp (код)288 |
| Восстановить «сырые» файлы из корня накопителя | пункт ищет в корне My_collection*, Network_folders*, Plugins*, Favorites+Recent*, Settings*, One_plugin_{*}*, при необходимости переименовывает _ после типа в дефис и вызывает upload.sh с маркером; маркеры в .sms: !OFF_ON! для «Моей коллекции» и «Настроек», !reboot! для остальных |
файлы должны лежать в корне | Dune BackUp (код)289 |
10.7. Атомарная запись и файлы, общие с другими процессами¶
Файл, который читает другой процесс (оболочка, CGI, демон), пишут через временный файл и переименование — так читатель не увидит половину содержимого.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Атомарно записать файл | <path>.tmp + rename; вариант _if_changed сравнивает содержимое и не пишет без изменений |
при ошибке rename временный файл удаляется |
GlobalTV (код)290 |
| Обмен с фоновым процессом через файлы | результат — в res.json.part, затем переименование в res.json; командный файл удаляется после чтения; при старте оба файла удаляются |
— | Online Movies (eng) (код)291 |
| Подменить данные системного виджета | строка пишется в .tmp и переносится mv -f в $FS_PREFIX/tmp/weather.txt — тем же приёмом и в том же формате, что встроенный run_widget.sh |
— | Widget Ext (код)292 |
| Не конфликтовать с процессом прошивки | тот же lock-файл $FS_PREFIX/tmp/run/widget.lock и захват через set -C, что у run_widget.sh |
— | Widget Ext (код)293 |
| Файл состояния для CGI и GUI | каталог 0700, временный файл 0600, при необходимости chown на владельца bridge.php, затем rename; сессия старше 12 часов отвергается |
по словам автора в комментарии кода, HTTP CGI на некоторых прошивках работает от root, а GUI PHP — от владельца плагина; каталог по умолчанию — /tmp/lampa_dune_bridge |
Lampa bridge (код, форум)294 |
10.8. Кэш и состояние между вызовами¶
Кэш у плагинов трёх видов: файлы в DATA (переживают перезагрузку), файлы во временном каталоге и статические или глобальные переменные PHP-процесса.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Обновлять серверный кэш | сначала сравнить cache.timestamp; затем скачать cache2.zip, распаковать (system("unzip")) в main_cache.json, rename в active_cache.json, метку перенести последней; URL переопределяются файлами в /config |
старый кэш сохраняется только при неудаче загрузки или записи архива; перед unzip active_cache.json и tv_cache*.json удаляются, так что ошибка распаковки или rename — ошибка загрузки кэша |
GlobalTV (код)295 |
| Отдать список каналов файлом | PluginTvInfo::channels_file = путь к tv_cache_<section>.json в DATA; при смене родительского пароля tv_cache_xxx.json и tv_cache_all.json удаляются |
— | GlobalTV (код)296 |
| Работать при недоступном сервере | ответ /config кэшируется в config_cache.json и грузится в фоновом потоке |
— | Online Movies (eng) (код)297 |
| Кэш с временем жизни | плейлист — пара .m3u8 + .db, устаревает по mtime + часы из настройки (PHP_INT_MAX — вечно); HTTP-ответы — файл по md5(url [+ post]) на file_cache_time часов, с If-None-Match по ETag из etags.db |
— | ProIPTV (код)298 |
| Кэш метаданных и обложек | JSON и постер по id элемента в DATA; обложки и описания — в /persistfs/plugins_data/<плагин>/…, размер — du -h, очистка — rm; Bazinga3: разобранные данные фильма — в <data>/pluginCache/md5(movie_id.class_name).srz (при posterCashe=1 для избранного), постер — <md5(mUrl)>.jpg |
altSource: id папки — только basename, id видео — md5(dirname + basename) |
altSource (код)299; DunePlexCatalog (код)300; Bazinga3 (код)301 |
Кэш ответа API в /tmp |
ответ пишется в файл, при наличии файла сеть не запрашивается; при смене ключа файл удаляется | itv: один файл /tmp/itv_api_new кэширует два разных ответа — кто запишет первым, тот и останется |
zlostnyi (код)302 |
| Очистить кэш | кнопка удаляет файлы временного каталога | FREE TV «Очистить кэш EPG» удаляет все файлы tmp_dir_path, а не только EPG |
FREE TV (код)303 |
| Кэш в памяти процесса | глобальная переменная: если задана, база берётся из неё, иначе шесть лент загружаются заново | диск не используется | Apple Trailers (код)304 |
| Кэш разбора страниц | serialize в файл под tmp_dir_path, запись или чтение по наличию константы async_icon_loading |
kinokrad берёт чужое имя кэш-файла cacheLinkApiUst и пишет при незаданной переменной |
Smart_* (link_api) (код)305 |
| Сбросить кэш при входе в список | get_folder_view очищает кэш фильмов и счётчик перед загрузкой |
— | Smart_* (код)306 |
| Передать данные между экранами | JSON после разделителя \|\| в media_url (HD::encode_user_data/decode_user_data); выбранный элемент приходит в selected_media_url |
без разделителя user_data = null |
Widget Ext (код)307 |
| Состояние между вызовами поставщика | private — JSON (pub_by_id, files_by_ep_key), который оболочка возвращает в следующий вызов; id файла — JSON {pub_id, file_url} |
без private — пустой список со статусом done |
Online Movies (rus) (код)308 |
| Состояние в объекте плагина | поля объекта или static (кэш торрентов фильма, фильтр файлов, данные стрима для get_vod_info) |
Twitch TV заполняет поля только в get_folder_view, а читает в get_vod_info; фильтр altSource — статическое поле |
Online Movies (TV Series) (код)309; Twitch TV (код)310; altSource (код)311 |
| Периодически обновлять справочник | файл с датой загрузки; повторная загрузка, если файла нет или прошло больше 604800 с | — | liteIPTV (код)312 |
| Дождаться фонового кэша | MainHelper задаёт в tmp_dir_path пути main_cache.json и wake_flag, URL кэша — http://dunemdb.dune-hd.com/dunehdtv/cache.json; EpfsHandler::wait_if_needed сразу выходит, если интернета нет или файл кэша уже есть, иначе до 100 раз по 0,1 с ждёт файл, проверяя интернет каждые 5 итераций |
— | Dune HD TV (код)313 |
Как кэш папок обновляется со стороны платформы (invalidate_folders) — guide/gui-screens.md §2.7.
13. Фоновые процессы, демоны и системные действия¶
Объект: плагины Cleanup, DLNA Renderer, DunePlexServer, MPD, TorrServe, PeerflixServer, Entware/Wallpaper, служебные
установщики hdtv (LTU_install, Codec_install, ExtendRC_install, Platform_install, umount, mark.it, DuneArc), Dune BackUp,
Widget Ext, Torrent Center, rclone, altIPTV, liteIPTV, ProIPTV, GlobalTV, YouTube (Smart_*), altSource, MegaAnime,
MegaTorrents, remote-control, Apple Trailers, Jellyfin Bridge и другие (code, кое-где forum); платформа и прошивка
исполнения у большинства не установлены, ветки «Android»/«APK» — как написано в коде плагина. Поведение платформы — SDK
плагинов (doc) и tv188b r25 (device).
PHP-вызов плагина идёт как операция с тайм-аутом (см. guide/plugin-operations.md §2), поэтому
всё долгое и всё, что должно жить без экрана, плагины выносят наружу: в shell-скрипты в фоне, демоны, cron и
загрузочные скрипты. Точка входа для кода без пользователя — global_actions: SDK называет события boot, install,
update и uninstall (SDK)314, boot_end — с прошивки 130917_b9 (SDK)315, gui_start — с
130914_b8 (SDK)316; для boot поддерживается только plugin_system (SDK)317. На tv188b r25
boot и boot_end при повторных стартах приложения не выполняются (устройство r25)318, gui_start —
при каждом старте (устройство r25)319; plugin_system запускается как sh <абсолютный путь>
(устройство r25)320 под uid 1000 с FS_PREFIX=/data/data/com.dunehd.app (устройство r25)321.
Подробнее — guide/plugin-packaging.md §3 «Действия плагина при установке». Управление демоном
по HTTP (service_api) — §15.2, IP Control из плагина — §15.5.
13.1. Запуск при загрузке, старте GUI и установке: global_actions и /config/boot¶
Самый короткий приём — plain-плагин без экранов, весь код которого — скрипты в global_actions.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Поднять демон в конце загрузки без PHP | global_actions/boot_end → plugin_system с run_string bin/<скрипт> & |
— | Cleanup (код)322; DLNA Renderer (код)323; TorrServe (код)324 |
| Плагин без экранов | манифест type plain без entry_points; только global_actions boot_end/install/update/uninstall |
install и update перезапускают демон (restart &), uninstall (cleanup) — без &, то есть синхронно |
DLNA Renderer (код)325 |
| Стартовать сервис при загрузке через свой CGI | boot → bin/t.sh &, скрипт делает wget на …/cgi-bin/plugins/<плагин>/service_api?cmd=plex_start в фоне |
CGI стартует сервер, только если есть файл plexlibrary_location |
DunePlexServer (код)326 |
| Сделать что-то при каждом старте GUI | gui_start.sh |
Dune BackUp перед запуском демона проверяет ps w и pidof, а при наличии /system/dunehd/dunehd_service запускает через dunehd_service do |
Widget Ext (код)327; Dune BackUp (код)328 |
| Пересоздать свои задания после загрузки и убрать при удалении | boot.sh пересоздаёт cron по сохранённым настройкам; uninstall.sh удаляет свои строки cron и восстанавливает системный run_widget.sh |
boot.sh проверяет /flashdata/plugins_data без $FS_PREFIX, остальные скрипты — с ним |
Widget Ext (код)329 |
| Поставить сторонний пакет при установке плагина | install/update → plugin_system bin/<установщик>.sh &, uninstall → bin/<деинсталлятор>.sh & |
у Codec_install и Platform_install из global_actions объявлен только uninstall — установка идёт с экрана |
LTU_install (код)330; ExtendRC_install (код)331; Codec_install (код)332; Platform_install (код)333; mark.it (install и boot → bin/start.sh &) (код)334 |
| Автозапуск в обход манифеста | скопировать загрузочный скрипт или демон в /config/boot |
Platform_install пишет /config/boot/platform.sh, но сам симлинк сразу не создаёт — лог просит перезагрузку; remote-control патчит скопированный скрипт (pushd в каталог CGI) |
LTU (код)335; Codec_install (код)336; ExtendRC (код)337; Platform_install (код)338; remote-control (код)339 |
| Включать загрузочное действие правкой своего манифеста | boot с пустым run_string; при настройке плагин заменяет в dune_plugin.xml пустой run_string на bin/start.sh & и просит перезагрузку |
подхватит ли оболочка правку — не проверено (§19) | umount (код)340 |
| Запустить плагин при включении плеера | auto_start с entry_point_media_url, force_on_start=black_screen, force_on_finish=main_screen |
среди веб-плагинов так сделан только amediateka | веб-плагины (код)341 |
13.2. Автозапуск, который пользователь включает в настройках¶
Общий приём — поставлять загрузочный скрипт с закомментированной строкой запуска и из экрана настроек снимать или ставить комментарий; состояние переключателя читается из того же файла.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Переключатель «автозапуск» без переустановки | комбобокс правит строку в своём загрузочном скрипте: #wget/wget в bin/t.sh, #mpd-start/mpd-start, #export+#forever в bin/boot_end.sh; TorrServe перезаписывает bin/boot.sh целиком (start-stop-daemon либо exit 0) |
по умолчанию выключено: у TorrServe boot.sh — только exit 0, у PeerflixServer строки закомментированы; по сообщениям пользователей, на Neo 4K автостарт PeerflixServer после перезагрузки не срабатывал |
DunePlexServer (код)342; MPD (код)343; TorrServe (код)344; PeerflixServer (код, форум)345 |
| Несколько сервисов в одном загрузочном скрипте | строки #transmission-start, deluge-start/S80deluged, автозапуск tor и S55portmap/S56unfsd в bin/boot_end.sh |
— | Entware (код)346 |
| Свой планировщик пунктов «после загрузки / раз в день / неделю / месяц / по воскресеньям» | блоки #<start> в auto_start.sh, режим в .if, дата последнего запуска в .ld; демон demon_as.sh раз в 60 с проверяет разрешение и запускает |
разницу дней считает своя count_minutes, потому что DMC неправильно обрабатывает date -d |
Dune BackUp (код)347 |
| Сменить интервал периодической задачи | экран меняет интервал регуляркой прямо в bin/start.sh |
нужна перезагрузка | mark.it (код)348 |
| Не стартовать фоновую задачу без интернета | test_internet.sh считает интернет доступным, только если системная дата не раньше 2026-08-01 и хотя бы один запрос wget --spider к google.com/httpbin.org или ping yandex.ru успешен |
без интернета автостарт ждёт | Dune BackUp (код)349 |
13.3. Демон: один экземпляр, pid-файл, остановка¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Не запустить второй экземпляр | проверить процесс по имени перед стартом: killall -0 <имя>, pgrep, ps \| grep, ps w и pidof |
проверка идёт по имени процесса, а не по pid-файлу | DLNA Renderer (код)350; Apple Trailers (код)351; remote-control (код)352; Dune BackUp (код)328 |
| Запустить и остановить внешний бинарник | start-stop-daemon -Sbvmp с pid-файлом /tmp/<имя>.pid; остановка — pidof + kill; статус — pidof; у DLNA Renderer Start запускает bin/gmediarender демоном с логом /tmp/plugins/dlna_renderer/gmediarender.log и ограничением лога 10 000 |
метка online на экране TorrServe ставится по pidof, а не по ответу сервера |
TorrServe (код)353; DLNA Renderer (код)354 |
| Перезапустить свой фоновый процесс | перед стартом убить прежний процесс: по сохранённому pid (ProIPTV, altIPTV) или найденный через ps ax (DunePlexCatalog: kill -9, затем bash … &) |
— | ProIPTV (Sleep_Timer) (код)355; altIPTV (pid_inf) (код)356; DunePlexCatalog (код)357 |
| Погасить демон корректно | killall -INT, ожидание до 30 с, затем killall -9 |
— | DLNA Renderer (код)358 |
| Демон без PHP | бесконечный цикл со sleep 60 |
— | Cleanup (код)359 |
| Найти и убить процесс другого плагина | pid из /tmp/run/<плагин>.pid; имя плагина — из nav_state.txt или из ярлыка main_screen_items/<ярлык>/dune_folder.txt; затем убить дочерние процессы и shell-процесс плагина |
по сообщениям пользователей, демон задуман освобождать память каждую минуту | Cleanup (код, форум)360 |
| Не убить плагин, в котором находится пользователь | исключить pid работающего плагина (RUNNING_PLUGIN_PID) из списка shell-процессов |
работает, только если pid определён | Cleanup (код)361 |
| Не убить плагин после переключения | дважды снять stat -c %Y nav_state.txt до и после сканирования и убивать, только если mtime не изменился |
сравнение по mtime, а не по содержимому | Cleanup (код)362 |
| Убить дочерние процессы плагина | искать по общим pipe-дескрипторам в /proc/<pid>/fd и по PPID через pgrep -P, объединить, убрать дубликаты и убить каждый |
только SIGTERM |
Cleanup (код)363 |
| Остановить скрипт вместе с дочерними | bin/kill_process_and_child.sh по имени .sh: pid через ps w, затем процесс и рекурсивно его дети; в журнал — pid, имя и время, при необходимости сообщение в .sms |
— | Dune BackUp (код)364 |
| Остановить свой демон после выхода из плеера | check_stop.sh раз в 5 с читает player_state из $FS_PREFIX/tmp/run/ext_command.state и при состоянии непустом и не file_playback выполняет killall receive5; pid — в $FS_PREFIX/tmp/run/dunehdtv_check_stop.pid |
опрос раз в 5 с | Dune HD TV (код)365 |
| Убить старые процессы при установке | bin/killr.sh выполняет killall -9 для receive2…receive5; вызывают install.sh и uninstall.sh |
— | Dune HD TV (код)366 |
| Остановить конкурирующие торрент-серверы перед стартом своего | HD::check_*_kill: найти процесс и вызвать stop-команду service_api чужого плагина на 127.0.0.1 |
— | MegaTorrents (код)367; TorrServe (код)368 |
| Обновить модуль ядра вместе с плагином | сравнить файл VERSION в каталогах установки и данных; при различии rmmod, остановка сервера ключом -t; перед стартом lsmod \| grep |
загрузочный скрипт при ошибке удаляется из /config/boot |
remote-control (код)369 |
13.4. Долгая операция вне PHP-вызова и возврат результата в GUI¶
Схема у всех одна: PHP запускает процесс в фоне и сразу возвращает действие, процесс пишет результат или ход работы в файл, а экран читает файл по GUI-таймеру. Прогресс-диалог оболочки — guide/plugin-operations.md §4.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Запустить скрипт и не ждать | shell_exec("<путь> > /dev/null &") |
вызов в фоне, результат не ждут | Widget Ext (код)370 |
| Сетевой запрос отдельным PHP-процессом | HD::asyncExec держит proc_open на php-cgi -f www/cgi-bin/run.php; run.php пишет ответ в exec_result_<action>; экран обновляется таймером 1000 мс |
файл результата — один на action, не на задание |
Torrent Center (код)371 |
Вынести тяжёлый разбор в отдельный php-cgi |
HD::asyncExec запускает вложенный <install>/www/cgi-bin/php-cgi -f classActions.php action=getIframe class_name=… params=<urlencode json>; JSON пишется в /tmp/plugins/<name>/exec_result_<action>; так же работают действия getMovieScreenInf, loadM3uVod, getNewFavItems и запросы списков торрентов в run.php |
HD::asyncExec держит один статический процесс и при смене команды закрывает предыдущий; файл результата — один на action |
Bazinga3 (код)372 |
| Shell-команда с результатом | команда пишет JSON в exec_log, PHP читает status/descr; на Android команда идёт через /system/dunehd/dunehd_service do, иначе system() |
rclone_kill.sh всегда завершается с кодом 1 — об успехе судят только по JSON |
rclone (код)373 |
| Понять, что фоновый скрипт закончил | скрипт удаляет свой лог в конце; экран, пока файл есть, раз в секунду перерисовывает диалог (timer 1000 → close_dialog_and_run) и не запускает скрипт повторно |
— | Platform_install (код)374; DuneArc (код)375 |
| Передать скрипту параметры запуска | команда собирается из пути скрипта, накопителя (с папкой при #<fold>), пути .sms, значения #<choice> и ID/модели; аргумент накопителя — только при $1_ok, все части в одинарных кавычках |
— | Dune BackUp (код)376 |
| Показать ход и ошибку фонового скрипта | при обычном запуске скрипт идёт в фоне (Config::do_cmd($cmd.' > /dev/null &')) и помечается work; в базовом режиме без #<mode_full> открывается light_show_run, иначе экран переходит на timer; скрипт пишет .log и .err рядом с .sms, экран показывает до 10 последних строк (с переворотом при #<LGrv> и сжатием процентов при #<LG%%>), меняет иконку кадрами timer_NN, а при непустом .err и неработающем скрипте показывает error в базовом режиме или error/error2 в полном |
лог только 10 строк; при первом появлении ошибки в базовом режиме текст %tr%error_info дописывается в .sms |
Dune BackUp (код)377 |
| Проверить условия до запуска скрипта | каждое условие #<test> выполняется через shell; при ложном условии показывается заголовок скрипта и #<test.txt> (или стандартный текст), скрипт не запускается; в #<warning> и #<mesg> условие отделяется \?, в #<warning> подставляются $^1 (накопитель с папкой), $^3 (выбранное значение) и $^4 (ID/модель), в #<mesg> — $^4; в условиях и тексте через test_condition дополнительно доступны $^0 (путь скрипта) и $^2 (путь .sms) |
условие — произвольный exec; показывается только текст после \? при истинном условии |
Dune BackUp (код)378 |
| Обновлять свои скрипты по URL | при директиве #<update> плагин скачивает новый текст скрипта в tmp/load_script.sh, сравнивает md5_file с текущим и при различии копирует на место и перечитывает список; my_wget читает URL по очереди и пишет первый успешный результат, удаляя прежний файл |
скрипт копируется поверх текущего | Dune BackUp (код)379 |
| Длинная операция через свой CGI | wget к своему do в фоне, затем диалог с timer(1000), который по GUI_EVENT_TIMER через close_dialog_and_run открывает себя заново |
— | altIPTV (код)380 |
| Тяжёлая индексация отдельным PHP | JSON-конфиг в tmp, отдельный процесс <php> bin/index_epg.php <config> через shell_exec с логом; блокировка is_index_locked |
— | ProIPTV (код)381 |
| Скачать и распаковать силами оболочки | действие wget с target_path и target_cmd (cd … && unzip … && rm -f …); результат приходит в user_input по ключам <prefix>status/text/url; цепочка запускается таймером topmenu_timer |
— | GlobalTV (код)382 |
| Очередь действий между срабатываниями таймера | файл settings/post_action, по JSON-действию в строке; на каждом timer снимается и выполняется первое |
— | Dune BackUp (код)383 |
| Обновлять папку, пока идёт фон | Action_Factory::timer(1000) в списках каналов и групп |
— | ProIPTV (код)384 |
| Скачать видео в фоне | exec youtube_download.sh или iptv_record.sh (из bin/ плагина или /codecpack/script/), PATH и LD_LIBRARY_PATH на ffmpeg_install/bin |
— | YouTube (код)385 |
| Конвертировать видео в фоне по профилям | пункт «Конвертирование медиа-файлов через ffmpeg» ищет в выбранной папке mp4, mkv, avi, mov, 3gp, m2ts, vob и mp3, предлагает профили по битрейту 360k/576k/1080k/2048k, CRF 18/23, замену аудио, удаление субтитров и обрезку; результат — в folder_out/<выбранный профиль>/<имя папки> рядом с исходной |
— | Dune BackUp (код)386 |
13.5. Периодические задачи: cron и свой цикл¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Ставить cron переносимо | crontask.sh: на Android — перезаписать $FS_PREFIX/tmp/cron/crontabs/root и перезапустить crond; при HD_APK=1 вместо crond — свой bin/crond.sh; вне Android — crontab -u root; без аргументов печатает расписание, -строка удаляет, +строка добавляет |
«-» удаляет все совпадающие строки; почему на APK свой цикл — §19 | Widget Ext (код)387 |
| Перевести интервал в расписание | mkcron_fix.sh отображает минуты в cron-строку (по умолчанию 10 * * * *) |
вариант «1 min» включается только файлом /config/weather_ext_debug |
Widget Ext (код)388 |
| Cron на Android-прошивке | записать /tmp/cron/crontabs/root и перезапустить crond через dunehd_service do |
— | Torrent Center (код)389 |
| Периодически дёргать свой CGI | дописать в /tmp/cron/crontabs/root */1 * * * * wget … /cgi-bin/plugins/<плагин>/do и выполнить crontab -e |
только при наличии /persistfs |
mark.it (код)348 |
| Обойтись без cron | свой демон с циклом раз в 60 с | — | Dune BackUp (код)390; Cleanup (код)359 |
| Раз в сутки дёрнуть внешний счётчик | www_counter: если дата в settings/last_act_data отличается и test_date.sh прошёл, ставится post_action run_every_day и запрашивается HD::http_get_document по URL из <check_update>/www_counter/url_all.txt (для русского) или url_mod.txt |
сам запрос не выполняется для каталога /storage/emulated/0/DuneHD/flashdata и версии с дефисом |
Dune BackUp (код)391 |
13.6. Таймер сна, перезагрузка, выключение и перезапуск оболочки¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Таймер сна через IP Control | cron-строка с wget на локальный /cgi-bin/do?cmd=standby |
liteIPTV помечает строку #sleep <unix_time>, сам чистит просроченные и предупреждает, если осталось меньше 120 с; MegaRadio удаляет прежние #sleep, пишет crontab с chmod 0575 и выполняет crontab -e, а его таймер при sleep_warn = false (интервал 5000 мс или timer_osd) удаляет истёкшую строку и предупреждает при остатке меньше 120 с |
altIPTV (код)392; liteIPTV (код)393; Smart_* (код)394; MegaRadio (код)395 |
| Таймер сна через ИК-код | cron-строка echo A15EBF00 > /proc/ir/button с меткой #sleep |
вариант altSource «после текущей серии» выключает в playback_stop, если таймер не отложен |
Torrent Center (код)396; altSource (код)397 |
| Таймер сна своим процессом | bin/sleep_timer.sh в фоне с pid- и log-файлами; оставшееся время — в OSD |
— | ProIPTV (код)355 |
| Перезагрузить плеер | shell_exec('reboot') из пункта меню или настроек |
MegaTorrents и YouTube возвращают вывод shell_exec как результат обработчика; plugtv предлагает в диалоге быструю (killall shell) и полную перезагрузку; у PeerflixServer popup do_hard_reset тоже выполняет reboot |
altSource (код)398; MegaAnime (код)399; MegaTorrents (код)400; rclone (код)401; YouTube (код)402; altIPTV (код)403; plugtv (код)404; umount (код)405; Platform_install (код)406; Bazinga3 (код)407; PeerflixServer (код)408 |
| Перезапустить оболочку | shell_exec('killall shell') |
killall shell убивает все процессы с именем shell, включая оболочки плагинов |
youtube_api/folder_cache (14 из 15 пакетов) (код)409; altIPTV (код)403; plugtv (код)404; umount (код)405; MPD (код)410 |
| Перезапустить оболочку безопасно | ActionFactorySafe::stb_shell_reboot(): если определён RESTART_ACTION_ID, вернуть действие с reboot=false, иначе попробовать change_settings(null, false, true) и лишь затем выполнить exec('killall shell') |
если RESTART_ACTION_ID не определён, fallback убивает shell |
FREE TV (код)411 |
| Мягкий и полный рестарт на разных платформах | меню: быстрый перезапуск — при before_r11 bin/restart.sh shell, иначе ActionFactory::change_settings с restart_gui; вне APK ещё полная перезагрузка (bin/restart.sh reboot → change_settings с reboot) и выключение (bin/restart.sh off) |
на APK полная перезагрузка и выключение недоступны — показывается перезапуск DMC (do_hard_reset_dune) |
Dune BackUp (код)412 |
| Пункт «Выключить плеер» | shell_exec('echo A15EBF00 > /proc/ir/button') |
что именно делает запись кода — не проверено (§19); IP Control-вариант — §15.5 | MegaTorrents (код)413; MegaAnime (код)399; rclone (код)414; YouTube (код)415; altSource (код)398; Bazinga3 (код)407; PeerflixServer (код)408 |
| Послать ИК-коды после действия | запись EA15BF00 и E916BF00 в /proc/ir/button после zoom_apply |
значение кодов в базе не описано | altIPTV (код)416 |
13.7. Запись ТВ по расписанию¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Записать канал | внешний /codecpack/script/iptv_record.sh с протоколом, URL, именем и путём; имя фоновой записи — в background_rec_stop |
нужен Codec_install: liteIPTV при входе предлагает его поставить | altIPTV (код)417; liteIPTV (код)418 |
| Запланировать старт и стоп | блок в /tmp/cron/crontabs/root (старт iptv_record.sh, запись имени, скрипт остановки) и crontab -e |
— | altIPTV (код)419; liteIPTV (код)420 |
13.8. Система: накопители, монтирование, swap, FUSE, профиль, часовой пояс¶
Сюда попали приёмы, которые меняют систему плеера; почти все требуют root и /persistfs. На tv188b r25 встроенный PHP
в shell_exec добавляет $FS_PREFIX к словам /tmp/…, /firmware/…, /config/…, /flashdata/… и к путям в
одинарных кавычках, но не в двойных (устройство r25)421.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Выбрать, куда ставить | /persistfs, если он ровно один в /proc/mounts; иначе /flashdata, если /D не смонтирован и /flashdata существует; иначе /D |
— | Codec_install (код)422 |
| Требовать системный накопитель | mountpoint -q /persistfs или file_exists('/persistfs/'); экран показывает состояние «нет накопителя / не установлено / нужна перезагрузка / готово» |
— | LTU (код)423; ExtendRC (код)424; Platform_install (код)406 |
| Выбрать сборку под CPU | grep по /proc/cpuinfo (MIPS 74K, ARMv7) |
LTU пишет в лог одно и то же имя архива в обеих ветках | LTU (код)425; Codec_install (код)426 |
| Добавить подкачку | файл 256 МБ в /persistfs, mkswap/swapon, хук /config/boot/swap_mount.sh (TorrServe ещё ставит vm.swappiness=10); выключение — swapoff и удаление обоих файлов |
только при /persistfs; у DunePlexServer экран вызывает bin/swap.sh, которого в пакете нет |
TorrServe (код)427; Entware (код)428; DunePlexServer (код)429 |
| Подготовить FUSE и смонтировать облако | modprobe fuse, иначе mknod /dev/fuse c 10 229; rclone mount --daemon … --ca-cert /firmware/certs/ca-bundle.crt; через 3 с фоновый rclone rc vfs/refresh |
если /etc/ssl/certs/ca-bundle.crt нет, скрипт rclone удаляет /etc/ssl/certs и делает ln -s /firmware/certs /etc/ssl |
rclone (код)430; Dune BackUp (код)431 |
| Смонтировать сетевые папки пользователя | прочитать /config/network_folders.properties и выполнить mount -t cifs -o username=…,password=… или mount -t nfs в /tmp/mnt/smb/<n>//tmp/mnt/network/<n> |
логин и пароль идут в командной строке mount |
DuneArc (код)432; umount (SMB в /D) (код)405 |
| Попросить систему смонтировать сетевую папку | Ipc::write_request публикует <cmd_name>.<pid>-<cmd_id>.cmd в /tmp/run/ipc__<server_id> через временный файл и rename; Ipc::network_mount передаёт сетевому менеджеру тип, сервер, каталог, имя пользователя, пароль и proto командой mount |
— | Torrent Center (код)433 |
| Найти SMB-шары | прошивочный smbtree через proc_open с LD_LIBRARY_PATH, имена — nmblookup |
путь к бинарнику зависит от прошивки (/tango/firmware/bin, /tango3/firmware/bin, /firmware_ext/smbcommon/bin) |
DuneArc (код)434; altSource (код)435 |
| Найти NFS-копию файла без настройки путей | /tmp/run/network_mount_list.xml: mount с type=nfs и status=mounted; файл ищется по имени и размеру, URL — nfs-tcp:///nfs-udp:///nfs://server:export:путь |
нет файла или ошибка разбора — пустой список; одноимённый файл другого размера не считается совпадением; по README, при неудаче играется HTTP-URL Jellyfin, а NFS нужен, чтобы плеер видел соседние субтитры | Jellyfin Bridge (код, форум)436 |
| Показать накопители и место | /tmp/run/storage_list.xml (только status=mounted, без /persistfs) или свой список каталогов; размер — disk_total_space/disk_free_space |
Dune BackUp ограничивает сканирование 30 с | altSource (код)437; Dune BackUp (код)438 |
| Безопасно извлечь накопитель | список из df, затем umount <dev> && eject <dev> |
по справке плагина, SD-карта снова монтируется при возврате в меню | umount (код, форум)439 |
| Свой хук на выключение | заменить ::shutdown в /etc/inittab на свой скрипт и kill -HUP 1 |
ExtendRC делает это, только если /sbin/onshutdown.sh (от LTU) нет |
LTU (код)440; ExtendRC (код)441 |
| Окружение для консоли | дописать подключение своего profile в /etc/profile, симлинки /ltu, /codecpack, /platform |
— | LTU (код)440; Codec_install (код)336; Platform_install (код)338 |
| Сетевой твик ядра | 16384 87380 87380 в /proc/sys/net/ipv4/tcp_rmem при USE_FIX_TCP_RMEM |
обоснование — только комментарий автора («prevent kernel crash») | LTU (код)442 |
| Часовой пояс в PHP | date_default_timezone_set("UTC"), смещение — из date +%z |
Peers.TV зашивает Etc/GMT+7 и сдвиг −7 ч в EPG |
GlobalTV (код)443; Peers.TV (код)444 |
13.9. Внешние бинарники и сервисы: установка и управление¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Поставить сервер, которого нет в пакете | установщик качает архив или ELF (часто с dune-club.info), распаковывает в bin/, ставит права, пишет лог |
у DunePlexServer и MPD — только при /persistfs; у MPD в пакете нет самого mpd — только установщик; DunePlexServer удаляет лог в конце |
DunePlexServer (код)445; MPD (код)446; TorrServe (код)447 |
| Запустить TorrServer, которого нет в пакете | torrserve.php: на Android при наличии /data/data/ru.yourok.torrserve/files/torrserver и пустом pidof torrserver запускает его с -k -d /sdcard/Android/data/ru.yourok.torrserve/files; вне Android, если файла нет, при найденном в /tmp/run/installed_plugins.xml TorrServe вызывает http://127.0.0.1:<port>/cgi-bin/plugins/TorrServe/service_api?cmd=torrserve_start |
pidof torrserver == false трактуется как «TorrServer is running» — проверка инвертирована; если TorrServe не найден или файла нет на Android, возвращается status=false |
Bazinga3 (код)448 |
| Показать версию и бэкенды внешнего бинарника | пункт «Изменения» выполняет bin/rclone version --config <data_dir>/config, скачивает info.txt с dune-club.info и отдельной кнопкой выводит rclone help backends |
info.txt скачивается с dune-club.info |
rclone (код)449 |
| Сделать миниатюру видео | do.php mark.it при thumb_file=1 для файла, просмотренного больше чем на 5% и без готовой миниатюры, вызывает /codecpack/script/thumb.sh "<файл>" "<каталог>/.<имя>.jpg" 350 <процент> |
зависит от Codec_install: при включении опции экран требует /codecpack/version.txt с v ≥ 24, иначе предлагает обновить или установить |
mark.it (код)450 |
| Обёртки управления в системе | создать /usr/bin/mpd-start/mpd-stop/mpd-restart над своим mpd.rc |
— | MPD (код)451 |
| Управлять сервисами Entware | экраны запуска/остановки по pidof, правка конфигов (/opt/etc/deluge/auth, /opt/etc/exports), OpenVPN --daemon --writepid с выбором *.conf/*.ovpn и .pass |
внешний IP OpenVPN-экран берёт со стороннего сайта; по сообщению автора, после установки Entware-ng включается telnet | Entware (код, форум)452 |
| Запустить локальный Transmission | rc.transmission start/stop из LTU (/ltu/etc/init.d) или OPT (/opt/etc/init.d) через exec |
тип определяется по наличию файлов LTU/OPT | RemTor (код)453 |
| Telnet, root и монтирования на Android | busybox telnetd через dunehd_service do и /config/telnetd; копирование .dsf; mount копий flashdata/config/tmp поверх …/emulated/0/DuneHD/<имя> |
— | Dune BackUp (код)454 |
| CLI-обёртка сервиса для ручного управления | tscli.php status/start/stop/list_torrents/… |
start ждёт до 10 с, stop — до 3 с |
Online Movies (TV Series) (код)455 |
13.10. Бэкап и восстановление данных¶
Выгрузка, загрузка и очистка каталога DATA — §10.6.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Бэкап своих настроек | zip всех .db из каталога данных плюс lcfg_proiptv_epg_*.txt из /config; полный вариант — с кэшем картинок |
— | ProIPTV (код)456 |
| Восстановить с откатом | проверить имя архива, распаковать во временный каталог, текущие .db → .prev, скопировать, при неудаче вернуть .prev; затем init_plugin(true) и ACTION_RELOAD |
принимается только имя proiptv_backup_<версия>_<дата>_<время>.zip |
ProIPTV (код)457 |
| Архив данных плеера | tar -z -v -c -p -f по списку путей; прогресс — find считает элементы, tar -v + awk; проверка tar -t, при ошибке файл удаляется |
— | Dune BackUp (код)458 |
| Восстановление на другой платформе | сравнить флаги платформы в settings.properties и отказаться при различии; после распаковки чужого бэкапа или на Android — chown -R по каталогу и chmod -R 777 |
длинный список исключений (свой плагин, кэши, данные чужой платформы) | Dune BackUp (код)459 |
| Восстановить один плагин из общего архива | tar -ztf → список плагинов → tar -x только путей выбранного, его plugins_data и cookies |
— | Dune BackUp (код)460 |
15. Веб-интерфейс, CGI и внешние приложения¶
Объект: CGI и веб-страницы плагинов Screenshoter, remote-control, Torrent Center, 101.ru, MegaRadio, surface_,
liteIPTV, ProIPTV, FREE TV, Smart_ (link_api), youtube_api/folder_cache, YouTube, TorrServe, MPD, служебных установщиков
hdtv, веб-плагинов; запуск плагинов и Android-приложений в Online services/Megogo/Okko (dunemdb), MegaTorrents,
MegaAnime, RemTor, Lampa bridge (dune-voice), Jellyfin Bridge; внешний инструмент watch-sync (code, кое-где forum).
Платформа и прошивка исполнения у плагинов не установлены; поведение платформы — SDK (doc), код tv188b r24 и
наблюдения на tv188b r25 (device).
Встроенный HTTP-сервер отдаёт www/* плагина по http://<STB>/plugins/<plugin_name>/* и исполняет www/cgi-bin/* по
http://<STB>/cgi-bin/plugins/<plugin_name>/* (SDK)461, причём не только локально, но и из локальной
сети (SDK)462. CGI-скрипт запускается run_plugin_cgi как shell-скрипт, поэтому PHP-обработчик плагин
вызывает сам (код r24)463. На tv188b r25 CGI получает PLUGIN_NAME, PLUGIN_CGI_DIR и
SCRIPT_FILENAME (устройство r25)464, текущий каталог — PLUGIN_CGI_DIR (устройство r25)465
и работает под root (устройство r25)466. Подробнее — guide/plugin-packaging.md §1
«Веб-часть плагина»; IP Control — guide/ip-control.md. Фоновые демоны, которыми управляют эти CGI, —
§13.
15.1. Свой PHP в CGI: обёртка do, php-cgi, php.ini и DuneSystem¶
Многие разобранные плагины с веб-частью несут однотипную shell-обёртку www/cgi-bin/do (у части — с шапкой «Andrii
Kopyniak» (код)467): она восстанавливает окружение плагина и запускает
свой php-cgi на do.php.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Восстановить окружение плагина в CGI | имя плагина — третий с конца компонент $PWD, каталог установки — путь без www/cgi-bin; задаются PLUGIN_TMP_DIR_PATH, PLUGIN_WWW_URL и PLUGIN_CGI_URL (последние два — на 127.0.0.1, у Screenshoter и Bazinga3 — с $HD_HTTP_LOCAL_PORT); PLUGIN_DATA_DIR_PATH — /persistfs/plugins_data/<имя>, иначе …/flashdata/plugins_data/<имя>, иначе пусто; Bazinga3 дополнительно выводит PLUGIN_NAME и PLUGIN_INSTALL_DIR_PATH из PWD и дописывает в LD_LIBRARY_PATH ./lib, /usr/lib и /tango3/firmware_ext/flashlite/lib |
одни обёртки учитывают $FS_PREFIX и HD_HTTP_LOCAL_PORT (Screenshoter, Radiorecord.ru), другие зашивают /tmp/plugins и http://127.0.0.1 (remote-control, rmfon.pl) |
Screenshoter (код)468; remote-control (код)469; Torrent Center (код)470; 101.ru (код)471; youtube_api/folder_cache (код)472; Smart_* (код)473; surface_* (код)474; MegaRadio (код)475; altIPTV (код)476; TorrServe (код)477; LTU_install (код)478; Bazinga3 (код)479 |
Запустить свой php-cgi |
подменить SCRIPT_FILENAME на do.php (у index — дописать .php), при необходимости дополнить LD_LIBRARY_PATH, выполнить ./php-cgi; Bazinga3 держит по копии обёртки на каждый CGI-скрипт (do, classActions, doHeader, hlsProxy, torrserve), копии отличаются только именем .php в подмене |
Screenshoter пишет stderr в cgi_err.log с ротацией после 10000 байт; у Bazinga3 обёртка копируется на каждый скрипт |
Screenshoter (код)480; remote-control (код)481; Torrent Center (код)482; Smart_* (код)483; mark.it (код)484; Bazinga3 (код)485 |
| То же на Android-прошивке | FS_PREFIX по умолчанию /data/data/com.dunehd.app, LD_LIBRARY_PATH с firmware/lib, SCRIPT_FILENAME из PLUGIN_CGI_DIR, REDIRECT_STATUS=200, php-cgi с cgi.force_redirect=0 |
по комментариям автора, run_plugin_cgi вызывает файл через sh и на Android 11, а php-cgi предпочитает SCRIPT_FILENAME опции -f |
Lampa bridge (код, форум)486 |
Нести php-cgi в пакете |
свой ELF www/cgi-bin/php-cgi; у части пакетов две сборки — основная и .platform.87xx/www/cgi-bin/php-cgi |
в строках php-cgi Screenshoter есть libphp5.so; использует ли он системную библиотеку — §19 |
Screenshoter (код)487; Smart_* (код)488; MegaAnime (код)489; mark.it (код)490 |
| Запустить PHP-скрипт поставщика | cd <bin> и $FS_PREFIX/firmware_ext/php/php-cgi -c <bin> -f ./run.php; свой bin/php.ini |
php-cgi из .platform.87xx пакета — CGI-сборка PHP 5, загружающая libphp5.so |
Online Movies (TV Series) (код)491 |
| Настроить PHP для CGI | свой www/cgi-bin/php.ini: cgi.force_redirect = 0, max_execution_time = 0, error_reporting = 0, date.timezone = UTC (набор у пакетов немного различается) |
ошибки PHP не выводятся; время CGI-скриптов пакета — UTC | Screenshoter (код)492; 101.ru (код)493; surface_* (код)494; MegaAnime (код)495; altIPTV (код)496; mark.it (код)484; Bazinga3 (код)497 |
| Получить свойства плагина в CGI | фреймворк плагина в CGI не подключается: do_config.php сам объявляет DuneSystem и заполняет DuneSystem::$properties из PLUGIN_* в $_ENV |
список переменных поддерживается вручную в обёртке и в do_config.php |
Screenshoter (код)498; Torrent Center (код)499; altIPTV (код)500; youtube_api/folder_cache (код)501 |
| Использовать код плагина вне оболочки | файл поставщика при отсутствии класса DuneSystem (например, из CGI) сам объявляет hd_print и DuneSystem и заполняет properties из __DIR__ (plugins/<name>/lib) и /persistfs или /flashdata |
— | Bazinga3 (код)502 |
У встроенного shell_ext на tv188b r25 (android-dune-fw, 261021_0117_r25) свой www/cgi-bin/php.ini:
cgi.force_redirect = 0, cgi.redirect_status_env = yes, date.timezone = UTC,
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED (E_WARNING включён), magic_quotes_gpc = 0,
display_errors = 0, log_errors = 1, error_log = /tmp/run/shell_ext_cgi.log
(код r25)503.
15.2. API плагина по HTTP: service_api, JSON и XML¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Взять данные из своего CGI в PHP-экране | HD::http_get_document(plugin_cgi_url . 'service_api?cmd=…') и json_decode |
TorrServe после torrserve_start ждёт 5 с и показывает лог |
LTU_install (код)504; TorrServe (код)368 |
| Управлять сервисом соседнего плеера | запрос к http://<ip>/cgi-bin/plugins/LTU_install/service_api?cmd=transmission_start |
— | RemTor (код)505 |
| Отдавать файлы shell-CGI | #!/bin/sh, FS_PREFIX, PATH_INFO; channels отдаёт файл или 404, epg ждёт до 120 × 0,1 с появления JSON, delay — иконку с Content-Length |
у channels дублирован заголовок Content-Type; epg ждёт файл, а не строит его |
ProIPTV (код)506 |
| Отдать M3U по HTTP | Content-type: audio/x-mpegurl и cat <data>/playlists${PATH_INFO} |
PATH_INFO не нормализуется (§19) |
remote-control (код)507 |
| XML-API в стиле IP Control | do.php отвечает text/xml с корнем command_result и protocol_version = 5, switch по cmd, пары <param name value> |
в успешном ответе player_state — имя команды, а не состояние плеера |
remote-control (код)508 |
| JSON-API для своей веб-страницы | do.php берёт action из GET или POST, отвечает application/json, без action — status=error |
del_el удаляет файл по пути из POST без проверки |
Screenshoter (код)509 |
| Принять действия и загрузки с веб-страницы | link.php по POST action; file пишет загруженный файл |
do_img.php передаёт img прямо в file_get_contents, file пишет по пути из имени поля формы; save_cutname и vsetvIDupd ответа не возвращают |
liteIPTV (код)510 |
| Ответ PHP-помощника | статус — return строк JSON, ответ service_api — echo |
при ложном pidof возвращается status=true |
Torrent Center (код)511 |
15.3. Прокси картинок и потоков через свой CGI¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Отдать постер через локальный URL | в элементе — plugin_cgi_url . 'do?img=<url>'; do.php скачивает URL и отдаёт с Content-Type: image/jpeg |
тип фиксирован; у youtube_api/folder_cache и YouTube при GIF89a4 или ошибке запасная картинка дописывается после уже выведенного ответа; у Radiorecord.ru запасного файла в пакете нет |
Torrent Center (код)512; Smart_* (код)513; youtube_api/folder_cache (код)514; YouTube (код)515; surface_* (код)516 |
| Грузить постер через прокси плагина | при включённом прокси в элементе — <plugin_cgi_url>do?img=<url>&proxy=<cName>; do.php читает proxySettings (proxy, proxyType=SOCKS5 → CURLOPT_PROXYTYPE 7, proxyAccount), для относительного img при заданных cName и DomainName дополняет домен настройкой <cName>DomainName или переданным DomainName, при GIF89a4, ответе 40x или false отдаёт rPath либо icons/poster_none.png, иначе при savePath сохраняет картинку в файл |
при прокси относительный URL дополняется доменом | Bazinga3 (код)517 |
Прокси на shell без php-cgi |
img.sh: curl --include $QUERY_STRING; curl выбирается по platform_kind из /tmp/run/versions.txt из сборок в bin/, иначе прошивочный |
Filmix_API направляет постеры через img.sh только при DUNE_FIRMWARE_BN < 11 |
FREE TV (код)518; Smart_* (Filmix_API) (код)519 |
| Переписать HLS-плейлист на себя | space.sh переписывает ссылки в .m3u8 на http://127.0.0.1:$HD_HTTP_LOCAL_PORT$SCRIPT_NAME?… |
запросы идут с User-Agent WINK и сторонним Origin |
FREE TV (код)520 |
| Проксировать HLS своим CGI | hlsProxy.php?path=<url>: cURL с Content-Type: application/vnd.apple.mpegurl, если в URL есть m3u8, иначе video/mpegts; опции — из сериализованного <tmp_dir_path>/hlsProxyArgs (['rp'] при rp и наличии ключа, иначе ['opts']); при rp строки плейлиста переписываются на <plugin_cgi_url>/hlsProxy?path=… |
вне hlsProxy.php в PHP-коде пакета нет ни ссылок на hlsProxy, ни записи hlsProxyArgs; кто их создаёт — §19 |
Bazinga3 (код)521 |
| Отдать m3u8 с нужными заголовками | do3.php/doHeader.php: cURL с Referer и User-Agent, ответ application/vnd.apple.mpegurl; резолвер возвращает <plugin_cgi_url>doHeaderBazon?path=…; у Bazinga3 doHeader.php проксирует path как m3u8 с зашитым Referer https://farsihd.pw и User-Agent Opera/9.80 |
прокси FilmHD1080.Net включается только для URL с vkuservideo.net; у Bazinga3 один зашитый Referer |
Smart_* (код)522; link_api (код)523; Bazinga3 (код)524 |
| RTMP/RTSP/FLV через Codec_install | поток через CGI codecpack на 127.0.0.1:81; при необходимости запустить httpd -h /codecpack/WWW -p 81 |
нужен установленный /codecpack; парсер KinoProfi без /codecpack и не на Android сразу возвращает false |
altIPTV (код)525; link_api (код)526 |
15.4. Веб-страница плагина в www/¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Страница с кнопками, вызывающими свой CGI | index.php с кнопками; index.js зовёт do относительным URL; во время записи статус опрашивается раз в секунду |
— | Screenshoter (код)527 |
| Взять готовое веб-приложение для страницы | do.php использует AudioAddict: application.css, remote.js, application.js, объект this.AudioAddict.API.Config, вызов di.app.start({}), событие start:module ChannelBrowserApp и контейнеры секций Favorites, User Radio, Radio Channels и Personal radio |
— | 101.ru (код)528 |
| Галерея файлов по HTTP | симлинки <storage>/screenshots → www/dss, <imem>/screenshots → www/sdss; ссылки через PLUGIN_WWW_URL с IP устройства вместо 127.0.0.1 |
работа сервера по симлинкам — §19 | Screenshoter (код)529 |
| Запустить радио из браузера без ТВ | список станций со ссылками javascript:playCode(…); link.php разрешает поток и вызывает http://127.0.0.1/cgi-bin/do?cmd=start_file_playback&media_url=… (MegaRadio — start_playlist_playback с M3U в /tmp/www; Radiopotok.ru вызывает start_file_playback прямо из JS) |
по сообщениям пользователей, так радио 101.ru запускается без включения ТВ | 101.ru (код, форум)530; surface_* (код)531; MegaRadio (код)532 |
| Веб-пульт | keyCode() → http://<ip>/cgi-bin/do?cmd=ir_code&ir_code=<код>; IP устройства — из ifconfig |
коды зашиты в HTML; 101.ru и MegaRadio при открытии страницы шлют A05FBF00 |
101.ru (код)533; MegaRadio (код)534; surface_* (код)535 |
| Добавить станцию с веб-формы | POST send проверяет path/name и наличие http, добавляет станцию в начало плейлиста |
— | MegaRadio (код)536 |
| Переиспользовать веб-среду другого плагина | побайтно одинаковые do, do_config.php, php.ini, переводы; отличаются do.php и remote.js |
— | surface_* (код)537 |
| Импорт файла пользователя и чтение cookies на странице | первый user_radio.m3u по mount_path из /tmp/run/storage_list.xml; избранное — regex по /config/<plugin_name>_plugin_cookies.properties |
читается только первый найденный файл | 101.ru (код)538 |
| Админка плейлистов и архивов | index.php (режимы full/sorted), playlists.php, arhive.php (URL, 1–20 дней, User-Agent) |
см. пути из запроса в §15.2 | liteIPTV (код)539 |
| Локальное веб-приложение как плагин | страница на 127.0.0.1/plugins/<name>/ (index.html, у bonus-tv — ping.html), файлы — в www/; параметры background_color, input_handler |
— | веб-плагины (код)540 |
| Плагин-ярлык на внешний сайт | ровно одна entry_point, её key_enter — launch_media_url с URL в actions/key_enter/data/url; у 12 php-плагинов main.php — 6 байт (только <?php), у plain-манифестов нет params/program |
точка входа целиком задана манифестом; 12 из 18 плагинов ведут на внешний сайт, 4 — на 127.0.0.1/plugins/<имя>/, 2 — на swf://plugin_file:// |
веб-плагины (код)541 |
| Включить полноэкранный ТВ-режим веб-приложения | для www:// документ перечисляет fullscreen, webapp_keys, zoom_level, overscan, user_agent, background_color, osd_size и рекомендует для полноэкранных ТВ-приложений fullscreen=1, webapp_keys=1, zoom_level=100, overscan=0, а для тёмных — background_color=black; fullscreen=1 — страница на весь экран, webapp_keys=1 — JS обрабатывает все клавиши (при 0 часть клавиш, например STOP, обрабатывает браузер), zoom_level=100 — без масштабирования, overscan=0 — без обрезки |
документ рекомендует эти значения для полноэкранных ТВ-приложений; user_agent переопределяет UA браузера, background_color по умолчанию white, osd_size задаёт разрешение отрисовки |
веб-плагины (SDK)542 |
| Нестандартные параметры web-URL | zoomby — единственный манифест с webapp_keys=2 и input_handler=1; impulstv запускает внешний URL с input_handler=0 и osd_size=1280x720, без exit_key, power_key и volume_handler; libduneshell.so r24 разбирает также input_handler, engine_flags, navigation_highlight, exit_key, power_key, auto_auth_cancel, volume_handler и hbbtv |
документ эти параметры не описывает | веб-плагины (код)543 |
| HTML/Flash-плагин без PHP | type=plain, без program; main.php не нужен |
для чистых FlashLite/HTML-плагинов | веб-плагины (код, SDK)544 |
| Отдать сгенерированный файл плееру | перезаписать www/<файл>.m3u, sync, вернуть plugin_file:///www/<файл>.m3u |
CGI у плагина нет | DunePlexCatalog (код)545 |
| Показать веб-интерфейс стороннего демона | экран показывает адрес http://<ip>:<порт> (TorrServe 8090, peerflix-server 9000, Transmission 9091, Deluge 888, rclone 5572); rclone ждёт адрес до 120 опросов и строит QR через api.qrserver.com |
логин rclone по умолчанию admin/admin; по сообщениям пользователей, Dropbox через WEB GUI rclone не добавлялся, место на флеше выросло с 2 до 25 МБ, config после остановки пропадал |
TorrServe (код)546; PeerflixServer (код, форум)547; Entware (код)548; rclone (код, форум)549 |
| Подменить CGI прошивки (Flash) | install_cgi.sh: killall httpd, собрать /tmp/cgi-bin, смонтировать его поверх /firmware/ext_command/cgi-bin, запустить httpd заново |
требует bin/native.cgi и bin/curl.867x; меняет общий httpd прошивки |
веб-плагины (код)550 |
| Плагин без веб-части и настроек | в пакете нет www/, cgi-bin/, файлов настроек и кода их сохранения |
веб-интерфейса и собственных настроек нет | Apple Trailers (код)551 |
15.5. IP Control из CGI плагина и из внешнего приложения¶
Другие обращения к сети приставки (сетевые папки, multicast) — §9.6.
IP Control — локальный /cgi-bin/do прошивки (guide/ip-control.md). На r25 его команды ждут конца
идущей операции плагина (устройство r25)552.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Запустить воспроизведение на плеере из своего CGI | file_get_contents('http://127.0.0.1/cgi-bin/do?cmd=start_file_playback&media_url=…') |
— | 101.ru (код)553; surface_* (код)554; MPD (поток http://127.0.0.1:8000) (код)555 |
| Перезагрузить плеер снаружи | cmd=ir_code с A15EBF00 раз в секунду до player_state=standby, затем A05FBF00 до выхода из standby |
вызов helper exec_do в rc_extension.bash закомментирован |
remote-control (код)556 |
| Управлять курсором с телефона | dune_rc_extension_mipsel слушает --port (по умолчанию 7777) и пишет x y buttons wheel в /sys/devices/platform/vms/coordinates; vmdriver_864x.ko, vmdriver_8671.ko и vmdriver_8674.ko — «Virtual mouse driver» Dune HD; rc_extension.bash по uname -r выбирает чип 864x/8671/8674/86??, снимает старый модуль rmmod, загружает новый insmod и перезапускает сервер |
нужен модуль ядра под конкретный чип | remote-control (код)557 |
| Найти IP Control из Android-приложения | кэшированный порт, иначе перебор 80 и 11080; Proxy.NO_PROXY; принять ответ при HTTP 200, protocol_version и command_status=ok |
— | Lampa bridge (dune-voice) (код)558 |
| Следить за позицией плеера из JS | cmd=status&result_syntax=json на 127.0.0.1 и 127.0.0.1:11080; ответ Dune — строки product_id/player_state, непустой product_name, protocol_version ≥ 5; опрос ~1 с, wake() на focus/pageshow/visibilitychange |
сессия ожидания истекает через 180 с, любая — через 12 часов | Lampa bridge (код)559 |
| Разбудить плеер перед командой | при !power.isInteractive() — WakeActivity с FLAG_ACTIVITY_NEW_TASK и ожидание до 5 с |
standby не отправляется, если устройство уже в режиме ожидания |
Lampa bridge (dune-voice) (код)560 |
| Управлять плеером и оболочкой | home → cmd=main_screen, standby → cmd=standby; при player_state *_playback — playback_action&action=stop или set_playback_state&speed=0/256; вне воспроизведения — медиа-клавиши через AudioManager |
— | Lampa bridge (dune-voice) (код)561 |
Таймер сна через cmd=standby — §13.6.
15.6. Запуск, установка и удаление других плагинов и встроенных приложений¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Открыть другой плагин или предложить установить | проверить имя в /tmp/run/installed_plugins.xml; есть — plugin_launcher://<имя>, нет — plugin_installer://<url>:::name=…&space_needed=…&need_confirm_replace=0 |
— | LTU_install (код)562; Entware (код)563 |
| Открыть своё приложение из настроек | кнопка go2app в AceSearchSetupScreen (ветка elseif action_type=apply) отправляет LAUNCH_MEDIA_URL_ACTION_ID с LaunchMediaUrlActionData::url = plugin_launcher://acestreamsearch |
ветка apply идёт после confirm |
AceStreamSearch (код)564 |
| Поставить зависимость и сразу её открыть | launch_media_url с plugin_installer://… и post_action plugin_launcher://<имя> |
на Android YouTube ставит другой пакет (ffmpeg_install) и вместо запуска делает reset_controls |
YouTube (код)565; liteIPTV (код)566 |
Поставить вспомогательный плагин из своего www/ |
записать файл install (version_index, space_needed, download_url) и запустить plugin_installer://<plugin_www_url>install:::schema=1&name=… |
— | Dune BackUp (код)567 |
| Ставить плагины и APK из внешнего списка | коллекции Dune BackUp загружают список с dl.dropboxusercontent.com или dune-club.info через my_wget, затем устанавливают выбранное маркерами !install_plugin! или !install_apk! (или скачивают файл через curl), а для плагинов и APK возвращают !return_start!; «Коллекция файлов» качает выбранный URL прошивочным curl с прогрессом из tmp/log_curl |
установка управляется маркерами из внешнего списка | Dune BackUp (код)568 |
| Удалить плагин | launch_media_url('plugin_uninstaller://<имя>') |
GlobalTV делает это только для страны CN | GlobalTV (код)569; altSource (код)398 |
| Передать задание другому плагину | JSON {url, plugin} в /tmp/run/remtor.in, затем plugin_launcher://{name=rem_tor}; приёмник при входе видит файл, отвечает в remtor.out и возвращает plugin_launcher://<plugin>; отправитель принимает ответ только со своим plugin |
по сообщению автора, так RemTor принимает magnet от сторонних плагинов | RemTor (код, форум)570 |
| Настроить или переустановить чужой плагин из своего меню | пункт меняет ext/TorrServer.php плагина dunemdb_supplier_online_movies (torrServAction 1/0), bin/rec.sh Screenshoter (1280x720/1920x1080), content_box_y темы иконок (400↔630; при установке 630 обнуляет cycle_mode_gap_width/cycle_mode_gap_icon_path), пишет выбранное зеркало Jackett в config/online_movies_jacket.txt (или удаляет файл для default), а также удаляет dunemdb_supplier_online_movies маркером !uninstall_plugin! и ставит выбранный архив mod_85.tar.gz/86.tgz маркером !install_plugin! |
правки файлов чужих плагинов; пункты возвращают !reboot!, переустановка online_movies — !OFF_ON! |
Dune BackUp (код)571 |
| Запустить действие плагина из чужого плеера | одноэлементный www/launch.m3u с plugin_launcher://{name=…}{action_id=play} |
по комментарию автора, выбор плеера Android не принимает схему plugin_launcher, поэтому нужен M3U; на r25 plugin_launcher в M3U передаёт from в user_input (guide/ip-control.md §2) |
Lampa bridge (код, форум)572; r25 (устройство r25)573 |
| Открыть папку во встроенном файловом браузере | embedded_app://{name=file_browser}{url=…}; /tmp/mnt/storage → storage_name://, SMB → smb://[user:password@]host, NFS → nfs-tcp:///nfs-udp:// |
— | surface_* (код)574; YouTube (код)575 |
15.7. Android-приложения: am start, deeplink и предложение установки¶
Поставщики dunemdb отвечают оболочке командой запуска приложения; оболочка запускает её через launch_ext_app, а
error.missing_app превращает в установку приложения (код r24)576. На tv188b r25 строку am start … разбирает само приложение
оболочки, без запуска am или sh (устройство r25)577. Протокол поставщика целиком —
guide/movie-suppliers.md §4 и §8.
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Принять команду оболочки | run.php: ровно один аргумент, JSON из stdin, JSON в stdout; поддержан только start_playback_app |
другое число аргументов — Usage и код 1; невалидный JSON и неизвестная команда — error |
Online services (код)578; Megogo (код)579; Okko (код)580 |
| Ответить командой запуска | {bin: "am start …", package, wait_app_start_delay: 10, title, indirect, urls} |
Online services берёт только первую публикацию; у Okko в run.py ответ без title/indirect/urls |
Online services (код)581; Megogo (код)582; Okko (код)583 |
| Предложить установить приложение | проверить пакет по $FS_PREFIX/tmp/applications/app_data.json или /data/data/<пакет>; нет — error.missing_app с title, package, indirect: true, urls |
Megogo выбирает URL по пакету только в run.py |
Online services (код)584; Megogo (код)585; Okko (код)586 |
| Достать пакет из deeplink | package=([^;]*), иначе часть component= до /, иначе таблица «сервис/домен → пакет»; замена com.netflix.ninja на com.netflix.mediaclient по HD_FW_APK/HD_APK |
компонент без / или с / в начале пакета не даёт |
Online services (код)587 |
Собрать am start |
по умолчанию am start '<deeplink>'; не intent:…#Intent — для http при пустом FS_PREFIX am start -d, при известном пакете -p '<package>'; либо явная форма -a VIEW -d megogo://video/<id> <пакет> или intent://…#Intent;scheme=…;package=…;end |
у Megogo в run.py три пакета, для net.megogo.box — своя activity и GLOBALSEARCH; Okko делит id публикации по :; в run.php Okko закомментирован старый вариант am start -d 'yotaplay://movie?…', рабочей остаётся intent-форма |
Online services (код)588; Megogo (код)589; Okko (код)590 |
| Найти и запустить activity установленного приложения | найти пакет в /tmp/applications/app_data.json и выполнить am start <package>/<activity> |
MegaTorrents после запуска ждёт 15 с и проверяет сервис | MegaTorrents (код)591; Torrent Center (Transmission BTC) (код)592 |
| Открыть файл внешним приложением по MIME | am start -a android.intent.action.VIEW с video/*, audio/x-mpegurl, application/x-bittorrent, image/* |
— | MegaAnime (код)593; Torrent Center (код)594 |
Отдавать .torrent Android-приложению |
дописать объект TORRENT в /config/app_by_file_ext.json |
меняется общий конфиг плеера | Torrent Center (код)595 |
| Голосовой ввод через отдельное приложение | удалить our_file.txt в данных приложения через dunehd_service do, затем am start com.example.dunevoice -a android.intent.category.DEFAULT |
по сообщениям в теме, нужно поставить DuneVoice.apk |
YouTube (код, форум)596 |
| Поставить APK из плагина | ActionFactory::download_and_install_apk возвращает DOWNLOAD_AND_INSTALL_APK_ACTION_ID с caption, package, urls, indirect и post_action, если константа определена; Bazinga3 на Android при отсутствии /data/data/com.example.dunevoice, если не сработал ранний возврат диалога о доступе к Кинопоиску, plugin_cookies->duneVoiceAsk === 0 и не задан $user_input->install, показывает диалог установки DuneVoice с http://dune-club.info/plugins/update/_other/DuneVoice.apk |
при отсутствии константы действие — null; dontAsk пишет 1 в plugin_cookies->duneVoiceAsk |
Bazinga3 (код)597 |
| Собрать APK и настройки установленных приложений | пункт «Создать файлы apk» читает tmp/applications/app_data.json, берёт caption, package_name, version, source_dir и копирует найденные в /data/app/ файлы в dune_bcp/dune_apk_(<ID>)/<caption><version>.apk; пункты настроек копируют каталоги NUM, SmartTube и ButtonRemapper в dune_bcp/abcp_ГГГГ_ММ_ДД и обратно (при восстановлении удаляется прежний NUM) |
данные приложений не сохраняются | Dune BackUp (код)598 |
15.8. Своё Android-приложение рядом с плагином: dune-voice и Jellyfin Bridge¶
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Видеть пакеты Dune и Lampa | <queries> с com.dunehd.app и top.rootu.lampa; minSdkVersion 26, targetSdkVersion 30 |
— | Lampa bridge (dune-voice) (код)599 |
| Перехватить кнопку микрофона и выполнить «Назад» | accessibility-сервис RemoteKeys (flagRequestFilterKeyEvents); «Назад» — performGlobalAction(GLOBAL_ACTION_BACK) |
без включённого сервиса — ошибка «Включите службу кнопки микрофона»; подробнее — guide/input-dialogs.md §4.6 | Lampa bridge (dune-voice) (код)600 |
| Открыть поиск в другом приложении | Lampa — явный компонент и ACTION_SEARCH с extra query; YouTube-клиенты — ACTION_VIEW на youtube.com/results?search_query=… с setPackage |
SmartTube игнорирует ACTION_SEARCH |
Lampa bridge (dune-voice) (код)601 |
| Громкость | AudioManager.adjustStreamVolume(STREAM_MUSIC, ADJUST_*, FLAG_SHOW_UI) в главном потоке |
— | Lampa bridge (dune-voice) (код)602 |
| UI-действие из фонового потока | сразу в главном Looper или FutureTask через Handler(mainLooper) с ожиданием до 5 с |
— | Lampa bridge (dune-voice) (код)603 |
| Не блокировать UI поиском файла | поиск в рабочем потоке, запуск плеера — в главном, только если activity не isFinishing()/isDestroyed(); ошибка поиска — запуск по исходному URL |
— | Jellyfin Bridge (код)604 |
| Опрашивать статус плеера | один планировщик: раз в 250 мс, пока начальная перемотка не подтверждена и прошло меньше 30 с, затем раз в 1000 мс | — | Jellyfin Bridge (код)605 |
15.9. JS-плагин для Lampa: подмена плеера на нативный плеер Dune¶
Объект: dune-native-player.js и dune-local-progress.js в Lampa bridge 1.0.1 (code).
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Подключиться и не сломать другой плагин | не ставиться повторно при window.DuneNativePlayer или без AndroidJS; после appready заменить Lampa.Android.openPlayer обёрткой; destroy() возвращает исходный метод, только если на месте всё ещё обёртка |
— | Lampa bridge (код)606 |
| Не запустить плеер по устаревшему ответу | счётчик sequence и флаг dead: поздние колбэки выходят, если id не текущий |
— | Lampa bridge (код)607 |
| Собрать карточку и плейлист для моста | карточка из data.card → data.movie → активный экран; payload — только title, description, poster, items, index, position |
субтитры не передаются; название до 512, описание до 15000 символов | Lampa bridge (код)608 |
| Отказаться от нативного пути целиком | headers, больше 250 элементов, невалидный элемент, ненайденный URL, выключенная настройка или молчание моста — вызвать исходный openPlayer |
без частичной подмены | Lampa bridge (код)609 |
| Передать плейлист и открыть нативную карточку | запрос к CGI api; принять ответ только с plugin и точным launch_url; подменить URL на launch.m3u, удалить playlist и вызвать исходный openPlayer |
по комментарию автора, второй плейлист в Android APK строить нельзя: timeline-колбэки Lampa уже привязаны к исходному | Lampa bridge (код, форум)610 |
| Добавить настройки в Lampa | при наличии Lampa.SettingsApi плагин добавляет компонент «Dune HD», addParam для dune_native_player_enabled (по умолчанию true) и dune_native_torrserver_url с подсказкой http://SERVER:8095 |
при изменении URL запоминается source — базовый URL выбранного в Lampa TorrServer (torrserver_url или torrserver_url_two по torrserver_use_link) |
Lampa bridge (код)611 |
15.10. Внешний инструмент по adb: синхронизация истории просмотра (watch-sync)¶
Объект: dune-hd-watch-sync 0.1.0 — Python-сервис на NAS, который пишет историю просмотра плеера по adb (code;
поведение плеера — со слов автора, forum).
| Задача | Приём | Грабли и ограничения | Плагины и claims |
|---|---|---|---|
| Записать файл в каталог приложения | adb push в /data/local/tmp/dunesync, затем cat tmp > target, chown system:system, chmod 644, restorecon, sync |
по сообщению автора, adb push прямо в каталог приложения делает файл root, а редирект сохраняет владельца, режим и SELinux-контекст |
watch-sync (код, форум r22)612 |
| Заставить навигатор перечитать историю | am force-stop com.dunehd.app, пауза 2 с, am start -n com.dunehd.app/com.dunehd.shell.MainActivity |
по сообщению автора, без force-stop запись не вступает в силу, без am start приложение поднимается полуинициализированным; am start не будит спящий плеер |
watch-sync (код, форум r22)613 |
| Не потерять несброшенную историю | писать, только если есть расхождения, плеер в navigator/standby/loading и mtime истории сдвинулся после конца file_playback |
по сообщению автора, force-stop может потерять ещё не сброшенный сеанс |
watch-sync (код, форум r22)614 |
| Писать формат байт-в-байт | шарды по 40 записей, %06d.json, одна запись на строку, UTF-8 без \u; удалённая запись — ровно {"deleted": 1}; timestamp — unix-время в микросекундах |
— | watch-sync (код)615 |
| Включать запись осторожно | по умолчанию dry_run=true; write: false для плеера только для чтения; бэкап перед каждой записью, последние 30 на плеер |
— | watch-sync (код)616 |
Вызывать adb из скрипта |
всегда stdin=/dev/null |
adb shell читает stdin и при запуске из пайпа съедает остаток скрипта |
watch-sync (код)617 |
| Держать сервис запущенным | watch.sh сканирует /proc, выходит, если python3 -m dunesync уже работает, иначе exec с логом |
— | watch-sync (код)618 |
Расхождения¶
Объект: места, где плагины делают одно и то же по-разному или где код плагина расходится с документацией и
кодом платформы; плагины (code, платформа и прошивка исполнения не установлены), SDK плагинов (doc) и прошивки,
если на них есть ссылка. Связь conflicts_with указана там, где она заведена; где её нет — это кандидат для lead.
Сеть¶
- Успешный HTTP-код в
HD::http_get_document. Хелпер прошивки tv188b r24 бросаетDuneCurlExceptionпри любом коде, кроме 200 (код r24)2; копия в GlobalTV считает успехом 200 и 201 (код)23. Связиconflicts_withнет (это разные реализации, а не спор источников о поведении). - Реакция хелпера на сетевую ошибку. Одноимённый
HD::http_get_documentв разных плагинах при ошибке бросает исключение (код)6, возвращает пустую строку (код)8, возвращаетnullна 404 (код)24 или только пишет лог и возвращает тело (код)25. Код, перенесённый из одного плагина в другой, меняет поведение при ошибке. Связиconflicts_withнет.
Настройки¶
- Cookie видимости значка в surface_. SDK: видимость точки входа задаёт cookie из
show_cookie_name(SDK)193; surface_ объявляет в манифестеshow_application, но ни один из трёх плагинов его не пишет — rmfon.pl и wwcam пишутshow_tv(код)196. Это несогласованность плагина с собственным манифестом, связиconflicts_withнет. - Две копии
smbtreeс разным списком «проблемных» платформ. В Radiorecord.ru копия вsurface_file_screen.phpпроверяет только 8672, а копия вdo_config.php— 8672, 8673 и 8758 (код)619; liteIPTV включает обход для 8672, 8673 и 8758 (код)251. Последствие для 8673/8758 — гипотеза, см. §19. Связиconflicts_withнет. - Путь к
network_folders.properties. В remote-control модульnetwork_folderчитает/config/network_folders.properties, аsources—/mnt/config/network_folders.properties; совпадают ли эти файлы на устройстве, не проверено (код)620. Torrent Center читает/config/…(код)104. Связиconflicts_withнет. - *
get_data_pathв семействе Smart_. В YouTubeSmartConfig::get_data_pathвозвращает путь, а в эталоне семейства значение не возвращается (код)240; KinoFrance, MoviesTape и Vimeo строят путь тем же приёмом (код)239. Расхождение копий кода, связиconflicts_withнет.
Фон¶
- Cron на Android-прошивке. Torrent Center пишет
/tmp/cron/crontabs/rootи перезапускает системныйcrondчерезdunehd_service do(код)389; Widget Ext приHD_APK=1системныйcrondне запускает и крутит свойbin/crond.sh(код)621. Почему на APK нужен свой цикл — гипотеза, см. §19. Связиconflicts_withнет. - Таймер сна: IP Control или ИК-код. altIPTV, liteIPTV и Smart_* ставят в cron
wgetнаcmd=standby(код)622; Torrent Center и altSource пишут в cronecho A15EBF00 > /proc/ir/button(код)623. Что делает запись кода — не проверено (§19). Это разные приёмы, а не противоречие; связиconflicts_withнет. - Действие на
boot: толькоplugin_systemили нет. SDK: дляbootподдерживается толькоplugin_system(SDK)317; в r24 встроенный radiotime, по предположению, ставит вbootrun_builtin— этоinference(§19), поэтому вопрос не решён. Связиconflicts_withесть у обеих сторон.
Веб и приложения¶
- Окружение CGI: вычислять из
$PWDили брать готовое. Обёрткиdoмногих плагинов вычисляют имя плагина как третий с конца компонент$PWD(код)624; на tv188b r25 (device) CGI сам получаетPLUGIN_NAME,PLUGIN_CGI_DIRиSCRIPT_FILENAME(устройство r25)464, и обёртка Lampa bridge берётSCRIPT_FILENAMEизPLUGIN_CGI_DIR(код)625. Противоречия нет: старые обёртки просто не опираются на переменные прошивки; на каких прошивках эти переменные есть, кроме r25, в базе не описано. Связиconflicts_withнет. - Ответ поставщика Okko в двух вариантах.
run.phpвозвращаетbin,package,wait_app_start_delay,title,indirectиurls(код)626,run.py— толькоbin,packageиwait_app_start_delay(код)627. Различие внутри одного пакета; связиconflicts_withнет.
Не проверено¶
Объект: гипотезы (inference) и оспоренные утверждения (disputed) из разборов плагинов, относящиеся к
приёмам этой главы; платформа и прошивка — как в scope claim. Это кандидаты на проверку в коде или на устройстве;
в разделах выше они не цитируются.
| Утверждение | Уровень, статус | Claim | Раздел |
|---|---|---|---|
wget на устройствах, возможно, не умеет HTTPS — поэтому Widget Ext качает https-сервис Gismeteo отдельным curl |
inference | (вывод)628 | §9 |
Init-скрипты tv175u r24/r22 пишут /tmp/run/versions.txt строками key=value (формат, по которому Widget Ext выбирает curl) |
code, disputed | (код r22, r24)629 | §9 |
На Sigma-платформах platform_kind в versions.txt, вероятно, — 4-символьный код чипа (87xx/864x/867x/865x) |
inference | (вывод)630 | §9 |
zlostnyi: проверка ошибки медиатеки is_null($doc) не ловит строку nottoken от HD::check_token, и сообщение о неверном ключе не показывается |
inference | (вывод)631 | §9 |
RemTor: checkconnect может зациклиться, если get_session_stats вернёт пустой массив без исключения |
inference | (вывод)632 | §9 |
Twitch TV: при резервной регулярке HLS во второй группе оказывается запятая вместо RESOLUTION |
inference | (вывод)633 | §9, §17 |
Online Movies (rus): с упакованным link_api.php вызов zonaMobi::getRCPC() — фатальная ошибка |
inference | (вывод)634 | §9, §17 |
watch-sync: позицию во время воспроизведения можно получить только по HTTP (cmd=status), на диск она попадает после остановки |
inference | (вывод r22)635 | §9 |
| MegaRadio: без LISTEN KEY категории DI.FM не заполняются | inference | (вывод)636 | §9 |
Виджет погоды оболочки, вероятно, показывает данные из $FS_PREFIX/tmp/weather.txt, поэтому Widget Ext подменяет источник данных встроенного виджета, а не рисует свой |
inference, disputed | (вывод)637 | §10 |
WeburgTV: раз do_get_control_defs возвращает null, полей buffer_time и epg_shift на экране нет и ветки их сохранения недостижимы |
inference | (вывод)638 | §10 |
youtube_api/folder_cache (YouTubeMult): data_type, data_dir и SMB-поля не влияют на файлы избранного и поиска — lib/utils.php всегда пишет в data_dir_path |
inference | (вывод)639 | §10 |
MegaAnime: HD::pCopyFolders и ряд методов SmartConfig вызываются, но в пакете не определены; если link_api.php их не добавляет, выгрузка/загрузка DATA завершится fatal error |
inference | (вывод)640 | §10 |
PeerflixServer: пока config->tmp равен /D/torrent-stream, экран скрывает панель сервера — после установки нужно выбрать накопитель |
inference | (вывод)641 | §10 |
surface_* (Radiorecord.ru): на 8673 и 8758 файловый экран не включает обход бага SMB, потому что его копия get_bug_platform_kind() проверяет только 8672 |
inference | (вывод)642 | §10 |
Цикл crond.sh Widget Ext для APK — не настоящий cron: читает интервал из $FS_PREFIX/tmp/cron/interval и в бесконечном цикле со sleep вызывает скрипт погоды |
code, disputed | (код)643 | §13 |
При HD_APK=1 crontask.sh заменяет системный crond своим циклом, вероятно, потому что crond там недоступен без root; HD_APK=1 выставляет и Android-прошивка Dune, а не только сторонний APK |
inference, disputed | (вывод r24)644 | §13 |
umount монтирует сетевую папку при каждой загрузке через свой переписанный global_actions/boot; правка подхватывается, только если оболочка перечитывает dune_plugin.xml |
inference | (вывод)645 | §13 |
Автостарт PeerflixServer может не срабатывать там, где /bin/sh не понимает bash-подстроку ${ROOT_DIR::${#ROOT_DIR}-4} в bin/boot_end.sh |
inference | (вывод)646 | §13 |
Запись A15EBF00 в /proc/ir/button выключает плеер; запись IR-кода туда эмулирует нажатие кнопки пульта |
inference | (вывод)647 | §13 |
В r24 на событие boot, вероятно, допустимо не только plugin_system: встроенный radiotime ставит туда run_builtin |
inference | (вывод r24)648 | §13 |
HTTP-сервер устройства отдаёт файлы и по симлинкам www/dss/www/sdss, на чём строится галерея Screenshoter |
inference | (вывод)649 | §15 |
Bazinga3: hlsProxy.php и файл hlsProxyArgs включает внешний link_api.php, которого в пакете нет; в копии link_api ##673## запись hlsProxyArgs и URL hlsProxy?rp= есть, но закомментированы |
inference | (вывод)650 | §15 |
Через CGI playlists remote-control можно прочитать файл вне каталога плейлистов: PATH_INFO не нормализуется |
inference | (вывод)651 | §15, §17 |
www/cgi-bin/.htaccess 101.ru — чужой конфиг (пути Nextcloud), плагином не используется |
inference | (вывод)652 | §15 |
PeerflixServer не участвует в воспроизведении: торрент добавляется и раздаётся через веб-интерфейс peerflix-server на :9000 |
inference | (вывод)653 | §15 |
com.example.dunevoice в YouTube и org.duckdns.dunevoice.tv в dune-voice — разные сборки голосового ввода |
inference | (вывод)654 | §15 |
Ветка перезапуска своего плагина plugin_launcher://{name=<plugin_name>} в YouTube недостижима: control_id aplаy (с кириллической «а») нигде не создаётся |
inference | (вывод)655 | §15 |
watch-sync (Solo 8K, Pro 8K Plus, Android-прошивка r22): отметка «просмотрено» в навигаторе выводится из самих записей истории, а не из watched_files.txt/watched_movies.txt |
inference | (вывод r22)656 | §10 |
-
fw-tv188b-260827-0003-r24--php-framework.c056 · code · tv188b, android-dune-fw; прошивка 260827_0003_r24 · HD::http_get_document по умолчанию отключает проверку TLS-сертификата (CURLOPT_SSL_VERIFYPEER=false), следует редиректам, ставит CURLOPT_ENCODING=1 и тайм-ауты из $DEFAULT_CURL_*; опции вызывающего применяются поверх ↩
-
fw-tv188b-260827-0003-r24--php-framework.c058 · code · tv188b, android-dune-fw; прошивка 260827_0003_r24 · HD::http_get_document бросает DuneCurlException при ошибке curl и при любом HTTP-коде, кроме 200 (включая 301/302/304); при ошибке curl создаёт флаг /tmp/run/network_monitor/force_check_on_error ↩↩
-
fw-tv188b-261021-0117-r25.c249 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 в php_server и php-cgi curl_version() сообщает version 7.67.0, ssl_version OpenSSL/1.0.1u, libz_version 1.2.11, host arm-unknown-linux-androideabi. ↩
-
fw-tv188b-261021-0117-r25.c250 · device · tv188b, android-dune-fw; прошивка 261021_0117_r25 · На tv188b r25 в php_server и php-cgi не определены константы CURLOPT_ACCEPT_ENCODING, CURLOPT_RESOLVE, CURL_SSLVERSION_TLSv1_2, CURLOPT_SSL_VERIFYSTATUS, CURLOPT_TCP_KEEPALIVE, CURLMOPT_PIPELINING и CURLMOPT_MAXCONNECTS; CURLOPT_ENCODING (10102), CURLOPT_SSLVERSION, CURLOPT_CAINFO, CURLOPT_TIMEOUT_MS, CURLOPT_CONNECTTIMEOUT_MS, CURLOPT_NOSIGNAL и CURLOPT_IPRESOLVE определены. ↩
-
plg-dc-globaltv.c075 · code · unknown; прошивка — · HD::http_get_document отключает проверку SSL-сертификатов (CURLOPT_SSL_VERIFYPEER = false) и следует редиректам; таймауты — 30 с на соединение и 60 с на запрос. ↩
-
plg-gh-aspel-twitch-dune-plugin.c047 · code · unknown; прошивка — · HD::http_get_document выполняет запрос через curl с CURLOPT_SSL_VERIFYPEER = false, CURLOPT_CONNECTTIMEOUT = 10, CURLOPT_TIMEOUT = 10 и User-Agent DuneHD/1.0; второй аргумент $opts позволяет переопределить curl-опции; при ошибке curl или HTTP-коде, отличном от 200, пишет hd_print и бросает Exception. ↩↩↩↩↩
-
plg-gh-sndpl-apple-trailers-dune-plugin.c051 · code · unknown; прошивка — · HD::http_get_document выполняет curl с connect- и общим таймаутом 10 с и User-Agent 'DuneHD/1.0', возвращает тело ответа, а при ошибке curl или HTTP-коде не 200 печатает сообщение hd_print и бросает Exception. ↩↩↩
-
plg-gh-rpervykh-dune-plugin-anidub-com.c036 · code · unknown; прошивка — · HD::http_get_document делает запрос через curl с CONNECTTIMEOUT и TIMEOUT 10 с, FOLLOWLOCATION=1, ENCODING=1 и User-Agent Firefox 7; при ошибке curl или HTTP-коде не 200 возвращает пустую строку, а не исключение. ↩↩↩↩
-
plg-hdtv-pirates-radio.c052 · code · unknown; прошивка — · HD::http_get_document в копии lib/ ставит CURLOPT_CONNECTTIMEOUT и CURLOPT_TIMEOUT по 10 секунд, следует редиректам, представляется User-Agent Firefox 7.0.1 и бросает Exception при ошибке curl или HTTP-коде, отличном от 200. ↩↩↩
-
plg-dc-widget-ext.c042 · code · unknown; прошивка — · HD::http_get_document делает запрос через расширение curl PHP: SSL-проверка отключена, CONNECTTIMEOUT 11, TIMEOUT 10, User-Agent Firefox/53, при коде ≠ 200 бросает Exception ↩↩↩
-
plg-gh-mdpuma-dune-plugin-altiptv.c076 · code · unknown; прошивка — · HD::http_get_document использует curl с SSL_VERIFYPEER=false, FOLLOWLOCATION=1 и таймаутами соединения/запроса по 25 секунд; переданные opts могут заменить параметры. ↩↩
-
plg-hdtv-plugtv.c048 · code · unknown; прошивка — · В http_get_document отключена проверка TLS-сертификата, тайм-ауты увеличены до 25 с, включены редиректы и сжатие, User-Agent подменён на Firefox 25 + DuneHD/1.0. ↩↩
-
- plg-hdtv-zlostnyi-iptv.c036 · code · unknown; прошивка — · HD::check_token и HD::http_get_document ставят одинаковые опции curl: CURLOPT_SSL_VERIFYPEER FALSE, connect/total timeout 25 с, FOLLOWLOCATION, User-Agent «Opera/9.80 (Windows NT 6.0; Opera Mobi/49; U; en) Presto/2.4.18 Version/10.00».
- plg-hdtv-zlostnyi-iptv.c166 · code · unknown; прошивка — · Копии lib/ пяти M3U-пакетов (ottclub, shara-club, smile, sharavoz, tvteam) отличаются от bcu в 3–8 файлах из 43: общие — utils.php (HD::http_get_document с UA DuneHD/1.0 и таймаутом 40 с вместо Opera/25 с) и tv/tv_channel_list_screen.php (ссылка на свой setup-класс); в abstract_tv.php у shara-club, smile, sharavoz, tvteam буферизация по умолчанию 1000 мс вместо 500.
-
plg-hdtv-smart-vod.c117 · code · unknown; прошивка — · HD::http_get_document в lib/utils.php эталона задаёт cURL timeout/connecttimeout 40 с, followlocation=1 и SSL_VERIFYPEER/SSL_VERIFYHOST=0, после чего позволяет переданным opts переопределить параметры. ↩↩
-
plg-dc-dunemdb-supplier-movies-rus.c034 · code · unknown; прошивка — · run.php определяет собственный класс HD с единственным методом http_get_document(): проверка SSL отключена (CURLOPT_SSL_VERIFYPEER/VERIFYHOST = 0), редиректы включены, таймауты 40 с, задан UA Firefox 7.0.1 и CURLOPT_ENCODING. ↩↩
-
plg-dc-torrent-center.c135 · code · unknown; прошивка — · HD::http_get_document отключает проверку TLS peer и host перед cURL-запросом. ↩
-
plg-gh-kocourkuba-proiptv.c059 · code · unknown; прошивка — · Curl_Wrapper по умолчанию отключает проверку SSL (VERIFYPEER/VERIFYHOST=0), следует до 5 редиректам, включает gzip и ставит User-Agent из HD::get_dune_user_agent(); connect/download timeouts и срок файлового кэша берутся из параметров плагина в Default_Dune_Plugin::reset_curl, а HD::http_init собирает UA 'DuneHD/1.0', который при наличии в /tmp/sysinfo.txt строк product_id/firmware_version дополняется ими и подписью плагина (app_caption + app_version). ↩↩
-
plg-dc-bazinga3.c056 · code · unknown; прошивка — · HD::http_get_document делает cURL-запрос с отключённой проверкой TLS peer/host, таймаутами 30 с, редиректами, gzip и User-Agent Chrome/80; служебные ключи opts — getHttpCode, hideUrl, silent. ↩
-
plg-dc-widget-ext--lib.c063 · code · unknown; прошивка — · HD::http_get_document применяет переданные opts после стандартных curl_setopt, позволяя заменить их значения. ↩
-
- plg-dc-widget-ext--lib.c064 · code · unknown; прошивка — · HD::http_post_document вызывает http_get_document с CURLOPT_POST = true и CURLOPT_POSTFIELDS = post_data.
- plg-dc-widget-ext--lib.c065 · code · unknown; прошивка — · HD::make_json_rpc_request создаёт массив jsonrpc = 2.0, id с предынкрементом статического счётчика, method и params.
-
plg-gh-rpervykh-dune-plugin-anidub-com.c037 · code · unknown; прошивка — · HD::http_post_document вызывает http_get_document с CURLOPT_POST=true и CURLOPT_POSTFIELDS=post_data. ↩
-
plg-hdtv-polsky-tv.c024 · code · unknown; прошивка — · service_api_call отправляет запрос к сервису статистики через fetch_document с телом get_post_data() (JSON), то есть POST-JSON с отключённой проверкой сертификата (CURLOPT_SSL_VERIFYPEER=0 и CURLOPT_SSL_VERIFYHOST=0). ↩
-
plg-dc-globaltv.c076 · code · unknown; прошивка — · HTTP-ответы с кодом, отличным от 200 и 201, HD::http_get_document считает ошибкой и бросает DuneCurlException. ↩↩
-
plg-hdtv-duneplexcatalog.c037 · code · unknown; прошивка — · PL::http_get_document_t делает HTTP-запрос через curl с User-Agent DuneHD/1.0, CURLOPT_CONNECTTIMEOUT 0 и CURLOPT_TIMEOUT 120; ответ 404 возвращает null, прочие не-200 и ошибки curl бросают исключение. ↩↩↩
-
plg-gh-mdpuma-dune-plugin-altiptv.c077 · code · unknown; прошивка — · При ошибке curl либо HTTP-коде, отличном от 200, HD::http_get_document пишет лог, но строки throw закомментированы и возвращается content. ↩↩
-
plg-dc-globaltv.c094 · code · unknown; прошивка — · При сетевой ошибке curl плагин (при наличии сетевого монитора) атомарно записывает 1 в /tmp/run/network_monitor/force_check_on_error. ↩
-
plg-hdtv-zlostnyi-iptv.c035 · code · unknown; прошивка — · HD::check_token (lib/utils.php, своё дополнение копии lib) делает curl-запрос и возвращает строку «nottoken», если curl_exec вернул false или HTTP-код не 200; иначе — тело ответа. ↩
-
plg-hdtv-megatorrents.c040 · code · unknown; прошивка — · HD::isDomainAvailible проверяет URL через cURL с CONNECTTIMEOUT 10 с по умолчанию; для URL, оканчивающегося на /echo, возвращает тело ответа, для прочих делает HEAD (CURLOPT_NOBODY) и возвращает true/false. ↩
-
- plg-gh-valerievitch-dune-plugin-acestreamsearch.c067 · code · unknown; прошивка — · AceSearchTv::ace_api_response получает документ через file_get_contents($url); при FALSE бросает DuneException 'HTTP network error' с фатальным действием show_error.
- plg-gh-valerievitch-dune-plugin-acestreamsearch.c069 · code · unknown; прошивка — · AceSearchTv::ace_api_response при неудачном json_decode бросает DuneException 'Response parsing error' с сообщением 'Cannot parse data from remote search engine'.
-
- plg-dc-widget-ext.c099 · code · unknown; прошивка — · Погоду OpenWeatherMap, Яндекса и rp5 скрипты плагина качают по http через wget, а Gismeteo — по https через $CURL с ключом -k
- plg-dc-widget-ext.c063 · code · unknown; прошивка — · Gismeteo запрашивается по HTTPS https://services.gismeteo.ru/inform-service/inf_chrome/forecast/?city=
&lang=<…> через curl с ключами -s --location -k (без проверки сертификата)
-
- plg-dc-widget-ext.c065 · code · sigma-smp86xx, sigma-smp87xx, android; прошивка — · Скрипт gismeteo выбирает curl по platform_kind из $FS_PREFIX/tmp/run/versions.txt: android → $FS_PREFIX/firmware/bin/curl; 87.., 864., 867., 865. → собственные bin/curl.87xx, curl.864x, curl.867x, curl.865x; при любом другом platform_kind CURL остаётся пустым
- plg-dc-widget-ext.c067 · code · sigma-smp86xx, sigma-smp87xx; прошивка — · Вложенные бинарники curl: curl.864x и curl.867x — curl 7.19.5 (mipsel-unknown-linux-gnu), curl.87xx — curl 7.36.0 (arm-buildroot-linux-gnueabi) из sigma-buildroot_2014.05 (bdk8756)
- plg-dc-widget-ext.c068 · code · unknown; прошивка — · bin/curl.864x плагина побайтно совпадает (sha256 917d95cf…611a, 85377 байт) с shell_ext/bin/curl встроенного плагина прошивки tv188b 260827_0003_r24
-
- plg-dc-dunemdb-supplier-movies-eng.c057 · code · unknown; прошивка — · Перед проверкой URL плагин отрезает суффиксы «|Referer…» и «|Cookie…».
- plg-dc-dunemdb-supplier-movies-eng.c058 · code · unknown; прошивка — · Каждый найденный URL проверяется HTTP-запросом Range bytes=0-10000 с таймаутом 1 с; при ошибке источник отбрасывается.
-
- plg-dc-torrent-center.c077 · code · unknown; прошивка — · torrserverActionUpload отправляет file=@<путь> на /torrent/upload и возвращает hash при наличии его в JSON.
- plg-dc-torrent-center.c078 · code · unknown; прошивка — · torrserverActionAdd посылает на /torrents JSON action=add с link и save_to_db, который сбрасывается при dontSave.
-
plg-hdtv-youtube.c089 · code · unknown; прошивка — · Экраны YouTube создают плейлист аккаунта POST /playlists?part=snippet,status с описанием «Created on Dune HD! Enjoy!» и privacyStatus private и добавляют видео POST /playlistItems?part=snippet через http_get_api_v3. ↩
-
plg-ds-dune-hd-tv.c059 · code · unknown; прошивка — · run.php ходит в сеть через curl с таймаутом 40 с и User-Agent «Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1». ↩
-
plg-dc-globaltv.c093 · code · unknown; прошивка — · User-Agent HTTP-запросов плагина — DuneHD/1.0 с добавкой строк product_id и firmware_version из /tmp/sysinfo.txt. ↩
-
plg-hdtv-zlostnyi-iptv.c036 · code · unknown; прошивка — · HD::check_token и HD::http_get_document ставят одинаковые опции curl: CURLOPT_SSL_VERIFYPEER FALSE, connect/total timeout 25 с, FOLLOWLOCATION, User-Agent «Opera/9.80 (Windows NT 6.0; Opera Mobi/49; U; en) Presto/2.4.18 Version/10.00». ↩
-
- plg-hdtv-youtube.c068 · code · unknown; прошивка — · SmartConfig::getYtbTvApiReq YouTube собирает JSON-контекст TV-клиента (screenWidthPoints 3840, tvAppInfo и т. п.), добавляет continuation, browseId, params, playlistId, query, videoId и др. из аргументов и отправляет его POST на https://www.googleapis.com/youtubei/v1/
?key= . - plg-hdtv-youtube.c069 · code · unknown; прошивка — · SmartConfig::http_get_ytb YouTube шлёт запросы с заголовками Content-Type application/json, Origin https://www.youtube.com, Referer https://www.youtube.com/tv, User-Agent SMART-TV Tizen 5.0 и X-Goog-Visitor-Id из visitor_data; Authorization добавляется только при наличии access_token и noLogIn == false.
- plg-hdtv-youtube.c068 · code · unknown; прошивка — · SmartConfig::getYtbTvApiReq YouTube собирает JSON-контекст TV-клиента (screenWidthPoints 3840, tvAppInfo и т. п.), добавляет continuation, browseId, params, playlistId, query, videoId и др. из аргументов и отправляет его POST на https://www.googleapis.com/youtubei/v1/
-
- plg-hdtv-web-launchers.c022 · code · unknown; прошивка — · bonus-tv запускает локальную страницу ping.html с user_agent=DUNE и show_by_default=lang(russian,ukrainian); это единственный манифест с user_agent=DUNE.
- plg-hdtv-web-launchers.c018 · code · unknown; прошивка — · xsmart запускает внешний URL http://app.xsmart.tv/?platform=dune&size=1280 с параметрами webapp_keys=1, user_agent=dune, osd_size=1280x720, background_color=black; это единственный внешний URL с параметром platform.
-
plg-dc-globaltv.c084 · code · unknown; прошивка — · Строку авторизации устройства плагин читает из /tmp/dune_auth.txt и дописывает в query-строку запросов к серверу как есть. ↩
-
plg-hdtv-jurt.c031 · code · unknown; прошивка — · Сохранение логина и пароля: apply_subscription проверяет непустой user_name, пишет cookies user_name/password, сбрасывает сессию и пробует try_login; ошибка DuneException превращается в post_action. ↩
-
plg-hdtv-moidom.c010 · code · unknown; прошивка — · api_exception для не-MoiDom_Exception возвращает DuneException с ActionFactory::show_error; для MoiDom_Exception фатальными считаются коды 12 при сообщении 'Authentification error', 17 и 5 — тогда вызывается unset_login; остальные ошибки для не-playback показываются с кодом и сообщением, для playback — только сообщением в заголовке. ↩
-
plg-dc-globaltv.c098 · code · unknown; прошивка — · Коды ошибок сервера 201–204 плагин показывает как «нет доступа», «пробный период окончен», «пробный период недоступен» (с кнопкой оплаты) и «сервис недоступен»; остальные — как техработы. ↩
-
- plg-hdtv-youtube.c073 · code · unknown; прошивка — · При control_id=do_login главное меню YouTube отправляет POST client_id и scope=http://gdata.youtube.com на https://www.youtube.com/o/oauth2/device/code; при получении user_code ждёт interval секунд (sleep) и переходит к login_page с verification_url, interval, device_code и user_code.
- plg-hdtv-youtube.c074 · code · unknown; прошивка — · При control_id=login_page главное меню YouTube показывает диалог с адресом https://www.youtube.com/activate и кодом, опрашивает https://www.youtube.com/o/oauth2/token и, пока ответ содержит error, через timer(5000) повторяет login_page; при access_token и refresh_token сохраняет ответ в tokens (или user_plus_tokens) и инвалидирует main_menu.
-
plg-hdtv-youtube.c126 · forum · unknown; прошивка — · В первом посте темы 15724 (со ссылкой на dimaS1410) вход в аккаунт описан так: синяя кнопка показывает адрес и код, код вводится в браузере компьютера с выполненным входом, после чего Дюна сообщает OK. ↩
-
plg-hdtv-youtube.c070 · code · unknown; прошивка — · http_get_ytb и http_get_api_v3 YouTube при ответе error.code 401 и наличии access_token обновляют токен POST-запросом grant_type=refresh_token на https://www.youtube.com/o/oauth2/token, сохраняют новый access_token через get_tokens и повторяют запрос. ↩
-
plg-hdtv-youtube.c072 · code · unknown; прошивка — · SmartConfig::get_tokens YouTube хранит OAuth-токены основного аккаунта в HD-элементе tokens, а дополнительных пользователей — в user_plus_tokens[<имя>]; текущее имя — static uname (по умолчанию default). ↩
-
- plg-hdtv-remtor.c110 · code · unknown; прошивка — · GetSessionID делает GET без тела, ждёт ответ 409 и извлекает значение заголовка X-Transmission-Session-Id в session_id.
- plg-hdtv-remtor.c107 · code · unknown; прошивка — · TransmissionRPC отправляет JSON {method, arguments} методом POST с Content-type application/json и заголовком X-Transmission-Session-Id; при заданных username и password добавляет Authorization: Basic.
- plg-hdtv-remtor.c108 · code · unknown; прошивка — · HTTP-контекст TransmissionRPC задаёт timeout 10 секунд, ignore_errors = true и User-Agent «TransmissionRPC for PHP/0.3».
- plg-hdtv-remtor.c109 · code · unknown; прошивка — · При ответе 401 TransmissionRPC бросает исключение E_AUTHENTICATION, при 409 — E_SESSIONID с требованием вызвать GetSessionID.
-
plg-gh-aspel-twitch-dune-plugin.c041 · code · unknown; прошивка — · Плагин запрашивает Twitch Kraken API по адресам api.twitch.tv/kraken/games/top?limit=100, /kraken/streams?limit=100, /kraken/streams?game=
&limit=100, /kraken/users/ и /kraken/streams/ ; в каждом запросе, кроме followed, жёстко задан client_id=9w0wfeb3nd0iuovyl0i32kpyyzktyh9. ↩ -
plg-hdtv-smart-vod--link-api.c056 · code · unknown; прошивка — · В коде жёстко заданы ключи и токены: bazon c118eb5f8d36565b2b08b5342da97f79, HDVB f25f5636f9a8d8cf99b6367e14dff52e, Kodik b7cc4293ed475c4ad1fd599d114f4435, TheMovieDB d56e51fb77b081a9cb5192eaaa7823ad, Twitch client_id jzkbprff40iqj646a697cyrvl0zt2m6 и YouTube AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8. ↩
-
plg-hdtv-megaradio.c152 · code · unknown; прошивка — · get_radio_stream_info для не-JSON названия вида «artist - track» ищет обложку через ws.audioscrobbler.com методом track.search с api_key 8077e41f067a717abb49db6159081cb5; обложки альбомов запрашивает artist.gettopalbums, текст — на lyrics.wikia.com; оба запроса выполняются только при actions = true и use_osd не равном 3, текст — дополнительно при use_osd не равном 2. ↩
-
plg-hdtv-smart-vod.c270 · code · unknown; прошивка — · Filmix get_tlogin_check('filmix') сначала возвращает true, если существует cookie-файл tmp_dir_path/filmix_cooki; иначе читает login_settings и при отсутствии логина или пароля возвращает false, иначе отправляет POST login_name/login_password/login=submit с заголовком cookie x-a-key=sinatra и cookie-файлом tmp_dir_path/filmix_cooki; ошибкой считает наличие form action= в ответе. ↩
-
- plg-ds-dune-hd-tv.c026 · code · unknown; прошивка — · Эндпоинты авторизации в I24hSession: v2/otps, v2/auth/otp, v2/auth/login, v2/auth/device, v2/users/self/devices, v2/users/self/network, v2/users/self/promokeys.
- plg-ds-dune-hd-tv.c027 · code · unknown; прошивка — · Вход по телефону: api_login отправляет POST на v2/auth/otp с phone (ведущая 8 заменяется на 7) и token (пароль из SMS) и берёт access_token из ответа.
-
- plg-ds-dune-hd-tv.c029 · code · unknown; прошивка — · register_device отправляет POST v2/users/self/devices с vendor DUNE, model (product из versions.txt или 'dune'), version плагина, device_type stb, serial (из лицензии) и application_type dune; при ответе 400 «Too many devices.» или «Ограничение по количеству устройств.» открывает экран списка устройств.
- plg-ds-dune-hd-tv.c031 · code · unknown; прошивка — · Серийный номер устройства плагин берёт из первой строки /fconfig/dune_license.dlf (третье поле, без дефисов); device_id хранится в plugin_cookies->device_id, а при его отсутствии используется серийный номер.
-
plg-ds-dune-hd-tv.c028 · code · unknown; прошивка — · verify_device при заданном в plugin_cookies device_id отправляет POST v2/auth/device с device_id; при успешном ответе берёт access_token и запрашивает v2/users/self (id, phone, username, parental_code, provider). ↩
-
plg-ds-dune-hd-tv.c033 · code · unknown; прошивка — · api_call декодирует JSON-ответ; status_code вне 200, 400, 401, 403, 404 даёт исключение (с диалогом «Ошибка взаимодействия с сервером.», если есть error.message), а 400, 401, 403 и 404 возвращаются вызывающему как данные. ↩
-
plg-hdtv-smart-vod.c335 · code · unknown; прошивка — · Активация Filmix_API: синяя кнопка главного меню «Активация» вызывает control_id=login; при заданном selected_media_url он запрашивает HOST_API_URL . "/token_request" с user_dev_apk, user_dev_id, user_dev_name, user_dev_os, пустым user_dev_token и user_dev_vendor и, если ответ не со status=error, показывает URL https://filmix.tech/console и user_code (иначе «Не удалось получить код.»); control_id=do_slogin_action при заданном selected_media_url сохраняет token_request в DuneSystem::$properties["user_dev_token"] и HD::save_items('tokens'), затем запрашивает "/user_profile" и при наличии user_data показывает «Успешно», иначе «Логин не удался». ↩
-
plg-hdtv-smart-vod.c339 · forum · unknown; прошивка — · В первом посте темы Filmix_Api (19814) avenso пишет, что для качества 720p требуется регистрация на Filmix без оплаты, для более высокого качества — оплата Pro-аккаунта; в обоих случаях нужна активация устройства по кнопке «D» с добавлением устройства в личном кабинете; без регистрации доступно только 480p. ↩
-
- plg-hdtv-remtor.c115 · code · unknown; прошивка — · Конструктор TransmissionRPC сразу вызывает sget() и сохраняет rpc_version из ответа.
- plg-hdtv-remtor.c116 · code · unknown; прошивка — · RemoteTorrentClass::get_rpc_version выполняет пустой rpc_request и возвращает rpc_version созданного клиента.
-
plg-hdtv-remtor.c118 · code · unknown; прошивка — · use_alt_speed вызывает get_session_stats, но результат игнорирует; читает сохранённый general_info['alt-speed-enabled'], сравнивает его со строкой 'true' и вызывает sset с противоположным значением. ↩
-
- plg-gh-rpervykh-dune-plugin-anidub-com.c087 · code · unknown; прошивка — · Cursor::parse_page разбирает HTML главной/категорийной страницы по маркерам div class="newstitle", a href, data-original и div class="title" itemprop="name"; при отсутствии data-original подставляет plugin_file://skins/no_cover.png.
- plg-gh-rpervykh-dune-plugin-anidub-com.c100 · code · unknown; прошивка — · parse_season_info скачивает страницу сезона и вырезает блок от до