diff --git a/.env.example b/.env.example
index d9b5a33..320cf0d 100644
--- a/.env.example
+++ b/.env.example
@@ -9,6 +9,6 @@ LEGACY_DATA_PATH=.
HEARTBEAT_PATH=data/scheduler-heartbeat.json
GEONAMES_USERNAME=
GEONAMES_ENDPOINT=https://secure.geonames.org
-SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0
+SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0
CUSTOM_EMOJI_ENABLED=1
diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md
index 7323052..58f9d5a 100644
--- a/.github/CODE_OF_CONDUCT.md
+++ b/.github/CODE_OF_CONDUCT.md
@@ -1,39 +1,39 @@
-# Contributor Covenant Code of Conduct
-
-## Our Pledge
-
-We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
-
-## Our Standards
-
-Examples of behavior that contributes to a positive environment for our community include:
-- Using welcoming and inclusive language
-- Being respectful of differing viewpoints and experiences
-- Gracefully accepting constructive criticism
-- Showing empathy towards other community members
-
-Examples of unacceptable behavior include:
-- The use of sexualized language or imagery and unwelcome sexual attention or advances
-- Trolling, insulting or derogatory comments, and personal or political attacks
-- Public or private harassment
-- Publishing others’ private information, such as a physical or electronic address, without explicit permission
-
-## Our Responsibilities
-
-Project maintainers are responsible for clarifying the standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior.
-
-## Scope
-
-This Code of Conduct applies within all project spaces and in public spaces when an individual is representing the project or its community.
-
-## Enforcement
-
-Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [@WizardLoop on Telegram](https://t.me/WizardLoop) or contact@wizardloop.com.
-
-All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
-
-## Attribution
-
-This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
-
-[homepage]: https://www.contributor-covenant.org
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our community include:
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Showing empathy towards other community members
+
+Examples of unacceptable behavior include:
+- The use of sexualized language or imagery and unwelcome sexual attention or advances
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others’ private information, such as a physical or electronic address, without explicit permission
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and will take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+## Scope
+
+This Code of Conduct applies within all project spaces and in public spaces when an individual is representing the project or its community.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [@WizardLoop on Telegram](https://t.me/WizardLoop) or contact@wizardloop.com.
+
+All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+
+[homepage]: https://www.contributor-covenant.org
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index cf693c6..ba94d46 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -12,4 +12,4 @@ Follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). Explain the problem, resulting
Existing project contact: [@WizardLoop on Telegram](https://t.me/WizardLoop).
-Composer validation uses --strict --no-check-all because MadelineProto is intentionally pinned to the exact reviewed source version. This retains schema and lock validation; only generic version-range recommendations are omitted.
+MadelineProto uses a stable compatible range in composer.json. Deployment always uses composer.lock; dependency upgrades require fresh source review and patch manifests for the exact locked release. Never run composer update as a routine server upgrade. Composer validation retains strict schema and lock checks; --no-check-all suppresses generic version-range advice for reviewed dependency policies.
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 6d83f6e..1c634ae 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,2 +1,2 @@
-github: ['WizardLoop']
-custom: ['https://WizardLoop.t.me']
+github: ['WizardLoop']
+custom: ['https://WizardLoop.t.me']
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index 9ca37fa..daf22f4 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -1,37 +1,37 @@
-name: "🐞 Bug report"
-description: "Report a reproducible bug"
-labels: [bug]
-body:
- - type: textarea
- attributes:
- label: "Describe the bug"
- description: "A clear and concise description of what the bug is."
- placeholder: "Bug description"
- - type: textarea
- attributes:
- label: "Steps to Reproduce"
- description: "What steps did you take that led to the bug?"
- placeholder: "1. Go to ...\n2. Click ...\n3. See error"
- - type: textarea
- attributes:
- label: "Expected behavior"
- description: "What did you expect to happen?"
- placeholder: "Expected behavior"
- - type: textarea
- attributes:
- label: "Screenshots/Logs"
- description: "Use synthetic examples and redact tokens, sessions, private group/user IDs, payment data and live databases."
- - type: input
- attributes:
- label: "Bot Version / Commit"
- description: "What version or commit are you using?"
- - type: dropdown
- attributes:
- label: "Environment"
- options:
- - Self-hosted Linux
- - Windows
- - Other
+name: "🐞 Bug report"
+description: "Report a reproducible bug"
+labels: [bug]
+body:
+ - type: textarea
+ attributes:
+ label: "Describe the bug"
+ description: "A clear and concise description of what the bug is."
+ placeholder: "Bug description"
+ - type: textarea
+ attributes:
+ label: "Steps to Reproduce"
+ description: "What steps did you take that led to the bug?"
+ placeholder: "1. Go to ...\n2. Click ...\n3. See error"
+ - type: textarea
+ attributes:
+ label: "Expected behavior"
+ description: "What did you expect to happen?"
+ placeholder: "Expected behavior"
+ - type: textarea
+ attributes:
+ label: "Screenshots/Logs"
+ description: "Use synthetic examples and redact tokens, sessions, private group/user IDs, payment data and live databases."
+ - type: input
+ attributes:
+ label: "Bot Version / Commit"
+ description: "What version or commit are you using?"
+ - type: dropdown
+ attributes:
+ label: "Environment"
+ options:
+ - Self-hosted Linux
+ - Windows
+ - Other
- type: textarea
attributes:
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 2fe4d12..78ee1fb 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -1,18 +1,18 @@
-name: "✨ Feature request"
-description: "Suggest an idea or improvement"
-labels: [enhancement]
-body:
- - type: textarea
- attributes:
- label: "Feature description"
- description: "What would you like to see added?"
- placeholder: "Feature details"
- - type: textarea
- attributes:
- label: "Use case"
- description: "Describe a real scenario where this feature would help."
- placeholder: "Use case"
- - type: textarea
- attributes:
- label: "Additional context"
- description: "Anything else?"
+name: "✨ Feature request"
+description: "Suggest an idea or improvement"
+labels: [enhancement]
+body:
+ - type: textarea
+ attributes:
+ label: "Feature description"
+ description: "What would you like to see added?"
+ placeholder: "Feature details"
+ - type: textarea
+ attributes:
+ label: "Use case"
+ description: "Describe a real scenario where this feature would help."
+ placeholder: "Use case"
+ - type: textarea
+ attributes:
+ label: "Additional context"
+ description: "Anything else?"
diff --git a/.github/ISSUE_TEMPLATE/improvement_question.yml b/.github/ISSUE_TEMPLATE/improvement_question.yml
index 6c1b496..39209e8 100644
--- a/.github/ISSUE_TEMPLATE/improvement_question.yml
+++ b/.github/ISSUE_TEMPLATE/improvement_question.yml
@@ -1,14 +1,14 @@
-name: "❓ Improvement / Question"
-description: "Suggest an improvement or ask a question"
-labels: [question]
-body:
- - type: textarea
- attributes:
- label: "Improvement or Question"
- description: "Describe your suggestion or question."
- placeholder: "Your suggestion/question"
- - type: textarea
- attributes:
- label: "Context"
- description: "Where in the project do you want to see this?"
- placeholder: "Relevant files, code, or context"
+name: "❓ Improvement / Question"
+description: "Suggest an improvement or ask a question"
+labels: [question]
+body:
+ - type: textarea
+ attributes:
+ label: "Improvement or Question"
+ description: "Describe your suggestion or question."
+ placeholder: "Your suggestion/question"
+ - type: textarea
+ attributes:
+ label: "Context"
+ description: "Where in the project do you want to see this?"
+ placeholder: "Relevant files, code, or context"
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
index 33fac37..d9e3b52 100644
--- a/.github/SECURITY.md
+++ b/.github/SECURITY.md
@@ -1,13 +1,14 @@
-# Security Policy
-
-## Reporting a Vulnerability
-
-If you find a security issue, **do not open an issue on GitHub**.
-Please report privately to [@WizardLoop on Telegram](https://t.me/WizardLoop) or via email: contact@wizardloop.com
-
----
-
-We will address all reports promptly and responsibly.
+# Security Policy
+
+## Reporting a Vulnerability
+
+If you find a security issue, **do not open an issue on GitHub**.
+
+Please report privately to [@WizardLoop on Telegram](https://t.me/WizardLoop) or via email: contact@wizardloop.com
+
+---
+
+We will address all reports promptly and responsibly.
## Safe reproduction information
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6ebbf4f..2227d81 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -6,19 +6,33 @@ permissions:
contents: read
jobs:
php:
+ name: php (${{ matrix.php }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ["8.3", "8.4", "8.5"]
+ include:
+ - php: "8.3"
+ version: "8.3.36"
+ - php: "8.4"
+ version: "8.4.27"
+ - php: "8.5"
+ version: "8.5.12"
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1
+ env:
+ update: true
with:
- php-version: ${{ matrix.php }}
+ php-version: ${{ matrix.version }}
extensions: pdo_sqlite, mbstring, xml, dom, fileinfo, zlib, zip
tools: composer:2.10.3
coverage: none
+ - name: Verify exact security-patched PHP runtime
+ env:
+ EXPECTED_PHP_VERSION: ${{ matrix.version }}
+ run: php -r 'if (PHP_VERSION !== getenv("EXPECTED_PHP_VERSION")) { fwrite(STDERR, "Unexpected PHP runtime " . PHP_VERSION . "\n"); exit(1); } echo "Verified PHP " . PHP_VERSION . "\n";'
- run: composer validate --strict --no-check-all
- run: composer install --no-interaction --prefer-dist
- run: composer check-platform-reqs
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d12796e..ef39f1a 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -10,11 +10,15 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1
+ env:
+ update: true
with:
- php-version: "8.4"
+ php-version: "8.4.27"
extensions: pdo_sqlite, mbstring, xml, dom, fileinfo, zlib, zip
tools: composer:2.10.3
coverage: none
+ - name: Verify exact security-patched PHP runtime
+ run: php -r 'if (PHP_VERSION !== "8.4.27") { fwrite(STDERR, "Unexpected PHP runtime " . PHP_VERSION . "\n"); exit(1); } echo "Verified PHP " . PHP_VERSION . "\n";'
- run: composer validate --strict --no-check-all
- run: composer install --no-interaction --prefer-dist
- run: composer check-platform-reqs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d1d516..dd6ca23 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,16 @@
PHP 8.3 compatibility: module-delivery bookkeeping now uses the database-owned `BEGIN IMMEDIATE` transaction state and exact connection identity; native callback/message fixtures initialize inherited readonly properties from their declaring class. Regression tests cover rejected foreign/outside transactions, rollback and state reset.
+## 3.1.0
+
+- Require PHP 8.3.36, 8.4.27 or 8.5.12 and later patches on those branches, incorporating the upstream security fixes published on 22 October 2026. Pin the Docker image to verified PHP 8.4.27 bytes and verify exact patched runtimes in CI and release packaging.
+- Upgrade the official MadelineProto dependency to the reviewed stable 8.11.10 / TL layer 232 line, with reproducible Composer locking and a stable compatible version range.
+- Retire the upstreamed UpdateLoop/cancellation, GeoPoint and formatted-date patch sets. Re-review the Fresh Peer and BroadcastManager patches against the updated dependency source.
+- Update the central keyboard compatibility boundary for the new native inline constructors while preserving saved templates, callback identifiers, styles and reply-keyboard separation.
+- Make legacy import reviewable with equivalent preview/apply parsing, duplicate and directory-only group reporting, bound comparison reports and post-import verification. Existing settings and unverified permission snapshots remain protected.
+- Shorten the parallel English/Hebrew READMEs, consolidate historical development reports into current references, and provide a Hebrew staged upgrade/import/rollback guide that verifies the actual production path.
+- Required clean-install, regression, static-analysis, Docker and archive checks must pass before a stable tag/release. Earlier 3.0.0 live acceptance is not new 3.1.0 acceptance. No production deployment is performed by this upgrade work.
+
## 3.0.0 - stable
- Promote the reviewed dev.9 implementation to stable 3.0.0 while retaining MadelineProto 8.7.0, SQLite, the Composer lock, all five approved patch sets and migrations 001–016. No new runtime feature or migration is introduced by this promotion.
@@ -50,7 +60,7 @@ PHP 8.3 compatibility: module-delivery bookkeeping now uses the database-owned `
## 3.0.0-dev.6 - permission equivalence and callback integration
- Correct the public statistics callback allowlist at the actual SDK update-handler boundary, including callbacks emitted by the home menu and statistics tabs. Unavailable original panels return a localized callback response without new-message flooding.
-- Compare reviewed Telegram-equivalent default permission representations consistently for manual and automatic transitions, retaining original snapshots and genuine-conflict protection. See the dev.6 feedback report for evidence and limits.
+- Compare reviewed Telegram-equivalent default permission representations consistently for manual and automatic transitions, retaining original snapshots and genuine-conflict protection. Historical evidence and limits are preserved in the 3.0.0 Git history.
- Shabbat messages across public, inline and scheduled defaults show the nearest Shabbat-containing period and current/upcoming holidays, including verified entrance/final-exit times for weekday Yom Tov before Shabbat, without later Shabbat summaries, numeric UTC suffixes or visible source/update footers. Actual configured methods and validated source provenance remain intact.
- Recognize both captured provider spellings of Chol Hamoed for reminder policy, while retaining its non-Yom-Tov classification. Keep a verified active festival visible when its final exit is after civil midnight.
- Direct test-folder upload is documented; deployment ZIP/checksum files are excluded from Docker context. No dependency, patch or migration update is required.
@@ -68,7 +78,7 @@ PHP 8.3 compatibility: module-delivery bookkeeping now uses the database-owned `
- `source` combines repository, license and build identity. Legacy `license`/`version` commands remain aliases; the project repository is always linked separately from the deployment's exact source offer.
- Expanded help and all changes are translated into Hebrew, English, Russian, French, Spanish and Brazilian Portuguese.
-Migrations 001-012, Composer lock and all four library patch sets are unchanged from dev.4. No new schema migration is needed for dev.5, but the stopped-writer backup/migrate command remains part of the update procedure. See [the 11-item verification map](docs/DEV5_TEST_FEEDBACK.md) and [Docker test deployment](docs/SERVER_TEST_DEPLOYMENT.md). The supplied log proves repeated auxiliary IPC churn, not a completed reproduction of a live Telegram restart hang or the original permission error. No Docker or real Telegram acceptance is claimed.
+Migrations 001-012, Composer lock and all four library patch sets are unchanged from dev.4. No new schema migration is needed for dev.5, but the stopped-writer backup/migrate command remains part of the update procedure. See [Docker test deployment](docs/SERVER_TEST_DEPLOYMENT.md). The supplied log proves repeated auxiliary IPC churn, not a completed reproduction of a live Telegram restart hang or the original permission error. No Docker or real Telegram acceptance is claimed.
## 3.0.0-dev.4 - unpublished local development snapshot
@@ -157,7 +167,7 @@ Dependencies, four reviewed library patches and eight migration files remain unc
* Exact 8.5-degree nightfall and explicit minute choices are retained without integer truncation or arbitrary minute adjustments.
* Native integer peer IDs are handled in private GPS and payment updates; bot-owned GPS reply tokens remain scoped to their user/group.
* A separate exact-source MadelineProto GeoPoint correction preserves fractional coordinates before inline dispatch.
-* A new reviewed formatted-date correction completes the locked entity factory and adds a typed native/Bot API wrapper. It preserves timestamps, UTF-16 offsets and valid flags, with strict two-file/schema guards; historical reference code with unresolved grants is not redistributed. See [review](docs/MADELINE_FORMATTED_DATE.md).
+* A new reviewed formatted-date correction completes the locked entity factory and adds a typed native/Bot API wrapper. It preserves timestamps, UTF-16 offsets and valid flags, with strict two-file/schema guards; historical reference code with unresolved grants is not redistributed. See [historical source and license findings](docs/THIRD_PARTY_DETAILS.md).
* Permission FLOOD_WAIT deadlines survive restart, stale/expired owners cannot confirm mutations, and desired state is refreshed before RPCs.
* Content waits for bot-owned permission recovery; Omer waits its configured gap after the actual restore. Eligibility deferrals do not exhaust transport retries.
* Explicit group rejoining preserves settings, while startup list import cannot reactivate removed groups. Startup schema validation rejects missing or changed migrations without writing.
diff --git a/Dockerfile b/Dockerfile
index fd2a1dc..b289779 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
FROM composer:2.10.3@sha256:af98f42dfff7c68ba8d53c2164fd9fde1087b7d449514baa38c418b1f6bc4bac AS composer
-FROM php:8.4.26-cli-bookworm@sha256:836ac6c672d1372a47c8fd61b625015bd07760f493fb2eaab2087636498a2b4b
+FROM php:8.4.27-cli-bookworm@sha256:496b5e02fe9fe44fcfb715023b931048111dc4e0bc719789d83c906be9f04b05
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates tzdata libsqlite3-dev libonig-dev libxml2-dev libzip-dev unzip curl build-essential pkg-config \
&& curl --fail --location --proto '=https' --tlsv1.2 https://www.sqlite.org/2026/sqlite-autoconf-3510300.tar.gz -o /tmp/sqlite.tar.gz \
@@ -18,7 +18,6 @@ WORKDIR /app
COPY composer.json composer.lock ./
COPY patches ./patches
COPY scripts ./scripts
-COPY src/Runtime/AddedFilePatchManager.php ./src/Runtime/AddedFilePatchManager.php
COPY src/Runtime/PatchManager.php ./src/Runtime/PatchManager.php
COPY src/Runtime/PatchSet.php ./src/Runtime/PatchSet.php
COPY src/Runtime/SingleInstance.php ./src/Runtime/SingleInstance.php
diff --git a/README.md b/README.md
index dbcd611..9436fee 100644
--- a/README.md
+++ b/README.md
@@ -1,97 +1,98 @@
-# 🕯️ WizardLoop Shabbat Bot
+# 🕯️ Shabbat Bot
-A Telegram bot built with PHP, MadelineProto and SQLite for Shabbat and festival group quiet periods, Jewish calendar views and opt-in reminders.
+A Telegram bot for Shabbat and festival group quiet periods, Jewish calendar information and optional reminders. Built with PHP, MadelineProto and SQLite.
[English](README.md) | [עברית](readme-he.md)
[](LICENSE)
[](composer.json)
-[](composer.lock)
-[](VERSION)
+[](composer.lock)
-**Current version: 3.0.0, stable.** Use the matching [release assets](https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0) or tagged checkout and retain its build metadata. The owner confirmed dev.9 live group locking, unlocking, original-permission restoration and restart. This does not establish holy-day timing, load capacity or a long-running soak; automated and host-specific acceptance remain separate. For an existing bot, follow the [production upgrade and rollback guide](docs/PRODUCTION_UPGRADE.md) before replacing files or starting a second instance. See [publication status](docs/PUBLICATION_STATUS.md), [changes](CHANGELOG.md) and [delivery safety](docs/DEV9_DELIVERY_SAFETY.md). Badges describe source configuration, not production acceptance.
+**Version 3.1.0.** Release requirements and acceptance limits are described in [implementation status](docs/IMPLEMENTATION_STATUS.md). For an existing installation, start with the [upgrade guide](docs/PRODUCTION_UPGRADE.md) ([עברית](docs/PRODUCTION_UPGRADE_HE.md)); the commands below create a new database.
-## Contents
-
-[Features](#features) · [Requirements](#requirements) · [Docker installation](#docker-installation) · [Manual installation](#manual-installation) · [Configuration](#configuration) · [Telegram setup](#telegram-setup) · [Group setup](#group-setup) · [Location and languages](#location-and-languages) · [Calendar modules](#calendar-modules) · [Bot commands](#bot-commands) · [Operations](#operations) · [Upgrade and legacy import](#upgrade-and-legacy-import) · [Backup and rollback](#backup-and-rollback) · [Troubleshooting](#troubleshooting) · [Project and development](#project-and-development) · [License and credits](#license-and-credits)
+[Features](#features) · [Requirements](#requirements) · [Install](#install) · [Configure](#configure) · [First use](#first-use) · [Operate and update](#operate) · [Documentation](#documentation) · [License](#license)
-## Features
-
-| Area | Implemented behavior |
-|---|---|
-| Shabbat/festivals | Per-group location, Israel/diaspora calendar, candle/havdalah methods, operational offsets and continuous adjacent holy-day closures. |
-| Modes | Off, messages only, lock only, or lock and messages; Shabbat and festivals are selected separately. |
-| Permission recovery | Original 22-flag snapshots, verified fresh reads, durable restoration state, conflicts and an authorized recovery panel. The default lock mask has 21 selectable member restrictions; administrator powers are separate. |
-| Private controls | Known groups, guided settings, independent personal preferences, preview and confirmation. |
-| Calendar/reminders | Daily zmanim, Daf Yomi, tefillin and seasonal Omer with explicit group opt-in and separate settings. |
-| Message design | Text, Telegram entities, reusable media and default/custom/no keyboards; separate close/open/announcement/module templates. Optional cleanup defaults off. |
-| Administration | Full/limited/view-only managers, subscriber directory, broadcasts, statistics, diagnostics, system links and tracking links. |
-| Storage/operation | SQLite migrations/backups, durable delivery jobs, independent scheduler heartbeats, one application writer and explicit maintenance tools. |
-| Donations/source | Optional Telegram Stars, including whole custom amounts 1–10000; version, license and an operator-supplied exact source URL. |
-
-3.0.0 retains dev.9 delivery-time eligibility checks, bounded reminder backlogs, actual spacing/quiet-window checks and independent permission, notification and broadcast work. MadelineProto remains 8.7.0 and the dependency lock is retained. Missing solar values are reported; no polar fallback is invented. Times and ritual texts are informational, with method choices made by the administrator.
+## What it does
-
-## Requirements
+- Close and reopen groups for Shabbat and festivals, with verified original permissions and guarded recovery.
+- Choose each group's location, timezone, Israel/diaspora calendar, candle lighting and havdalah settings.
+- Show daily zmanim and Daf Yomi; optionally schedule zmanim, Daf, tefillin and Omer reminders.
+- Manage groups through private panels; customize messages, media and buttons.
+- Provide delegated bot administration, broadcasts, statistics and optional Telegram Stars donations.
-| Component | Requirement |
-|---|---|
-| Recommended deployment | Linux, Docker Engine and Compose v2, outbound HTTPS/Telegram access, persistent storage. |
-| Manual runtime | 64-bit PHP 8.3/8.4/8.5 and Composer 2. Docker pins PHP 8.4.26 and Composer 2.10.3. |
-| Extensions | PDO/PDO SQLite, mbstring, XML, DOM, fileinfo, zlib; ZIP for the optional development packager. Verify all locked requirements with `composer check-platform-reqs`. Docker also builds pcntl and sockets. |
-| SQLite | Application minimum 3.35. Release gate accepts 3.51.3+, or reviewed 3.44.6 / 3.50.7. Check PHP's loaded library. Docker builds checksum-verified 3.51.3. |
-| Telegram | Your application API ID/hash, BotFather token and configured operator user IDs or resolvable usernames. |
-| GeoNames | Your webservice-enabled account for city search/automatic timezone lookup. Known cities and explicit coordinates remain available without it. |
-| Filesystem | Persistent application data and separate MadelineProto session. The runtime also needs a writable working directory for its library worker log and PrimeModule copies. |
+Six interface catalogs are supplied: Hebrew, English, Russian, French, Spanish and Brazilian Portuguese. External content and Hebrew ritual text can remain in their original language. See [group settings](docs/GROUP_SETTINGS.md) for details.
-Offline tests use fake Telegram gateways and provider fixtures without bot credentials. Recheck permission restoration and restart on the deployment target; test topics, client rendering, inline/GPS, Stars and command menus where used. See the precise [acceptance record](docs/IMPLEMENTATION_STATUS.md).
+
+## Before you begin
-
-## Docker installation
+You need a Linux server with persistent storage, internet access, **Docker Engine and the Docker Compose plugin**, plus:
-Shell examples use a Linux/POSIX terminal. Run Docker commands **on the host, from the extracted project root**, with Docker-daemon access. The image runs as `shabbat`, UID/GID `10001`. There is no separate Composer service.
+| Item | Where to obtain it |
+|---|---|
+| Telegram API ID and API hash | [Telegram application management](https://my.telegram.org/apps) |
+| Bot token | Create/select your bot with [BotFather](https://t.me/BotFather) |
+| Administrator ID | Your trusted Telegram user ID; multiple IDs are comma-separated |
+| GeoNames username | [GeoNames account](https://www.geonames.org/login) with web services enabled, for city/automatic timezone search |
-1. Obtain the reviewed source. For the release deployment archive:
+Install [Docker Engine for your Linux distribution](https://docs.docker.com/engine/install/) and [the Compose plugin](https://docs.docker.com/compose/install/linux/), then check:
~~~sh
-unzip shabbat-3.0.0.zip -d shabbat
-cd shabbat
-unset BUILD_COMMIT
+docker --version
+docker compose version
~~~
-It contains source and `composer.lock`, without installed `vendor/`. Docker installs locked production dependencies. **Retain archive `build-info.json`.** The release archive records its exact reviewed commit, `local_changes=false` and the application-source fingerprint. Leave `BUILD_COMMIT` absent from `.env`; the archive example clears an inherited value so it cannot override this identity. For a reviewed Git checkout instead, supply its actual commit before building:
+Docker supplies PHP 8.4.27, Composer, SQLite and the locked dependencies. Manual installations require 64-bit PHP **8.3.36+, 8.4.27+ or 8.5.12+**, within those supported branches. See the [22 October 2026 security baseline](docs/INSTALLATION.md#php-security-baseline) and [manual installation](docs/INSTALLATION.md#manual-installation).
-~~~sh
-export BUILD_COMMIT="$(git rev-parse HEAD)"
-~~~
+
+## 1. Extract a fresh installation
-Use an unchanged release archive or a clean matching Git checkout. Do not substitute an unrelated commit or retain archive metadata after editing its source.
-
-2. Create private configuration once in this new installation:
+Download `shabbat-3.1.0.zip` and `SHA256SUMS` from the matching [GitHub release](https://github.com/WizardLoop/shabbat/releases). Run in **Bash on the server**, in the upload directory, with Docker access. The checksum must report `OK`.
~~~sh
+set -euo pipefail
+umask 077
+awk '$2 == "shabbat-3.1.0.zip" {
+ if (NF != 2 || length($1) != 64 || $1 ~ /[^0-9a-f]/) exit 1
+ print; n++
+} END { if (n != 1) exit 1 }' SHA256SUMS > deployment.sha256
+sha256sum --check deployment.sha256
+test ! -e shabbat-3.1.0
+unzip -q shabbat-3.1.0.zip -d shabbat-3.1.0
+cd shabbat-3.1.0
cp .env.example .env
chmod 600 .env
+unset BUILD_COMMIT
~~~
-Edit `.env`: replace Telegram examples, set `ADMIN`, your GeoNames account when needed, and `SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0` for this unchanged release, whose corresponding-source asset must be available. For modified deployments, provide their exact matching source instead. Keep simple `KEY=value` syntax compatible with PHP raw INI and Compose. Exclude the configured file from uploads.
+Keep the supplied `build-info.json`. Do not add `BUILD_COMMIT` to `.env` for an unchanged release archive. Never extract an upgrade over a running installation.
-3. Build and check the image. These steps install/patch dependencies and write image metadata without starting the bot:
+
+## 2. Configure the bot
-~~~sh
-docker compose build
-docker compose run --rm --no-deps shabbat php bin/self-check.php --release
-docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+Edit `.env` privately. Replace the example credentials and administrator ID:
+
+~~~dotenv
+API_ID=123456
+API_HASH=replace_with_your_32_character_api_hash
+BOT_TOKEN=replace_with_your_bot_token
+ADMIN=123456789
+GEONAMES_USERNAME=your_geonames_username
+SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0
~~~
-4. Initialize a **new empty database**, with the service stopped. Existing databases require the upgrade/backup procedure.
+Keep the other values from `.env.example` unless an advanced setting is needed. Never publish this file or use test credentials in production. The source URL must offer the exact deployed source, including the corresponding-source archive. See [all configuration variables](docs/CONFIGURATION.md).
+
+From the extracted project root, build and check the image, then initialize the **new empty database**. These commands do not start the bot:
~~~sh
+docker compose build shabbat
+docker compose run --rm --no-deps shabbat php bin/self-check.php --release
+docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
docker compose run --rm --no-deps shabbat php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite
~~~
-5. Start when ready for real Telegram connections and operations on registered groups:
+Start when ready to connect to Telegram:
~~~sh
docker compose up -d shabbat
@@ -100,368 +101,54 @@ docker compose logs --tail=100 shabbat
docker compose exec shabbat php bin/health.php
~~~
-Service: `shabbat`. Named volumes: `bot-data` → `/app/data`, `madeline-session` → `/app/runtime`; actual names include the Compose project name. Preserve the project identity and volumes during upgrades. Compose forces `DATA_DIR=/app/data` and `SESSION_PATH=/app/runtime/bot.shabbat`. Initial health waits for both scheduler loops; the configured start period is 90 seconds.
-
-[Installation details](docs/INSTALLATION.md) · [Staging guide](docs/SERVER_TEST_DEPLOYMENT.md)
-
-
-## Manual installation
-
-Use separate source and a non-root service account that can write the working/data/session directories. Run **from that project root** after copying/configuring `.env` as above:
-
-~~~sh
-composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
-composer check-platform-reqs --no-dev
-mkdir -p data/session
-php bin/self-check.php --release
-php bin/runtime-permissions.php --require-non-root
-php bin/migrate.php --writers-stopped --db data/shabbat.sqlite
-php bot.php
-~~~
-
-The last command starts the bot in the foreground and connects to Telegram. Stop with Ctrl+C and wait for exit; repeat `php bot.php` to start again. Manual process supervision is the operator's responsibility; no systemd unit is supplied. Windows can run many offline checks; the POSIX non-root probe and Linux deployment acceptance require the appropriate host.
-
-Composer normally applies/verifies local patches on install. If scripts were disabled, run these **in the stopped installation**:
-
-~~~sh
-composer install --no-dev --no-scripts --no-interaction --prefer-dist
-php scripts/apply-patches.php
-php scripts/verify-patches.php
-~~~
-
-Unknown/partially modified dependency bytes fail verification. Reapplication is idempotent. Never patch an installed library while its bot is running.
-
-
-## Configuration
-
-The bot reads project-root `.env` as raw INI. Nonempty process environment values take precedence for credential/path lookup; avoid duplicate empty overrides. Maintenance path resolution also reads `.env`; explicit `--db` selects the target database. Relative paths are rooted at the project.
-
-| Variable | Default / requirement | Purpose |
-|---|---|---|
-| `API_ID` | Required positive integer | Telegram application identifier. |
-| `API_HASH` | Required 32 hexadecimal characters | Telegram application secret. |
-| `BOT_TOKEN` | Required | This installation's BotFather token. |
-| `ADMIN` | Configure for operator access | Comma-separated IDs/resolvable usernames; numeric IDs avoid ambiguity. Configured owners retain recovery/restart access. |
-| `DATA_DIR` | Project `data` | Application and BroadcastManager state; Compose overrides to `/app/data`. |
-| `APP_DB_PATH` | `DATA_DIR/shabbat.sqlite` | Application database; example explicitly uses `data/shabbat.sqlite`. |
-| `SESSION_PATH` | Project `bot.shabbat` | MadelineProto session; example uses `data/session/bot.shabbat`, Compose uses `/app/runtime/bot.shabbat`. |
-| `HEARTBEAT_PATH` | `DATA_DIR/scheduler-heartbeat.json` | Permission/notification heartbeat file. |
-| `LEGACY_DATA_PATH` | Project root | Read-only legacy root containing `data/DBgroups.txt`; startup only adds missing registrations. |
-| `GEONAMES_USERNAME` | Empty | Your webservice account; demo is unsupported. |
-| `GEONAMES_ENDPOINT` | `https://secure.geonames.org` | Verified HTTPS endpoint, no HTTP fallback. |
-| `CUSTOM_EMOJI_ENABLED` | `1` | `0` selects basic emoji; definite eligibility failures also trigger guarded fallback. |
-| `SOURCE_URL` | Empty; set before deployment | HTTPS exact corresponding source URL. Missing configuration is reported, not blocked at startup. |
-| `BUILD_COMMIT` | Archive metadata or 40-hex commit | Build/runtime identity and Compose build argument. Preserve fingerprints for local changes. |
-
-[Configuration details](docs/CONFIGURATION.md) · [Privacy](docs/PRIVACY.md)
-
-
-## Telegram setup
-
-1. Obtain API credentials through [Telegram application management](https://my.telegram.org/apps).
-2. Create/select the bot with [BotFather](https://t.me/BotFather), obtain its token and allow group additions.
-3. Open the bot privately with `/start`. Add it to the intended group with rights to restrict members/change default permissions. Optional deletion/pinning needs the relevant Telegram rights.
-4. Enable BotFather `/setinline` for inline search/sharing. Suggested placeholder: `shabbat · zmanim · daf · omer · loc city`. City-name search requires neither `/setinlinegeo` nor `/setinlinefeedback`; GPS sharing is explicit.
-5. With command-menu mutation access, send `/setcommands all all preview` privately to inspect the menu count; `/setcommands all all` updates Telegram. Group administration alone does not grant that access.
-
-Optional cleanup only processes updates Telegram delivers. General messages from other bots require the receiving bot's **Bot-to-Bot Communication Mode** enabled through BotFather, group administrator status and **Group Privacy Mode** disabled, as described in [Telegram's bot-to-bot documentation](https://core.telegram.org/api/bots/bot-to-bot). Deletion still needs the relevant rights; this is not a guarantee of receiving every message.
-
-
-## Group setup
-
-1. Send `/add` **as a group administrator in the group**. New groups added this way start **off** and open private setup.
-2. Confirm the named group, location, IANA zone and Israel/diaspora calendar. Jerusalem defaults must be reviewed; they are not inferred location.
-3. Select mode and Shabbat/festival policy, then candle/havdalah methods and operational offsets.
-4. Explicitly enable desired zmanim/Daf/tefillin/Omer modules. Preview privately; a group TEST needs separate confirmation and is rate limited.
-5. Return through private `/groups` or group `/settings`. Personal and group settings remain separate.
-
-**Current registration caveat:** `/settings` can register a previously unknown group after verifying its administrator, and that path inherits the database's **lock** default. Use `/add` for the explicit off-first flow and review mode/location immediately. `/settings` does not reactivate a removed group; `/add` can. This behavior is documented as implemented, not silently changed during publication preparation.
-
-Panels show current values, upcoming work and recovery status. Changes require current authority and a user/group/revision-bound confirmation. A missing/closed forum topic produces an error, not redirection. Restoration uses saved original rights; missing/unverified/conflicting snapshots need authorized resolution. Optional cleanup of member/bot messages starts disabled. Group removal is blocked by unresolved restoration debt.
-
-[Settings](docs/GROUP_SETTINGS.md) · [Guided interface](docs/USER_EXPERIENCE.md) · [Permission recovery](docs/PERMISSION_RECOVERY.md)
-
-
-## Location and languages
-
-Six locale catalogs are supplied: Hebrew `he`, English `en`, Russian `ru`, French `fr`, Spanish `es`, Brazilian Portuguese `pt-br`. Their keys/placeholders are checked; this is not a promise that every third-party error or inherited interface is translated. Hebrew ritual wording remains Hebrew, with supplied explanatory text. Telegram menus use `pt`; client menu language and the saved bot preference are separate.
-
-Use private `/preferences` or `/language`; group `/language` requires its administrator. For city search, create a [GeoNames account](https://www.geonames.org/login), activate free webservices and set `GEONAMES_USERNAME`.
-
-In the appropriate panel: **location/timezone → inline city search → city/country/region → inspect coordinates/timezone → confirm the named target**. Private search, known cities, coordinates, IANA zone search and prompted GPS replies are available. Choices expire, belong to one user and are consumed once. Changing timezone does not move coordinates.
-
-Public `loc city` and a bare city name support location search/sharing. Public timezone queries include `tz Jerusalem` or `Asia/Jerusalem`; they do not update settings. Setup queries `location CITY` and `timezone QUERY` require the active private location/timezone prompt and lead to confirmation. Other modes: `shabat`, `shabbat`, `שבת`, `zmanim`, `daf`, `omer`. Check the result's displayed location: personal sharing and an authorized group-context preview may differ. Quota/account failures remain visible errors.
-
-[Inline/GeoNames guide](docs/INLINE_GEONAMES.md)
-
-
-## Calendar modules
-
-| Module | Implemented settings / limits |
-|---|---|
-| Shabbat/festivals | City candle custom or exact 10/15/18/20/22/30/40/custom minutes. Jerusalem city default is 40; explicit 18 remains 18. Havdalah: 8.5° or fixed 42/50/72/custom minutes. Fixed 72 does not represent every Rabbeinu Tam method. |
-| Group timing | Close-before-candles/open-after-havdalah offsets are separate. Adjacent holy days stay closed continuously. Israel/diaspora is explicit. Announcements have independent timing/design, Hebrew dates and Torah-portion metadata. |
-| Zmanim | Civil date/IANA zone; dawn, misheyakir, sunrise, Gra/MGA Shema/prayer, midday, mincha, plag, sunset, nightfall and midnight where available. Missing values remain unavailable. |
-| Daf Yomi | Civil-date calculation and provider study link; skipping sends never pauses the cycle. |
-| Tefillin | Fixed/interval/sunset-relative schedules, deduplication, limits, spacing, quiet windows/pause. Start uses 11.5° `misheyakir`; the stricter provider field is not selectable. No Shabbat/Yom Tov sends; explicit Chol HaMoed/observed Tisha B'Av policies. Cutoff rechecked at dispatch. Optional unique-user acknowledgement toggles participation. |
-| Omer | 49-day seasonal count advances across unsent days/years. Night sends wait for selected nightfall and group quiet-period end; optional day completion omits blessing. `ashkenaz` and documented `sephard` sequence, not every community variant. Full form includes selected preparation/traditional additions. |
-
-Blessing guidance concerns individual eligibility; delivery history is not a person's counting history. See [method definitions](docs/ZMANIM_METHODS.md), [calendar presentation](docs/CALENDAR_PRESENTATION.md) and [text provenance](THIRD_PARTY_NOTICES.md).
-
-
-## Bot commands
-
-Send these **in Telegram**. Menus are shortcuts, not a full permission contract. `[...]` means optional.
-
-### Users
-
-| Command | Where / permission | Effect |
-|---|---|---|
-| `/start`, `/help` | Private; any user | Home menu/help. |
-| `/preferences` | Private; own settings | Personal location/calendar/methods. |
-| `/language`, `/lang` | Private; own settings | Personal language; group usage needs group admin. |
-| `/groups [search]` | Private; fresh group-admin checks | List/search manageable known groups. |
-| `/shabat [YYYY-MM-DD]`, `/shabbat [YYYY-MM-DD]` | Private or registered group; any user | Shabbat/festival times for that context. |
-| `/zmanim [YYYY-MM-DD]` | Private or registered group; any user | Daily times. |
-| `/daf [YYYY-MM-DD]` | Private or registered group; any user | Daf Yomi. |
-| `/omer [YYYY-MM-DD]` | Private or registered group; any user | Count/season for the selected date. |
-| `/stats` | Private or group; any user | Public aggregates, without subscriber identities. |
-| `/donate` | Private; any user | Optional Stars offers; payment needs Telegram checkout. |
-| `/source`, `/license`, `/version` | Private or group; any user | Source offer, licensing/build identity. |
-
-### Group administrators
-
-| Command | Where / permission | Effect |
-|---|---|---|
-| `/add` | Group; current group admin | Register/reactivate and open setup. |
-| `/remove` | Group; current group admin | Deactivate; restoration debt blocks removal. |
-| `/settings` | Group; current group admin | Private group settings; see registration caveat above. |
-| `/settings [GROUP_ID]` | Private; current target-group admin | Open target or list groups without ID. |
-| `/language`, `/lang` | Group; current group admin | Private selection of group language. |
-
-Advanced **private** forms require the panel's exact token, its owner/scope/revision and current group authority for group targets. Prefer the guided buttons.
+Health can take the initial 90-second startup period to become ready. The service is `shabbat`. Named volumes `bot-data` and `madeline-session` preserve application and session data; their full names include the Compose project name.
-| Form | Effect |
-|---|---|
-| `/city TOKEN QUERY` | Search pending location. |
-| `/coordinates TOKEN LATITUDE LONGITUDE IANA_ZONE [NAME]` | Preview explicit coordinates/zone. |
-| `/location TOKEN IANA_ZONE` or `/location TOKEN auto` | Prompt for GPS reply; auto requires GeoNames. |
-| `/timezone TOKEN QUERY` | Search IANA zones. |
-| `/configure TOKEN FORM` | Preview the panel's supported settings form. |
-| `/viewdate TOKEN YYYY-MM-DD` | Selected calendar date. |
-| `/template TOKEN` + newline + content | Review a group template candidate. |
-| `/buttons TOKEN` + newline + keyboard content | Review JSON/legacy keyboard content. |
-
-### Bot managers
+
+## 3. Set up Telegram and your first group
-All below run **in private**. Bot-manager roles are separate from group administration; view-only roles cannot mutate.
-
-| Command | Required access | Effect |
-|---|---|---|
-| `/admin` | Bot manager | Administration panel. |
-| `/adminstats` | Statistics | Administrative aggregates. |
-| `/testzmanim [GROUP_ID]` | Statistics | Paged diagnostics/filter/search and optional private JSON export. |
-| `/subscribers` | Subscribers | Known peer/profile directory. |
-| `/broadcast` | Broadcast | Drafts/jobs; sending/editing/deleting needs mutation rights and relevant confirmation. |
-| `/managers` | Manage managers | Delegated roles within actor's authority. |
-| `/systemlinks` | System links | Navigation links, which confer no permissions. |
-| `/trackinglinks` | Tracking links | Activation counters/management; changes need mutation access. |
-| `/setcommands [LANGUAGE] [SCOPE] [preview]` | Command-menu mutation, even preview | Inspect or update Telegram menus. |
-| `/closegroups`, `/opengroups` | Group-operations mutation | Immediately apply a one-hour override to active registered groups; preserve prelocks/report conflicts. Real permission operations. |
-| `/restart` | Configured `ADMIN` owner only | Orderly runtime restart. |
+1. In BotFather, allow group additions. Enable `/setinline` for inline location/calendar search.
+2. Send `/start` privately. Check the home buttons, `/preferences` and your language.
+3. Add the bot as a group administrator with permission to restrict members. Optional deletion/pinning requires the corresponding rights.
+4. As a group administrator, send `/add` **in the group**. This creates a new group in **off** mode and opens setup.
+5. Review location, timezone, calendar, mode and candle/havdalah methods. Enable only the reminders you want. Return through `/groups` privately or `/settings` in the group.
-Menu languages: `all|he|en|ru|fr|es|pt-br`; scopes: `all|private|operators|groups|group_admins`; defaults: `all all`. Example: `/setcommands ru group_admins preview`. Group menus currently list `/settings`; other supported commands can be typed.
+Use `/add` for first setup: direct `/settings` registration currently inherits lock mode. Review the defaults before enabling a real group. Bot administrators and group administrators have separate permissions.
-[Administration](docs/ADMIN_PANEL.md) · [Diagnostics](docs/DIAGNOSTICS.md)
+[All bot commands](docs/COMMANDS.md) · [Group settings](docs/GROUP_SETTINGS.md) · [Location and inline search](docs/INLINE_GEONAMES.md)
-
-## Operations
+
+## Everyday operation and updates
-Docker commands run **on the host at the same project root/project identity**, with daemon access. PHP commands run **inside the image at /app**, or at the manual root as its service user. Operational output can contain group IDs/state; keep it private.
+Run **on the host, from the installed project root**, with Docker access and the same Compose project identity:
-| Task | Command | Effect / condition |
+| Action | Command | Effect |
|---|---|---|
-| Build | `docker compose build` | Build from source/lock. |
-| Start | `docker compose up -d shabbat` | Start/recreate and connect to Telegram. |
-| Stop | `docker compose stop shabbat` | Graceful stop, 60-second grace; retain volumes. |
-| Restart | `docker compose restart shabbat` | Restart same service; does not rebuild image. |
-| Status | `docker compose ps` | Container/service state. |
-| Logs | `docker compose logs --tail=100 shabbat` | Read logs; add `--follow` to stream, Ctrl+C exits viewer. |
-| Health | `docker compose exec shabbat php bin/health.php` | Schema/connection, both heartbeats and queue/lock metrics. |
-| Deep health | `docker compose exec shabbat php bin/health.php --deep` | Also integrity/foreign-key checks; more expensive. |
-| Release gate | `docker compose run --rm --no-deps shabbat php bin/self-check.php --release` | Offline platform/patch checks. |
-| Write probe | `docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root` | Offline temporary-file probe; may append to existing worker log. |
-
-Both heartbeats must be no older than 180 seconds. Offline/restored DBs can pass structural checks yet return `healthy=false` / exit 1 without schedulers. Never manufacture heartbeat files.
-
-Run direct maintenance below **at project root as service user**. In Docker, prefix PHP commands with `docker compose run --rm --no-deps shabbat` and use container paths. `--writers-stopped` is an attestation, not a stop command.
-
-| Task | Command | Effect / requirement |
-|---|---|---|
-| Migrate | `php bin/migrate.php --writers-stopped --db data/shabbat.sqlite --backup-dir backups` | All writers stopped, existing backup directory. Back up existing DB/apply migrations; omit backup only for new DB. |
-| Backup | `php bin/backup.php --db data/shabbat.sqlite --directory backups --keep 7` | Consistent SQLite copy/manifest; retain seven tool-named backups. Online maintenance allowed. |
-| Restore | `php bin/restore.php --backup backups/CHOSEN.sqlite --db data/shabbat.sqlite --writers-stopped` | Verified chosen backup, stopped writers; previous destination retained. |
-| Inspect legacy | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --dry-run` | Inspect/report, no imported-record writes or Telegram actions. |
-| Import legacy | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --apply --writers-stopped --backup-dir backups` | Existing migrated DB/backup directory, stopped writers; additive import. |
-| Calendar diagnostic | `php bin/check-calendar.php --date=2026-10-15` | Public HTTPS only; no DB, .env or session. `--help` lists coordinates/zone/calendar/language options. |
-| Verify patches | `php scripts/verify-patches.php` | Inspect approved installed bytes. |
-| Apply patches | `composer patches` | Apply/verify; stopped installation only. |
-| Build identity | `php bin/build-metadata.php --commit=YOUR_40_HEX_COMMIT` | Replace placeholder with verified provenance; writes metadata/rejects stale fingerprint. |
-
-
-## Upgrade and legacy import
-
-Preserve private configuration, data/session and Compose project identity. Use reviewed source/lock; stop every writer before schema or installed dependency changes. Routine upgrades use `composer install`, not `composer update`.
-
-For an existing Compose DB, from the prepared project connected to the **same volumes**:
-
-~~~sh
-docker compose build
-docker compose stop shabbat
-docker compose run --rm --no-deps shabbat mkdir -p /app/data/backups
-docker compose run --rm --no-deps shabbat php bin/backup.php --db /app/data/shabbat.sqlite --directory /app/data/backups --keep 7
-~~~
-
-Complete the stopped session/BroadcastManager backup and restore rehearsal below **before proceeding**. Then apply the schema and release checks:
-
-~~~sh
-docker compose run --rm --no-deps shabbat php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite --backup-dir /app/data/backups
-docker compose run --rm --no-deps shabbat php bin/self-check.php --release
-~~~
+| Start | `docker compose up -d shabbat` | Start/connect the bot |
+| Stop | `docker compose stop shabbat` | Stop the bot; retain volumes |
+| Restart | `docker compose restart shabbat` | Restart the current image |
+| Status | `docker compose ps` | Display service state |
+| Logs | `docker compose logs --tail=100 -f shabbat` | Follow logs; Ctrl+C stops the log view |
+| Health | `docker compose exec shabbat php bin/health.php --deep` | Check the running scheduler/database |
-`docker compose up -d shabbat` then activates the reviewed image; inspect logs/health. Manual installations follow stop/backup/install-from-lock/migrate/check/start.
+**Updating requires a stopped-writer backup and migration check.** Follow the [upgrade guide](docs/PRODUCTION_UPGRADE.md) ([עברית](docs/PRODUCTION_UPGRADE_HE.md)) for verified paths, staging, import or SQLite upgrade, session preservation and rollback. Rebuilding alone does not migrate a database; `restart` alone does not install a new image. Do not run `composer update` for an ordinary deployment or remove data volumes.
-3.0.0 adds no migration beyond dev.9. dev.8 → dev.9 added `016_delivery_safety.sql`. dev.6 also needs 013–015; earlier versions apply all missing migrations automatically. Do not edit applied SQL. Uncertain past delivery attempts are handled conservatively; older unverified permission snapshots still require administrator review.
+
+## More help
-For the old file-based bot: preserve a protected legacy copy; stop old writers for final import/cutover; initialize a new DB; run dry-run, compare counts/templates/rights/warnings, then apply with stopped writers and backup directory. The exact commands appear above. For Docker mount only the protected copy read-only:
-
-~~~sh
-docker compose run --rm --no-deps --volume /absolute/path/legacy-copy:/legacy:ro shabbat php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /legacy --dry-run
-~~~
-
-Explicit import preserves applicable groups, templates/entities/media/buttons, drafts, known peers and permission evidence without Telegram calls. New reminder modules remain off; malformed/missing snapshots remain review items. The startup `DBgroups.txt` bridge only adds registrations and does not replace full import. Never substitute a test bot's DB/session for production state.
-
-[Migration](docs/MIGRATION.md) · [Schema](docs/DATABASE.md) · [Older snapshots](docs/DEV8_PERMISSIONS.md)
-
-
-## Backup and rollback
-
-SQLite backup uses `VACUUM INTO`, validates integrity/foreign keys/schema history and writes SHA-256 metadata. Copying only a live main file can omit committed WAL. Retention only removes this tool's strictly named backups in the chosen directory; choose `--keep` deliberately.
-
-SQLite does **not** include the session or all BroadcastManager files. Stop their writers and keep these separate paths, private configuration and matching code/lock alongside the DB backup. Docker example **after stopping the service**, on the host project root. Use a new empty snapshot directory for each backup (replace `../shabbat-private-backup` consistently):
-
-~~~sh
-mkdir -p ../shabbat-private-backup
-chmod 700 ../shabbat-private-backup
-docker compose cp shabbat:/app/data ../shabbat-private-backup/data
-docker compose cp shabbat:/app/runtime ../shabbat-private-backup/runtime
-cp .env ../shabbat-private-backup/config.env
-chmod 600 ../shabbat-private-backup/config.env
-~~~
-
-This copies complete stopped durable directories to a sibling outside the Docker build context. Keep them private, outside publication material. For manual installation copy the actual resolved data/session paths with writers stopped. Verify all backups before replacement.
-
-Create a separate rehearsal directory and restore a chosen verified SQLite backup there:
-
-~~~sh
-mkdir -p ../shabbat-rehearsal
-php bin/restore.php --backup backups/CHOSEN.sqlite --db ../shabbat-rehearsal/restored.sqlite --writers-stopped
-php bin/health.php --db ../shabbat-rehearsal/restored.sqlite --deep
-~~~
-
-Replace `CHOSEN.sqlite` with the real filename. Inspect structural fields, schema and sampled records; overall health may exit 1 without live heartbeats.
-
-Rollback: stop writers; retain a current recovery backup; resolve/record outstanding Telegram permission obligations; restore older compatible DB/code/lock/session/BroadcastManager state; start one matching instance and review fresh remote reconciliation. DB restoration cannot reverse already accepted Telegram changes. Restore validates the input/manifest, obtains the writer lock and retains `*.before-restore-*`. Busy writers or incompatible schema require investigation, not deleting locks/volumes.
-
-[Backup/restore details](docs/BACKUP_RESTORE.md)
-
-
-## Troubleshooting
-
-| Symptom | Action |
+| Topic | Guide |
|---|---|
-| Missing commit/changed source at build | Retain verified archive metadata or supply actual reviewed checkout identity. Regenerate archive metadata after source changes. |
-| SQLite release gate fails | Use the pinned image/accepted fixed runtime; development warnings are not production acceptance. |
-| Schema missing/stale | Stop writers, back up and migrate explicit paths. Startup does not migrate. |
-| Patch failure | Check lock/manifests; reinstall in a clean stopped copy. Do not weaken verification. |
-| New group sends nothing | Review mode, location, module opt-in and schedule; `/add` starts off. |
-| Settings inaccessible/expired | Open private chat and fresh `/settings` as current group administrator. |
-| City search fails | Check GeoNames activation/account/quota/HTTPS; use known cities/coordinates if needed. |
-| Unhealthy status | Inspect both heartbeat ages, schema, queue and logs; stopped schedulers have no fresh heartbeat. |
-| Group not reopening | Use recovery/diagnostics for missing/unverified/conflicting snapshots; preserve original restrictions. |
-| Missing/late reminder | Check timezone/date, quiet hours, holiday/cutoff policy, module and topic. Dispatch rechecks eligibility. |
-| Custom emoji rejection | Set `CUSTOM_EMOJI_ENABLED=0`; definite eligibility failures also trigger fallback. |
-| Permission-denied files | Check image UID/GID 10001 and working/data/session paths; run write probe. Avoid world-writable permissions. |
-
-[More troubleshooting](docs/TROUBLESHOOTING.md) · [Privacy](docs/PRIVACY.md) · [Security reporting](.github/SECURITY.md)
-
-
-## Project and development
-
-| Path | Contents |
-|---|---|
-| `bot.php`, `src/` | Entry point; calendar/UI/scheduling/storage/Telegram/runtime services. |
-| `bin/`, `migrations/` | Maintenance tools and immutable numbered schema changes. |
-| `resources/` | Six locales, attributed Omer resources and PHP configuration. |
-| `patches/` | Reviewed bases/replacements/diffs, provenance and SHA-256 manifests. |
-| `tests/` | Offline tests and required JSON/TXT/PHP fixtures. |
-| `scripts/` | Patches, quality, dependencies and local packaging. |
-| `docs/`, `LICENSES/` | Guides, provenance and license texts. |
-| `.github/` | CI/release workflows and contribution/security templates. |
-
-Run **in a separate development copy at its root as developer**, without production state/credentials. Install includes test tools; tests use isolated temporary state.
-
-~~~sh
-composer install --no-interaction --prefer-dist
-composer validate --strict --no-check-all
-composer check-platform-reqs
-php scripts/verify-patches.php
-composer test
-composer lint
-composer style
-composer analyse
-composer check-locales
-composer check-docs
-composer self-check
-~~~
-
-`--no-check-all` omits generic version-range advice for the deliberate exact MadelineProto pin; strict schema/lock checks remain. `lint` checks syntax/quality; `style` enforces PHPCS errors; `analyse` runs PHPStan. `composer style-review` includes the broader style report; `composer style-fix` **rewrites files**, for reviewed development copies only.
-
-At the same development root:
-
-~~~sh
-composer show --locked --format=json
-composer licenses --format=json
-composer audit --locked --format=json
-composer dependencies
-~~~
-
-These report locked packages, installed licenses and current advisories; audit contacts advisory services. `dependencies` writes evidence under `docs/`; review/sanitize it before inclusion. Do not replace the lock to silence a check.
-
-Developer-only patch regeneration, from the development root:
-
-~~~sh
-php patches/madelineproto/generate-artifacts.php
-php patches/broadcastmanager/generate-artifacts.php
-~~~
-
-These commands rewrite patch artifacts/manifests from bundled reviewed sources. They are for an intentional patch review, not routine installation. Review the changed hashes/diffs and run the full patch checks afterward. The apply/verify PHP scripts also accept an optional first positional vendor directory; leave it unset for the normal `vendor/` path.
-
-For release packaging from a clean committed checkout, with Git, Python 3.9+ and the locked development installation available:
-
-~~~sh
-php scripts/package.php
-~~~
-
-This writes `shabbat-3.0.0.zip`, `shabbat-3.0.0-corresponding-source.zip`, `RELEASE_MANIFEST.json` and `SHA256SUMS` to `dist/`, without publishing. The source bundle includes locked runtime sources, reviewed patches and pinned preferred-source supplements. The legacy three-archive tool is available only through `php scripts/package.php --development` for local development, with default output `dist/development/`; its installed tool distributions do not constitute a release corresponding-source offer. See [release preparation](docs/RELEASE.md) for prerequisites, source scope and artifact checks.
-
-[Architecture](docs/ARCHITECTURE.md) · [Dependencies](docs/DEPENDENCIES.md) · [Patches](docs/PATCHES.md) · [Release preparation](docs/RELEASE.md) · [Contributing](.github/CONTRIBUTING.md) · [Code of conduct](.github/CODE_OF_CONDUCT.md)
-
-
+| Detailed installation and manual PHP setup | [Installation](docs/INSTALLATION.md) |
+| Environment variables and preferences | [Configuration](docs/CONFIGURATION.md) |
+| Commands and administration | [Commands](docs/COMMANDS.md), [operations](docs/OPERATIONS.md), [admin panel](docs/ADMIN_PANEL.md) |
+| Upgrade, import and recovery | [English](docs/PRODUCTION_UPGRADE.md), [עברית](docs/PRODUCTION_UPGRADE_HE.md), [import mapping](docs/MIGRATION.md), [backup/restore](docs/BACKUP_RESTORE.md) |
+| Permissions, timing and reminders | [Permission recovery](docs/PERMISSION_RECOVERY.md), [calendar methods](docs/ZMANIM_METHODS.md), [delivery safety](docs/DELIVERY_SAFETY.md) |
+| Problems and diagnostics | [Troubleshooting](docs/TROUBLESHOOTING.md), [diagnostics](docs/DIAGNOSTICS.md) |
+| Development and validation | [Contributing](.github/CONTRIBUTING.md), [architecture](docs/ARCHITECTURE.md), [acceptance status](docs/IMPLEMENTATION_STATUS.md) |
+| Releases and source packaging | [Changelog](CHANGELOG.md), [release notes](docs/RELEASE_NOTES.md), [release process](docs/RELEASE.md) |
+
+
## License and credits
-The integrated application is **AGPL-3.0-only**: [LICENSE](LICENSE), [licensing policy](docs/LICENSING.md). Historical MIT notices/prior grants remain. Dependency, data and transcription licenses are separate; their headers/notices are preserved.
-
-Credit to [WizardLoop](https://github.com/WizardLoop), [MadelineProto](https://github.com/danog/MadelineProto), [BroadcastManager](https://github.com/WizardLoop/BroadcastManager), [Hebcal](https://www.hebcal.com/), [GeoNames](https://www.geonames.org/) and attributed Hebrew Wikisource liturgy sources. Components, licenses, immutable revisions, modifications and attribution are recorded in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md), dependency manifests and resource provenance.
+The application is **AGPL-3.0-only**. Preserve its [license](LICENSE), historical copyright notices and [third-party notices](THIRD_PARTY_NOTICES.md). Dependency licenses remain separate. MadelineProto, BroadcastManager, Hebcal, GeoNames and bundled resource sources are credited there.
-Operators/forks must make the **exact deployed corresponding source** available, including local application/dependency changes and necessary build material, and set `SOURCE_URL`. A different public `main` is insufficient. Publication material excludes private configuration, live DB/WAL/SHM, sessions, backups, logs and caches, while retaining required source, tests/fixtures, patch baselines and license texts.
+Operators must offer the exact corresponding source of deployed modifications. The separate corresponding-source ZIP includes the application and documented runtime sources, with no claim to the whole operating system or every development tool. See [licensing](docs/LICENSING.md).
diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index 9c03394..a0c53ae 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -1,21 +1,22 @@
# Third-party notices
-WizardLoop Shabbat **3.0.0** is distributed as an **AGPL-3.0-only** application. Dependency, historical-source and data licenses retain their own scope. The full application license is in [LICENSE](LICENSE); the [licensing guide](docs/LICENSING.md) explains the source offer. Exact locked versions, sources, license paths and findings are recorded in the [dependency inventory](docs/dependencies.json).
+WizardLoop Shabbat **3.1.0** uses **AGPL-3.0-only** for the combined application. Dependencies, historical source and data retain their own grants and notices. The complete application license is in [LICENSE](LICENSE); exact versions, source revisions, license files and findings are in the [dependency inventory](docs/dependencies.json).
## Code and tools
-| Component | Source and license | Attribution and local changes |
+| Component | Source and license evidence | Attribution and local changes |
|---|---|---|
-| Original WizardLoop Shabbat | [WizardLoop/shabbat](https://github.com/WizardLoop/shabbat), historical MIT | Copyright (c) 2024 WizardLoop. The complete original grant is retained in [SHABBAT-LEGACY-MIT.txt](LICENSES/SHABBAT-LEGACY-MIT.txt); earlier grants remain effective. |
-| MadelineProto 8.7.0 | [Pinned source](https://github.com/danog/MadelineProto/tree/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed), package metadata AGPL-3.0-only | Preserve its distributed license and copyright headers. Four local compatibility patches cover update-loop cancellation, fractional coordinates, formatted-date entities and fresh full-peer response evidence. |
-| WizardLoop BroadcastManager 3.2.2 | [Pinned source](https://github.com/WizardLoop/BroadcastManager/tree/f2792a383416b66bb68e55f09414563e540538d6), AGPL-3.0-only | Preserve WizardLoop notices. The local patch adds presentation, message-transport, authorization, cancellation and joined-worker lifecycle hooks. |
-| Amp and Revolt | [Amp](https://github.com/amphp) and [Revolt](https://github.com/revoltphp/event-loop), MIT | Distributed author/copyright notices remain in their packages. Exact direct and transitive versions are in the inventory. |
-| Development tools | PHPUnit and PHP_CodeSniffer: BSD-3-Clause; PHPStan: MIT | Locked tool and transitive-package notices are inventoried separately from runtime dependencies. The runtime corresponding-source archive does not bundle the development tools. |
-| SQLite | [SQLite public-domain dedication](https://sqlite.org/copyright.html) | External PHP-loaded runtime library. The Dockerfile identifies the reviewed source version and checksum; SQLite is not relicensed as application code. |
+| Original WizardLoop Shabbat | [WizardLoop/shabbat](https://github.com/WizardLoop/shabbat), historical MIT | Copyright (c) 2024 WizardLoop. The original [MIT grant](LICENSES/SHABBAT-LEGACY-MIT.txt) remains effective. |
+| MadelineProto 8.11.10 | [Pinned source](https://github.com/danog/MadelineProto/tree/49d3d8460257c7bfb1a7e12708e1bfdd59e898c1), metadata AGPL-3.0-only; source headers version 3 or later | Preserve original notices. One local PeerHandler patch exposes fresh full-peer response evidence. Official UpdateLoop, GeoPoint and FormattedDate source replaces those former local patches. |
+| WizardLoop BroadcastManager 3.2.2 | [Pinned source](https://github.com/WizardLoop/BroadcastManager/tree/f2792a383416b66bb68e55f09414563e540538d6), AGPL-3.0-only | Preserve WizardLoop notices. The local patch supplies presentation, transport, authorization, cancellation and joined-worker lifecycle hooks. |
+| Amp and Revolt | [Amp](https://github.com/amphp), [Revolt](https://github.com/revoltphp/event-loop), MIT | Original package notices remain attached; Windows helper source is supplied separately with its MIT license. |
+| PHP RTC components | [danog repositories](https://github.com/danog), exact pins in the inventory | Most declare BSD-3-Clause. **php-rtc-av declares MIT in metadata but distributes a BSD-3-Clause LICENSE and BSD source headers.** Both are preserved; the MIT declaration is not confirmed by its distributed license. Optional FFmpeg/native libraries are not included. |
+| Development tools | PHPUnit/PHP_CodeSniffer: BSD-3-Clause; PHPStan: MIT | All 26 development packages are inventoried separately and excluded from the runtime source collection. |
+| SQLite | [Public-domain dedication](https://sqlite.org/copyright.html) | External PHP-loaded library. Docker pins its source checksum; it is not relicensed as application code. |
-There are **five active patch sets**. Their original sources, approved intermediate sources, diffs, added source and SHA-256 manifests are preserved under [patches/](patches). [Technical provenance](docs/THIRD_PARTY_DETAILS.md) records exact identities and historical changes. Installation verifies them before startup; running vendor trees must not be changed.
+There are **two active patch sets**, with immutable baselines, reviewed outputs, diffs and SHA-256 manifests under [patches](patches). Installation applies and verifies them before startup. Do not modify a running vendor tree. [Technical provenance](docs/THIRD_PARTY_DETAILS.md) records their identities and the retirement of earlier patches. Using official SDK code does not establish that every shutdown regression is resolved.
-MadelineProto package metadata says `AGPL-3.0-only`, while retained source headers allow version 3 or later. The new formatted-date wrapper also grants `AGPL-3.0-or-later`. These grants are preserved; the combined application's policy uses version 3. The metadata/header difference remains a recorded finding.
+The source collection contains 83 locked runtime packages and pinned preferred-source supplements. It is not a complete operating-system/container source distribution or a claim of reproducible native binary rebuilding. [Licensing and archive scope](docs/LICENSING.md) records the boundaries and unresolved provenance evidence.
## Data and text
@@ -29,10 +30,10 @@ MadelineProto package metadata says `AGPL-3.0-only`, while retained source heade
The complete [CC-BY-4.0](LICENSES/CC-BY-4.0.txt) and [CC-BY-SA-4.0](LICENSES/CC-BY-SA-4.0.txt) terms are retained unchanged. [Detailed resource provenance](docs/THIRD_PARTY_DETAILS.md#data-provenance) links the exact fixture records and Wikisource revisions. Traditional underlying liturgy is distinguished from the separately attributed transcription/editorial resource; no complete modern siddur is claimed.
-## References and unresolved evidence
+## References and historical evidence
-[JewishPulse](https://github.com/WizardLoop/JewishPulse/tree/d7b06eb1acb206543dcff35a7c14ebce4760b4e5), AGPL-3.0-only, informed the interface comparison and documentation structure. Its branding and hardcoded bot links are not used. The [feature comparison](docs/FEATURE_PARITY.md) describes the reference relationship.
+[JewishPulse](https://github.com/WizardLoop/JewishPulse/tree/d7b06eb1acb206543dcff35a7c14ebce4760b4e5), AGPL-3.0-only, informed the interface comparison and documentation organization. Its branding and hardcoded bot links are not used; this is a historical reference relationship.
No third-party graphic asset was added. Telegram standard emoji and button metadata are interface features. Provenance of an older remote thumbnail is unestablished; current inline results do not depend on it.
-Historical formatted-date reference exports had conflicting project declarations and no recovered standalone grant or Git history. Their hashes and findings are retained in [the provenance review](docs/MADELINE_FORMATTED_DATE.md); those original exports are not redistributed. On 2026-10-16, the project maintainer stated that they authored the retained historical UpdateLoop helper and explicitly authorized distribution under AGPL-3.0-only. The dated, hash-scoped attestation is recorded in [its manifest](patches/madelineproto/manifest.json); the original helper bytes remain unchanged. This records the maintainer's statement, not an independent legal certification.
+The former local UpdateLoop helper, GeoPoint patch and independently authored formatted-date wrapper are no longer shipped in this source tree. Earlier releases retain their historical notices and hash-scoped provenance. The maintainer's 2026-10-16 authorization of the historical UpdateLoop helper is limited to that exact prior helper; it does not change dependency grants. Historical formatted-date exports with conflicting project declarations were never redistributed. [Technical provenance](docs/THIRD_PARTY_DETAILS.md) retains their identifying hashes without treating them as active installation inputs.
diff --git a/VERSION b/VERSION
index 4a36342..fd2a018 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.0
+3.1.0
diff --git a/bin/import-legacy.php b/bin/import-legacy.php
index 7523e65..10ac453 100644
--- a/bin/import-legacy.php
+++ b/bin/import-legacy.php
@@ -9,7 +9,7 @@
use Shabbat\Storage\Database;
use Shabbat\Storage\LegacyImporter;
use Shabbat\Time\SystemClock;
-$options = getopt('', ['db:','legacy:','dry-run','apply','writers-stopped','backup-dir:']);
+$options = getopt('', ['db:','legacy:','dry-run','apply','writers-stopped','backup-dir:','expect-report:']);
try {
if (!isset($options['legacy'])) {
throw new RuntimeException('Specify the read-only legacy source using --legacy=/path/to/old/bot or /path/to/data.');
@@ -18,6 +18,22 @@
throw new RuntimeException('Choose either --dry-run or --apply.');
}
$dryRun = !isset($options['apply']);
+ $expectedReport = null;
+ if (isset($options['expect-report'])) {
+ $reportPath = (string)$options['expect-report'];
+ if (!is_file($reportPath) || is_link($reportPath) || filesize($reportPath) > 16 * 1024 * 1024) {
+ throw new RuntimeException('Expected report must be a readable regular JSON file of at most 16 MiB.');
+ }
+ $contents = file_get_contents($reportPath);
+ if ($contents === false) {
+ throw new RuntimeException('Cannot read the expected legacy report.');
+ }
+ $expectedReport = json_decode($contents, true, 64, JSON_THROW_ON_ERROR);
+ if (!is_array($expectedReport)) {
+ throw new RuntimeException('Expected report must contain a dry-run JSON object.');
+ }
+ }
+ $backup = null;
$path = (string)($options['db'] ?? \Shabbat\Runtime\RuntimePaths::resolve(dirname(__DIR__))->databasePath);
if (!$dryRun) {
if (!isset($options['writers-stopped'])) {
@@ -31,14 +47,20 @@
}
$lock = new InstanceLock($path . '.writer.lock');
$db = Database::open($path);
- (new BackupService())->backup($db, $options['backup-dir'] . '/shabbat-backup-' . gmdate('Ymd-His') . '-' . bin2hex(random_bytes(4)) . '.sqlite');
+ $db->assertCurrentSchema();
+ $backup = (new BackupService())->backup($db, $options['backup-dir'] . '/shabbat-backup-' . gmdate('Ymd-His') . '-' . bin2hex(random_bytes(4)) . '.sqlite');
} elseif (is_file($path)) {
$db = Database::open($path);
} else {
$db = Database::open(':memory:');
$db->migrate();
}
- echo Database::encode((new LegacyImporter($db, new SystemClock()))->run((string)$options['legacy'], $dryRun)) . "\n";
+ $db->assertCurrentSchema();
+ $report = (new LegacyImporter($db, new SystemClock()))->run((string)$options['legacy'], $dryRun, $expectedReport);
+ if ($backup !== null) {
+ $report['pre_import_backup'] = $backup;
+ }
+ echo Database::encode($report) . "\n";
} catch (Throwable $error) {
fwrite(STDERR, $error->getMessage() . "\n");
exit(1);
diff --git a/bin/self-check.php b/bin/self-check.php
index b046266..c1fcc4c 100644
--- a/bin/self-check.php
+++ b/bin/self-check.php
@@ -4,6 +4,13 @@
// SPDX-License-Identifier: AGPL-3.0-only
$root = dirname(__DIR__);
+require_once $root . '/src/Runtime/PhpRuntime.php';
+try {
+ \Shabbat\Runtime\PhpRuntime::assertSupported();
+} catch (\RuntimeException $error) {
+ echo json_encode(['php' => PHP_VERSION, 'secrets_required' => false, 'failures' => [$error->getMessage()]], JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . "\n";
+ exit(1);
+}
require_once $root . '/vendor/autoload.php';
require_once $root . '/scripts/apply-patches.php';
$failures = [];
@@ -13,9 +20,6 @@
$failures[] = 'Missing PHP extension ' . $extension;
}
}
-if (PHP_INT_SIZE !== 8 || PHP_VERSION_ID < 80300 || PHP_VERSION_ID >= 80600) {
- $failures[] = 'Supported platform is 64-bit PHP 8.3, 8.4 or 8.5.';
-}
try {
$pdo = new PDO('sqlite::memory:');
$sqlite = $pdo->query('SELECT sqlite_version()')->fetchColumn();
@@ -37,7 +41,7 @@
}
try {
$patches = \Shabbat\Runtime\PatchSet::process($root, false);
- $patch = $patches['madelineproto'];
+ $patch = $patches['madelineproto-fresh-peer'];
} catch (Throwable $error) {
$patch = 'FAILED';
$failures[] = $error->getMessage();
diff --git a/bot.php b/bot.php
index 758c5fe..860c4a3 100644
--- a/bot.php
+++ b/bot.php
@@ -12,6 +12,14 @@
* @link wizardloop => https://wizardloop.t.me
*/
+require_once __DIR__.'/src/Runtime/PhpRuntime.php';
+try {
+ \Shabbat\Runtime\PhpRuntime::assertSupported();
+} catch (\RuntimeException $error) {
+ fwrite(STDERR, $error->getMessage()."\n");
+ exit(1);
+}
+
$autoload = __DIR__.'/vendor/autoload.php';
if (!file_exists($autoload)) {
die("Autoload file not found. Please run 'composer install'.");
diff --git a/composer.json b/composer.json
index e5fbd31..96e0691 100644
--- a/composer.json
+++ b/composer.json
@@ -9,11 +9,11 @@
}
],
"require": {
- "php": "~8.3.0 || ~8.4.0 || ~8.5.0",
+ "php": "~8.3.36 || ~8.4.27 || ~8.5.12",
"ext-pdo": "*",
"ext-pdo_sqlite": "*",
"ext-mbstring": "*",
- "danog/madelineproto": "8.7.0",
+ "danog/madelineproto": "^8.11.10",
"wizardloop/broadcastmanager": "~3.2.2",
"amphp/amp": "^3.1.1",
"amphp/file": "^3.2",
diff --git a/composer.lock b/composer.lock
index 242eb69..34fba19 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "a66db3dc1cf910ea659bd986ec4af70a",
+ "content-hash": "a97058db3883fce1e08983afa5d9e2ab",
"packages": [
{
"name": "amphp/amp",
@@ -1944,18 +1944,78 @@
},
"time": "2026-04-05T21:06:35+00:00"
},
+ {
+ "name": "brick/math",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/brick/math.git",
+ "reference": "2effe05d2177c451b86c6a073196a4034c02f211"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/brick/math/zipball/2effe05d2177c451b86c6a073196a4034c02f211",
+ "reference": "2effe05d2177c451b86c6a073196a4034c02f211",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "2.2.13",
+ "phpstan/phpstan-phpunit": "2.0.18",
+ "phpunit/phpunit": "^11.5"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Brick\\Math\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Arbitrary-precision arithmetic library",
+ "keywords": [
+ "Arbitrary-precision",
+ "BigInteger",
+ "BigRational",
+ "arithmetic",
+ "bigdecimal",
+ "bignum",
+ "bignumber",
+ "brick",
+ "decimal",
+ "integer",
+ "math",
+ "mathematics",
+ "rational"
+ ],
+ "support": {
+ "issues": "https://github.com/brick/math/issues",
+ "source": "https://github.com/brick/math/tree/1.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/BenMorel",
+ "type": "github"
+ }
+ ],
+ "time": "2026-09-12T10:28:18+00:00"
+ },
{
"name": "danog/async-orm",
- "version": "1.1.4",
+ "version": "1.1.6",
"source": {
"type": "git",
"url": "https://github.com/danog/AsyncOrm.git",
- "reference": "495f335d8ddb9dae8b773025911191f31c45e9ea"
+ "reference": "4a2a7a54c5002bef6cdf80b338085e9e131bf719"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/AsyncOrm/zipball/495f335d8ddb9dae8b773025911191f31c45e9ea",
- "reference": "495f335d8ddb9dae8b773025911191f31c45e9ea",
+ "url": "https://api.github.com/repos/danog/AsyncOrm/zipball/4a2a7a54c5002bef6cdf80b338085e9e131bf719",
+ "reference": "4a2a7a54c5002bef6cdf80b338085e9e131bf719",
"shasum": ""
},
"require": {
@@ -1999,7 +2059,7 @@
"description": "Async ORM based on AMPHP v3 and fibers.",
"support": {
"issues": "https://github.com/danog/AsyncOrm/issues",
- "source": "https://github.com/danog/AsyncOrm/tree/1.1.4"
+ "source": "https://github.com/danog/AsyncOrm/tree/1.1.6"
},
"funding": [
{
@@ -2007,7 +2067,7 @@
"type": "github"
}
],
- "time": "2025-07-12T18:39:01+00:00"
+ "time": "2026-10-19T18:46:06+00:00"
},
{
"name": "danog/better-prometheus",
@@ -2151,16 +2211,16 @@
},
{
"name": "danog/ipc",
- "version": "1.0.1",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/danog/ipc.git",
- "reference": "505e672b76af6ec623f7ef78efb2416f62ef8e29"
+ "reference": "eea6de6a57273f32a4f90a652ae1409786be18a0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/ipc/zipball/505e672b76af6ec623f7ef78efb2416f62ef8e29",
- "reference": "505e672b76af6ec623f7ef78efb2416f62ef8e29",
+ "url": "https://api.github.com/repos/danog/ipc/zipball/eea6de6a57273f32a4f90a652ae1409786be18a0",
+ "reference": "eea6de6a57273f32a4f90a652ae1409786be18a0",
"shasum": ""
},
"require": {
@@ -2176,6 +2236,9 @@
"phpunit/phpunit": "^9.6.22",
"psalm/phar": "^5.26.1"
},
+ "suggest": {
+ "ext-sockets": "Required for UNIX socket support on Windows (TCP is used otherwise)"
+ },
"type": "library",
"autoload": {
"files": [
@@ -2214,9 +2277,9 @@
],
"support": {
"issues": "https://github.com/danog/ipc/issues",
- "source": "https://github.com/danog/ipc/tree/1.0.1"
+ "source": "https://github.com/danog/ipc/tree/1.1.0"
},
- "time": "2025-04-18T14:42:00+00:00"
+ "time": "2026-10-18T18:06:10+00:00"
},
{
"name": "danog/libdns-json",
@@ -2342,41 +2405,61 @@
},
{
"name": "danog/madelineproto",
- "version": "8.7.0",
+ "version": "8.11.10",
"source": {
"type": "git",
"url": "https://github.com/danog/MadelineProto.git",
- "reference": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed"
+ "reference": "49d3d8460257c7bfb1a7e12708e1bfdd59e898c1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/MadelineProto/zipball/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "reference": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
+ "url": "https://api.github.com/repos/danog/MadelineProto/zipball/49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
+ "reference": "49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
"shasum": ""
},
"require": {
- "amphp/amp": "^3.1.1",
+ "amphp/amp": "^3.1.3",
"amphp/byte-stream": "^2.1.2",
- "amphp/dns": "^2.4.0",
+ "amphp/dns": "^2.4.1",
"amphp/file": "^3.2.0",
"amphp/http": "^2.1.2",
- "amphp/http-client": "^5.3.4",
+ "amphp/http-client": "^5.3.6",
"amphp/http-client-cookies": "^2",
- "amphp/http-server": "^3.4.3",
+ "amphp/http-server": "^3.4.6",
"amphp/log": "^2",
- "amphp/mysql": "^3",
- "amphp/postgres": "^2.1.1",
- "amphp/redis": "^2.0.3",
- "amphp/socket": "^2.3.1",
+ "amphp/mysql": "^3.1.1",
+ "amphp/postgres": "^2.2.1",
+ "amphp/process": "^2.1",
+ "amphp/redis": "^2.0.4",
+ "amphp/socket": "^2.4.1",
"amphp/websocket-client": "^2.0.2",
- "bacon/bacon-qr-code": "^3.0.1",
- "danog/async-orm": "^1.1.4",
+ "bacon/bacon-qr-code": "^3.1.1",
+ "danog/async-orm": "^1.1.6",
"danog/better-prometheus": "^0.1.1",
"danog/dns-over-https": "^1.0.1",
- "danog/ipc": "^1.0.1",
+ "danog/ipc": "^1.1.0",
"danog/loop": "^1.1.1",
+ "danog/php-rtc-av": "^1.1.11",
+ "danog/php-rtc-codecs": "^1.1.19",
+ "danog/php-rtc-datachannel": "^1.1.10",
+ "danog/php-rtc-dtls": "^2.0.19",
+ "danog/php-rtc-exception": "^1.1.10",
+ "danog/php-rtc-ice": "^2.0.18",
+ "danog/php-rtc-mdns": "^1.1.12",
+ "danog/php-rtc-mixin": "^2.0.9",
+ "danog/php-rtc-ntp": "^1.1.14",
+ "danog/php-rtc-rtcp": "^1.1.11",
+ "danog/php-rtc-rtp": "^2.0.23",
+ "danog/php-rtc-rtp-parameter": "^1.1.8",
+ "danog/php-rtc-sctp": "^2.0.14",
+ "danog/php-rtc-sdp": "^1.1.12",
+ "danog/php-rtc-srtp": "^1.1.16",
+ "danog/php-rtc-stats": "^1.1.7",
+ "danog/php-rtc-stun": "^2.0.18",
+ "danog/php-rtc-turn": "^2.0.9",
+ "danog/php-rtc-webrtc": "^2.0.19",
"danog/primemodule": "^1.0.13",
- "danog/telegram-entities": "^1.0.5",
+ "danog/telegram-entities": "^1.1.0",
"danog/tg-dialog-id": "^2",
"danog/tg-file-decoder": "^1.0.2",
"ext-dom": "*",
@@ -2386,16 +2469,20 @@
"ext-json": "*",
"ext-xml": "*",
"ext-zlib": "*",
- "league/uri": "^7.5.1",
- "nikic/php-parser": "^5.6.2",
+ "league/uri": "^7.8.1",
+ "nikic/php-parser": "^5.9.0",
"php-64bit": ">=8.2",
- "phpseclib/phpseclib": "^3.0.47",
+ "phpseclib/phpseclib": "^4.0.1",
"psr/http-factory": "^1.1.0",
"psr/log": "^3.0.2",
- "revolt/event-loop": "^1.0.7",
- "symfony/polyfill-mbstring": ">=1.32",
- "symfony/polyfill-php83": "^1.32",
- "webmozart/assert": "^1.12.1"
+ "revolt/event-loop": "^1.0.9",
+ "symfony/polyfill-iconv": "^1.37",
+ "symfony/polyfill-mbstring": ">=1.38.2",
+ "symfony/polyfill-php83": "^1.41",
+ "symfony/polyfill-php84": "^1.38",
+ "symfony/polyfill-php85": "^1.41",
+ "symfony/polyfill-php86": "^1.41",
+ "webmozart/assert": "^2.4.1"
},
"conflict": {
"ext-pthreads": "*",
@@ -2403,25 +2490,25 @@
},
"require-dev": {
"amphp/phpunit-util": "^3",
- "bamarni/composer-bin-plugin": "1.8.2",
+ "bamarni/composer-bin-plugin": "1.9.1",
"brianium/paratest": "^6.11.1",
"danog/phpdoc": "^0.1.24",
"dg/bypass-finals": "dev-master",
"ext-ctype": "*",
- "phpunit/phpunit": "^9.6.29",
- "quasarstream/webrtc": "^1.0",
- "revolt/event-loop-adapter-react": "^1.1.1",
- "sebastian/diff": "^4.0",
- "symfony/yaml": "^6.4.26",
+ "phpunit/phpunit": "^9.6.36",
+ "sebastian/diff": "^4.0.6",
+ "symfony/yaml": "^6.4.45",
"vimeo/psalm": "dev-master"
},
"suggest": {
"ext-bcmath": "Install the bcmath extension to speed up authorization",
- "ext-ffi": "Install the primemodule and FFI extensions to speed up MadelineProto (https://prime.madelineproto.xyz)",
+ "ext-ffi": "Install the FFI extension (with libopus, libvpx and ffmpeg) to transcode audio and video in realtime; not required to play and record video and audio inside calls",
"ext-gmp": "Install the gmp extension to speed up authorization",
"ext-openssl": "Install the openssl extension for faster crypto",
"ext-pdo": "Install the pdo extension to store session data on MySQL",
"ext-primemodule": "Install the primemodule and FFI extensions to speed up MadelineProto (https://prime.madelineproto.xyz)",
+ "ext-sockets": "Install the sockets extension on Windows to use UNIX sockets for IPC (otherwise TCP on 127.0.0.1 is used, which any local user can connect to)",
+ "ext-sodium": "Install the sodium extension for faster crypto",
"ext-uv": "Install the uv extension to greatly speed up MadelineProto!"
},
"type": "library",
@@ -2461,7 +2548,7 @@
],
"support": {
"issues": "https://github.com/danog/MadelineProto/issues",
- "source": "https://github.com/danog/MadelineProto/tree/8.7.0"
+ "source": "https://github.com/danog/MadelineProto/tree/8.11.10"
},
"funding": [
{
@@ -2469,790 +2556,920 @@
"type": "github"
}
],
- "time": "2026-05-12T07:44:57+00:00"
+ "time": "2026-10-21T19:38:35+00:00"
},
{
- "name": "danog/primemodule",
- "version": "1.0.13",
+ "name": "danog/php-rtc-av",
+ "version": "1.1.11",
"source": {
"type": "git",
- "url": "https://github.com/danog/PrimeModule.git",
- "reference": "e7ebfc1ea64c24186e49064cd4b76bc76c28600e"
+ "url": "https://github.com/danog/php-rtc-av.git",
+ "reference": "f328e6b5682d7e885dcfab425839921312162008"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/PrimeModule/zipball/e7ebfc1ea64c24186e49064cd4b76bc76c28600e",
- "reference": "e7ebfc1ea64c24186e49064cd4b76bc76c28600e",
+ "url": "https://api.github.com/repos/danog/php-rtc-av/zipball/f328e6b5682d7e885dcfab425839921312162008",
+ "reference": "f328e6b5682d7e885dcfab425839921312162008",
"shasum": ""
},
"require": {
- "php": "^8.0"
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^1.1.6 || ^2.0",
+ "php-64bit": "^8.2"
},
"require-dev": {
- "phabel/phabel": "^1"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"suggest": {
- "ext-primemodule": "Install the native C++ extension for extremely fast factorization (https://prime.madelineproto.xyz)"
+ "ext-ffi": "Install the FFI extension and libavcodec/libavformat/libavfilter to transcode media; not required to mux or packetize already-encoded media"
},
"type": "library",
"extra": {
- "phabel": {
- "revision": 0
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
- "psr-0": {
- "danog\\": "lib/"
+ "psr-4": {
+ "Webrtc\\AVCodec\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "AGPL-3.0-only"
+ "MIT"
],
"authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
{
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
],
- "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
+ "description": "FFmpeg/libav FFI bindings for PHP media processing. MadelineProto's PHP 8.2+ fork uses lazy, optional FFI, strict ABI checks, and the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-av",
+ "keywords": [
+ "WebRTC",
+ "avcodec",
+ "avfilter",
+ "avformat",
+ "codec",
+ "ffmpeg",
+ "libavcodec",
+ "libavfilter",
+ "libavformat",
+ "libswscale",
+ "swscale"
+ ],
"support": {
- "issues": "https://github.com/danog/PrimeModule/issues",
- "source": "https://github.com/danog/PrimeModule/tree/1.0.13"
+ "issues": "https://github.com/danog/php-rtc-av/issues",
+ "source": "https://github.com/danog/php-rtc-av/tree/1.1.11"
},
- "time": "2023-05-27T14:41:40+00:00"
+ "time": "2026-10-06T15:43:53+00:00"
},
{
- "name": "danog/telegram-entities",
- "version": "1.0.5",
+ "name": "danog/php-rtc-codecs",
+ "version": "1.1.19",
"source": {
"type": "git",
- "url": "https://github.com/danog/telegram-entities.git",
- "reference": "19ab8a48bc4b9519c4493e2c62eb171fba8b58b4"
+ "url": "https://github.com/danog/php-rtc-codecs.git",
+ "reference": "00836382276949099077e19659ff6648b823284f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/telegram-entities/zipball/19ab8a48bc4b9519c4493e2c62eb171fba8b58b4",
- "reference": "19ab8a48bc4b9519c4493e2c62eb171fba8b58b4",
+ "url": "https://api.github.com/repos/danog/php-rtc-codecs/zipball/00836382276949099077e19659ff6648b823284f",
+ "reference": "00836382276949099077e19659ff6648b823284f",
"shasum": ""
},
"require": {
- "php-64bit": ">=8.2.4",
- "symfony/polyfill-mbstring": "*",
- "webmozart/assert": "^1.11"
+ "danog/php-rtc-av": "^1.1.3",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-rtp-parameter": "^1.1.4",
+ "php": "^8.2"
},
"require-dev": {
- "amphp/http-client": "^5.0",
- "amphp/php-cs-fixer-config": "^2.0.1",
- "danog/phpdoc": "^0.1.22",
- "friendsofphp/php-cs-fixer": "^3.52.1",
- "infection/infection": "^0.28.1",
- "phpunit/phpunit": "^11.0.9",
- "vimeo/psalm": "dev-master"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
+ },
+ "suggest": {
+ "ext-ffi": "Install the FFI extension and libopus/libvpx/libavcodec to transcode media; not required to packetize already-encoded media"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
"psr-4": {
- "danog\\TelegramEntities\\": "src/"
+ "Webrtc\\Codecs\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "Apache-2.0"
+ "BSD-3-Clause"
],
"authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
{
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
],
- "description": "A library to work with Telegram UTF-16 styled text entities.",
+ "description": "WebRTC audio/video codec and RTP packetization utilities. MadelineProto's PHP 8.2+ fork adds optional transcoding FFI, VP9 packetization, and the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-codecs",
+ "keywords": [
+ "WebRTC",
+ "codecs",
+ "h264",
+ "opus",
+ "pcma",
+ "pcmu",
+ "vp8"
+ ],
"support": {
- "issues": "https://github.com/danog/telegram-entities/issues",
- "source": "https://github.com/danog/telegram-entities/tree/1.0.5"
+ "issues": "https://github.com/danog/php-rtc-codecs/issues",
+ "source": "https://github.com/danog/php-rtc-codecs/tree/1.1.19"
},
- "funding": [
- {
- "url": "https://github.com/danog",
- "type": "github"
- }
- ],
- "time": "2025-06-22T12:27:39+00:00"
+ "time": "2026-10-16T23:52:08+00:00"
},
{
- "name": "danog/tg-dialog-id",
- "version": "2.0.0",
+ "name": "danog/php-rtc-datachannel",
+ "version": "1.1.10",
"source": {
"type": "git",
- "url": "https://github.com/danog/tg-dialog-id.git",
- "reference": "d03c653b2dad43d739675c83a6e8fa14b3b43636"
+ "url": "https://github.com/danog/php-rtc-datachannel.git",
+ "reference": "3a5ad6f76326514f41a9e1847b41d503e157c459"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/tg-dialog-id/zipball/d03c653b2dad43d739675c83a6e8fa14b3b43636",
- "reference": "d03c653b2dad43d739675c83a6e8fa14b3b43636",
+ "url": "https://api.github.com/repos/danog/php-rtc-datachannel/zipball/3a5ad6f76326514f41a9e1847b41d503e157c459",
+ "reference": "3a5ad6f76326514f41a9e1847b41d503e157c459",
"shasum": ""
},
"require": {
- "php-64bit": ">=8.1"
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^2.0",
+ "php": "^8.2",
+ "psr/log": "^3.0.2"
},
"require-dev": {
- "amphp/file": "^3.1",
- "amphp/php-cs-fixer-config": "^2.0.1",
- "danog/phpdoc": "^0.1.22",
- "infection/infection": "^0.28.1",
- "phpunit/phpunit": "^11.0.9|^10",
- "vimeo/psalm": "dev-master"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
"psr-4": {
- "danog\\DialogId\\": "src/"
+ "Webrtc\\DataChannel\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "Apache-2.0"
+ "BSD-3-Clause"
],
"authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
{
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
],
- "description": "A library to work with Telegram bot API dialog IDs",
+ "description": "A PHP implementation of WebRTC's RTCDataChannel interface. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-datachannel",
+ "keywords": [
+ "WebRTC",
+ "datachannel"
+ ],
"support": {
- "issues": "https://github.com/danog/tg-dialog-id/issues",
- "source": "https://github.com/danog/tg-dialog-id/tree/2.0.0"
+ "issues": "https://github.com/danog/php-rtc-datachannel/issues",
+ "source": "https://github.com/danog/php-rtc-datachannel/tree/1.1.10"
},
- "funding": [
- {
- "url": "https://github.com/danog",
- "type": "github"
- }
- ],
- "time": "2025-06-28T15:36:24+00:00"
+ "time": "2026-09-16T11:03:48+00:00"
},
{
- "name": "danog/tg-file-decoder",
- "version": "1.0.2",
+ "name": "danog/php-rtc-dtls",
+ "version": "2.0.20",
"source": {
"type": "git",
- "url": "https://github.com/danog/tg-file-decoder.git",
- "reference": "f4da78c28d47b658c4596249f1d6595956f3b796"
+ "url": "https://github.com/danog/php-rtc-dtls.git",
+ "reference": "794180b0c3cf54842df44b7bcb44f8fb50f199c8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/danog/tg-file-decoder/zipball/f4da78c28d47b658c4596249f1d6595956f3b796",
- "reference": "f4da78c28d47b658c4596249f1d6595956f3b796",
+ "url": "https://api.github.com/repos/danog/php-rtc-dtls/zipball/794180b0c3cf54842df44b7bcb44f8fb50f199c8",
+ "reference": "794180b0c3cf54842df44b7bcb44f8fb50f199c8",
"shasum": ""
},
"require": {
- "php-64bit": ">=8.2"
+ "amphp/amp": "^3.1.3",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-ice": "^1.1.18 || ^2.0",
+ "danog/php-rtc-mixin": "^2.0",
+ "danog/php-rtc-rtp": "^2.0.23",
+ "danog/php-rtc-sctp": "^1.1.5 || ^2.0",
+ "danog/php-rtc-sdp": "^1.1.6",
+ "danog/php-rtc-srtp": "^1.1.16",
+ "danog/php-rtc-stats": "^1.1.3",
+ "php-64bit": "^8.2",
+ "phpseclib/phpseclib": "^4.0",
+ "symfony/polyfill-php84": "*"
},
"require-dev": {
- "amphp/php-cs-fixer-config": "^2",
- "danog/phpdoc": "^0.1.22",
- "phpunit/phpunit": "^11",
- "vimeo/psalm": "dev-master"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "dg/bypass-finals": "dev-master",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
},
- "type": "project",
"autoload": {
"psr-4": {
- "danog\\Decoder\\": "src/"
+ "Webrtc\\DTLS\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "AGPL-3.0-only"
+ "BSD-3-Clause"
],
"authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
{
"name": "Daniil Gentili",
"email": "daniil@daniil.it"
}
],
- "description": "Decode Telegram bot API file IDs",
+ "description": "Pure-PHP DTLS 1.2 for WebRTC, powered by phpseclib and Amp v3.",
+ "homepage": "https://github.com/danog/php-rtc-dtls",
"keywords": [
- "audio",
- "bot api",
- "file ID",
- "files",
- "mtproto",
- "stickers",
- "telegram",
- "video"
+ "certificate",
+ "crypto",
+ "dtls",
+ "openssl",
+ "privateKey",
+ "rtp",
+ "ssl",
+ "x509"
],
"support": {
- "issues": "https://github.com/danog/tg-file-decoder/issues",
- "source": "https://github.com/danog/tg-file-decoder/tree/1.0.2"
+ "issues": "https://github.com/danog/php-rtc-dtls/issues",
+ "source": "https://github.com/danog/php-rtc-dtls/tree/2.0.20"
},
- "funding": [
- {
- "url": "https://github.com/danog",
- "type": "github"
- }
- ],
- "time": "2025-05-31T15:14:35+00:00"
+ "time": "2026-10-17T20:02:59+00:00"
},
{
- "name": "dasprid/enum",
- "version": "1.0.7",
+ "name": "danog/php-rtc-exception",
+ "version": "1.1.10",
"source": {
"type": "git",
- "url": "https://github.com/DASPRiD/Enum.git",
- "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
+ "url": "https://github.com/danog/php-rtc-exception.git",
+ "reference": "f9347a5376bb6b7b2fb008e06a8fd9fb6d9febd7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
- "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
+ "url": "https://api.github.com/repos/danog/php-rtc-exception/zipball/f9347a5376bb6b7b2fb008e06a8fd9fb6d9febd7",
+ "reference": "f9347a5376bb6b7b2fb008e06a8fd9fb6d9febd7",
"shasum": ""
},
"require": {
- "php": ">=7.1 <9.0"
+ "php": "^8.2"
},
"require-dev": {
- "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
- "squizlabs/php_codesniffer": "*"
+ "bamarni/composer-bin-plugin": "^1.9.1"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
"psr-4": {
- "DASPRiD\\Enum\\": "src/"
+ "Webrtc\\Exception\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "BSD-2-Clause"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Ben Scholzen 'DASPRiD'",
- "email": "mail@dasprids.de",
- "homepage": "https://dasprids.de/",
- "role": "Developer"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "PHP 7.1 enum implementation",
+ "description": "Lightweight exceptions shared by the WebRTC components. MadelineProto's PHP 8.2+ fork is a Composer-compatible foundation of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-exception",
"keywords": [
- "enum",
- "map"
+ "WebRTC"
],
"support": {
- "issues": "https://github.com/DASPRiD/Enum/issues",
- "source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
+ "issues": "https://github.com/danog/php-rtc-exception/issues",
+ "source": "https://github.com/danog/php-rtc-exception/tree/1.1.10"
},
- "time": "2025-09-16T12:23:56+00:00"
+ "time": "2026-09-16T11:03:57+00:00"
},
{
- "name": "daverandom/libdns",
- "version": "v2.1.0",
+ "name": "danog/php-rtc-ice",
+ "version": "2.0.18",
"source": {
"type": "git",
- "url": "https://github.com/DaveRandom/LibDNS.git",
- "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a"
+ "url": "https://github.com/danog/php-rtc-ice.git",
+ "reference": "91c53e982f334cf3bfe64a9e298d874bba51a3f1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a",
- "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a",
+ "url": "https://api.github.com/repos/danog/php-rtc-ice/zipball/91c53e982f334cf3bfe64a9e298d874bba51a3f1",
+ "reference": "91c53e982f334cf3bfe64a9e298d874bba51a3f1",
"shasum": ""
},
"require": {
- "ext-ctype": "*",
- "php": ">=7.1"
+ "amphp/amp": "^3.1.3",
+ "amphp/dns": "^2.4.1",
+ "amphp/socket": "^2.4.1",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mdns": "^1.1.7",
+ "danog/php-rtc-mixin": "^2.0.9",
+ "danog/php-rtc-stun": "^2.0.17",
+ "danog/php-rtc-turn": "^2.0.9",
+ "php-64bit": "^8.2",
+ "psr/log": "^3.0.2",
+ "symfony/polyfill-php84": "*"
},
- "suggest": {
- "ext-intl": "Required for IDN support"
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "mockery/mockery": "^1.6.15",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
- "files": [
- "src/functions.php"
- ],
"psr-4": {
- "LibDNS\\": "src/"
+ "Webrtc\\ICE\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
- ],
- "description": "DNS protocol implementation written in pure PHP",
- "keywords": [
- "dns"
+ "BSD-3-Clause"
],
- "support": {
- "issues": "https://github.com/DaveRandom/LibDNS/issues",
- "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0"
- },
- "time": "2024-04-12T12:12:48+00:00"
- },
- {
- "name": "kelunik/certificate",
- "version": "v1.1.3",
+ "authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "WebRTC ICE connectivity in PHP, ported to Amp v3 fibers and sockets. MadelineProto's PHP 8.2+ fork integrates the modular danog/php-rtc STUN, TURN, and mDNS stack.",
+ "homepage": "https://github.com/danog/php-rtc-ice",
+ "keywords": [
+ "WebRTC",
+ "ice",
+ "stun",
+ "turn"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-ice/issues",
+ "source": "https://github.com/danog/php-rtc-ice/tree/2.0.18"
+ },
+ "time": "2026-10-16T21:18:22+00:00"
+ },
+ {
+ "name": "danog/php-rtc-mdns",
+ "version": "1.1.12",
"source": {
"type": "git",
- "url": "https://github.com/kelunik/certificate.git",
- "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e"
+ "url": "https://github.com/danog/php-rtc-mdns.git",
+ "reference": "ff3f4315339ddcdd4d71bd4e02156903261ef57a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e",
- "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e",
+ "url": "https://api.github.com/repos/danog/php-rtc-mdns/zipball/ff3f4315339ddcdd4d71bd4e02156903261ef57a",
+ "reference": "ff3f4315339ddcdd4d71bd4e02156903261ef57a",
"shasum": ""
},
"require": {
- "ext-openssl": "*",
- "php": ">=7.0"
+ "amphp/amp": "^3.1.3",
+ "amphp/socket": "^2.4.1",
+ "danog/php-rtc-exception": "^1.1.5",
+ "daverandom/libdns": "^2.1.0",
+ "php": "^8.2"
},
"require-dev": {
- "amphp/php-cs-fixer-config": "^2",
- "phpunit/phpunit": "^6 | 7 | ^8 | ^9"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "Kelunik\\Certificate\\": "src"
+ "Webrtc\\MDNS\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Niklas Keller",
- "email": "me@kelunik.com"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "Access certificate details and transform between different formats.",
+ "description": "An Amp v3 Multicast DNS resolver for WebRTC. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-mdns",
"keywords": [
- "DER",
- "certificate",
- "certificates",
- "openssl",
- "pem",
- "x509"
+ "mDNS",
+ "multicastdns"
],
"support": {
- "issues": "https://github.com/kelunik/certificate/issues",
- "source": "https://github.com/kelunik/certificate/tree/v1.1.3"
+ "issues": "https://github.com/danog/php-rtc-mdns/issues",
+ "source": "https://github.com/danog/php-rtc-mdns/tree/1.1.12"
},
- "time": "2023-02-03T21:26:53+00:00"
+ "time": "2026-09-16T11:04:05+00:00"
},
{
- "name": "league/uri",
- "version": "7.8.1",
+ "name": "danog/php-rtc-mixin",
+ "version": "2.0.9",
"source": {
"type": "git",
- "url": "https://github.com/thephpleague/uri.git",
- "reference": "08cf38e3924d4f56238125547b5720496fac8fd4"
+ "url": "https://github.com/danog/php-rtc-mixin.git",
+ "reference": "e7a086a7fe01875f52e1f08301195db05e7ff9a5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4",
- "reference": "08cf38e3924d4f56238125547b5720496fac8fd4",
+ "url": "https://api.github.com/repos/danog/php-rtc-mixin/zipball/e7a086a7fe01875f52e1f08301195db05e7ff9a5",
+ "reference": "e7a086a7fe01875f52e1f08301195db05e7ff9a5",
"shasum": ""
},
"require": {
- "league/uri-interfaces": "^7.8.1",
- "php": "^8.1",
- "psr/http-factory": "^1"
- },
- "conflict": {
- "league/uri-schemes": "^1.0"
+ "php": "^8.2"
},
- "suggest": {
- "ext-bcmath": "to improve IPV4 host parsing",
- "ext-dom": "to convert the URI into an HTML anchor tag",
- "ext-fileinfo": "to create Data URI from file contennts",
- "ext-gmp": "to improve IPV4 host parsing",
- "ext-intl": "to handle IDN host with the best performance",
- "ext-uri": "to use the PHP native URI class",
- "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
- "league/uri-components": "to provide additional tools to manipulate URI objects components",
- "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
- "php-64bit": "to improve IPV4 host parsing",
- "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
- "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ "require-dev": {
+ "bamarni/composer-bin-plugin": ">=1.9.1"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "7.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "League\\Uri\\": ""
+ "Webrtc\\Mixin\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Ignace Nyamagana Butera",
- "email": "nyamsprod@gmail.com",
- "homepage": "https://nyamsprod.com"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "URI manipulation library",
- "homepage": "https://uri.thephpleague.com",
+ "description": "Common PHP classes and traits for WebRTC components. MadelineProto's PHP 8.2+ fork is a Composer-compatible foundation of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-mixin",
"keywords": [
- "URN",
- "data-uri",
- "file-uri",
- "ftp",
- "hostname",
- "http",
- "https",
- "middleware",
- "parse_str",
- "parse_url",
- "psr-7",
- "query-string",
- "querystring",
- "rfc2141",
- "rfc3986",
- "rfc3987",
- "rfc6570",
- "rfc8141",
- "uri",
- "uri-template",
- "url",
- "ws"
+ "WebRTC"
],
"support": {
- "docs": "https://uri.thephpleague.com",
- "forum": "https://thephpleague.slack.com",
- "issues": "https://github.com/thephpleague/uri-src/issues",
- "source": "https://github.com/thephpleague/uri/tree/7.8.1"
+ "issues": "https://github.com/danog/php-rtc-mixin/issues",
+ "source": "https://github.com/danog/php-rtc-mixin/tree/2.0.9"
},
- "funding": [
- {
- "url": "https://github.com/sponsors/nyamsprod",
- "type": "github"
- }
- ],
- "time": "2026-03-15T20:22:25+00:00"
+ "time": "2026-10-06T12:36:35+00:00"
},
{
- "name": "league/uri-components",
- "version": "7.8.1",
+ "name": "danog/php-rtc-ntp",
+ "version": "1.1.15",
"source": {
"type": "git",
- "url": "https://github.com/thephpleague/uri-components.git",
- "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675"
+ "url": "https://github.com/danog/php-rtc-ntp.git",
+ "reference": "d70dc01410dba146cb808b9c2bf3c28ed1199d20"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/848ff9db2f0be06229d6034b7c2e33d41b4fd675",
- "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675",
+ "url": "https://api.github.com/repos/danog/php-rtc-ntp/zipball/d70dc01410dba146cb808b9c2bf3c28ed1199d20",
+ "reference": "d70dc01410dba146cb808b9c2bf3c28ed1199d20",
"shasum": ""
},
"require": {
- "league/uri": "^7.8.1",
- "php": "^8.1"
+ "php-64bit": "^8.2",
+ "symfony/polyfill-php83": "*"
},
- "suggest": {
- "ext-bcmath": "to improve IPV4 host parsing",
- "ext-fileinfo": "to create Data URI from file contennts",
- "ext-gmp": "to improve IPV4 host parsing",
- "ext-intl": "to handle IDN host with the best performance",
- "ext-mbstring": "to use the sorting algorithm of URLSearchParams",
- "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
- "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
- "php-64bit": "to improve IPV4 host parsing",
- "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
- "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2",
+ "symfony/phpunit-bridge": "7.3.x-dev"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "7.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "League\\Uri\\": ""
+ "Webrtc\\NTP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Ignace Nyamagana Butera",
- "email": "nyamsprod@gmail.com",
- "homepage": "https://nyamsprod.com"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "URI components manipulation library",
- "homepage": "http://uri.thephpleague.com",
+ "description": "Pure-PHP NTP timestamp conversion for WebRTC. MadelineProto's PHP 8.2+ fork fixes unsigned 64-bit handling and integrates with the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-ntp",
"keywords": [
- "authority",
- "components",
- "fragment",
- "host",
- "middleware",
- "modifier",
- "path",
- "port",
- "query",
- "rfc3986",
- "scheme",
- "uri",
- "url",
- "userinfo"
+ "multicastdns",
+ "ntp"
],
"support": {
- "docs": "https://uri.thephpleague.com",
- "forum": "https://thephpleague.slack.com",
- "issues": "https://github.com/thephpleague/uri-src/issues",
- "source": "https://github.com/thephpleague/uri-components/tree/7.8.1"
+ "issues": "https://github.com/danog/php-rtc-ntp/issues",
+ "source": "https://github.com/danog/php-rtc-ntp/tree/1.1.15"
},
- "funding": [
- {
- "url": "https://github.com/nyamsprod",
- "type": "github"
- }
- ],
- "time": "2026-03-15T20:22:25+00:00"
+ "time": "2026-10-16T23:17:01+00:00"
},
{
- "name": "league/uri-interfaces",
- "version": "7.8.1",
+ "name": "danog/php-rtc-rtcp",
+ "version": "1.1.11",
"source": {
"type": "git",
- "url": "https://github.com/thephpleague/uri-interfaces.git",
- "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928"
+ "url": "https://github.com/danog/php-rtc-rtcp.git",
+ "reference": "f2e7c76d040fb0c4b2e4b62a611d13c6352af145"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928",
- "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928",
+ "url": "https://api.github.com/repos/danog/php-rtc-rtcp/zipball/f2e7c76d040fb0c4b2e4b62a611d13c6352af145",
+ "reference": "f2e7c76d040fb0c4b2e4b62a611d13c6352af145",
"shasum": ""
},
"require": {
- "ext-filter": "*",
- "php": "^8.1",
- "psr/http-message": "^1.1 || ^2.0"
+ "danog/php-rtc-exception": "^1.1.5",
+ "php-64bit": "^8.2"
},
- "suggest": {
- "ext-bcmath": "to improve IPV4 host parsing",
- "ext-gmp": "to improve IPV4 host parsing",
- "ext-intl": "to handle IDN host with the best performance",
- "php-64bit": "to improve IPV4 host parsing",
- "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
- "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "7.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "League\\Uri\\": ""
+ "Webrtc\\RTCP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Ignace Nyamagana Butera",
- "email": "nyamsprod@gmail.com",
- "homepage": "https://nyamsprod.com"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
- "homepage": "https://uri.thephpleague.com",
+ "description": "Pure-PHP RTCP packet parsing and generation. MadelineProto's PHP 8.2+ fork fixes unsigned NTP handling and integrates with the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-rtcp",
"keywords": [
- "data-uri",
- "file-uri",
- "ftp",
- "hostname",
- "http",
- "https",
- "parse_str",
- "parse_url",
- "psr-7",
- "query-string",
- "querystring",
- "rfc3986",
- "rfc3987",
- "rfc6570",
- "uri",
- "url",
- "ws"
+ "rtcp",
+ "rtp"
],
"support": {
- "docs": "https://uri.thephpleague.com",
- "forum": "https://thephpleague.slack.com",
- "issues": "https://github.com/thephpleague/uri-src/issues",
- "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1"
+ "issues": "https://github.com/danog/php-rtc-rtcp/issues",
+ "source": "https://github.com/danog/php-rtc-rtcp/tree/1.1.11"
},
- "funding": [
- {
- "url": "https://github.com/sponsors/nyamsprod",
- "type": "github"
- }
- ],
- "time": "2026-03-08T20:05:35+00:00"
+ "time": "2026-10-16T23:52:08+00:00"
},
{
- "name": "monolog/monolog",
- "version": "3.12.1",
+ "name": "danog/php-rtc-rtp",
+ "version": "2.0.23",
"source": {
"type": "git",
- "url": "https://github.com/Seldaek/monolog.git",
- "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15"
+ "url": "https://github.com/danog/php-rtc-rtp.git",
+ "reference": "e9bee7a5aae91f6abec1fe9a599eefbce219d967"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15",
- "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15",
+ "url": "https://api.github.com/repos/danog/php-rtc-rtp/zipball/e9bee7a5aae91f6abec1fe9a599eefbce219d967",
+ "reference": "e9bee7a5aae91f6abec1fe9a599eefbce219d967",
"shasum": ""
},
"require": {
- "php": ">=8.1",
- "psr/log": "^2.0 || ^3.0"
- },
- "provide": {
- "psr/log-implementation": "3.0.0"
+ "amphp/amp": "^3.1.3",
+ "amphp/pipeline": "^1.2.7",
+ "danog/php-rtc-codecs": "^1.1.18",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^2.0",
+ "danog/php-rtc-ntp": "^1.1.14",
+ "danog/php-rtc-rtcp": "^1.1.4",
+ "danog/php-rtc-rtp-parameter": "^1.1.4",
+ "danog/php-rtc-sdp": "^1.1.6",
+ "danog/php-rtc-stats": "^1.1.3",
+ "php-64bit": "^8.2",
+ "ramsey/uuid": "^4.9.3",
+ "symfony/polyfill-php83": "*"
},
"require-dev": {
- "aws/aws-sdk-php": "^3.0",
- "doctrine/couchdb": "~1.0@dev",
- "elasticsearch/elasticsearch": "^7 || ^8",
- "ext-json": "*",
- "graylog2/gelf-php": "^1.4.2 || ^2.0",
- "guzzlehttp/guzzle": "^7.4.5",
- "guzzlehttp/psr7": "^2.2",
- "mongodb/mongodb": "^1.8 || ^2.0",
- "php-amqplib/php-amqplib": "~2.4 || ^3",
- "php-console/php-console": "^3.1.8",
- "phpstan/phpstan": "^2",
- "phpstan/phpstan-deprecation-rules": "^2",
- "phpstan/phpstan-strict-rules": "^2",
- "phpunit/phpunit": "^10.5.17 || ^11.0.7",
- "predis/predis": "^1.1 || ^2",
- "psr/clock": "^1.0",
- "rollbar/rollbar": "^4.0",
- "ruflin/elastica": "^7 || ^8",
- "symfony/mailer": "^5.4 || ^6",
- "symfony/mime": "^5.4 || ^6"
- },
- "suggest": {
- "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
- "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
- "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
- "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
- "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
- "ext-mbstring": "Allow to work properly with unicode symbols",
- "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
- "ext-openssl": "Required to send log messages using SSL",
- "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
- "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
- "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
- "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
- "psr/clock": "Required to pass a clock to the Logger and control the timestamp of log records",
- "rollbar/rollbar": "Allow sending log messages to Rollbar",
- "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "dg/bypass-finals": "dev-master",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2",
+ "symfony/phpunit-bridge": "7.3.x-dev"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "3.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "Monolog\\": "src/Monolog"
+ "Webrtc\\RTP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Jordi Boggiano",
- "email": "j.boggiano@seld.be",
- "homepage": "https://seld.be"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
- "homepage": "https://github.com/Seldaek/monolog",
+ "description": "RTP packet and media transport handling for PHP, ported to Amp v3. MadelineProto's PHP 8.2+ fork supports optional media FFI in the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-rtp",
"keywords": [
- "log",
- "logging",
- "psr-3"
+ "WebRTC",
+ "real-time-transport-protocol",
+ "rtp"
],
"support": {
- "issues": "https://github.com/Seldaek/monolog/issues",
- "source": "https://github.com/Seldaek/monolog/tree/3.12.1"
+ "issues": "https://github.com/danog/php-rtc-rtp/issues",
+ "source": "https://github.com/danog/php-rtc-rtp/tree/2.0.23"
},
- "funding": [
+ "time": "2026-10-16T23:52:08+00:00"
+ },
+ {
+ "name": "danog/php-rtc-rtp-parameter",
+ "version": "1.1.8",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/php-rtc-rtp-parameter.git",
+ "reference": "cd1e34df768ddae43fc50c1306c2332cf99f07eb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/php-rtc-rtp-parameter/zipball/cd1e34df768ddae43fc50c1306c2332cf99f07eb",
+ "reference": "cd1e34df768ddae43fc50c1306c2332cf99f07eb",
+ "shasum": ""
+ },
+ "require": {
+ "danog/php-rtc-mixin": "^1.1.6 || ^2.0",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": ">=1.9.1"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webrtc\\RTPParameter\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
{
- "url": "https://github.com/Seldaek",
- "type": "github"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
},
{
- "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
- "type": "tidelift"
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "time": "2026-09-29T19:21:12+00:00"
+ "description": "RTP codec, payload, SSRC, header-extension, and RTCP parameter objects. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-rtp-parameter",
+ "keywords": [
+ "WebRTC",
+ "rtp",
+ "rtp-parameter"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-rtp-parameter/issues",
+ "source": "https://github.com/danog/php-rtc-rtp-parameter/tree/1.1.8"
+ },
+ "time": "2026-09-16T11:04:26+00:00"
},
{
- "name": "nikic/php-parser",
- "version": "v5.9.0",
+ "name": "danog/php-rtc-sctp",
+ "version": "2.0.14",
"source": {
"type": "git",
- "url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def"
+ "url": "https://github.com/danog/php-rtc-sctp.git",
+ "reference": "741697e355abd7eb8e8134b115fab775bb5ccd06"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/9e33da9553fe7786f0962b35f4e4ecf01be89def",
- "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def",
+ "url": "https://api.github.com/repos/danog/php-rtc-sctp/zipball/741697e355abd7eb8e8134b115fab775bb5ccd06",
+ "reference": "741697e355abd7eb8e8134b115fab775bb5ccd06",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "ext-tokenizer": "*",
- "php": ">=7.4"
+ "amphp/amp": "^3.1.3",
+ "danog/php-rtc-datachannel": "^1.1.4",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-ice": "^1.1.18 || ^2.0",
+ "danog/php-rtc-mixin": "^2.0",
+ "danog/php-rtc-sdp": "^1.1.6",
+ "danog/php-rtc-stats": "^1.1.3",
+ "php-64bit": "^8.2",
+ "symfony/polyfill-mbstring": "*"
},
"require-dev": {
- "ircmaxell/php-yacc": "^0.0.7",
- "phpunit/phpunit": "^9.0"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "dg/bypass-finals": "dev-master",
+ "mockery/mockery": "^1.6.15",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2",
+ "symfony/phpunit-bridge": "7.3.x-dev"
},
- "bin": [
- "bin/php-parse"
- ],
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "5.x-dev"
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
}
},
"autoload": {
"psr-4": {
- "PhpParser\\": "lib/PhpParser"
+ "Webrtc\\SCTP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -3261,346 +3478,2032 @@
],
"authors": [
{
- "name": "Nikita Popov"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "A PHP parser written in PHP",
+ "description": "SCTP for PHP WebRTC data channels, ported to Amp v3 fibers and timers. MadelineProto's PHP 8.2+ fork is part of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-sctp",
"keywords": [
- "parser",
- "php"
+ "WebRTC",
+ "datachannel",
+ "sctp"
],
"support": {
- "issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0"
+ "issues": "https://github.com/danog/php-rtc-sctp/issues",
+ "source": "https://github.com/danog/php-rtc-sctp/tree/2.0.14"
},
- "time": "2026-09-13T18:51:52+00:00"
+ "time": "2026-10-06T15:18:53+00:00"
},
{
- "name": "paragonie/constant_time_encoding",
- "version": "v3.1.3",
+ "name": "danog/php-rtc-sdp",
+ "version": "1.1.12",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/constant_time_encoding.git",
- "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77"
+ "url": "https://github.com/danog/php-rtc-sdp.git",
+ "reference": "315b9cbaff71625351864c292de0b6ac3b3a39fc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
- "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
+ "url": "https://api.github.com/repos/danog/php-rtc-sdp/zipball/315b9cbaff71625351864c292de0b6ac3b3a39fc",
+ "reference": "315b9cbaff71625351864c292de0b6ac3b3a39fc",
"shasum": ""
},
"require": {
- "php": "^8"
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-ice": "^1.1.18 || ^2.0",
+ "danog/php-rtc-rtp-parameter": "^1.1.4",
+ "php": "^8.2",
+ "symfony/polyfill-php84": "*"
},
"require-dev": {
- "infection/infection": "^0",
- "nikic/php-fuzzer": "^0",
- "phpunit/phpunit": "^9|^10|^11",
- "vimeo/psalm": "^4|^5|^6"
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
"psr-4": {
- "ParagonIE\\ConstantTime\\": "src/"
+ "Webrtc\\SDP\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com",
- "role": "Maintainer"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
},
{
- "name": "Steve 'Sc00bz' Thomas",
- "email": "steve@tobtu.com",
- "homepage": "https://www.tobtu.com",
- "role": "Original Developer"
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "description": "SDP parsing and generation for PHP WebRTC. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-sdp",
"keywords": [
- "base16",
- "base32",
- "base32_decode",
- "base32_encode",
- "base64",
- "base64_decode",
- "base64_encode",
- "bin2hex",
- "encoding",
- "hex",
- "hex2bin",
- "rfc4648"
+ "SDP",
+ "rtp"
],
"support": {
- "email": "info@paragonie.com",
- "issues": "https://github.com/paragonie/constant_time_encoding/issues",
- "source": "https://github.com/paragonie/constant_time_encoding"
+ "issues": "https://github.com/danog/php-rtc-sdp/issues",
+ "source": "https://github.com/danog/php-rtc-sdp/tree/1.1.12"
},
- "time": "2025-09-24T15:06:41+00:00"
+ "time": "2026-09-16T11:04:35+00:00"
},
{
- "name": "paragonie/random_compat",
- "version": "v9.99.100",
+ "name": "danog/php-rtc-srtp",
+ "version": "1.1.16",
"source": {
"type": "git",
- "url": "https://github.com/paragonie/random_compat.git",
- "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
+ "url": "https://github.com/danog/php-rtc-srtp.git",
+ "reference": "b19959292663d8933a0a48cd1fda05788fb5c542"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
- "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
+ "url": "https://api.github.com/repos/danog/php-rtc-srtp/zipball/b19959292663d8933a0a48cd1fda05788fb5c542",
+ "reference": "b19959292663d8933a0a48cd1fda05788fb5c542",
"shasum": ""
},
"require": {
- "php": ">= 7"
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^1.1.6 || ^2.0",
+ "php-64bit": "^8.2",
+ "phpseclib/phpseclib": "^4.0"
},
"require-dev": {
- "phpunit/phpunit": "4.*|5.*",
- "vimeo/psalm": "^1"
- },
- "suggest": {
- "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webrtc\\Srtp\\": "src"
+ }
+ },
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Paragon Initiative Enterprises",
- "email": "security@paragonie.com",
- "homepage": "https://paragonie.com"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
}
],
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "description": "Pure-PHP SRTP and SRTCP encryption using phpseclib, with AES-CM and AES-GCM profiles. MadelineProto's PHP 8.2+ fork removes the libsrtp/FFI dependency.",
+ "homepage": "https://github.com/danog/php-rtc-srtp",
"keywords": [
- "csprng",
- "polyfill",
- "pseudorandom",
- "random"
+ "srtp"
],
"support": {
- "email": "info@paragonie.com",
- "issues": "https://github.com/paragonie/random_compat/issues",
- "source": "https://github.com/paragonie/random_compat"
+ "issues": "https://github.com/danog/php-rtc-srtp/issues",
+ "source": "https://github.com/danog/php-rtc-srtp/tree/1.1.16"
},
- "time": "2020-10-15T08:29:30+00:00"
+ "time": "2026-10-16T22:00:35+00:00"
},
{
- "name": "phpseclib/phpseclib",
- "version": "3.0.57",
+ "name": "danog/php-rtc-stats",
+ "version": "1.1.7",
"source": {
"type": "git",
- "url": "https://github.com/phpseclib/phpseclib.git",
- "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4"
+ "url": "https://github.com/danog/php-rtc-stats.git",
+ "reference": "137934d7d57e97184d5b6b2fb58e571e0d3f9fbd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
- "reference": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
+ "url": "https://api.github.com/repos/danog/php-rtc-stats/zipball/137934d7d57e97184d5b6b2fb58e571e0d3f9fbd",
+ "reference": "137934d7d57e97184d5b6b2fb58e571e0d3f9fbd",
"shasum": ""
},
"require": {
- "paragonie/constant_time_encoding": "^1|^2|^3",
- "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
- "php": ">=5.6.1"
+ "danog/php-rtc-ice": "^1.1.18 || ^2.0",
+ "danog/php-rtc-mixin": "^1.1.6 || ^2.0",
+ "php": "^8.2"
},
"require-dev": {
- "phpunit/phpunit": "*"
- },
- "suggest": {
- "ext-dom": "Install the DOM extension to load XML formatted public keys.",
- "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
- "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
- "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
- "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ "bamarni/composer-bin-plugin": ">=1.9.1"
},
"type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
"autoload": {
- "files": [
- "phpseclib/bootstrap.php"
- ],
"psr-4": {
- "phpseclib3\\": "phpseclib/"
+ "Webrtc\\Stats\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "MIT"
+ "BSD-3-Clause"
],
"authors": [
{
- "name": "Jim Wigginton",
- "email": "terrafrost@php.net",
- "role": "Lead Developer"
- },
- {
- "name": "Patrick Monnerat",
- "email": "pm@datasphere.ch",
- "role": "Developer"
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
},
{
- "name": "Andreas Fischer",
- "email": "bantu@phpbb.com",
- "role": "Developer"
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
},
{
- "name": "Hans-Jürgen Petrich",
- "email": "petrich@tronic-media.com",
- "role": "Developer"
+ "name": "Quasar Stream Community"
},
{
- "name": "Graham Campbell",
- "email": "graham@alt-three.com",
- "role": "Developer"
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "WebRTC statistics objects for RTP, DTLS, ICE, and media metrics. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-stats",
+ "keywords": [
+ "WebRTC",
+ "stats"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-stats/issues",
+ "source": "https://github.com/danog/php-rtc-stats/tree/1.1.7"
+ },
+ "time": "2026-09-16T11:04:43+00:00"
+ },
+ {
+ "name": "danog/php-rtc-stun",
+ "version": "2.0.18",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/php-rtc-stun.git",
+ "reference": "7f1b48a736e6d7a9ad174e7dc58b794168befed4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/php-rtc-stun/zipball/7f1b48a736e6d7a9ad174e7dc58b794168befed4",
+ "reference": "7f1b48a736e6d7a9ad174e7dc58b794168befed4",
+ "shasum": ""
+ },
+ "require": {
+ "amphp/amp": "^3.1.3",
+ "amphp/socket": "^2.4.1",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^2.0",
+ "php-64bit": "^8.2",
+ "psr/log": "^3.0.2",
+ "ramsey/uuid": "^4.9.3"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "dg/bypass-finals": "dev-master",
+ "mockery/mockery": "^1.6.15",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webrtc\\STUN\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "STUN transactions and NAT discovery for PHP, ported to Amp v3 sockets and fibers. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-stun",
+ "keywords": [
+ "SessionTraversalUtilitiesForNAT",
+ "WebRTC",
+ "stun"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-stun/issues",
+ "source": "https://github.com/danog/php-rtc-stun/tree/2.0.18"
+ },
+ "time": "2026-10-06T15:41:42+00:00"
+ },
+ {
+ "name": "danog/php-rtc-turn",
+ "version": "2.0.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/php-rtc-turn.git",
+ "reference": "5789c0d4b23c6097c72812fa8f9e9930ac288bc6"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/php-rtc-turn/zipball/5789c0d4b23c6097c72812fa8f9e9930ac288bc6",
+ "reference": "5789c0d4b23c6097c72812fa8f9e9930ac288bc6",
+ "shasum": ""
+ },
+ "require": {
+ "amphp/amp": "^3.1.3",
+ "amphp/socket": "^2.4.1",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-mixin": "^2.0",
+ "danog/php-rtc-stun": "^2.0.17",
+ "php": "^8.2",
+ "psr/log": "^3.0.2"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "mockery/mockery": "^1.6.15",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webrtc\\TURN\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "TURN relay transport for PHP WebRTC, ported to Amp v3 TCP, UDP, and fibers. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "homepage": "https://github.com/danog/php-rtc-turn",
+ "keywords": [
+ "WebRTC",
+ "traversal-using-relays-around-nat",
+ "turn"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-turn/issues",
+ "source": "https://github.com/danog/php-rtc-turn/tree/2.0.9"
+ },
+ "time": "2026-10-06T13:18:16+00:00"
+ },
+ {
+ "name": "danog/php-rtc-webrtc",
+ "version": "2.0.20",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/php-rtc-webrtc.git",
+ "reference": "58f8a24180cd1e137127214f9bfba3b0a7eff97b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/php-rtc-webrtc/zipball/58f8a24180cd1e137127214f9bfba3b0a7eff97b",
+ "reference": "58f8a24180cd1e137127214f9bfba3b0a7eff97b",
+ "shasum": ""
+ },
+ "require": {
+ "amphp/amp": "^3.1.3",
+ "danog/php-rtc-dtls": "^1.1.9 || ^2.0",
+ "danog/php-rtc-exception": "^1.1.5",
+ "danog/php-rtc-ice": "^2.0.17",
+ "danog/php-rtc-mixin": "^2.0",
+ "danog/php-rtc-ntp": "^1.1.6",
+ "danog/php-rtc-rtp": "^2.0.23",
+ "danog/php-rtc-sctp": "^2.0.14",
+ "danog/php-rtc-sdp": "^1.1.6",
+ "danog/php-rtc-stats": "^1.1.3",
+ "php": "^8.2",
+ "symfony/polyfill-php84": "*"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.9.1",
+ "phpunit/phpunit": "^11.5 || ^12.0 || ^13.3.2"
+ },
+ "type": "library",
+ "extra": {
+ "bamarni-bin": {
+ "bin-links": true,
+ "forward-command": true
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webrtc\\Webrtc\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Amin Yazdanpanah",
+ "email": "github@aminyazdanpanah.com"
+ },
+ {
+ "name": "Sana Moniri",
+ "email": "s.mo@quasarstream.com"
+ },
+ {
+ "name": "Quasar Stream Community"
+ },
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "A modular PHP WebRTC stack for PHP 8.2+, ported to Amp v3 with pure-PHP DTLS/SRTP and optional media FFI. Maintained by danog for MadelineProto.",
+ "homepage": "https://github.com/danog/php-rtc-webrtc",
+ "keywords": [
+ "WebRTC",
+ "rtp"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/php-rtc-webrtc/issues",
+ "source": "https://github.com/danog/php-rtc-webrtc/tree/2.0.20"
+ },
+ "time": "2026-10-16T23:52:08+00:00"
+ },
+ {
+ "name": "danog/primemodule",
+ "version": "1.0.13",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/PrimeModule.git",
+ "reference": "e7ebfc1ea64c24186e49064cd4b76bc76c28600e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/PrimeModule/zipball/e7ebfc1ea64c24186e49064cd4b76bc76c28600e",
+ "reference": "e7ebfc1ea64c24186e49064cd4b76bc76c28600e",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "phabel/phabel": "^1"
+ },
+ "suggest": {
+ "ext-primemodule": "Install the native C++ extension for extremely fast factorization (https://prime.madelineproto.xyz)"
+ },
+ "type": "library",
+ "extra": {
+ "phabel": {
+ "revision": 0
+ }
+ },
+ "autoload": {
+ "psr-0": {
+ "danog\\": "lib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "AGPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
+ "support": {
+ "issues": "https://github.com/danog/PrimeModule/issues",
+ "source": "https://github.com/danog/PrimeModule/tree/1.0.13"
+ },
+ "time": "2023-05-27T14:41:40+00:00"
+ },
+ {
+ "name": "danog/telegram-entities",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/telegram-entities.git",
+ "reference": "92ca7621594b7a6c4a820c3b557e66ee1d439273"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/telegram-entities/zipball/92ca7621594b7a6c4a820c3b557e66ee1d439273",
+ "reference": "92ca7621594b7a6c4a820c3b557e66ee1d439273",
+ "shasum": ""
+ },
+ "require": {
+ "php-64bit": ">=8.2.4",
+ "symfony/polyfill-mbstring": "*",
+ "webmozart/assert": "^2"
+ },
+ "require-dev": {
+ "amphp/http-client": "^5.0",
+ "amphp/php-cs-fixer-config": "^2.0.1",
+ "danog/phpdoc": "^0.1.22",
+ "friendsofphp/php-cs-fixer": "^3.52.1",
+ "phpunit/phpunit": "^11.0.9",
+ "vimeo/psalm": "dev-master"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "danog\\TelegramEntities\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "A library to work with Telegram UTF-16 styled text entities.",
+ "support": {
+ "issues": "https://github.com/danog/telegram-entities/issues",
+ "source": "https://github.com/danog/telegram-entities/tree/1.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/danog",
+ "type": "github"
+ }
+ ],
+ "time": "2026-10-18T15:46:15+00:00"
+ },
+ {
+ "name": "danog/tg-dialog-id",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/tg-dialog-id.git",
+ "reference": "d03c653b2dad43d739675c83a6e8fa14b3b43636"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/tg-dialog-id/zipball/d03c653b2dad43d739675c83a6e8fa14b3b43636",
+ "reference": "d03c653b2dad43d739675c83a6e8fa14b3b43636",
+ "shasum": ""
+ },
+ "require": {
+ "php-64bit": ">=8.1"
+ },
+ "require-dev": {
+ "amphp/file": "^3.1",
+ "amphp/php-cs-fixer-config": "^2.0.1",
+ "danog/phpdoc": "^0.1.22",
+ "infection/infection": "^0.28.1",
+ "phpunit/phpunit": "^11.0.9|^10",
+ "vimeo/psalm": "dev-master"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "danog\\DialogId\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "A library to work with Telegram bot API dialog IDs",
+ "support": {
+ "issues": "https://github.com/danog/tg-dialog-id/issues",
+ "source": "https://github.com/danog/tg-dialog-id/tree/2.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/danog",
+ "type": "github"
+ }
+ ],
+ "time": "2025-06-28T15:36:24+00:00"
+ },
+ {
+ "name": "danog/tg-file-decoder",
+ "version": "1.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danog/tg-file-decoder.git",
+ "reference": "f4da78c28d47b658c4596249f1d6595956f3b796"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danog/tg-file-decoder/zipball/f4da78c28d47b658c4596249f1d6595956f3b796",
+ "reference": "f4da78c28d47b658c4596249f1d6595956f3b796",
+ "shasum": ""
+ },
+ "require": {
+ "php-64bit": ">=8.2"
+ },
+ "require-dev": {
+ "amphp/php-cs-fixer-config": "^2",
+ "danog/phpdoc": "^0.1.22",
+ "phpunit/phpunit": "^11",
+ "vimeo/psalm": "dev-master"
+ },
+ "type": "project",
+ "autoload": {
+ "psr-4": {
+ "danog\\Decoder\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "AGPL-3.0-only"
+ ],
+ "authors": [
+ {
+ "name": "Daniil Gentili",
+ "email": "daniil@daniil.it"
+ }
+ ],
+ "description": "Decode Telegram bot API file IDs",
+ "keywords": [
+ "audio",
+ "bot api",
+ "file ID",
+ "files",
+ "mtproto",
+ "stickers",
+ "telegram",
+ "video"
+ ],
+ "support": {
+ "issues": "https://github.com/danog/tg-file-decoder/issues",
+ "source": "https://github.com/danog/tg-file-decoder/tree/1.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/danog",
+ "type": "github"
+ }
+ ],
+ "time": "2025-05-31T15:14:35+00:00"
+ },
+ {
+ "name": "dasprid/enum",
+ "version": "1.0.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DASPRiD/Enum.git",
+ "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
+ "reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1 <9.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
+ "squizlabs/php_codesniffer": "*"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DASPRiD\\Enum\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-2-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Ben Scholzen 'DASPRiD'",
+ "email": "mail@dasprids.de",
+ "homepage": "https://dasprids.de/",
+ "role": "Developer"
+ }
+ ],
+ "description": "PHP 7.1 enum implementation",
+ "keywords": [
+ "enum",
+ "map"
+ ],
+ "support": {
+ "issues": "https://github.com/DASPRiD/Enum/issues",
+ "source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
+ },
+ "time": "2025-09-16T12:23:56+00:00"
+ },
+ {
+ "name": "daverandom/libdns",
+ "version": "v2.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/DaveRandom/LibDNS.git",
+ "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a",
+ "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "php": ">=7.1"
+ },
+ "suggest": {
+ "ext-intl": "Required for IDN support"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "LibDNS\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "DNS protocol implementation written in pure PHP",
+ "keywords": [
+ "dns"
+ ],
+ "support": {
+ "issues": "https://github.com/DaveRandom/LibDNS/issues",
+ "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0"
+ },
+ "time": "2024-04-12T12:12:48+00:00"
+ },
+ {
+ "name": "kelunik/certificate",
+ "version": "v1.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/kelunik/certificate.git",
+ "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e",
+ "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "php": ">=7.0"
+ },
+ "require-dev": {
+ "amphp/php-cs-fixer-config": "^2",
+ "phpunit/phpunit": "^6 | 7 | ^8 | ^9"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Kelunik\\Certificate\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Niklas Keller",
+ "email": "me@kelunik.com"
+ }
+ ],
+ "description": "Access certificate details and transform between different formats.",
+ "keywords": [
+ "DER",
+ "certificate",
+ "certificates",
+ "openssl",
+ "pem",
+ "x509"
+ ],
+ "support": {
+ "issues": "https://github.com/kelunik/certificate/issues",
+ "source": "https://github.com/kelunik/certificate/tree/v1.1.3"
+ },
+ "time": "2023-02-03T21:26:53+00:00"
+ },
+ {
+ "name": "league/uri",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri.git",
+ "reference": "08cf38e3924d4f56238125547b5720496fac8fd4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri/zipball/08cf38e3924d4f56238125547b5720496fac8fd4",
+ "reference": "08cf38e3924d4f56238125547b5720496fac8fd4",
+ "shasum": ""
+ },
+ "require": {
+ "league/uri-interfaces": "^7.8.1",
+ "php": "^8.1",
+ "psr/http-factory": "^1"
+ },
+ "conflict": {
+ "league/uri-schemes": "^1.0"
+ },
+ "suggest": {
+ "ext-bcmath": "to improve IPV4 host parsing",
+ "ext-dom": "to convert the URI into an HTML anchor tag",
+ "ext-fileinfo": "to create Data URI from file contennts",
+ "ext-gmp": "to improve IPV4 host parsing",
+ "ext-intl": "to handle IDN host with the best performance",
+ "ext-uri": "to use the PHP native URI class",
+ "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
+ "league/uri-components": "to provide additional tools to manipulate URI objects components",
+ "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
+ "php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
+ "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "URI manipulation library",
+ "homepage": "https://uri.thephpleague.com",
+ "keywords": [
+ "URN",
+ "data-uri",
+ "file-uri",
+ "ftp",
+ "hostname",
+ "http",
+ "https",
+ "middleware",
+ "parse_str",
+ "parse_url",
+ "psr-7",
+ "query-string",
+ "querystring",
+ "rfc2141",
+ "rfc3986",
+ "rfc3987",
+ "rfc6570",
+ "rfc8141",
+ "uri",
+ "uri-template",
+ "url",
+ "ws"
+ ],
+ "support": {
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri-src/issues",
+ "source": "https://github.com/thephpleague/uri/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-15T20:22:25+00:00"
+ },
+ {
+ "name": "league/uri-components",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri-components.git",
+ "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri-components/zipball/848ff9db2f0be06229d6034b7c2e33d41b4fd675",
+ "reference": "848ff9db2f0be06229d6034b7c2e33d41b4fd675",
+ "shasum": ""
+ },
+ "require": {
+ "league/uri": "^7.8.1",
+ "php": "^8.1"
+ },
+ "suggest": {
+ "ext-bcmath": "to improve IPV4 host parsing",
+ "ext-fileinfo": "to create Data URI from file contennts",
+ "ext-gmp": "to improve IPV4 host parsing",
+ "ext-intl": "to handle IDN host with the best performance",
+ "ext-mbstring": "to use the sorting algorithm of URLSearchParams",
+ "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain",
+ "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP",
+ "php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
+ "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "URI components manipulation library",
+ "homepage": "http://uri.thephpleague.com",
+ "keywords": [
+ "authority",
+ "components",
+ "fragment",
+ "host",
+ "middleware",
+ "modifier",
+ "path",
+ "port",
+ "query",
+ "rfc3986",
+ "scheme",
+ "uri",
+ "url",
+ "userinfo"
+ ],
+ "support": {
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri-src/issues",
+ "source": "https://github.com/thephpleague/uri-components/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-15T20:22:25+00:00"
+ },
+ {
+ "name": "league/uri-interfaces",
+ "version": "7.8.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/uri-interfaces.git",
+ "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/85d5c77c5d6d3af6c54db4a78246364908f3c928",
+ "reference": "85d5c77c5d6d3af6c54db4a78246364908f3c928",
+ "shasum": ""
+ },
+ "require": {
+ "ext-filter": "*",
+ "php": "^8.1",
+ "psr/http-message": "^1.1 || ^2.0"
+ },
+ "suggest": {
+ "ext-bcmath": "to improve IPV4 host parsing",
+ "ext-gmp": "to improve IPV4 host parsing",
+ "ext-intl": "to handle IDN host with the best performance",
+ "php-64bit": "to improve IPV4 host parsing",
+ "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification",
+ "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "7.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\Uri\\": ""
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ignace Nyamagana Butera",
+ "email": "nyamsprod@gmail.com",
+ "homepage": "https://nyamsprod.com"
+ }
+ ],
+ "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
+ "homepage": "https://uri.thephpleague.com",
+ "keywords": [
+ "data-uri",
+ "file-uri",
+ "ftp",
+ "hostname",
+ "http",
+ "https",
+ "parse_str",
+ "parse_url",
+ "psr-7",
+ "query-string",
+ "querystring",
+ "rfc3986",
+ "rfc3987",
+ "rfc6570",
+ "uri",
+ "url",
+ "ws"
+ ],
+ "support": {
+ "docs": "https://uri.thephpleague.com",
+ "forum": "https://thephpleague.slack.com",
+ "issues": "https://github.com/thephpleague/uri-src/issues",
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sponsors/nyamsprod",
+ "type": "github"
+ }
+ ],
+ "time": "2026-03-08T20:05:35+00:00"
+ },
+ {
+ "name": "monolog/monolog",
+ "version": "3.12.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/monolog.git",
+ "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7059e4c691d05ea1222b5124bed0f961be46e15",
+ "reference": "d7059e4c691d05ea1222b5124bed0f961be46e15",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "psr/log": "^2.0 || ^3.0"
+ },
+ "provide": {
+ "psr/log-implementation": "3.0.0"
+ },
+ "require-dev": {
+ "aws/aws-sdk-php": "^3.0",
+ "doctrine/couchdb": "~1.0@dev",
+ "elasticsearch/elasticsearch": "^7 || ^8",
+ "ext-json": "*",
+ "graylog2/gelf-php": "^1.4.2 || ^2.0",
+ "guzzlehttp/guzzle": "^7.4.5",
+ "guzzlehttp/psr7": "^2.2",
+ "mongodb/mongodb": "^1.8 || ^2.0",
+ "php-amqplib/php-amqplib": "~2.4 || ^3",
+ "php-console/php-console": "^3.1.8",
+ "phpstan/phpstan": "^2",
+ "phpstan/phpstan-deprecation-rules": "^2",
+ "phpstan/phpstan-strict-rules": "^2",
+ "phpunit/phpunit": "^10.5.17 || ^11.0.7",
+ "predis/predis": "^1.1 || ^2",
+ "psr/clock": "^1.0",
+ "rollbar/rollbar": "^4.0",
+ "ruflin/elastica": "^7 || ^8",
+ "symfony/mailer": "^5.4 || ^6",
+ "symfony/mime": "^5.4 || ^6"
+ },
+ "suggest": {
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
+ "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
+ "ext-mbstring": "Allow to work properly with unicode symbols",
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
+ "ext-openssl": "Required to send log messages using SSL",
+ "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
+ "psr/clock": "Required to pass a clock to the Logger and control the timestamp of log records",
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Monolog\\": "src/Monolog"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "homepage": "https://github.com/Seldaek/monolog",
+ "keywords": [
+ "log",
+ "logging",
+ "psr-3"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/monolog/issues",
+ "source": "https://github.com/Seldaek/monolog/tree/3.12.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/Seldaek",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-09-29T19:21:12+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/9e33da9553fe7786f0962b35f4e4ecf01be89def",
+ "reference": "9e33da9553fe7786f0962b35f4e4ecf01be89def",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0"
+ },
+ "time": "2026-09-13T18:51:52+00:00"
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "version": "v3.1.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
+ "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
+ "reference": "d5b01a39b3415c2cd581d3bd3a3575c1ebbd8e77",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8"
+ },
+ "require-dev": {
+ "infection/infection": "^0",
+ "nikic/php-fuzzer": "^0",
+ "phpunit/phpunit": "^9|^10|^11",
+ "vimeo/psalm": "^4|^5|^6"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ParagonIE\\ConstantTime\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com",
+ "role": "Maintainer"
+ },
+ {
+ "name": "Steve 'Sc00bz' Thomas",
+ "email": "steve@tobtu.com",
+ "homepage": "https://www.tobtu.com",
+ "role": "Original Developer"
+ }
+ ],
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "keywords": [
+ "base16",
+ "base32",
+ "base32_decode",
+ "base32_encode",
+ "base64",
+ "base64_decode",
+ "base64_encode",
+ "bin2hex",
+ "encoding",
+ "hex",
+ "hex2bin",
+ "rfc4648"
+ ],
+ "support": {
+ "email": "info@paragonie.com",
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
+ "source": "https://github.com/paragonie/constant_time_encoding"
+ },
+ "time": "2025-09-24T15:06:41+00:00"
+ },
+ {
+ "name": "phpseclib/phpseclib",
+ "version": "4.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phpseclib/phpseclib.git",
+ "reference": "1fe20b9acb08ce810cec24d8a9d02e7c13426e4c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/1fe20b9acb08ce810cec24d8a9d02e7c13426e4c",
+ "reference": "1fe20b9acb08ce810cec24d8a9d02e7c13426e4c",
+ "shasum": ""
+ },
+ "require": {
+ "paragonie/constant_time_encoding": "^2|^3",
+ "php": ">=8.1",
+ "symfony/polyfill-php82": "^1.26"
+ },
+ "require-dev": {
+ "brianium/paratest": "^7.22",
+ "ext-xml": "*",
+ "php-parallel-lint/php-parallel-lint": "^1.3",
+ "phpunit/phpunit": "^13",
+ "squizlabs/php_codesniffer": "^3.7",
+ "vimeo/psalm": "*"
+ },
+ "suggest": {
+ "ext-dom": "Install the DOM extension to load XML formatted public keys.",
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "phpseclib/bootstrap.php"
+ ],
+ "psr-4": {
+ "phpseclib4\\": "phpseclib/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jim Wigginton",
+ "email": "terrafrost@php.net",
+ "role": "Lead Developer"
+ },
+ {
+ "name": "Patrick Monnerat",
+ "email": "pm@datasphere.ch",
+ "role": "Developer"
+ },
+ {
+ "name": "Andreas Fischer",
+ "email": "bantu@phpbb.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Hans-Jürgen Petrich",
+ "email": "petrich@tronic-media.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Graham Campbell",
+ "email": "graham@alt-three.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Jack Worman",
+ "email": "jack.worman@gmail.com",
+ "homepage": "https://jackworman.com",
+ "role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
- "homepage": "http://phpseclib.sourceforge.net",
+ "homepage": "https://phpseclib.com/",
+ "keywords": [
+ "BigInteger",
+ "aes",
+ "asn.1",
+ "asn1",
+ "blowfish",
+ "crypto",
+ "cryptography",
+ "encryption",
+ "rsa",
+ "security",
+ "sftp",
+ "signature",
+ "signing",
+ "ssh",
+ "twofish",
+ "x.509",
+ "x509"
+ ],
+ "support": {
+ "issues": "https://github.com/phpseclib/phpseclib/issues",
+ "source": "https://github.com/phpseclib/phpseclib/tree/4.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/terrafrost",
+ "type": "github"
+ },
+ {
+ "url": "https://www.patreon.com/phpseclib",
+ "type": "patreon"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-10-07T19:55:38+00:00"
+ },
+ {
+ "name": "promphp/prometheus_client_php",
+ "version": "v2.15.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/PromPHP/prometheus_client_php.git",
+ "reference": "e153786bda5ca1d07335a2b5f477742c37195c40"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/PromPHP/prometheus_client_php/zipball/e153786bda5ca1d07335a2b5f477742c37195c40",
+ "reference": "e153786bda5ca1d07335a2b5f477742c37195c40",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "php": "^8.2"
+ },
+ "replace": {
+ "endclothing/prometheus_client_php": "*",
+ "jimdo/prometheus_client_php": "*",
+ "lkaemmerling/prometheus_client_php": "*"
+ },
+ "require-dev": {
+ "guzzlehttp/guzzle": "^6.3|^7.0",
+ "phpstan/extension-installer": "^1.0",
+ "phpstan/phpstan": "^1.5.4",
+ "phpstan/phpstan-phpunit": "^1.1.0",
+ "phpstan/phpstan-strict-rules": "^1.1.0",
+ "phpunit/phpunit": "^9.4",
+ "predis/predis": "^2.3",
+ "squizlabs/php_codesniffer": "^3.6 || ^4.0",
+ "symfony/polyfill-apcu": "^1.6"
+ },
+ "suggest": {
+ "ext-apc": "Required if using APCu.",
+ "ext-pdo": "Required if using PDO.",
+ "ext-redis": "Required if using Redis.",
+ "predis/predis": "Required if using Predis.",
+ "promphp/prometheus_push_gateway_php": "An easy client for using Prometheus PushGateway.",
+ "symfony/polyfill-apcu": "Required if you use APCu."
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Prometheus\\": "src/Prometheus/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "Apache-2.0"
+ ],
+ "authors": [
+ {
+ "name": "Lukas Kämmerling",
+ "email": "kontakt@lukas-kaemmerling.de"
+ }
+ ],
+ "description": "Prometheus instrumentation library for PHP applications.",
+ "support": {
+ "issues": "https://github.com/PromPHP/prometheus_client_php/issues",
+ "source": "https://github.com/PromPHP/prometheus_client_php/tree/v2.15.1"
+ },
+ "time": "2026-05-28T07:51:04+00:00"
+ },
+ {
+ "name": "psr/http-factory",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-factory.git",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1",
+ "psr/http-message": "^1.0 || ^2.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "keywords": [
+ "factory",
+ "http",
+ "message",
+ "psr",
+ "psr-17",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-factory"
+ },
+ "time": "2024-04-15T12:06:14+00:00"
+ },
+ {
+ "name": "psr/http-message",
+ "version": "2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/http-message.git",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Http\\Message\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for HTTP messages",
+ "homepage": "https://github.com/php-fig/http-message",
+ "keywords": [
+ "http",
+ "http-message",
+ "psr",
+ "psr-7",
+ "request",
+ "response"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/http-message/tree/2.0"
+ },
+ "time": "2023-04-04T09:54:51+00:00"
+ },
+ {
+ "name": "psr/log",
+ "version": "3.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/php-fig/log.git",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.0.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Psr\\Log\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "PHP-FIG",
+ "homepage": "https://www.php-fig.org/"
+ }
+ ],
+ "description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
+ "keywords": [
+ "log",
+ "psr",
+ "psr-3"
+ ],
+ "support": {
+ "source": "https://github.com/php-fig/log/tree/3.0.2"
+ },
+ "time": "2024-09-11T13:17:53+00:00"
+ },
+ {
+ "name": "ramsey/collection",
+ "version": "2.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/collection.git",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/collection/zipball/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "reference": "344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^8.1"
+ },
+ "require-dev": {
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.45",
+ "fakerphp/faker": "^1.24",
+ "hamcrest/hamcrest-php": "^2.0",
+ "jangregor/phpstan-prophecy": "^2.1",
+ "mockery/mockery": "^1.6",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.4",
+ "phpspec/prophecy-phpunit": "^2.3",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^10.5",
+ "ramsey/coding-standard": "^2.3",
+ "ramsey/conventional-commits": "^1.6",
+ "roave/security-advisories": "dev-latest"
+ },
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Ramsey\\Collection\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "description": "A PHP library for representing and manipulating collections.",
+ "keywords": [
+ "array",
+ "collection",
+ "hash",
+ "map",
+ "queue",
+ "set"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/collection/issues",
+ "source": "https://github.com/ramsey/collection/tree/2.1.1"
+ },
+ "time": "2025-03-22T05:38:12+00:00"
+ },
+ {
+ "name": "ramsey/uuid",
+ "version": "4.9.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/uuid.git",
+ "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/uuid/zipball/75d73f48d02797c2c285a7e9f348fadc0102ffe2",
+ "reference": "75d73f48d02797c2c285a7e9f348fadc0102ffe2",
+ "shasum": ""
+ },
+ "require": {
+ "brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14 || ^0.15 || ^0.16 || ^0.17 || ^0.18 || ^0.19 || ^0.20 || ^1.0",
+ "php": "^8.0",
+ "ramsey/collection": "^1.2 || ^2.0"
+ },
+ "replace": {
+ "rhumsaa/uuid": "self.version"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.25",
+ "captainhook/plugin-composer": "^5.3",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0",
+ "ergebnis/composer-normalize": "^2.47",
+ "mockery/mockery": "^1.6",
+ "paragonie/random-lib": "^2",
+ "php-mock/php-mock": "^2.6",
+ "php-mock/php-mock-mockery": "^1.5",
+ "php-parallel-lint/php-parallel-lint": "^1.4.0",
+ "phpbench/phpbench": "^1.2.14",
+ "phpstan/extension-installer": "^1.4",
+ "phpstan/phpstan": "^2.1",
+ "phpstan/phpstan-mockery": "^2.0",
+ "phpstan/phpstan-phpunit": "^2.0",
+ "phpunit/phpunit": "^9.6",
+ "slevomat/coding-standard": "^8.18",
+ "squizlabs/php_codesniffer": "^3.13"
+ },
+ "suggest": {
+ "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.",
+ "ext-gmp": "Enables faster math with arbitrary-precision integers using GMP.",
+ "ext-uuid": "Enables the use of PeclUuidTimeGenerator and PeclUuidRandomGenerator.",
+ "paragonie/random-lib": "Provides RandomLib for use with the RandomLibAdapter",
+ "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type."
+ },
+ "type": "library",
+ "extra": {
+ "captainhook": {
+ "force-install": true
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Ramsey\\Uuid\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
"keywords": [
- "BigInteger",
- "aes",
- "asn.1",
- "asn1",
- "blowfish",
- "crypto",
- "cryptography",
- "encryption",
- "rsa",
- "security",
- "sftp",
- "signature",
- "signing",
- "ssh",
- "twofish",
- "x.509",
- "x509"
+ "guid",
+ "identifier",
+ "uuid"
],
"support": {
- "issues": "https://github.com/phpseclib/phpseclib/issues",
- "source": "https://github.com/phpseclib/phpseclib/tree/3.0.57"
+ "issues": "https://github.com/ramsey/uuid/issues",
+ "source": "https://github.com/ramsey/uuid/tree/4.9.4"
},
- "funding": [
+ "time": "2026-09-16T11:39:30+00:00"
+ },
+ {
+ "name": "revolt/event-loop",
+ "version": "v1.0.9",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/revoltphp/event-loop.git",
+ "reference": "44061cf513e53c6200372fc935ac42271566295d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/44061cf513e53c6200372fc935ac42271566295d",
+ "reference": "44061cf513e53c6200372fc935ac42271566295d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "ext-json": "*",
+ "jetbrains/phpstorm-stubs": "^2019.3",
+ "phpunit/phpunit": "^9",
+ "psalm/phar": "6.16.*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Revolt\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
{
- "url": "https://github.com/terrafrost",
- "type": "github"
+ "name": "Aaron Piotrowski",
+ "email": "aaron@trowski.com"
},
{
- "url": "https://www.patreon.com/phpseclib",
- "type": "patreon"
+ "name": "Cees-Jan Kiewiet",
+ "email": "ceesjank@gmail.com"
},
{
- "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
- "type": "tidelift"
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering"
+ },
+ {
+ "name": "Niklas Keller",
+ "email": "me@kelunik.com"
}
],
- "time": "2026-08-26T12:13:21+00:00"
+ "description": "Rock-solid event loop for concurrent PHP applications.",
+ "keywords": [
+ "async",
+ "asynchronous",
+ "concurrency",
+ "event",
+ "event-loop",
+ "non-blocking",
+ "scheduler"
+ ],
+ "support": {
+ "issues": "https://github.com/revoltphp/event-loop/issues",
+ "source": "https://github.com/revoltphp/event-loop/tree/v1.0.9"
+ },
+ "time": "2026-05-16T17:55:38+00:00"
},
{
- "name": "promphp/prometheus_client_php",
- "version": "v2.15.1",
+ "name": "symfony/polyfill-iconv",
+ "version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/PromPHP/prometheus_client_php.git",
- "reference": "e153786bda5ca1d07335a2b5f477742c37195c40"
+ "url": "https://github.com/symfony/polyfill-iconv.git",
+ "reference": "254724d95fe01b679cd97d88786e9623ee00bfb7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PromPHP/prometheus_client_php/zipball/e153786bda5ca1d07335a2b5f477742c37195c40",
- "reference": "e153786bda5ca1d07335a2b5f477742c37195c40",
+ "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/254724d95fe01b679cd97d88786e9623ee00bfb7",
+ "reference": "254724d95fe01b679cd97d88786e9623ee00bfb7",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "php": "^8.2"
- },
- "replace": {
- "endclothing/prometheus_client_php": "*",
- "jimdo/prometheus_client_php": "*",
- "lkaemmerling/prometheus_client_php": "*"
+ "php": ">=7.2"
},
- "require-dev": {
- "guzzlehttp/guzzle": "^6.3|^7.0",
- "phpstan/extension-installer": "^1.0",
- "phpstan/phpstan": "^1.5.4",
- "phpstan/phpstan-phpunit": "^1.1.0",
- "phpstan/phpstan-strict-rules": "^1.1.0",
- "phpunit/phpunit": "^9.4",
- "predis/predis": "^2.3",
- "squizlabs/php_codesniffer": "^3.6 || ^4.0",
- "symfony/polyfill-apcu": "^1.6"
+ "provide": {
+ "ext-iconv": "*"
},
"suggest": {
- "ext-apc": "Required if using APCu.",
- "ext-pdo": "Required if using PDO.",
- "ext-redis": "Required if using Redis.",
- "predis/predis": "Required if using Predis.",
- "promphp/prometheus_push_gateway_php": "An easy client for using Prometheus PushGateway.",
- "symfony/polyfill-apcu": "Required if you use APCu."
+ "ext-iconv": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.0-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Prometheus\\": "src/Prometheus/"
+ "Symfony\\Polyfill\\Iconv\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
- "Apache-2.0"
+ "MIT"
],
"authors": [
{
- "name": "Lukas Kämmerling",
- "email": "kontakt@lukas-kaemmerling.de"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Prometheus instrumentation library for PHP applications.",
+ "description": "Symfony polyfill for the Iconv extension",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "iconv",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
"support": {
- "issues": "https://github.com/PromPHP/prometheus_client_php/issues",
- "source": "https://github.com/PromPHP/prometheus_client_php/tree/v2.15.1"
+ "source": "https://github.com/symfony/polyfill-iconv/tree/v1.43.0"
},
- "time": "2026-05-28T07:51:04+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-09-29T06:25:14+00:00"
},
{
- "name": "psr/http-factory",
- "version": "1.1.0",
+ "name": "symfony/polyfill-mbstring",
+ "version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/http-factory.git",
- "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a"
+ "url": "https://github.com/symfony/polyfill-mbstring.git",
+ "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
- "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
+ "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
"shasum": ""
},
"require": {
- "php": ">=7.1",
- "psr/http-message": "^1.0 || ^2.0"
+ "ext-iconv": "*",
+ "php": ">=7.2"
+ },
+ "provide": {
+ "ext-mbstring": "*"
+ },
+ "suggest": {
+ "ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Psr\\Http\\Message\\": "src/"
+ "Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -3609,53 +5512,80 @@
],
"authors": [
{
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "homepage": "https://symfony.com",
"keywords": [
- "factory",
- "http",
- "message",
- "psr",
- "psr-17",
- "psr-7",
- "request",
- "response"
+ "compatibility",
+ "mbstring",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
],
- "support": {
- "source": "https://github.com/php-fig/http-factory"
- },
- "time": "2024-04-15T12:06:14+00:00"
+ "time": "2026-09-24T15:19:04+00:00"
},
{
- "name": "psr/http-message",
- "version": "2.0",
+ "name": "symfony/polyfill-php82",
+ "version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/http-message.git",
- "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
+ "url": "https://github.com/symfony/polyfill-php82.git",
+ "reference": "843bbe8b2a7934307b749751eede0f111f5d1cfc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
- "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
+ "url": "https://api.github.com/repos/symfony/polyfill-php82/zipball/843bbe8b2a7934307b749751eede0f111f5d1cfc",
+ "reference": "843bbe8b2a7934307b749751eede0f111f5d1cfc",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "2.0.x-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Psr\\Http\\Message\\": "src/"
- }
+ "Symfony\\Polyfill\\Php82\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3663,52 +5593,79 @@
],
"authors": [
{
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Common interface for HTTP messages",
- "homepage": "https://github.com/php-fig/http-message",
+ "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
"keywords": [
- "http",
- "http-message",
- "psr",
- "psr-7",
- "request",
- "response"
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "source": "https://github.com/php-fig/http-message/tree/2.0"
+ "source": "https://github.com/symfony/polyfill-php82/tree/v1.43.0"
},
- "time": "2023-04-04T09:54:51+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-09-25T15:50:05+00:00"
},
{
- "name": "psr/log",
- "version": "3.0.2",
+ "name": "symfony/polyfill-php83",
+ "version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/php-fig/log.git",
- "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3"
+ "url": "https://github.com/symfony/polyfill-php83.git",
+ "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
- "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/80ccff923a8d61f73ebe9da0aa94e25232f004ce",
+ "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce",
"shasum": ""
},
"require": {
- "php": ">=8.0.0"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Psr\\Log\\": "src"
- }
+ "Symfony\\Polyfill\\Php83\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3716,55 +5673,79 @@
],
"authors": [
{
- "name": "PHP-FIG",
- "homepage": "https://www.php-fig.org/"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Common interface for logging libraries",
- "homepage": "https://github.com/php-fig/log",
+ "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
"keywords": [
- "log",
- "psr",
- "psr-3"
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "source": "https://github.com/php-fig/log/tree/3.0.2"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0"
},
- "time": "2024-09-11T13:17:53+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-09-25T15:50:05+00:00"
},
{
- "name": "revolt/event-loop",
- "version": "v1.0.9",
+ "name": "symfony/polyfill-php84",
+ "version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/revoltphp/event-loop.git",
- "reference": "44061cf513e53c6200372fc935ac42271566295d"
+ "url": "https://github.com/symfony/polyfill-php84.git",
+ "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/44061cf513e53c6200372fc935ac42271566295d",
- "reference": "44061cf513e53c6200372fc935ac42271566295d",
+ "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/22c6548499cbe5c5bb072fc0c42312dff062a015",
+ "reference": "22c6548499cbe5c5bb072fc0c42312dff062a015",
"shasum": ""
},
"require": {
- "php": ">=8.1"
- },
- "require-dev": {
- "ext-json": "*",
- "jetbrains/phpstorm-stubs": "^2019.3",
- "phpunit/phpunit": "^9",
- "psalm/phar": "6.16.*"
+ "php": ">=7.2"
},
"type": "library",
"extra": {
- "branch-alias": {
- "dev-main": "1.x-dev"
+ "thanks": {
+ "url": "https://github.com/symfony/polyfill",
+ "name": "symfony/polyfill"
}
},
"autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
"psr-4": {
- "Revolt\\": "src"
- }
+ "Symfony\\Polyfill\\Php84\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3772,62 +5753,62 @@
],
"authors": [
{
- "name": "Aaron Piotrowski",
- "email": "aaron@trowski.com"
- },
- {
- "name": "Cees-Jan Kiewiet",
- "email": "ceesjank@gmail.com"
- },
- {
- "name": "Christian Lück",
- "email": "christian@clue.engineering"
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
},
{
- "name": "Niklas Keller",
- "email": "me@kelunik.com"
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
- "description": "Rock-solid event loop for concurrent PHP applications.",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
"keywords": [
- "async",
- "asynchronous",
- "concurrency",
- "event",
- "event-loop",
- "non-blocking",
- "scheduler"
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
],
"support": {
- "issues": "https://github.com/revoltphp/event-loop/issues",
- "source": "https://github.com/revoltphp/event-loop/tree/v1.0.9"
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0"
},
- "time": "2026-05-16T17:55:38+00:00"
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2026-09-23T22:01:09+00:00"
},
{
- "name": "symfony/polyfill-mbstring",
+ "name": "symfony/polyfill-php85",
"version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72"
+ "url": "https://github.com/symfony/polyfill-php85.git",
+ "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
- "reference": "4d5d331bf731e0aedbc6b2f5e61135b7b7996a72",
+ "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/86a42cbcc07adc331481a5ab310a4024bfc227f6",
+ "reference": "86a42cbcc07adc331481a5ab310a4024bfc227f6",
"shasum": ""
},
"require": {
- "ext-iconv": "*",
"php": ">=7.2"
},
- "provide": {
- "ext-mbstring": "*"
- },
- "suggest": {
- "ext-mbstring": "For best performance"
- },
"type": "library",
"extra": {
"thanks": {
@@ -3840,8 +5821,11 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Mbstring\\": ""
- }
+ "Symfony\\Polyfill\\Php85\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -3857,17 +5841,16 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill for the Mbstring extension",
+ "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
- "mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0"
+ "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0"
},
"funding": [
{
@@ -3887,20 +5870,20 @@
"type": "tidelift"
}
],
- "time": "2026-09-24T15:19:04+00:00"
+ "time": "2026-09-25T15:46:47+00:00"
},
{
- "name": "symfony/polyfill-php83",
+ "name": "symfony/polyfill-php86",
"version": "v1.43.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce"
+ "url": "https://github.com/symfony/polyfill-php86.git",
+ "reference": "8840df45b24f33a49dc419fa18dc0057231ae1d8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/80ccff923a8d61f73ebe9da0aa94e25232f004ce",
- "reference": "80ccff923a8d61f73ebe9da0aa94e25232f004ce",
+ "url": "https://api.github.com/repos/symfony/polyfill-php86/zipball/8840df45b24f33a49dc419fa18dc0057231ae1d8",
+ "reference": "8840df45b24f33a49dc419fa18dc0057231ae1d8",
"shasum": ""
},
"require": {
@@ -3918,7 +5901,7 @@
"bootstrap.php"
],
"psr-4": {
- "Symfony\\Polyfill\\Php83\\": ""
+ "Symfony\\Polyfill\\Php86\\": ""
},
"classmap": [
"Resources/stubs"
@@ -3938,7 +5921,7 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "description": "Symfony polyfill backporting some PHP 8.6+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@@ -3947,7 +5930,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0"
+ "source": "https://github.com/symfony/polyfill-php86/tree/v1.43.0"
},
"funding": [
{
@@ -3967,27 +5950,27 @@
"type": "tidelift"
}
],
- "time": "2026-09-25T15:50:05+00:00"
+ "time": "2026-09-25T15:46:47+00:00"
},
{
"name": "webmozart/assert",
- "version": "1.12.1",
+ "version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/webmozarts/assert.git",
- "reference": "9be6926d8b485f55b9229203f962b51ed377ba68"
+ "reference": "8a163706bbcac613733dba03f51e13b5eb1bb819"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68",
- "reference": "9be6926d8b485f55b9229203f962b51ed377ba68",
+ "url": "https://api.github.com/repos/webmozarts/assert/zipball/8a163706bbcac613733dba03f51e13b5eb1bb819",
+ "reference": "8a163706bbcac613733dba03f51e13b5eb1bb819",
"shasum": ""
},
"require": {
"ext-ctype": "*",
"ext-date": "*",
"ext-filter": "*",
- "php": "^7.2 || ^8.0"
+ "php": "^8.2"
},
"suggest": {
"ext-intl": "",
@@ -3996,8 +5979,12 @@
},
"type": "library",
"extra": {
+ "psalm": {
+ "pluginClass": "Webmozart\\Assert\\PsalmPlugin"
+ },
"branch-alias": {
- "dev-master": "1.10-dev"
+ "dev-master": "2.0-dev",
+ "dev-feature/2-0": "2.0-dev"
}
},
"autoload": {
@@ -4013,6 +6000,10 @@
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
+ },
+ {
+ "name": "Woody Gilk",
+ "email": "woody.gilk@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
@@ -4023,9 +6014,9 @@
],
"support": {
"issues": "https://github.com/webmozarts/assert/issues",
- "source": "https://github.com/webmozarts/assert/tree/1.12.1"
+ "source": "https://github.com/webmozarts/assert/tree/2.5.0"
},
- "time": "2025-10-29T15:56:20+00:00"
+ "time": "2026-10-05T23:14:19+00:00"
},
{
"name": "wizardloop/broadcastmanager",
@@ -5905,11 +7896,11 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": "~8.3.0 || ~8.4.0 || ~8.5.0",
+ "php": "~8.3.36 || ~8.4.27 || ~8.5.12",
"ext-pdo": "*",
"ext-pdo_sqlite": "*",
"ext-mbstring": "*"
},
"platform-dev": {},
- "plugin-api-version": "2.6.0"
+ "plugin-api-version": "2.9.0"
}
diff --git a/docs/ADMIN_PANEL.md b/docs/ADMIN_PANEL.md
index 1b14f2a..cf4b127 100644
--- a/docs/ADMIN_PANEL.md
+++ b/docs/ADMIN_PANEL.md
@@ -74,7 +74,7 @@ Broadcast drafts show their content, recipient audience, pin, scheduled time, au
Public /stats provides only aggregate group/reminder information. Administrative statistics use audience, activity, group and delivery sections, each with refresh and return controls. A statistics-only manager can read those sections without access to subscriber identities.
-The auxiliary MadelineProto broadcast client is shared per event handler. Owner-only /restart has a bounded acknowledgement, stops application work and completes the pinned SDK loop. Docker's restart policy starts the process again. The integration also waits for the pinned SDK's pending API finalizers while the application writer lock remains held; this uses an internal public method of exact version8.7.0 and must be reviewed before any dependency upgrade. It is covered offline and still requires the separate test bot's server acceptance.
+The auxiliary MadelineProto broadcast client is shared per event handler. Owner-only /restart acknowledges the request and stops new application work before the reviewed SDK restart path. Shutdown preserves the writer lock while managed work and SDK finalizers drain. This lifecycle must be revalidated when upgrading MadelineProto; offline regression does not replace a restart test with the separate staging bot.
## Paged calendar diagnostics
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index fc1add6..4915ce5 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -1,4 +1,4 @@
-Current dev.9 runtime and migration changes: [delivery safety, independent scheduling, queue retention and verification limits](DEV9_DELIVERY_SAFETY.md). Historical release-specific numbers below apply to their named versions.
+Current runtime and migration rules: [delivery safety, independent scheduling, queue retention and verification limits](DELIVERY_SAFETY.md). Historical release-specific numbers below apply to their named versions.
# Architecture
diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md
new file mode 100644
index 0000000..de5324e
--- /dev/null
+++ b/docs/COMMANDS.md
@@ -0,0 +1,64 @@
+# Bot commands
+
+Send these **in Telegram**. Menus are shortcuts, not a full permission contract. `[...]` means optional.
+
+## Users
+
+| Command | Where / permission | Effect |
+|---|---|---|
+| `/start`, `/help` | Private; any user | Home menu/help. |
+| `/preferences` | Private; own settings | Personal location/calendar/methods. |
+| `/language`, `/lang` | Private; own settings | Personal language; group usage needs group admin. |
+| `/groups [search]` | Private; fresh group-admin checks | List/search manageable known groups. |
+| `/shabat [YYYY-MM-DD]`, `/shabbat [YYYY-MM-DD]` | Private or registered group; any user | Shabbat/festival times for that context. |
+| `/zmanim [YYYY-MM-DD]` | Private or registered group; any user | Daily times. |
+| `/daf [YYYY-MM-DD]` | Private or registered group; any user | Daf Yomi. |
+| `/omer [YYYY-MM-DD]` | Private or registered group; any user | Count/season for the selected date. |
+| `/stats` | Private or group; any user | Public aggregates, without subscriber identities. |
+| `/donate` | Private; any user | Optional Stars offers; payment needs Telegram checkout. |
+| `/source`, `/license`, `/version` | Private or group; any user | Source offer, licensing/build identity. |
+
+## Group administrators
+
+| Command | Where / permission | Effect |
+|---|---|---|
+| `/add` | Group; current group admin | Register/reactivate and open setup. |
+| `/remove` | Group; current group admin | Deactivate; restoration debt blocks removal. |
+| `/settings` | Group; current group admin | Private group settings; see the registration caveat in [group settings](GROUP_SETTINGS.md). |
+| `/settings [GROUP_ID]` | Private; current target-group admin | Open target or list groups without ID. |
+| `/language`, `/lang` | Group; current group admin | Private selection of group language. |
+
+Advanced **private** forms require the panel's exact token, its owner/scope/revision and current group authority for group targets. Prefer the guided buttons.
+
+| Form | Effect |
+|---|---|
+| `/city TOKEN QUERY` | Search pending location. |
+| `/coordinates TOKEN LATITUDE LONGITUDE IANA_ZONE [NAME]` | Preview explicit coordinates/zone. |
+| `/location TOKEN IANA_ZONE` or `/location TOKEN auto` | Prompt for GPS reply; auto requires GeoNames. |
+| `/timezone TOKEN QUERY` | Search IANA zones. |
+| `/configure TOKEN FORM` | Preview the panel's supported settings form. |
+| `/viewdate TOKEN YYYY-MM-DD` | Selected calendar date. |
+| `/template TOKEN` + newline + content | Review a group template candidate. |
+| `/buttons TOKEN` + newline + keyboard content | Review JSON/legacy keyboard content. |
+
+## Bot managers
+
+All below run **in private**. Bot-manager roles are separate from group administration; view-only roles cannot mutate.
+
+| Command | Required access | Effect |
+|---|---|---|
+| `/admin` | Bot manager | Administration panel. |
+| `/adminstats` | Statistics | Administrative aggregates. |
+| `/testzmanim [GROUP_ID]` | Statistics | Paged diagnostics/filter/search and optional private JSON export. |
+| `/subscribers` | Subscribers | Known peer/profile directory. |
+| `/broadcast` | Broadcast | Drafts/jobs; sending/editing/deleting needs mutation rights and relevant confirmation. |
+| `/managers` | Manage managers | Delegated roles within actor's authority. |
+| `/systemlinks` | System links | Navigation links, which confer no permissions. |
+| `/trackinglinks` | Tracking links | Activation counters/management; changes need mutation access. |
+| `/setcommands [LANGUAGE] [SCOPE] [preview]` | Command-menu mutation, even preview | Inspect or update Telegram menus. |
+| `/closegroups`, `/opengroups` | Group-operations mutation | Immediately apply a one-hour override to active registered groups; preserve prelocks/report conflicts. Real permission operations. |
+| `/restart` | Configured `ADMIN` owner only | Orderly runtime restart. |
+
+Menu languages: `all|he|en|ru|fr|es|pt-br`; scopes: `all|private|operators|groups|group_admins`; defaults: `all all`. Example: `/setcommands ru group_admins preview`. Group menus currently list `/settings`; other supported commands can be typed.
+
+[Administration](ADMIN_PANEL.md) · [Diagnostics](DIAGNOSTICS.md)
diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md
index 7dc7824..8111c45 100644
--- a/docs/CONFIGURATION.md
+++ b/docs/CONFIGURATION.md
@@ -18,7 +18,7 @@ The bot reads the private project-root `.env` as raw INI; nonempty process envir
| `GEONAMES_USERNAME` | Optional; required for remote city/ID/GPS timezone lookup | Operator-owned account with web services enabled. Manual coordinates plus an explicit IANA zone remain available without it. |
| `GEONAMES_ENDPOINT` | `https://secure.geonames.org` | Validated HTTPS provider endpoint. Account/quota errors are provider failures, not empty city lists. |
| `CUSTOM_EMOJI_ENABLED` | `1`; set `0` for basic emoji | Enables supplied custom icons. Definite eligibility errors also trigger the guarded basic-emoji fallback. Client/account acceptance still needs a live test. |
-| `SOURCE_URL` | Empty in unpublished example; required by deployment/source policy | HTTPS URL to the exact corresponding source of the deployed build. Missing/invalid values produce the source-offer warning; startup does not enforce this policy automatically. |
+| `SOURCE_URL` | Matching release URL in the public example; required by deployment/source policy | HTTPS URL to the exact corresponding source of the deployed build. Missing/invalid values produce the source-offer warning; startup does not enforce this policy automatically. |
| `BUILD_COMMIT` | Optional process/Compose build metadata | Actual matching 40-hex commit for build identity. Not a bot credential and not a replacement for the source fingerprint of local modifications. |
`BUILD_COMMIT` is intentionally not filled in `.env.example`. Do not enter the old repository commit as if it described new unpublished files. Compose's `environment` section overrides the data/session values from its `env_file`. Keep the same Compose project name on upgrades so named volumes remain attached.
@@ -29,7 +29,7 @@ Private preferences and authorized group settings are separate contexts. Each co
The six catalogs are `he`, `en`, `ru`, `fr`, `es` and `pt-br`. Catalog completeness and placeholder parity are checked automatically; this is not a claim of independent native-speaker review or complete translation of provider scripture/liturgy. Hebrew source text and external provider strings may remain in their source language.
-`/language` and `/lang` open the authorized language selector. `/setcommands all all preview` is an operator-only private preview; omitting `preview` writes command menus to Telegram. The menu language for Brazilian Portuguese is Telegram's `pt`, while application preferences use `pt-br`. Group administrator menus expose `/settings`. See the complete command tables in the READMEs and [operator guide](OPERATIONS.md).
+`/language` and `/lang` open the authorized language selector. `/setcommands all all preview` is an operator-only private preview; omitting `preview` writes command menus to Telegram. The menu language for Brazilian Portuguese is Telegram's `pt`, while application preferences use `pt-br`. Group administrator menus expose `/settings`. See the complete [command reference](COMMANDS.md) and [operator guide](OPERATIONS.md).
New daily-zmanim/daf, tefillin and Omer scheduling modules are opt-in. Group locking, closing/opening notices and other content settings are independently configurable; imported legacy alerts use reviewed legacy settings. See [group settings](GROUP_SETTINGS.md), [methods](ZMANIM_METHODS.md) and [migration](MIGRATION.md).
diff --git a/docs/DATABASE.md b/docs/DATABASE.md
index c81667f..e538db6 100644
--- a/docs/DATABASE.md
+++ b/docs/DATABASE.md
@@ -1,4 +1,4 @@
-Current dev.9 runtime and migration changes: [delivery safety, independent scheduling, queue retention and verification limits](DEV9_DELIVERY_SAFETY.md). Historical release-specific numbers below apply to their named versions.
+Current runtime and migration rules: [delivery safety, independent scheduling, queue retention and verification limits](DELIVERY_SAFETY.md). Historical release-specific numbers below apply to their named versions.
# Application database
diff --git a/docs/DEV9_DELIVERY_SAFETY.md b/docs/DELIVERY_SAFETY.md
similarity index 86%
rename from docs/DEV9_DELIVERY_SAFETY.md
rename to docs/DELIVERY_SAFETY.md
index 9ef7e1a..41cae60 100644
--- a/docs/DEV9_DELIVERY_SAFETY.md
+++ b/docs/DELIVERY_SAFETY.md
@@ -1,6 +1,6 @@
-# dev.9 delivery and scheduler safety
+# Delivery and scheduler safety
-This is an unpublished test build. It fixes the timing, backlog and scheduler isolation defects reproduced in the dev.8 read-only audit. MadelineProto remains exactly 8.7.0 at `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`; the Composer lock is unchanged. Migration 016 is additive; migrations 001-015 and all four MadelineProto patch sets retain their bytes. The separate BroadcastManager patch gains reviewed lifecycle hooks; its previous approved source is preserved.
+Current runtime rules for scheduled notifications, permission reconciliation and broadcasts. For executed checks and their limits, see [implementation status](IMPLEMENTATION_STATUS.md).
## Delivery rules and exceptions
@@ -18,7 +18,7 @@ Persisted due Tefillin reminders that were never dispatched are coalesced to the
Quiet hours are rechecked at delivery time for ordinary modules, including Omer, not only when planning. A delayed job may defer until quiet hours end if still valid. Overnight hours and both occurrences of repeated DST times are supported; missing wall-clock times are not guessed. Tefillin also checks current weekday, pause date, Chol Hamoed/Tisha B'Av policy, daylight window and sunset safety. Omer checks the actual restoration gap again at the final send fence.
-Migration 016 conservatively marks old attempt/delivery evidence. An unknown old attempt is not silently treated as never dispatched. This can intentionally suppress or defer an uncertain reminder; it cannot infer whether Telegram accepted an old request. The unchanged permission-provenance rules from dev.8 still apply to unresolved older group snapshots.
+Migration 016 conservatively marks old attempt/delivery evidence. An unknown old attempt is not silently treated as never dispatched. This can intentionally suppress or defer an uncertain reminder; it cannot infer whether Telegram accepted an old request. The permission-provenance rules still apply to unresolved older group snapshots.
## Independent scheduling and failure isolation
@@ -42,6 +42,4 @@ At most once per minute, bounded maintenance selects up to 200 eligible terminal
Regression tests cover slow provider/topic/emoji/media work crossing entry, direct and fallback sends, actual quiet hours, Omer restoration changes, persisted backlog, daily caps/spacing, uncertainty across restart, migration, fair traversal, bounded concurrency and shutdown. Queue tests simulate 1,000 groups with 3,000 due reminders and 180 virtual days with 7,200 deliveries. Application and broadcast load tests use isolated databases, controlled clocks and fake transports; they do not send messages or measure real Telegram capacity.
-The original dev.9 validation is historical development evidence. Exact results for this publication copy are recorded separately in the delivered checks report; see [publication status](PUBLICATION_STATUS.md). These simulations are not months of wall-clock soak or proof of unlimited group count. Docker is unavailable on the local Windows host; the pinned Linux image and live disposable-group acceptance must still pass on the test server. The local older SQLite must continue to fail the release-platform gate rather than bypass it.
-
-See [test deployment](SERVER_TEST_DEPLOYMENT.md), [permission recovery](PERMISSION_RECOVERY.md), [database](DATABASE.md), and [BroadcastManager patch provenance](../patches/broadcastmanager/README.md).
\ No newline at end of file
+These simulations do not establish real Telegram capacity, holy-day acceptance or a wall-clock soak. Keep target-host acceptance separate from offline regression results.
diff --git a/docs/DEPENDENCIES.md b/docs/DEPENDENCIES.md
index 2dcb19e..b8f4f97 100644
--- a/docs/DEPENDENCIES.md
+++ b/docs/DEPENDENCIES.md
@@ -1,24 +1,12 @@
# Dependency evidence
-[Machine-readable inventory](dependencies.json) is generated from composer.lock
-and installed license files with php scripts/dependencies.php. Each package has
-version, commit permalink, direct/indirect runtime/dev scope, SPDX metadata,
-license paths/SHA256 and unresolved findings. LICENSE_TEXT_PRESENT is evidence
-of a matching distributed text, not a complete legal compatibility certification.
+[dependencies.json](dependencies.json) is generated from the exact Composer lock and installed license files by php scripts/dependencies.php. It records 83 runtime and 26 development packages, versions, commits, runtime/dev scope, metadata, original license hashes and unresolved findings. LICENSE_TEXT_PRESENT is text evidence, not an authorship or legal-compatibility certificate.
-MadelineProto has the exact Composer constraint `8.7.0`, resolved to commit
-`7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`, for reviewed patch/source semantics.
-The [official release](https://github.com/danog/MadelineProto/releases/tag/8.7.0)
-is marked pre-release, not stable. On 2026-10-14 the checked official v8 head
-`b1a4c5efee60a87cdbe7bc2b1eb542166ec7e2e3` still lacked the formatted-date wrapper;
-no tested official replacement was selected. See the
-[formatted-date review](MADELINE_FORMATTED_DATE.md) for the exact source comparison.
-BroadcastManager uses ~3.2.2, resolved to 3.2.2, allowing maintenance fixes without
-the previous unrestricted * or an unreviewed 3.3 API change. Lock is real Composer
-output. Direct use of Amp, Amp File, Amp HTTP Client and Revolt is explicit.
-PHP 8.3/8.4/8.5, PDO SQLite and mbstring are required. Composer plugins are disabled.
+MadelineProto is constrained by ^8.11.10 and locked at **8.11.10**, commit **49d3d8460257c7bfb1a7e12708e1bfdd59e898c1**, with TL layer 232. BroadcastManager ~3.2.2 resolves to **3.2.2**, commit f2792a383416b66bb68e55f09414563e540538d6. Install from composer.lock; a normal upgrade does not run composer update. [PATCHES](PATCHES.md) describes the two active reviewed modifications.
-Reproduce:
+## Reproduce the evidence
+
+Run in an isolated repository root with the locked dependencies installed, using the documented PHP requirements and Composer 2.10.3:
composer validate --strict --no-check-all
composer show --locked --format=json
@@ -27,59 +15,20 @@ Reproduce:
composer check-platform-reqs
php scripts/dependencies.php
-`--no-check-all` omits Composer's advice against intentionally exact constraints;
-`--strict` and the normal lock/schema checks remain enabled. It does not disable
-lock consistency validation. The 2026-10-14 pin used the supported metadata-only
-`composer update --lock --no-install --no-scripts --no-plugins --no-audit --no-interaction --no-progress`.
-All 83 package versions and source/dist references stayed unchanged, and a byte
-comparison showed only Composer's `content-hash` changed in `composer.lock`.
-No installation or dependency lifecycle scripts ran for this metadata refresh.
+The first five commands inspect configuration, inventory, advisories or platform support. The final command rewrites docs/dependencies.json; no bot or Telegram session is started. Composer plugins are disabled. The --no-check-all validation option suppresses constraint-style advice while lock/schema checks and --strict remain enabled.
-Security audit is separate from license review. [Patch provenance](PATCHES.md)
-and [third-party notices](../THIRD_PARTY_NOTICES.md) describe preserved notices.
-MadelineProto package metadata says AGPL-3.0-only while source grants version 3
-or later: retained and reported. NOT VERIFIED entries require release review.
+[composer-show.json](composer-show.json) is the locked inventory; [composer-licenses.json](composer-licenses.json) records the exact installed package metadata using the supported licenses command. Neither substitutes for reading original license files. The project version in Composer metadata may be the checkout branch, while release identity comes from VERSION and the reviewed release commit. Security audit results are separate from license evidence; rerun the audit for the release commit.
-Hebcal/GeoNames data, texts and graphics have independent terms in third-party
-notices; application AGPL does not relicense them.
-Composer 2.8.8 does not implement licenses --locked. The attempted invocation
-failed; composer-licenses.json records the supported licenses --format=json
-command against the installation made from composer.lock. composer-show.json
-and composer-audit.json record the locked inventory and advisory check.
+## Licensing and source scope
-## SQLite runtime evidence
+MadelineProto metadata says AGPL-3.0-only while source headers allow version 3 or later; both remain unchanged. The new php-rtc-av metadata says MIT but its distributed LICENSE/PHP headers state BSD-3-Clause. The inventory leaves the declared MIT grant NOT VERIFIED. Checked-in AV FFI declarations are included verbatim; no native FFmpeg binary or generator output is inferred from that metadata, and external derivation provenance is not established.
-The Windows test host loads SQLite 3.45.2 through PHP PDO, not a separate CLI.
-Its version is older than the [official WAL-reset fix](https://sqlite.org/wal.html).
-This blocks release-platform approval even though isolated single-writer tests pass.
-The fix is present in 3.51.3+ (specific backports 3.44.6 and 3.50.7 are recognized).
-Docker builds 3.51.3 from a fixed publisher archive and verifies SHA256
-81f5be397049b0cae1b167f2225af7646fc0f82e4a9b3c48c9ea3a533e21d77a before
-compilation, then tests the PHP-loaded version with self-check --release.
-The image build is not locally tested because Docker is unavailable on this host.
-Runtime source is public-domain SQLite; keep its source/terms separate from AGPL.
+The corresponding-source collection contains all 83 locked runtime package trees, with two exact public Amp TLS example-key omissions, approved local patch outputs, original notices and 103 preferred-source supplements. It excludes the 26 development packages and generated Composer autoload/bin metadata. PHPStan's PHAR is not called preferred source. External PHP, SQLite, optional FFmpeg and operating-system/container source are outside this collection. See [LICENSING](LICENSING.md), [THIRD_PARTY_DETAILS](THIRD_PARTY_DETAILS.md) and the [source manifest](../resources/release/source-manifest.json).
-## Quality tooling and scope
+The omitted Amp HTTP Server tools/tls/localhost.pem and tools/tls/localhost.key.pem are public development examples unused by the bot; exact paths and SHA-256 remain recorded. This packaging omission does not change installed vendor. All other unknown runtime files and credential patterns fail source packaging.
-The locked development tools include PHPUnit, PHPStan, and PHP_CodeSniffer
-4.0.4 (BSD-3-Clause). The inventory includes their transitive dependencies and
-distributed license texts. `composer style` enforces PSR-12 errors in new `src`,
-`bin`, `scripts`, and `tests` PHP files. The reviewed immutable patch baseline and
-synthetic fixtures are excluded. `composer style-review` additionally reports
-advisory PSR-12 line-length warnings. No error baseline is applied.
-The preserved legacy `bot.php` is syntax checked, while integration fixtures,
-authorization tests, and manual review cover its changed boundaries.
+## SQLite and local validation limits
-The publication corresponding-source archive contains the application and the
-57 locked runtime Composer dependency source trees, with their distributed
-licenses and local patch bases/diffs. The 26 development-tool packages are not
-included; in particular, a PHPStan PHAR is not represented as preferred source.
-PHP, SQLite, and operating-system base-image source are outside this collection;
-the Dockerfile retains the pinned upstream build inputs. See
-[publication scope](PUBLICATION_STATUS.md) and the archive manifest.
+The earlier Windows check runtime loaded PHP 8.5.0 and SQLite 3.45.2, predating the current PHP security baseline and the [official WAL-reset fix](https://sqlite.org/wal.html). Those results do not approve it as a release runtime. The isolated verifier now uses publisher-hash-verified PHP 8.5.12 with SQLite 3.53.4; it does not replace the Linux image checks. Docker builds pinned SQLite 3.51.3, verifies its publisher SHA-256 and checks the PHP-loaded version with self-check --release. The source hash is 81f5be397049b0cae1b167f2225af7646fc0f82e4a9b3c48c9ea3a533e21d77a. Docker is unavailable locally; exact release-platform evidence must come from the actual hosted build/checks. SQLite retains its public-domain terms.
-Amp HTTP Server's public development TLS example keys `tools/tls/localhost.pem`
-and `tools/tls/localhost.key.pem` are omitted by exact reviewed path and SHA-256.
-They are unused by this bot. Their provenance and hashes are retained in the
-archive manifest. Other private-key material or Telegram token patterns fail
-the archive scan. This omission never changes the installed vendor directory.
+Locked development tools include PHPUnit, PHPStan and PHP_CodeSniffer. Style checks apply to application PHP, scripts and tests; original dependency baselines and deliberately synthetic fixtures retain their existing exclusions. [Publication status](PUBLICATION_STATUS.md) identifies release evidence and live-acceptance limits.
diff --git a/docs/DEV5_TEST_FEEDBACK.md b/docs/DEV5_TEST_FEEDBACK.md
deleted file mode 100644
index eedbd02..0000000
--- a/docs/DEV5_TEST_FEEDBACK.md
+++ /dev/null
@@ -1,35 +0,0 @@
-> Historical implementation record. Referenced `dist/VALIDATION-*` reports belong to earlier private development deliveries and are not bundled here. Current publication checks and limits are described in [publication status](PUBLICATION_STATUS.md).
-
-# dev.5 - requested test feedback
-
-| Request | Implementation | Verification |
-|---|---|---|
-| 1. Manual close/open failure | Valid explicit override no longer depends on a provider fetch; bounded per-group diagnostics distinguish confirmed, pending, protected pre-lock and failures | Offline override/provider failure, permission restoration/races, error formatter and batch isolation tests |
-| 2. Group commands | Only settings for both all-groups and group-admin scopes, in six languages | Command scope and localized publishing tests; no commands published to Telegram here |
-| 3. Single Shabbat overview | No paging controls; actual candle-eve weekday, Hebrew/civil dates, parsha/Mevarchim, continuous exit, nearby observances and next three Shabbat summaries | Recorded complete Hebcal replies, holy-sequence fixtures, bounded UTF-16 rendering |
-| 4. Logic and help | Fresh authorization, verified times and role-appropriate expanded help | Full regression suite and six-language help/navigation tests |
-| 5. Statistics | Public aggregate overview/reminders; admin audience/activity/groups/delivery tabs | No identity leakage; statistics-only role can navigate tabs without subscriber-directory access |
-| 6. Group settings | Four-mode chooser, subcategories, current effective candle setting and contextual return after save/cancel; paired rich-message editor | All six languages, custom input/page return, stale-flow and permissions tests |
-| 7. Source | Correct project URL plus license/version/commit card and optional exact build source link | Group/private language tests; existing version/license aliases preserved |
-| 8. Broadcast | Guided link buttons, preserved designed keyboard after text edits, resumable draft, explicit detailed final confirmation | URL rejection, actor isolation, expiry, cancellation, stale confirmation, rich entity retention |
-| 9. Telegram group support | Basic groups and supergroups supported; bot must have administrative restriction rights | Pinned SDK/native permission regressions and official docs |
-| 10. Languages | Hebrew, English, Russian, French, Spanish, Brazilian Portuguese | Identical locale keys/placeholders and localized output tests |
-| 11. Restart/load | Shared auxiliary IPC client and owner-only orderly restart lifecycle; permission work remains prioritized | Offline lifecycle/IPC reuse, concurrent/large group batches, shutdown and recovery tests |
-
-## What the supplied log establishes
-
-The 918-line supplied extract has one update-loop start and 44 auxiliary IPC connection/destruction cycles. It contains no permission RPC exception and no explicit restart failure trace. The repeated connection cycle matches the previous minute-by-minute broadcast-manager construction. This was corrected in application code. The exact Telegram error behind the reported manual 0-success/1-failure result cannot be established from that extract alone; the new diagnostic message makes the next result actionable without exposing arbitrary exception payloads.
-
-An explicit manual override is deliberately independent of provider availability until its expiry, while fresh group settings/activation, shutdown state and durable original-rights safeguards remain enforced. Expired overrides return control to verified calendar logic.
-
-## Sources and calendar boundaries
-
-Telegram documents [messages.editChatDefaultBannedRights](https://core.telegram.org/method/messages.editChatDefaultBannedRights) for groups and supergroups and explicitly rejects view_messages as a default restriction. [Bot API setChatPermissions](https://core.telegram.org/bots/api#setchatpermissions) likewise permits group and supergroup default permissions and requires restrict_members.
-
-Holiday categorization uses [Hebcal JSON yomtov](https://www.hebcal.com/home/195/jewish-calendar-rest-api), not holiday-name guesses. The verified calendar horizon remains the selected month minus 8 days through its last day plus 40 days. Unavailable distant holiday timings are not invented. Hanukkah observances do not create festival locking intervals. See [calendar presentation](CALENDAR_PRESENTATION.md).
-
-## Acceptance boundaries
-
-Final evidence and archive identity are in the versioned dist/VALIDATION-3.0.0-dev.5.json report. Local tests do not establish Telegram throughput, client appearance, actual server restart, command installation, or Docker image operation. Docker is unavailable on this development host. The loaded local SQLite version intentionally fails the release-platform gate; the pinned Docker SQLite must pass that gate on the isolated test server.
-
-No production data, active bot, real group, commit, tag, pull request or publication was changed. All earlier dev.4 features and the pinned MadelineProto 8.7.0 patches remain included.
diff --git a/docs/DEV6_TEST_FEEDBACK.md b/docs/DEV6_TEST_FEEDBACK.md
deleted file mode 100644
index aa290db..0000000
--- a/docs/DEV6_TEST_FEEDBACK.md
+++ /dev/null
@@ -1,32 +0,0 @@
-> Historical implementation record. Referenced `dist/VALIDATION-*` reports belong to earlier private development deliveries and are not bundled here. Current publication checks and limits are described in [publication status](PUBLICATION_STATUS.md).
-
-# Dev.6 - permission conflicts, Shabbat messages and statistics
-
-## 1. Manual and automatic close/open
-
-The reported conflict message is produced by the bot's saved-state comparison, not by a Telegram RPC error proving that an administrator changed permissions. A concrete representation mismatch was reproduced: requests use until_date=0 for permanent default restrictions while Telegram's official TDLib describes the returned permanent default restrictions with INT32_MAX (2147483647). TDLib also serializes granular send restrictions with the legacy send_messages/send_media aggregate flags cleared. Raw comparison could therefore reject a successful close and retain that debt as a later conflict.
-
-The fix uses a reviewed, conservative equivalence for both close and restoration in the shared coordinator. Only the two permanent sentinels are equal; finite expiries remain distinct. Aggregate flags can be redundant only when their corresponding granular restrictions are all explicitly present. Individual differences, reactions/member-tag differences, unknown flags, missing/corrupt snapshots and real administrator changes remain protected. Original snapshot JSON and its checksum are retained byte-for-byte. Compatible persisted dev.5 conflicts can recover on reconciliation without deleting records or guessing the original permissions.
-
-The supplied message alone does not contain current/saved permission values. It establishes the conflict branch, but cannot prove which representation differs on that particular live group. Safe differing-field diagnostics and updated wording distinguish a mismatch from a proven external actor. The same coordinator serves manual and automatic transitions.
-
-Evidence: [Telegram rights](https://core.telegram.org/api/rights), [native constructor](https://core.telegram.org/constructor/chatBannedRights), and the immutable [official TDLib implementation](https://github.com/tdlib/td/blob/ad2178896533ff92831accdf56ea7edd8393f2ca/td/telegram/DialogParticipant.cpp).
-
-## 2. One consistent Shabbat/holiday presentation
-
-Default command, menu, inline and group announcement output shows the nearest verified Shabbat-containing period in the main section. The holiday list starts at the current local date, so a separate Yom Tov before Shabbat remains visible with its verified entrance and final exit. Only strict Yom Tov events receive festival entrance/exit times; continuous Shabbat/festival periods retain one final exit. Later Shabbat summaries, scripture-reference rows, visible source/update footers and numeric timezone offsets are omitted. Times use the selected IANA timezone and Y-m-d H:i. The configured candle offset and havdalah policy are shown; a fixed 50-minute sample does not overwrite existing preferences or the default 8.5-degree policy.
-
-Actual Yom Tov boundaries and every required intermediate candle remain subject to verified data and continuous-period rules. Hanukkah is an observance, not a Yom Tov locking interval. Source attribution remains in the relevant information/license documentation, and internal provenance/freshness validation is unchanged. Custom templates remain administrator-owned; the update does not rewrite their saved text.
-
-Calendar day classification accepts both documented fixture forms of the original Chol Hamoed marker, (CH'M) and (CH''M). This keeps reminder policy aligned with the configured Chol Hamoed setting without promoting those dates to Yom Tov or adding lock periods. An active Yom Tov whose verified final exit falls after civil midnight remains visible until that exit, even when its calendar date is yesterday.
-## 3. Statistics callbacks
-
-Home and statistics screens emitted ps:overview / ps:modules, but the production upgradedCallbacks prefix allowlist omitted ps. Existing controller tests bypassed that adapter boundary and therefore did not detect the missing route. The allowlist is corrected. New regressions use native pinned SDK query wrappers and the actual update-handler method with callbacks read from generated markup, including non-manager private users, navigation, denied contexts and cancellation.
-
-Edits target the original private panel. A missing/deleted panel produces a localized callback response without new-message flooding. Group and inline callbacks cannot edit a private user's statistics panel.
-
-## 4. Release and verification
-
-All previous cumulative features remain included. No dependency or schema update is required. The direct /root/shabbat-test upload instructions exclude uploaded ZIP/checksum files from Docker context. Exact tests, fingerprints, archive contents and platform limits belong to dist/VALIDATION-3.0.0-dev.6.json.
-
-No production data, active bot, real Telegram group, commit, tag, push or publication was changed. Docker and Telegram acceptance were not executed locally. The host's older SQLite intentionally fails the release-platform gate; the Docker-pinned reviewed version must pass on the test server before startup. Automated tests establish the covered behavior, not a guarantee of indefinite uptime.
diff --git a/docs/DEV8_PERMISSIONS.md b/docs/DEV8_PERMISSIONS.md
deleted file mode 100644
index 1c64baf..0000000
--- a/docs/DEV8_PERMISSIONS.md
+++ /dev/null
@@ -1,38 +0,0 @@
-> Historical implementation record. Referenced `dist/VALIDATION-*` reports belong to earlier private development deliveries and are not bundled here. Current publication checks and limits are described in [publication status](PUBLICATION_STATUS.md).
-
-# Dev.8 permission reading and existing snapshots
-
-## Evidence and limits
-
-The supplied dev.6 database row was in `conflict`. Its original snapshot allowed all listed actions except editing a member's own tag; its checksum matched. The saved mask therefore explains why restoring it would allow media, invitations and pins even though the administrator reported earlier restrictions. A checksum establishes consistency of saved bytes, not whether the initial Telegram read was accurate. The literal missing-rights fallback cannot by itself produce that row's explicit `edit_rank=true` and `until_date=2147483647`. The exact server-side cause of this older snapshot has not been established.
-
-Independent offline investigation found a real read-integrity defect in the pinned SDK/helper path: `getFullInfo` combines a refreshed full object with earlier peer data, and `getInfo` can return its earlier minimal record after refreshing the peer cache. Re-reading that cache did not establish that permissions came from the just-completed request. An absent optional restriction object in verified complete data can legitimately mean no default restrictions; absence in incomplete or unverified data is not proof of that state.
-
-The separate `manage_topics` discrepancy does not justify ignoring this restriction for non-forum groups. No server normalization rule was established. Actual readback remains subject to comparison and unresolved evidence is retained.
-
-## Implemented protection
-
-MadelineProto remains exactly **8.7.0** at source commit `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`, with the existing Composer lock. A fifth, separately guarded local patch exposes the fresh raw full-peer response through the existing supported `getFullInfo` helper when caching is disabled. It does not call blacklisted namespace methods, change the public helper signature, or run patches while the bot is active. Its immutable source, diff, reviewed output, manifest and tests accompany the corresponding source.
-
-The permission reader validates matching requested peer, full-peer type/ID and complete non-minimal Chat from that response. It rejects malformed, absent, duplicate, forbidden or mismatched records. It does not substitute cached rights. Both manual and scheduled operations use this reader for capture and verification, and restore the original restriction object rather than constructing a general open mask. Cancellation and Telegram retry deadlines still propagate.
-
-Migration 015 records snapshot provenance. Existing unresolved snapshots from older versions remain intact and are treated as unverified; automatic or explicit restoration of those snapshots is blocked. A new week, restart or matching checksum does not make an older snapshot trustworthy. Completed cycles may take a new verified baseline at the next closure. Fresh captures preserve their original bytes, checksum and capture evidence through the cycle.
-
-The group recovery panel explains the legacy state in all six languages. Restore remains available for verified snapshots. A legacy snapshot requires the administrator to set the intended normal rights in Telegram, refresh the panel and explicitly confirm adoption, outside a protected period. The old snapshot remains as evidence. The diagnostics panel/export reports snapshot provenance without dumping JSON into messages.
-
-## Existing affected test group
-
-1. Deploy dev.8 with the same isolated test bot, `.env` and named volumes, after stopping writers and taking the migration backup.
-2. Outside Shabbat/Yom Tov and any active lock, use Telegram's group permissions to set the actual intended normal state. Do not copy the broadly permissive older snapshot.
-3. Open the bot's group settings, **Resolve permission problem**, then **Refresh**. Check the named group and the current permissions, then choose **Use current permissions** and confirm.
-4. Test a new manual close/open cycle in a disposable group with media, invitations and pinning deliberately restricted beforehand. Verify those exact restrictions after reopening and after a restart. Also check the automatic path at a controlled test boundary.
-
-Do not delete lock rows or adopt a currently locked mask as the normal state. An active close override, religious period, unavailable calendar or uncertain read prevents recovery. A readback conflict after an update can mean Telegram already changed permissions; it is not evidence that nothing happened.
-
-## Validation and live acceptance
-
-The versioned `dist/VALIDATION-3.0.0-dev.8.json` identifies the frozen source, full suite, quality gates, migration tests and extracted archive checks. Native SDK tests use the installed pinned trait with controlled RPC responses; they do not contact Telegram. Patch tests include clean apply, repeat, mismatch and partial installation. Database upgrade tests preserve older snapshots and prove that they cannot trigger unverified restoration.
-
-Docker is unavailable on the Windows development host. Its older local SQLite is intentionally rejected by the release platform gate; the pinned Docker runtime must pass that gate on the server. Live Telegram permissions, Telegram client rendering and actual group behavior still need isolated acceptance. No production data, bot sessions or real groups were used for development tests. No commit, tag, pull request or publication is part of this update.
-
-See [recovery](PERMISSION_RECOVERY.md), [deployment](SERVER_TEST_DEPLOYMENT.md), [patches](PATCHES.md) and the official [restriction flags](https://core.telegram.org/constructor/chatBannedRights), [default-rights method](https://core.telegram.org/method/messages.editChatDefaultBannedRights) and [MadelineProto helper requirement](https://docs.madelineproto.xyz/API_docs/methods/channels.getFullChannel.html).
diff --git a/docs/DIAGNOSTICS.md b/docs/DIAGNOSTICS.md
index a6151a2..772e2ad 100644
--- a/docs/DIAGNOSTICS.md
+++ b/docs/DIAGNOSTICS.md
@@ -14,4 +14,4 @@ Dev.7 adds migration 014 for expiring diagnostic snapshots and interaction/expor
Transport uses the locked MadelineProto implementation of [messages.sendMedia](https://docs.madelineproto.xyz/API_docs/methods/messages.sendMedia.html) with an in-memory JSON upload. Offline tests verify native payload construction and actual callback/message routes; they do not claim a real Telegram upload or flood-limit acceptance test.
-Dev.8 adds snapshot-verification status to the selected group's permissions section and JSON export. The indicator checks the original bytes and capture provenance; a legacy snapshot or checksum failure is not displayed as verified. See [the affected-group procedure](DEV8_PERMISSIONS.md).
+Dev.8 adds snapshot-verification status to the selected group's permissions section and JSON export. The indicator checks the original bytes and capture provenance; a legacy snapshot or checksum failure is not displayed as verified. See [the affected-group procedure](PERMISSION_RECOVERY.md).
diff --git a/docs/FEATURE_PARITY.md b/docs/FEATURE_PARITY.md
deleted file mode 100644
index a887d17..0000000
--- a/docs/FEATURE_PARITY.md
+++ /dev/null
@@ -1,219 +0,0 @@
-# Feature parity and source audit
-
-The interface reference is [WizardLoop/JewishPulse](https://github.com/WizardLoop/JewishPulse/tree/d7b06eb1acb206543dcff35a7c14ebce4760b4e5), reviewed on 2026-10-13. Shabbat retains its package name, bot identity, MTProto session, Stars donations, operator tools and BroadcastManager integration. Reference ideas were reimplemented; the unsafe reference location parser, implicit extra candle minute, truncated 8.5 angle and mutable global timezone were not imported.
-
-`UI` below means `src/UI/BotController.php`. Its panel labels use the administrator's personal language; calendar content uses the selected scope's language. Every settings write requires an unexpired user-bound flow and revision, current Telegram administrator permission for a group, and a one-use server-side confirmation. A public inline query never grants group authority.
-
-| Reference source and function | Existing behavior | Implemented equivalent | Scope | Automated evidence |
-|---|---|---|---|---|
-| `src/Handlers/Handlers.php::starthandle` | Private welcome and navigation | `UI::start` / `/start` | Personal | `UITest::testMenusAreBilingualWithStableCallbacksAndNativeColors` |
-| `Handlers.php::BackStart` | Return to welcome | `sb:start` → `UI::start` | Personal | Menu callback inventory in `UITest` |
-| `Handlers.php::SettingsMenu` | Four personal settings | `UI::panel` (personal and group) | Personal / group admin | Personal/group isolation and language tests |
-| `Handlers.php::SettingsLanguage` | Language selector | `UI::screen(language)`, `/language`, `/lang` | Personal / group admin | `testLanguageCommandAndGroupLanguageAreIndependent` |
-| `src/JewishPulse.php::handleSetLanguage` | Save personal language file | `sb:s:token:l:he/en/ru/fr/es/pt-br` + one-use confirmation | Personal / group admin | `testLanguageCommandAndGroupLanguageAreIndependent` |
-| `src/Locales/Lang.php::getUserLang`, `setUserLang` | Personal `lang.txt` | `SettingsRepository::getUser/updateUser`; group language separate | Personal / group | Isolation tests |
-| `Lang.php::loadTranslations` | HE fallback | `src/UI/Lang::text/validate` | Display | `testTranslationKeysPlaceholdersEscapingAndFallback` |
-| `Lang.php::getAvailableLanguages`, `getLanguageButtons` | Files scanned for two choices | Explicit he/en/ru/fr/es/pt-br registry; six real catalogs and stable identifiers | Display | Menu language test |
-| `Handlers.php::SettingsLocation` | `keyboardButtonSwitchInline`, same peer | `UI::locationScreen`, `GeoNames::search` with token | Personal / group admin | `testTwoGroupLocationFlowsSelectedInReverseOrder` |
-| `JewishPulse.php::onUpdateBotInlineQuery` city branch | Search every non-Shabbat string; IDs `geo_0` | Explicit `loc`, UTF-8 normalization, stable query-bound IDs, paging | Public read / authorized selection | `LocationTest`, two-flow UI test |
-| `JewishPulse.php::handleSaveLocationFromMessage` | Parse forgeable localized text and save | Replaced with `location_choice` → private preview → one-use `save` | Personal / group admin | Forged text, wrong user, replay, expiry and admin-loss tests |
-| `Storage/UserLocation.php::getGeonameId/setGeonameId` | Per-user JSON with implicit Jerusalem | SQLite scope settings + complete coordinates and IANA zone | Personal / group | Personal/group isolation, timezone tests |
-| `UserLocation.php::searchGeoNames` | Unencrypted HTTP, errors returned as no results | `src/Location/GeoNames`, verified HTTPS, typed errors, selected-place validation | Provider | All `LocationTest` cases |
-| `Handlers.php::SettingsCandles` | Display 10/15/18/20/22/30/40, save one more | Seven exact values including 40; city custom and validated form | Personal / group admin | `testAllSevenCandleOptionsAreStoredExactly` |
-| `JewishPulse.php::handleSetCandles`; `UserLocation::getCandleSetting/setCandleSetting` | Personal JSON with default 41 | Typed `candle_minutes`; no hidden adjustment | Personal / group | Exact seven-value test |
-| `Handlers.php::SettingsHavdalah` | 8.5°, 42, 72 | Separate method/value; 8.5°, 42, 50, 72 and custom minutes | Personal / group admin | `testDegreesRemainFloatAndFiftyMinutesAreAvailable` |
-| `JewishPulse.php::handleSetHavdalah`; `UserLocation::getHavdalahSetting/setHavdalahSetting` | Float saved, later cast to integer | Float preserved end to end | Personal / group | Exact methods test; `CalendarTest` |
-| `Handlers.php::ShabbatTimes` | Private upcoming times | `UI::renderView(shabbat)` from one common calendar | Personal / group preview | Rendering, calendar tests |
-| `Handlers.php::Shabbat_Times`; `JewishPulse.php::shabatCommand` | `/shabat` and share button | `/shabat`, `/shabbat`; group settings on group display | Personal / group | Calendar/UI tests; real Telegram routing requires staging |
-| `Handlers/ShabatTimes.php::parseShabatData` | `/shabbat` current-week response formatting | `CalendarService::snapshot` explicit coverage/current/next event | Calendar | `CalendarTest` before/during/after, Sunday, adjacent holidays |
-| `ShabatTimes.php::getNextShabbatDates` | Date calculation changes global timezone | UTC instants, explicit per-group IANA zones | Calendar | DST and concurrent-zone tests |
-| `JewishPulse.php::onUpdateBotInlineQuery` times branch | Share personal Shabbat times | Reserved aliases plus zmanim/daf/omer; authorized group share snapshot | Read-only | `testGroupShareUsesAuthorizedSnapshotInsteadOfPersonalLocation` |
-| `Handlers.php::DailyPage`; `ShabatTimes.php::getDailyPage` | Today's Daf from Hebcal; mostly hardcoded Hebrew | `/daf` with explicit today/tomorrow/date and trusted provider link | Personal / group | Fixture calendar checks; no real Telegram test |
-| `Handlers.php::AllCommands` | Help categories | `UI` help menu and actual command list | All users | Help translations/key validation |
-| `Handlers.php::BasicRules` | `/`, `!`, `.` prefixes | `UI::handleMessage` supports these prefixes | All users | Parser exercised by UI tests |
-| `Handlers.php::SettingsInfo` | Explain four personal options | Actual personal/group screens and `GROUP_SETTINGS.md` | All users / group admin | Screens and form tests |
-| `Handlers.php::CommandsAllUsers` | Commands and inline help | Localized implemented help commands | All users | Locale validation |
-| `Handlers.php::CloseMsgCommand` | Delete private menu message | Existing Shabbat close handler retained; back/cancel in new screens | Personal | Live deletion not tested |
-| `Handlers.php::StatsGroups`; `JewishPulse.php::StatsGroups` | Dialog scan/count | Known-group SQLite stats plus retained operator statistics | Public / system admin | Storage tests; live dialogs not tested |
-| `Handlers/AdminPanel.php::handle`, `admin_back` | Operator admin panel | Localized OperatorController + guarded legacy routing | System admin only | UIOperatorTest six-language frames and fresh role checks; no live operation |
-| `AdminPanel.php::statUsers` | Dialog statistics | SQLite group counts + known-peer type statistics | System admin only | Six-language statistics frames tested; live peer metadata not tested |
-| `AdminPanel.php::admin_broadcast`, `broadcast_back`, `handle_broadcast`, `back_broadcast` | Compose text/media broadcast | OperatorDraft rich scoped SQLite editor + retained BroadcastManager sending | System admin only | Atomic draft/digest/token/media/style tests; no live broadcast |
-| `AdminPanel.php::type_users`, `typemode1/2/3/4` | Users/channels/groups/all filters | Scoped users/channels/groups/all audience and pin controls | System admin only | Independent operator options and stable callbacks tested; no live broadcast |
-| `JewishPulse.php::handleAdminButtons`, `send_broadcast`, `handleBroadcastProgress` | Dispatch, broadcast and progress | Fresh-role private callbacks + one-use send + verified status formatter patch | System admin only | UIOperatorTest and library patch regression tests; no live broadcast |
-| `Payments/Payments.php::sendDonationOptions`, `handlePreCheckout`, `sendMessageToAdmins`; `JewishPulse.php::Payments`, `onupdateBotPrecheckoutQuery` | Stars support and payment reporting | Validated Stars intents/payment handlers, localized offers and duplicate-safe private operator notices | Personal / system admin report | DonationsTest offline; no real payment was submitted |
-
-## New capability evidence
-
-| New capability | Implementation | Evidence and practical limit |
-|---|---|---|
-| Group language, location, timezone, Israel/diaspora | UI scopes, SettingsRepository and FlowTokenRepository | All six locales, different groups, reversed selection, personal separation, stale/replayed flow tests |
-| Native colored buttons | MTProto `keyboardButtonStyle` in `UI::keyboard` | Installed `TL_telegram_v225.tl` constructors validated; primary/success/danger tested; rendering depends on Telegram client |
-| Full/short zmanim, today/tomorrow/date | `UI::view/renderView`, `CalendarService::zmanim` | Explicit date and missing values tested; polar calculations refuse guesses |
-| Tefillin times preview | `UI::renderView(tefillin)`, `ReminderPlanner` | Calculated jobs without enabling/sending; cutoff, dedup and holiday fixtures in calendar tests |
-| Omer, all 49 deterministic counts | `CalendarService::omer`, `Content/OmerText`, ReminderPlanner | Bundled 49-count and calendar fixtures; actual prayer recitation remains an individual responsibility |
-| Module enable/edit/reset/pause | Scoped UI forms and one-use confirms | Form validation, exact settings, replay/admin loss tests |
-| Rich group message editing and test send | `Content/TemplateEditor`, `TemplateRepository`, `TemplateRenderer` | Separate explicit test confirmation and five-minute rate limit; no production Telegram send |
-| UTC scheduling, recovery, snapshots, outbox | `Scheduling/`, `Runtime/Application` | Fake-gateway storage/scheduler tests; no claim of absolute exactly-once delivery |
-| Legacy membership carried forward | `LegacyImporter::importGroupListAutomatically` | Additive startup group registration; `/settings` opens a known group's panel without re-adding |
-
-## Six-language and operator verification
-
-The canonical locale registry is he, en, ru, fr, es and pt-br. All six catalogs have the same keys, nonempty translations and placeholder multisets. Telegram command language codes use pt for Brazilian Portuguese while application storage retains pt-br. UI tests exercise all six private menus and group saves without changing coordinates, stable callback IDs after language changes, and group content language independent from the administrator panel language.
-
-OperatorController and OperatorDraft replace active Hebrew-only operator frames while preserving the original guarded operation handlers. Subscribers use known database audiences, including separately imported broadcast peers; an explicitly removed Shabbat group is excluded. The original pure custom-button parser is bound through Application, preserving native colors/icons/copy/alerts. See GROUP_SETTINGS.md for confirmed broadcasts, per-operator state and the separate BroadcastManager delivery backend.
-
-## Source and infrastructure findings
-
-JewishPulse's inspected tree declares AGPL-3.0-only. Its README claims GitHub Actions CI, but no workflow files exist in that commit. Its `.github/ISSUE_TEMPLATE ` directory has a trailing space and cannot be checked out normally on Windows. Its Dockerfile uses an unpinned MadelineProto image and copies the complete checkout; these practices were not imported. Its graphic assets and external thumbnail were not reused because this upgrade needs no new graphic asset and their independent provenance was not established.
-
-The original Shabbat runtime was a single 7,195-line `bot.php`, MIT metadata, `danog/madelineproto:^8.6`, unrestricted BroadcastManager `*`, and no lock or automated tests. New documentation does not assert a live feature test where only source was reviewed. Retained donation/operator/broadcast features require an opt-in staging account; no actual Telegram group, active session or production data was changed.
-
-## Original Shabbat function inventory
-
-Each original function is listed below, including helpers. This is an inventory of source and its replacement/retained responsibility, not a statement that Telegram-side behavior was tested.
-
-| Original source function (`bot.php`) | Equivalent responsibility | Scope | Verification |
-|---|---|---|---|
-| `getTestShabbatLockTimes` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `getAlertTestTime` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `getZmanimForCities` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `getShabbatLockTimes` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `getShabbatCheckLock` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `isShabbatOrHolidayNow` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `getReportPeers` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `onStart` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `ChannelsLeave` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `StartCommand` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `BackCommand` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `ShabbatTimes` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `AllCommands` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `Rules` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `CommandForAdmins` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `CommandForAll` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `shabatCommand` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `onUpdateBotInlineQuery` | UI::start/handleMessage/handleCallback/handleInline/renderView | personal / group read | UITest + CalendarTest |
-| `closecommand` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `addgroupCommand` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `removegroupCommand` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `grupsettingsCommand` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `ifNotCommands` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `backtosettings` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `defaultset` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `defaultset1` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `infotimes` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `infomessages` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `TimesON` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `TimesOFF` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `MessagesON` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `MessagesOFF` | SQLite membership + UI::panel/screen/changes/moduleDefaults | group admin | UITest + StorageTest; live Telegram not run |
-| `parseButtonsold` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `parseButtons` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `buttonCallbacks` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `validateButtonsInput` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `openMessageGroup` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `closeGroupMessage` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `backGroupMessage` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `GroupTextSet1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveText1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveText1_1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `GroupTextView1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `GroupMsgMedia1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `GroupMsgMediaView1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveMedia1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveMedia1_1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `buttonsmanageviewgroup1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `GroupMsgButtonSet1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveButtons1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `RemoveButtons1_1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `HandleGroupMsgSet1` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `view_welcomeMessage_full` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `StatsGroups` | SQLite group/service/lock statistics | read-only | Storage fixture assertions |
-| `shabatCronClose` | Runtime/Application::tick and Scheduling lock/outbox state | runtime | CalendarTest + SchedulingTest |
-| `shabatCronOpen` | Runtime/Application::tick and Scheduling lock/outbox state | runtime | CalendarTest + SchedulingTest |
-| `shabatCronAlert` | Runtime/Application::tick and Scheduling lock/outbox state | runtime | CalendarTest + SchedulingTest |
-| `Payments` | Retained Stars donation and payment update handlers | personal / system admin | Source reviewed; real payment not run |
-| `onupdateBotPrecheckoutQuery` | Retained Stars donation and payment update handlers | personal / system admin | Source reviewed; real payment not run |
-| `onUpdateNewMessage` | Retained Stars donation and payment update handlers | personal / system admin | Source reviewed; real payment not run |
-| `closeGroupManually` | Authorized manual permission reconciliation with durable snapshots | system admin | Fake-gateway permission tests; live not run |
-| `openGroupManually` | Authorized manual permission reconciliation with durable snapshots | system admin | Fake-gateway permission tests; live not run |
-| `testzmanim` | CalendarService + Runtime/Application diagnostics | calendar / operator | CalendarTest; live diagnostics not run |
-| `setcommands` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `getAdminKeyboard` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `admincommand` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `addsohe1hazor` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `addsohe1hazor2` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `getPlugins` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `getPluginPaths` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `reshimamishtamshim` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `reshimamishtamshim2` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `reshimamishtamshim3` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `var_cat_command` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `adnimhandle` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `StatsUsers` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `closeBroadcastMsg` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadcastCommand` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `deleteLastBroadcast` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `deleteAllBroadcast` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `cancelPinned` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `LastBrodDATA` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `setBroadcast` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `handlebroadcast1` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `hazarashidur` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `addsoheshidur1forneitza1` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `addsoheshidur1forneitza2` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadsetsenders` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadsetsenders1` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadsetsenders2` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadsetsenders3` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `broadsetsenders4` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `hosafkaf` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `handlebuttons` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `parseButtons` | Content/TemplateEditor + TemplateRepository + TemplateRenderer | group admin | Fake Telegram template tests; live not run |
-| `buttonsmanageview` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `loadButtons` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `buttonsmanageview2` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `loadButtons` | Retained bot/operator integration | system admin / runtime | Live Telegram not run |
-| `comingsoon` | Legacy placeholder omitted from new navigation | none | No new inactive menu button |
-| `RunBot` | Runtime/Runner + configured error event handler and graceful stop | runtime | Runner/patch tests; no live bot startup |
-
-## Additional automated integration evidence
-
-`UITemplateTest` verifies private-only previews; a distinct named-group TEST confirmation; five-minute test-send rate limiting; user and administrator rechecks; replay and forwarded callback rejection; UTF-16 formatting entity clipping including emoji; media and buttons preservation; removal of one message component without resetting the rest; independent English/Hebrew editor menus; and rollback of both token consumption and settings revision on template CAS/SQLite write failure. Its gateway deliberately rejects permission RPCs and live HTTP.
-
-`UITest` additionally verifies reply-bound GPS selection for two groups completed in reverse order, wrong-user/unreplied/non-bot prompt rejection, private-panel language versus group-content language, full/short daily views, clearly missing solar values and tefillin jobs calculated in a private preview while the module stays disabled. These fixtures do not establish live Telegram behavior.
-## dev.4 cumulative interface and administration additions
-
-These are functional adaptations of the named local reference projects, with the current bot's authorization and storage boundaries. Visual identity is Shabbat; this table does not claim byte-identical output or live-client acceptance.
-
-| Request/reference | Current implementation | Automated evidence |
-| --- | --- | --- |
-| Exact opening, categorized help, original edit-based navigation | BotController, Lang, Presentation, CallbackUiGateway | PresentationTest, UiNavigationTest, AdminCrossFlowNavigationTest |
-| Twelve supplied custom emoji IDs and native colored buttons, owner-eligibility fallback | Presentation and MadelineGateway including BroadcastManager transport | CustomEmojiSerializationTest, CustomEmojiFallbackTest, PresentationTest, TefillinAckGatewayTest |
-| Simple group settings including all tefillin fields | SettingsWizard and BotController guided picker/input/confirmation | SettingsWizardTest, GuidedSettingsTest |
-| Upcoming complete holy sequences and holiday metadata | ShabbatTimesFormatter plus UI period navigation | ShabbatOverviewTest and existing calendar/formatter tests |
-| Custom Stars amount 1-10000 and old payment preservation | Donations, DonationController, migration 011 | DonationCustomAmountTest, CustomStarsMigrationTest, DonationsTest |
-| Delegated managers and immutable configured recovery owners (newsearch-v2 style) | AdminAccessRepository, AdminController, OperatorController | AdminRolesLinksTest and native bridge navigation tests |
-| Full known subscriber profile, user/group/channel/all filters, search/paging (psy-new style) | SubscriberDirectory, SubscriberController, AdminDirectoryText | SubscriberDirectoryTest, AdminCrossFlowNavigationTest |
-| Expanded rich broadcast drafts, audiences, pin, edit-last, timing, self-destruct and confirmations | BroadcastController, OperatorDraft, AdminIntegration, BroadcastJobs | BroadcastAdvancedTest, BroadcastJobsTest, UIOperatorTest, BroadcastPatchTest |
-| System deep links and tracking-link counters | SystemLinks, TrackingLinkRepository, AdminController | AdminRolesLinksTest |
-| Six-language role-scoped command menus | CommandMenus and current per-target capability filter | CommandMenusTest |
-| Native rich custom messages and independent button modes | TemplateEditor, TemplateRepository, TemplateRenderer, Application | GuidedTemplateTest, UITemplateTest, GroupMessageButtonsIntegrationTest |
-| Default delivered-group share actions | GroupMessageButtons: original shabat/zmanim/daf inline shortcuts | GroupMessageButtonsIntegrationTest; public results use the sharer's preferences |
-| Default blue tefillin count and unique reversible user votes | TefillinAcknowledgements, group callback/cron hooks and migration 012 | TefillinAcknowledgementsTest, TefillinAckGatewayTest, GroupMessageButtonsIntegrationTest |
-| Legacy full keyboard wrapper compatibility | Recognized read-time normalization in TemplateRepository, LegacyImporter and OperatorDraft | LegacyAdminImportTest, BroadcastAdvancedTest, TefillinAcknowledgementsTest |
-
-Private group-view sharing remains a distinct authorized read-only group snapshot. Default public announcement sharing keeps the original personal inline-query semantics. Preview acknowledgement buttons are inert; only verified delivered reminders create countable message bindings.
-
-All rows have offline implementation tests; real Telegram administration, appearance, payments, sending and Docker execution remain separate isolated acceptance work. Current aggregate results are in the version-matching validation report.
-
-## dev.5 test feedback
-
-The [eleven-item report](DEV5_TEST_FEEDBACK.md) maps the latest corrections to code behavior and tests. It supersedes dev.4's period-pagination description: the Shabbat/holiday screen is now a single overview. Group command scopes contain only settings. The fully preserved native rights snapshot has22flags, while Telegram-compatible group-wide selection has21 and excludes view_messages. Detailed manual-operation diagnosis, restart/IPC lifecycle, contextual settings return, grouped statistics and guided broadcast editing are implemented without changing migrations, locked dependencies or patch files.
-
-## dev.6 follow-up corrections
-
-The current [feedback report](DEV6_TEST_FEEDBACK.md) records conservative native-permission equivalence, recovery of compatible saved conflicts, actual SDK callback routing for public statistics, and a consistent nearest-period Shabbat message for public/inline/scheduled defaults. The previous next-three-Shabbat display is superseded by one nearest Shabbat-containing period plus a current/upcoming holiday list; separate weekday Yom Tov before Shabbat retains its verified entrance and final exit. Existing calendar policy, rich custom templates, library patches and all twelve migrations remain intact. New boundary tests exercise the actual handler, not only controller helpers.
-
-## Dev.7 recovery and diagnostics
-
-The [permission recovery flow](PERMISSION_RECOVERY.md) adds conservative automatic recovery and the two explicitly requested administrator choices without discarding original snapshots. The private [testzmanim panel](DIAGNOSTICS.md) replaces JSON message flooding with editable navigation, search, filters, quick page entry and JSON-file export. Both features include all six languages and additive migrations 013-014. Prior calendar, group settings, statistics, custom messages and pinned-library behavior remain covered by the complete regression suite.
diff --git a/docs/FUNCTIONAL_COMPARISON.md b/docs/FUNCTIONAL_COMPARISON.md
deleted file mode 100644
index 9ee5f22..0000000
--- a/docs/FUNCTIONAL_COMPARISON.md
+++ /dev/null
@@ -1,50 +0,0 @@
-# השוואה פונקציונלית ובקרות הקבוצה — 3.0.0-dev
-
-המימוש החדש משפר את התאוששות הסגירה והפתיחה ואת הטיפול ברצפי שבת וחג. הוא נבדק עם שעון מוזרק, נתוני ספק מבוקרים וגבולות ה־SDK הנעול. עדיין אין אישור לנכונות תפעולית מול Telegram אמיתי, ואין התחייבות לפעולה בשנייה המדויקת.
-
-| תחום | ההתנהגות הישנה | המימוש הנוכחי |
-|---|---|---|
-| סגירה ופתיחה | חלון פעולה קצר וסימוני הצלחה משותפים | מצב רצוי לכל קבוצה, צילום הרשאות לפני בקשה ואימות התוצאה; התאוששות גם אחרי הפעלה מאוחרת |
-| שבת וחג רצופים | תלות בצימוד האירועים מהתשובה ובמצב הלולאה | רצף קדושה מאוחד; הקבוצה נשארת סגורה עד סוף הרצף המופעל; זמני הדלקה ביניים מוצגים בנפרד |
-| שיקום הרשאות | נתוני קבצים והרשאות קיימות | שחזור מדויק מהצילום המקורי; שינוי ידני או צילום חסר עוצרים שחזור אוטומטי |
-| דגלי חסימה | רשימת דגלים קבועה | כל 22 הדגלים של chatBannedRights בשכבה הנעולה ניתנים לבחירה; ברירת המחדל כוללת 21, ובכללם send_reactions ו־edit_rank; view_messages נשמר כפי שהיה |
-| שינוי דגלים בזמן סגירה | ללא פאנל מלא | החלפה מהצילום המקורי, שמירה של המסכה הקודמת בזמן בקשה ושחזור גם אחרי כשל; אין הודעת סגירה חדשה רק עקב החלפת מסכה |
-| מחיקת הודעות בתקופת קדושה | ללא הבקרות החדשות | מתגים נפרדים לחברים ולבוטים אחרים, כבויים כברירת מחדל; תור מחיקה נפרד עם ניכוי כפילויות וניסיון חוזר מוגבל |
-| תפילין | היכולות הקודמות נשמרות במודול המורחב | תבנית עשירה, מדיה, כפתורים וצבעים; מחיקת הקודמת רק לאחר משלוח חדש מאומת, עם מזהים שנשמרים בין הפעלות |
-| הודעת הזמנים | פלואו מרובה אזורים ושעה ישנה | מיקום ואזור הזמן של הקבוצה בלבד; 10:00,11:00,12:00,12:30,13:00,13:30,14:00 או שעה מותאמת |
-| תוכן הודעת הזמנים | תוכן מוגבל לפי הפלואו | תאריכים אזרחיים ועבריים, כניסה ויציאה, סגירה ופתיחה, חג/שבת רצופים וזמני ביניים, פרשה ומברכים ונתוני JSON משמעותיים כשסופקו |
-| שפות | הממשק המקורי | עברית, אנגלית, רוסית, צרפתית, ספרדית ופורטוגזית ברזילאית; שפת קבוצה נפרדת מהעדפות המשתמש |
-| תאריך מעוצב בהודעה | התמיכה חסרה במעטפת ההודעות של MadelineProto הנבחרת | מעטפת טיפוסית ושימור ישות התאריך בקבלה ובשליחה; אין שינוי בחישוב זמני שבת וחג |
-
-## משמעות שתי ההרשאות
-
-בדגלי chatBannedRights הערך true פירושו חסימה. send_reactions מונע מחבר לשלוח תגובת אימוג׳י להודעה. edit_rank מונע מחבר לערוך את התג האישי שלו בקבוצה. הסרת דגל מרשימת החסימה שומרת את ערכו בצילום המקורי; היא אינה מעניקה אוטומטית הרשאה שנחסמה מלכתחילה.
-
-הרשאות מנהלים הן מנגנון Telegram נפרד. manage_ranks מאפשר שינוי תגים של אחרים; חסימת edit_rank לחברים אינה מסירה הרשאת מנהל זו. גם תגובות או הודעות של מנהלים אינן מובטחות להיחסם באמצעות הרשאות ברירת המחדל של החברים. אבחון הבוט מציג את כל 17 דגלי chatAdminRights, בלי קידום, הורדה או שינוי תפקידים אוטומטי. בחירה של כל הדגלים אינה מבטיחה שכל סוג קבוצה יקבל כל שילוב: אישור Telegram ואימות הקריאה החוזרת נשארים תנאי להצלחה.
-
-מקור ההגדרות: [הרשאות חסימה](https://core.telegram.org/constructor/chatBannedRights), [הרשאות מנהל](https://core.telegram.org/constructor/chatAdminRights).
-
-## מדיניות מחיקה בפועל
-
-המחיקה מטפלת בעדכונים רגילים שהבוט קיבל בקבוצות רשומות ופעילות, אחרי כניסת הקדושה ובתוך אותו רצף פעיל. סגירה מוקדמת לפני כניסת הקדושה אינה מפעילה מחיקה של הודעות מוקדמות. נבדקים מתג הסוג, תאריך השליחה המקורי, מצב קבוצה סגור בקריאה טרייה והרשאת delete_messages. פתיחה ידנית, מצב כבוי, כיבוי המתג או שינוי הגדרות, יציאה מהרצף, פקיעת בעלות או shutdown מונעים בקשת מחיקה חדשה.
-
-הודעות עצמיות של הבוט, הודעות שירות, הודעות ערוכות שמקורן לפני הכניסה, שולחים אנונימיים או בלתי מזוהים ותאריכים בלתי תקינים אינם נחשבים מועמדים. אין סריקת היסטוריה. הרשאה חסרה, הגבלת קצב או כשל תחבורה נשמרים בתור נפרד, עם השהיה ומספר ניסיונות מוגבל. ייתכן שהודעה לא תימחק אם אין הרשאה, אין עדכון, או שהתקופה הסתיימה לפני הניסיון הבא.
-
-למחיקת הודעות כלליות של בוטים אחרים נדרשת מסירת העדכונים מ־Telegram: מצב Bot-to-Bot Communication בבוט המקבל, הרשאת מנהל וכיבוי Group Privacy ב־BotFather. הפעלת המתג בפאנל אינה משנה את BotFather. ראו [התיעוד הרשמי](https://core.telegram.org/api/bots/bot-to-bot).
-
-בתפילין נשמרת ההודעה האחרונה שנשלחה בהצלחה. לאחר הודעה חדשה נשמרים מזהיה ורק המזהים הקודמים נכנסים למחיקה. כשל במחיקה או בשמירת נתוני הניקוי אינו מחזיר הודעה מאומתת לתור השליחה; נתוני ניקוי חסרים משוחזרים מהתגובה המתועדת. תגובה ללא מזהים מאומתים משאירה את ההודעה הקודמת ולא מנחשת מה למחוק. כיבוי המודול או אפשרות הניקוי מבטל ניקוי ממתין. ההודעה החדשה מוגנת ממחיקה.
-
-## נעילת MadelineProto ותאריך מעוצב
-
-MadelineProto נעולה ל־8.7.0 גם בדרישה המדויקת וגם בקובץ נעילת התלויות. התקנה משתמשת בגרסאות הנעולות; שינוי יזום של הגרסה מחייב סקירת מקור, חתימות ובדיקות תיקונים מחדש. אצל הספק זו גרסת קדם־שחרור, והמיזם נשאר גרסת פיתוח. הנעילה אינה התחייבות לתאימות לשינוי עתידי לא ידוע ב־Telegram או ב־PHP.
-
-תיקון התאריך מוסיף את המחלקה שחסרה במעטפת ההודעות, למרות שהישות כבר קיימת בסכמת Telegram הנעולה. המקור הלא מתוקן זרק AssertionError לפני הפעלת מטפל ההודעות. התיקון משמר את חותמת הזמן, מיקומי UTF-16 ודגלי העיצוב ומאמת יחד את המחלקה ואת מפעל הישויות. זהו תיקון חדש שנבדק מול המקור המדויק; המקורות המקומיים שנמצאו תועדו ולא הופצו עם טענת רישוי שלא אומתה. תצוגת HTML יכולה להציג את הטקסט בלי תג תאריך דינמי; תצוגה בלקוח Telegram אמיתי טרם נבדקה. ראו [דוח בדיקת התאריך והרישוי](MADELINE_FORMATTED_DATE.md).
-## מגבלות הבדיקה והפריסה
-
-המתזמן פועל במחזור של כ־60 שניות, ועבודה מרוחקת עשויה להוסיף השהיה. כשל בספק הזמנים עשוי לעכב פתיחה; הקוד שומר את חוב השחזור. מרווח מצומצם עדיין קיים בין שינוי הרשאות מאומת לבין שמירת הודעת המעבר. הבדיקות אינן טוענות שכל מקרה לוח בכל שנה נבדק מול ספק חי.
-
-כל שמונת קובצי המיגרציה והחתימות נבדקים לפני התחלת הבוט. 008 מוסיפה בקרות מחיקה, נתוני ניקוי ותבנית עצמאית להודעת הזמנים, ושומרת תוכן משותף קיים בעותק נפרד. שבע המיגרציות הקודמות לא שונו.
-
-השרת הנקי חייב לעבור את בדיקת דרישות PHP וה־SQLite הטעון. SQLite 3.45.2 במחשב הפיתוח אינו עובר את שער השחרור; Docker עם SQLite 3.51.3 הוכן אך טרם הורץ. פרטי בדיקות וארכיונים נמצאים ב[דוח המימוש](IMPLEMENTATION_STATUS.md), ושלבי בדיקה בשרת נמצאים ב[מדריך הפריסה לבדיקה](SERVER_TEST_DEPLOYMENT.md).
-
-לא שונו production או קונטיינר פעיל; לא נשלחו או נמחקו הודעות אמיתיות; לא נוצרו commit או tag במשימה ולא פורסמו שינויים.
diff --git a/docs/GROUP_SETTINGS.md b/docs/GROUP_SETTINGS.md
index cb374c5..3eddf79 100644
--- a/docs/GROUP_SETTINGS.md
+++ b/docs/GROUP_SETTINGS.md
@@ -40,6 +40,8 @@ Daily times and Daf expose today, tomorrow, selected date and sharing. Share fro
## Permissions, stale actions and recovery
+The current Telegram layer supports the `manage_linked_peers` restriction to the selectable mask. It is opt-in through its individual control or an explicit **All** selection; the existing 21-field default and saved masks are unchanged. Administrator-rights diagnostics recognize all 19 current fields, including `manage_linked_peers` and `manage_welcome_messages`, without granting those rights.
+
The bot rechecks current administrator permission for every sensitive callback and final save. Flow tokens carry settings revision; an older panel, expired token, other user, replay or forwarded button cannot change settings. Concurrent editors do not overwrite a newer revision. State is scoped to user/group/action; no shared mutable `groupid` is used for new settings.
Permission snapshots are saved durably before restriction, preserved while bot-owned restriction remains active, and restored exactly. A missing/corrupt snapshot or conflicting manual permission edit is a visible issue. Routine notification replanning never deletes an unresolved permission-restoration job. The scheduler reconciles desired state on restart, including an opening missed by more than the former six-minute window.
@@ -70,7 +72,7 @@ Next action: [calculated local datetime]
🛠 Status and issues
```
-This is a simulation, not a production chat capture. Automated fixture evidence is linked from [FEATURE_PARITY.md](FEATURE_PARITY.md). Telegram administration checks, inline client behavior, permission RPCs, topics, actual payments and broadcasts still require opt-in staging validation.
+This is a simulation, not a production chat capture. Automated fixture evidence is linked from [implementation status](IMPLEMENTATION_STATUS.md). Telegram administration checks, inline client behavior, permission RPCs, topics, actual payments and broadcasts still require opt-in staging validation.
## Original button input compatibility
Open **Messages and design**, choose the message, then **Buttons**. The simple link-button path asks for a label and URL separately. Advanced input includes concrete examples for the existing plaintext parser and JSON rows. Type the body directly into the active private question. Candidate content is previewed before explicit save, and cancellation preserves the stored design.
@@ -93,7 +95,7 @@ Offline evidence is in `UIOperatorTest`: all six frames and stable callbacks, se
## Group restrictions and message cleanup
-The **Group restrictions and cleanup** screen is group-only. A checked restriction means that action is blocked while the bot owns an active closure. The 21 global restriction fields from the locked Telegram layer are selectable. The full 22-field native snapshot is retained for validation and restoration. Telegram explicitly forbids `view_messages` in global default permissions ([official rights documentation](https://core.telegram.org/api/rights)); it is therefore excluded from selection and rejected before any RPC:
+The **Group restrictions and cleanup** screen is group-only. A checked restriction means that action is blocked while the bot owns an active closure. The 22 global restriction fields from the locked Telegram layer are selectable. The full 23-field native snapshot is retained for validation and restoration. Telegram explicitly forbids `view_messages` in global default permissions ([official rights documentation](https://core.telegram.org/api/rights)); it is therefore excluded from selection and rejected before any RPC:
| Native field | Member action |
|---|---|
@@ -118,12 +120,13 @@ The **Group restrictions and cleanup** screen is group-only. A checked restricti
| send_plain | Send plain text |
| edit_rank | Edit the member's own custom tag (rank) |
| send_reactions | Send reactions |
+| manage_linked_peers | Manage linked chats; opt-in restriction |
-Default selection blocks all 21 actions except viewing messages. **All**, **None** and **Default** create previews requiring final one-use confirmation. All and Default both exclude the unsupported `view_messages` flag. An older stored mask containing that flag must be reset using Default, All or None before it can be applied; it is never silently discarded. A selection never clears an existing manual restriction or replaces the original restoration snapshot. Changes and resets are isolated to the current group. The Shabbat module reset restores the default mask and switches both holy-period cleanup options off.
+**Default** retains the original 21-action mask. The additional `manage_linked_peers` restriction is selected individually or through **All**, which selects all 22 supported actions. **All**, **None** and **Default** create previews requiring final one-use confirmation. All and Default both exclude the unsupported `view_messages` flag. An older stored mask containing that flag must be reset using Default, All or None before it can be applied; it is never silently discarded. A selection never clears an existing manual restriction or replaces the original restoration snapshot. Changes and resets are isolated to the current group. The Shabbat module reset restores the default mask and switches both holy-period cleanup options off.
Default permission readback is compared by meaning within narrow, verified rules: `until_date=0` and `2147483647` both mean permanent restrictions; arbitrary finite expiries stay distinct. Legacy `send_media` and `send_messages` aggregate bits are redundant only when every corresponding granular send restriction is explicitly blocked on both sides. An individual flag change, including `send_reactions` or `edit_rank`, is still a conflict. Selecting an aggregate for a new lock explicitly includes its granular restrictions. Original native snapshots and their checksums are never rewritten by this comparison.
-These rules follow the [official TDLib permanent-default-rights reader](https://github.com/tdlib/td/blob/ad2178896533ff92831accdf56ea7edd8393f2ca/td/telegram/DialogParticipant.cpp#L220-L228) and [granular-rights serializer](https://github.com/tdlib/td/blob/ad2178896533ff92831accdf56ea7edd8393f2ca/td/telegram/DialogParticipant.cpp#L306-L314). The pinned MadelineProto 8.7.0 adapter refreshes full peer information with a zero cache lifetime and reads the updated peer again after the response. Both basic-group and supergroup refresh paths have offline tests using the actual pinned SDK method.
+These rules follow the [official TDLib permanent-default-rights reader](https://github.com/tdlib/td/blob/ad2178896533ff92831accdf56ea7edd8393f2ca/td/telegram/DialogParticipant.cpp#L220-L228) and [granular-rights serializer](https://github.com/tdlib/td/blob/ad2178896533ff92831accdf56ea7edd8393f2ca/td/telegram/DialogParticipant.cpp#L306-L314). The version-matched MadelineProto adapter validates permissions from the exact matching full-peer response returned by the reviewed Fresh Peer helper. Cached, minimal, mismatched or incomplete data cannot authorize capture or readback. Both basic-group and supergroup paths need regression coverage against the installed locked SDK.
After upgrading from dev.5, a retained prepared/error/conflict/restoring state can recover on the next manual operation or scheduled reconciliation only if fresh current rights match the original snapshot or a known bot-owned mask under those narrow rules. No database reset or new snapshot is needed for that case. Missing/corrupt snapshots, unmatched finite expiries, unknown restrictions and meaningful administrator changes remain protected. A genuine mismatch stops automatic changes and shows a bounded list of differing permission names; it does not establish who changed them. Normalization does not authorize the bot to overwrite that mismatch. A legacy aggregate-only snapshot without explicit granular rights stays strict because its equivalence cannot be proved.
@@ -175,3 +178,7 @@ The main group panel and Shabbat/permission categories include **Resolve permiss
Automatic recovery preserves only verified known results, proven never-dispatched first attempts and additional restrictions on known fields untouched by the bot. Original snapshot bytes remain available. Ambiguous bot-controlled, relaxed, unknown or expiry differences retain administrator review; a new week alone cannot reset them.
Current default Shabbat/holiday output uses local `Y-m-d H:i` without a numeric UTC suffix or source/update footer, as described in [calendar presentation](CALENDAR_PRESENTATION.md). This supersedes older presentation notes above; internal timezone/freshness metadata remains available in diagnostics.
+
+## Keyboard format compatibility
+
+Saved Bot API and earlier native keyboards are normalized by the central current-layer compatibility boundary. Inline and reply keyboards stay distinct; old stored templates are not rewritten solely for this upgrade. See [keyboard compatibility](KEYBOARD_COMPATIBILITY.md) for supported actions, styles, icon fallback and verification limits.
diff --git a/docs/IMPLEMENTATION_STATUS.md b/docs/IMPLEMENTATION_STATUS.md
index 58f8935..76183a0 100644
--- a/docs/IMPLEMENTATION_STATUS.md
+++ b/docs/IMPLEMENTATION_STATUS.md
@@ -1,6 +1,8 @@
# Implementation and acceptance status
-Version: **3.0.0**, stable. This document distinguishes implemented behavior from the evidence actually available. The application remains MadelineProto 8.7.0, PHP and SQLite. The stable release retains the dev.9 runtime behavior, approved patches, dependency lock and 16 migrations. It updates release identity, source packaging and deployment documentation.
+**Release policy: publication requires successful mandatory checks on the exact final commit. Use the matching GitHub Actions run and release manifest to verify the tested source and artifacts.**
+
+Version: **3.1.0**, targeting the locked official MadelineProto 8.11.10 / TL layer 232 release. Existing PHP/SQLite bot capabilities and migration bytes are retained. This page distinguishes implemented behavior, previous acceptance and checks still required on the final new tree.
## Implemented paths and limits
@@ -26,20 +28,22 @@ Version: **3.0.0**, stable. This document distinguishes implemented behavior fro
On 2026-10-16 the project owner reported successful live dev.9 tests of group locking, unlocking, restoration of the original permissions and restart. This is operator-reported evidence for those paths. It does not establish a real Shabbat/Yom Tov transition, a full holiday sequence, sustained load capacity, a long wall-clock soak, every client/language, payment flow or the legacy production migration.
-The stable version does not add a runtime feature or schema migration to dev.9. Keep the above acceptance tied to its actual tested behavior; the stable release's exact source, package checks and CI results are recorded separately.
+That confirmation belongs to the earlier implementation. It is not live acceptance of MadelineProto 8.11.10, the new keyboard boundary or the 3.1.0 import procedure. No new 3.1.0 Telegram acceptance is claimed.
## Automated verification and host limits
-The suites exercise fake transports, provider fixtures, controlled clocks, isolated databases, migration/restore, patch lifecycle and simulated load. Run them against the final reviewed stable commit and its locked installation. The dev.9 merged baseline passed its hosted checks, but that result is not a replacement for the stable commit's own checks. Release manifests, SHA-256 sums and the matching Actions run identify the tested source/artifacts. Local checks directories are external evidence, not runtime source.
+Shutdown coverage exercises official SDK loop recovery/stop behavior and real disconnect/finalize methods with an in-memory transport and modeled delayed flush. The lock barrier must retain writer ownership until finalization completes. Loop `stop()` prevents rescheduling after the current body returns; it does not promise immediate cancellation of that body. These fixtures do not serialize a real session or exercise Telegram, an IPC daemon or Linux signals. Platform-specific worker checks must be evaluated on the relevant operating system.
+
+The suites exercise fake transports, provider fixtures, controlled clocks, isolated databases, migration/restore, patch lifecycle and simulated load. Run them against the final reviewed 3.1.0 commit and locked installation. Earlier 3.0.0 hosted results do not replace this version's mandatory clean-install, regression, analysis, image and artifact checks. Publication requires those gates to pass on the exact final commit. Release manifests, SHA-256 sums and the matching GitHub Actions run identify the tested source/artifacts. Local checks directories are external evidence, not runtime source.
-Local Windows limitations include unavailable Docker and POSIX-only/symlink-dependent coverage. The local PHP-loaded SQLite 3.45.2 is deliberately rejected by the release gate; the Docker target pins SQLite 3.51.3 and must pass that gate. Do not describe an unexecuted image build, CI run or Telegram operation as successful. See [publication status](PUBLICATION_STATUS.md) for source scope and [release preparation](RELEASE.md) for gates.
+Local Windows limitations include unavailable Docker and POSIX-only/symlink-dependent coverage. The recorded local PHP 8.5.0 and PHP-loaded SQLite 3.45.2 are below the current deployment baseline; their test results remain compatibility evidence. The [22 October 2026 baseline](INSTALLATION.md#php-security-baseline) requires PHP 8.3.36+, 8.4.27+ or 8.5.12+ within those branches. Docker targets PHP 8.4.27 and SQLite 3.51.3 and must pass the release gate. Do not describe an unexecuted image build, CI run or Telegram operation as successful. See [publication status](PUBLICATION_STATUS.md) for source scope and [release preparation](RELEASE.md) for gates.
## Remaining deployment acceptance
On a separate bot and disposable groups, verify the feature paths your installation uses: conflicts/recovery, automatic protected-period transitions, interrupted work/shutdown, inline/GPS/client rendering, source offer, command menus, rich messages and payment flow where enabled. Exercise forum and non-forum groups if used. Observe a real scheduled close/open cycle and monitor queue/heartbeat behavior under your traffic; synthetic load is not a Telegram capacity guarantee.
-The `/root/shabat` legacy import still needs a stopped full backup, exact group-ID/settings comparison, permission review, restore rehearsal and monitored cutover. Test-bot data is never substituted for production data. Follow [the production upgrade guide](PRODUCTION_UPGRADE.md). Publishing the source/tag/release does not perform these server actions or restart the active bot.
+The actual production path must first be verified: /root/shabbat is requested, while older instructions named /root/shabat. Legacy import needs a stopped full backup, exact group-ID/settings comparison, permission review, restore rehearsal and monitored cutover. Test-bot data is never substituted for production data. Follow [the production upgrade guide](PRODUCTION_UPGRADE.md). Publishing the source/tag/release does not perform these server actions or restart the active bot.
## Documentation map
-[English README](../README.md) · [עברית](../readme-he.md) · [Installation](INSTALLATION.md) · [Configuration](CONFIGURATION.md) · [Group settings](GROUP_SETTINGS.md) · [Calendar methods](ZMANIM_METHODS.md) · [User experience](USER_EXPERIENCE.md) · [Administration](ADMIN_PANEL.md) · [Migration](MIGRATION.md) · [Backup/restore](BACKUP_RESTORE.md) · [Delivery safety](DEV9_DELIVERY_SAFETY.md) · [Permission recovery](PERMISSION_RECOVERY.md) · [Diagnostics](DIAGNOSTICS.md) · [Licensing](LICENSING.md) · [Release preparation](RELEASE.md)
+[English README](../README.md) · [עברית](../readme-he.md) · [Installation](INSTALLATION.md) · [Configuration](CONFIGURATION.md) · [Group settings](GROUP_SETTINGS.md) · [Calendar methods](ZMANIM_METHODS.md) · [User experience](USER_EXPERIENCE.md) · [Administration](ADMIN_PANEL.md) · [Migration](MIGRATION.md) · [Backup/restore](BACKUP_RESTORE.md) · [Delivery safety](DELIVERY_SAFETY.md) · [Permission recovery](PERMISSION_RECOVERY.md) · [Diagnostics](DIAGNOSTICS.md) · [Licensing](LICENSING.md) · [Release preparation](RELEASE.md)
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
index f030119..583e696 100644
--- a/docs/INSTALLATION.md
+++ b/docs/INSTALLATION.md
@@ -2,15 +2,22 @@
[English overview](../README.md) | [עברית](../readme-he.md) | [Configuration](CONFIGURATION.md) | [Migration](MIGRATION.md)
-This documents stable `3.0.0`. Install the matching release deployment ZIP or exact tagged checkout. The owner confirmed dev.9 live locking, unlocking, original-permission restoration and restart; acceptance on your host and remaining feature-specific tests are separate. See [publication status](PUBLICATION_STATUS.md).
+This documents version 3.1.0; check [acceptance status](IMPLEMENTATION_STATUS.md) before deployment. Install the matching release deployment ZIP or exact tagged checkout. The owner confirmed dev.9 live locking, unlocking, original-permission restoration and restart; acceptance on your host and remaining feature-specific tests are separate. See [publication status](PUBLICATION_STATUS.md).
## Requirements and command context
Run the following commands in the unpacked project root on Linux. Docker commands require access to the Docker daemon and Compose v2; that access is privileged. PHP maintenance commands run as the image's non-root user. The only Compose service is `shabbat`; there is no `composer` service.
-The Dockerfile pins PHP 8.4.19 and Composer 2.10.3 images by digest and builds checksum-verified SQLite 3.51.3. It installs dependencies from `composer.lock`, applies and verifies the five local patch sets before startup, and runs without root as UID/GID 10001. Image building uses network access but no bot credentials. CI uses the same Composer version, including the upstream [GitHub Actions token-validation and disclosure fix](https://github.com/composer/composer/security/advisories/GHSA-f9f8-rm49-7jv2); authentication and all validation gates remain enabled. Runtime requires a separate configured bot, Telegram access and calendar provider access.
+The Dockerfile pins PHP 8.4.27 and Composer 2.10.3 images by digest and builds checksum-verified SQLite 3.51.3. It installs dependencies from `composer.lock`, applies and verifies the two active local patch sets before startup, and runs without root as UID/GID 10001. Image building uses network access but no bot credentials. CI uses the same Composer version, including the upstream [GitHub Actions token-validation and disclosure fix](https://github.com/composer/composer/security/advisories/GHSA-f9f8-rm49-7jv2); authentication and all validation gates remain enabled. Runtime requires a separate configured bot, Telegram access and calendar provider access.
-Manual installation requires 64-bit PHP 8.3, 8.4 or 8.5, Composer 2, the extensions required by `composer check-platform-reqs`, and a patched PHP-loaded SQLite version accepted by `php bin/self-check.php --release`. That gate accepts SQLite >=3.51.3 or the explicitly reviewed 3.44.6/3.50.7 backports. A newer standalone `sqlite3` executable does not change the library loaded by PHP PDO. The image is the documented deployment baseline; native process supervision is operator-managed.
+Manual installation requires 64-bit PHP **8.3.36+, 8.4.27+ or 8.5.12+** within the 8.3/8.4/8.5 branches, Composer 2.10.3, the extensions required by `composer check-platform-reqs`, and a patched PHP-loaded SQLite version accepted by `php bin/self-check.php --release`. That gate accepts SQLite >=3.51.3 or the explicitly reviewed 3.44.6/3.50.7 backports. A newer standalone `sqlite3` executable does not change the library loaded by PHP PDO. The image is the documented deployment baseline; native process supervision is operator-managed.
+
+
+## PHP security baseline — 22 October 2026
+
+PHP's [official changelog](https://www.php.net/ChangeLog-8.php) dates the current patched releases 8.3.36, 8.4.27 and 8.5.12 to 22 October 2026. The [security notice published on 21 October](https://www.php.net/archive/2026.php) identifies fixes for [CVE-2026-109618](https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w) and [CVE-2026-109619](https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp). These versions are this release's minimum patch levels. Use maintained patch releases within the supported branches and recheck upstream advisories when deploying.
+
+The Docker baseline stays on the 8.4 branch and pins `php:8.4.27-cli-bookworm` by digest. Release checks must record the actual interpreter version and pass on the patched runtime. The advisory describes web-request SAPIs; it does not establish a demonstrated remote exploit against this CLI bot. Meeting these minimums addresses the identified upstream fixes and does not guarantee the absence of other vulnerabilities in PHP, extensions or the operating system.
## New isolated Docker installation
@@ -71,6 +78,7 @@ docker compose -p shabbat-test up -d --force-recreate shabbat
Migration verifies a backup before changing an existing database and rejects modified migration checksums. Startup validates the schema; it never silently migrates it. Keep independent private backups of the session and third-party runtime state as described in [backup and restore](BACKUP_RESTORE.md). Never remove named volumes as an upgrade step.
+
## Manual installation and no-scripts mode
Run as an unprivileged application owner in a separate checkout with writable private data/session directories. Use the supported PHP runtime, not a running bot's dependency tree.
diff --git a/docs/KEYBOARD_COMPATIBILITY.md b/docs/KEYBOARD_COMPATIBILITY.md
new file mode 100644
index 0000000..907df18
--- /dev/null
+++ b/docs/KEYBOARD_COMPATIBILITY.md
@@ -0,0 +1,45 @@
+# Keyboard compatibility
+
+Shabbat 3.1.0 converts keyboards immediately before transport through
+`Shabbat\Telegram\KeyboardMarkup`. MadelineProto 8.11.10 uses Telegram Layer 232:
+inline keyboards contain `keyboardInlineButtonRow`, `keyboardInlineButton`
+and a nested `InlineButtonType`. Reply keyboards use `keyboardButtonRow`,
+`keyboardButton` and `ButtonType`.
+
+## Existing settings and templates
+
+Existing Bot API arrays, native keyboards from MadelineProto 8.7 and current
+typed native keyboards are accepted. Stored JSON is read without rewriting it.
+The adapter preserves callback bytes, URLs, copy text, switch-inline queries,
+peer selection, login/WebApp actions, game/payment actions, background colors
+and custom emoji IDs. Unknown or mixed action/context formats fail before a
+message is sent. Existing native HTTP URL buttons remain supported; new flat
+Bot API URL buttons retain the HTTPS/Telegram URL policy. WebApp and login URLs
+require HTTPS. Login buttons can omit the optional bot field, using Telegram's
+current-bot default just as the official SDK converter does.
+
+Template buttons accept row arrays or recognized `inline_keyboard` /
+`replyInlineMarkup` wrappers. Template validation uses the same action rules
+as transport. Existing `inherit`, `custom` and `none` modes keep their meaning.
+
+## Transport and navigation
+
+Initial messages, media messages, edits, group acknowledgement counters,
+inline search results and BroadcastManager messages use the same adapter.
+Reply keyboards, keyboard removal and forced replies remain separate from
+inline keyboards. A callback continues editing its recorded message rather than
+sending a new menu.
+
+Colors remain `primary`, `danger`, `success` or the equivalent native
+`keyboardButtonStyle` flags. Explicit custom icons remain signed-int64 IDs.
+The custom-emoji fallback removes only unsupported animation and keeps the
+button action, color, count, callback binding and edit/message identity.
+
+## Offline verification
+
+`KeyboardCompatibilityTest` uses the installed official TL serializer and decoder
+without creating a Telegram session or calling Telegram. It covers old/current
+formats, supported actions, reply-keyboard separation, persisted templates,
+`/start` and callback navigation. Other gateway, emoji and template tests cover
+media/inline delivery and fallback behavior. A live Telegram smoke test is still
+required after deployment to a separate test bot.
diff --git a/docs/LICENSING.md b/docs/LICENSING.md
index fb05670..181814b 100644
--- a/docs/LICENSING.md
+++ b/docs/LICENSING.md
@@ -1,38 +1,38 @@
# Licensing and corresponding source
-WizardLoop Shabbat uses **AGPL-3.0-only** for the current combined application, as declared by `composer.json` and original application SPDX headers. [LICENSE](../LICENSE) is the complete, unchanged GNU AGPL version 3 text. [The historical MIT grant](../LICENSES/SHABBAT-LEGACY-MIT.txt) retains the original WizardLoop copyright and permission notice; the current policy does not revoke earlier grants or offer the whole new application under an alternative MIT license.
+WizardLoop Shabbat uses **AGPL-3.0-only** for the combined application, as declared in composer.json and original application SPDX headers. [LICENSE](../LICENSE) retains the complete GNU AGPL version 3 text. The [historical MIT grant](../LICENSES/SHABBAT-LEGACY-MIT.txt) remains effective for its original scope.
-## Preserve component grants
+## Preserve original grants
-Dependencies, imported fragments and patch baselines keep their original copyright and license notices. MadelineProto's package metadata declares `AGPL-3.0-only`; its source headers and the added formatted-date wrapper permit version 3 or later. These texts are retained unchanged and their common version 3 grant is used by the combined application. The difference is recorded, not silently rewritten.
+Dependency sources, patch baselines and upstream supplements retain original notices. MadelineProto metadata declares AGPL-3.0-only, while its source headers permit version 3 or later; the common version 3 grant is used without rewriting either text. The RTC AV package declares MIT in metadata but distributes a BSD-3-Clause license and BSD headers. This unresolved metadata difference is recorded, not silently repaired.
-Hebcal output, GeoNames place data and the Omer count resources retain **CC-BY-4.0**. The Wikisource Omer transcription/editorial resource retains **CC-BY-SA-4.0**, its contributor attribution, pinned revisions and modification notes. The complete Creative Commons legal texts are in [LICENSES](../LICENSES/README.md). API account terms and quotas are separate from these data grants. See [third-party notices](../THIRD_PARTY_NOTICES.md) and [technical provenance](THIRD_PARTY_DETAILS.md).
+Hebcal output, GeoNames data and Omer count resources retain CC-BY-4.0; the Wikisource Omer transcription/editorial resource retains CC-BY-SA-4.0. Preserve their attribution, pinned provenance and modification notes. Complete texts are in [LICENSES](../LICENSES/README.md). API access terms and quotas are separate from data grants.
-## Exact source offer
+## Exact deployed source offer
-`/source`, with `/license` and `/version` aliases, shows the application identity and source information. `SOURCE_URL` must identify the exact deployed corresponding source, including local application changes and all active patches. A moving upstream branch or the Composer lock alone cannot identify a modified deployment. `BUILD_COMMIT` is build metadata; a fabricated commit does not turn an unpublished working tree into published source.
+/source, /license and /version display application/source identity. SOURCE_URL must identify the exact deployed source, including application changes and active patches. A moving branch, lock file alone or fabricated BUILD_COMMIT cannot identify an unpublished modified deployment.
-When conveying a modified covered program, retain notices and the license, identify modifications and provide the required corresponding source. For remote interaction with the modified network program, GNU AGPL section 13 requires the applicable source offer. The complete conditions are in [LICENSE](../LICENSE), including sections 4–6 and 13, and the [official GNU text](https://www.gnu.org/licenses/agpl-3.0.html). This document records the project's release practice and evidence, not a certification of unrelated contributions or deployments.
+When conveying a modified covered program, retain notices, identify modifications and provide the required corresponding source. GNU AGPL section 13 governs the applicable source offer for remote interaction with a modified network program. Read [the complete license](../LICENSE), especially sections 4–6 and 13, and [the official GNU text](https://www.gnu.org/licenses/agpl-3.0.html). This document records release evidence and practice; it does not certify unrelated contributions or deployments.
-## Publication archive scope
+## 3.1.0 archive scope
-The `v3.0.0` release provides two separate artifacts:
-
-| Artifact | Scope |
+| Artifact | Contents |
|---|---|
-| `shabbat-3.0.0.zip` | Clean repository source: application, resources, migrations, tests, scripts, Composer manifest/lock, public configuration, Docker files, documentation, licenses and required GitHub files. No installed `vendor` tree. |
-| `shabbat-3.0.0-corresponding-source.zip` | Application material plus the 57 locked Composer runtime packages, their source/license notices and the applied reviewed patches. Exact contents, exclusions and hashes are recorded in its manifest. |
+| shabbat-3.1.0.zip | Clean application source, resources, migrations, tests, scripts, exact Composer lock, public configuration, Docker, documentation, licenses and GitHub workflows. No installed vendor tree. |
+| shabbat-3.1.0-corresponding-source.zip | The application plus 83 locked Composer runtime packages with their original source/notices, the two reviewed patch outputs and pinned preferred-source supplements. Its manifest states exact hashes and exclusions. |
+
+The checked-in [source manifest](../resources/release/source-manifest.json) pins **4,095 runtime dependency files and 103 supplementary source files**: 18 Windows helper source files, 84 MadelineProto build/schema/language inputs and the pinned RTC AV README. It verifies exact lock and runtime source bytes; generated Composer autoload/bin metadata and all 26 development packages are excluded. PHPStan's distributed PHAR is not described as its preferred source.
-The corresponding-source artifact is scoped to the application and its Composer runtime dependencies. Development tools are reproducible from `composer.lock` and are inventoried, but are not bundled in that runtime source artifact; PHPStan's distributed PHAR must not be called its preferred source. The archive is not a complete Docker-image or operating-system source distribution. PHP, SQLite, Composer and base-image/system components are external to that scope; Docker pins and source references describe the build inputs. Any unresolved or omitted preferred-source component must be listed in the publication report before the artifact can be described as complete within its stated scope.
+The two reviewed public Amp HTTP Server TLS example private keys are omitted by exact recorded hash; neither is used by the bot. Real credentials, sessions, databases, backups and private work material must never enter source archives.
-Keep the application source, all five patch sets, immutable bases/intermediates, added files, exact diffs, manifests and notices available together. The two reviewed public Amp HTTP Server TLS example private keys may be omitted from a distribution only with the exact omission records preserved; they are not used by this bot. Other private keys and real runtime credentials do not belong in source archives.
+Keep the two active patch sets, original bases/intermediates, reviewed outputs, diffs, manifests and notices together. Former local UpdateLoop, GeoPoint and formatted-date patches are retired; historical attribution findings are summarized in [technical provenance](THIRD_PARTY_DETAILS.md).
-Release packaging uses the checked-in [source-input manifest](../resources/release/source-manifest.json) and [preferred-source supplements](../resources/release/README.md). The manifest pins all 2,960 included runtime dependency files and 92 supplementary source files. Packaging verifies a locked, patched runtime installation against those hashes and adds the exact reviewed application tree; it excludes installed development tools and generated Composer autoload metadata. Original component notices and the two approved example-key omission records remain attached to that scope.
+## Explicit limits and review findings
-## Evidence and remaining review
+This is an application/Composer-runtime source collection, **not** the complete source of a Docker image, PHP, SQLite, external native multimedia libraries or every development tool. No reproducible native binary rebuild or all-platform source completeness is claimed. The retained Windows helper binaries have pinned associated preferred source, but their rebuild was not verified.
-The [dependency inventory](dependencies.json) distinguishes 57 runtime packages and 26 development packages, exact versions, metadata, distributed license files and findings. `LICENSE_TEXT_PRESENT` means a recognized license text was found; it is not an authorship or compatibility certificate. Regenerate it with `php scripts/dependencies.php` from the isolated locked installation. Composer security advisories are a separate check.
+Current TL232 and language-generator inputs are supplied; full historical schemas, complete upstream documentation, its toolchain and historical mutable RPC data are not. No generator or optional FFmpeg downloader was executed. The AV FFI declarations retain upstream bytes; whether they are directly maintained preferred source or generated derivatives is unestablished. No separate generator exists in the pinned package tree; external derivation provenance remains a review finding rather than an assumed MIT grant.
-On **2026-10-16**, the WizardLoop project maintainer stated that they authored the historical UpdateLoop helper retained at [original-reference.php](../patches/madelineproto/original-reference.php) and explicitly authorized its distribution under **AGPL-3.0-only**. The [manifest](../patches/madelineproto/manifest.json) binds this attestation to SHA-256 `1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9`. The exact headerless helper bytes are preserved; the dated statement supplies the maintainer's authorization without rewriting historical source or dependency licenses. It is not an independent authorship or legal certification.
+The [dependency inventory](dependencies.json) records 83 runtime and 26 development packages. LICENSE_TEXT_PRESENT means a recognized distributed license text was found; it is not an authorship or compatibility certificate. The AV metadata mismatch remains NOT VERIFIED. Regenerate with php scripts/dependencies.php in an isolated exact-lock installation. Composer advisories are a separate check.
-The historical formatted-date exports still have unresolved standalone grants and are not redistributed. Their finding is separate from the UpdateLoop attestation. Preserve any remaining contributor or deployment-only provenance findings. [Publication status](PUBLICATION_STATUS.md), release manifests and the recorded checks identify the evidence available for the actual release.
+Any unresolved source or licensing finding must remain in [publication status](PUBLICATION_STATUS.md) and the release report; do not label this a universally complete source distribution.
diff --git a/docs/MADELINE_FORMATTED_DATE.md b/docs/MADELINE_FORMATTED_DATE.md
deleted file mode 100644
index 4ed42b0..0000000
--- a/docs/MADELINE_FORMATTED_DATE.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# MadelineProto formatted-date compatibility and version policy
-
-Reviewed 2026-10-14. The selected package is danog/madelineproto 8.7.0, immutable commit 7b99dd0f2d964a492c377912ffce9f5ce61aa9ed. Both composer.json's exact constraint and composer.lock preserve this version; composer install uses the full 83-package lock. At the 2026-10-14 review, GitHub marked 8.7.0 as a pre-release and 8.6.5 as Latest; these are historical observations, not a current release lookup. This project remains a 3.0.0 development snapshot and does not describe the selected dependency as an upstream stable release.
-
-## The concrete error
-
-The package's layer 225 TL schema declares messageEntityFormattedDate#904ac7c7 with UTF-16 offset/length, a Unix timestamp and six boolean flags. The original EventHandler/Message/Entities/MessageEntity.php factory lacks both a FormattedDate wrapper and its dispatch branch. Valid received entities raise AssertionError: Unknown entity type: messageEntityFormattedDate at the original factory line 60. Message::__construct calls that factory before typed event-handler dispatch, so catching an error only inside a bot handler does not repair the missing wrapper.
-
-This is message-formatting metadata. It does not replace the group's IANA timezone, change calendar calculations, reinterpret Hebcal JSON dates or convert the operational Shabbat/festival boundaries.
-
-Before changing vendor, eight valid inputs reproduced the exact failure without creating an API, a session or a Telegram connection. A separate probe assembled explicitly labeled schema wire with the native integer encoder and used the actual locked TL decoder for all 19 valid flag combinations. It was not represented as a complete TL(null) serializer integration. Historical raw investigation output is not included in the publication source. Reproducible regression tests and the source artifacts remain included; the current publication report records fresh checks.
-
-## Available history and reference
-
-The local shabbat repository has 98 reachable commits across all references and reflogs. Searches of file paths, commit messages and content changes found no previous FormattedDate/messageEntityFormattedDate correction or dedicated test. This is the accessible local history; deleted/unavailable remote history is not claimed.
-
-Two local exports contain byte-identical implementations. The labels below are logical local-reference project/file identifiers, not public download URLs:
-
-- local-reference/newsearch-v2/docker/patch-madeline-formatted-date.php
-- local-reference/psy new/release-r21-work/docker/patch-madeline-formatted-date.php
-
-Their script SHA256 is c3091f61a401d8022b8ef1d228cf8c5f31a1094982de69a0be108e21885cb967. Their docker/madeline-formatted-date/FormattedDate.php wrapper SHA256 is a9e3146e49a88bec469e67e53f5e27cffb1b5127cde547590f2e385ef02dd264. The corresponding test is tests/madeline_formatted_date_compatibility_test.php.
-
-These directories have no usable Git history. Their filesystem modification timestamp is 2026-09-03T23:06:59Z; that is not asserted to be a commit or authorship date. The export package declarations conflict (MIT versus proprietary) and no standalone grant/header was found for those reference files. Their behavior and hashes were reviewed, but the original script/wrapper is not redistributed as an audited upstream artifact.
-
-A fresh implementation is based on the official protocol and the locked SDK's entity conventions. Its applied unified diff is a new reviewed correction, not described as the original unchanged historical patch. Native/BotAPI conversion retains the timestamp and UTF-16 offsets; the protocol's unknown-entity rejection remains in place. It does not add a broad catch-and-ignore fallback.
-
-## Official source check and protocol contract
-
-The official v8 head checked on 2026-10-14 was b1a4c5efee60a87cdbe7bc2b1eb542166ec7e2e3 (commit date2026-10-07); its entity factory still lacked this support. No newer compatible official correction was approved during this review. The exact tested 8.7.0 source is retained instead of silently selecting a moving branch.
-
-The supported BotAPI date_time format is r|w?[dD]?[tT]?. Empty formatting is valid. Relative formatting cannot be mixed with other flags; short/long variants of time or date cannot coexist. Telegram controls the actual client rendering. Generated HTML previews may preserve the underlying text without a dynamic date tag, while native entity capture/resend retains the date metadata; neither is claimed as a live client test.
-
-See the [official constructor](https://core.telegram.org/constructor/messageEntityFormattedDate), [date-time formatting](https://core.telegram.org/bots/api#date-time-entity-formatting), [selected release](https://github.com/danog/MadelineProto/releases/tag/8.7.0) and [checked official source](https://github.com/danog/MadelineProto/blob/b1a4c5efee60a87cdbe7bc2b1eb542166ec7e2e3/src/EventHandler/Message/Entities/MessageEntity.php).
-
-## Installation, licensing and future updates
-
-Use the shared [patch workflow](PATCHES.md): install from the lock, apply and verify approved patches before startup, and use the explicit route after --no-scripts. Startup only verifies; never change an active Composer tree or running container. The new class and factory are an approved set: partial, unknown, mismatched or incompatible source must stop the build. A matching already-patched set is a no-op. Corresponding-source archives retain the exact SDK baseline, new class, diff, manifest, rights notices and license.
-
-The supplied Docker layout mounts /app/data and /app/runtime only. It does not mount /app or /app/vendor, so an old named vendor volume cannot hide dependencies in that layout. Patching occurs during image construction. The other project's /opt/theisraelis copy workaround is specific to its broader runtime mounts and is not silently transplanted here.
-
-AGPLv3 allows conveying modified source and the modifications that produce it, subject to its conditions: retain notices/license, identify changes and dates, license the covered combined work appropriately, provide corresponding source with distributed object code, and offer the modified program's source to remote network users where section 13 applies. MadelineProto package metadata says AGPL-3.0-only; existing v3-or-later headers remain untouched, using their common version 3 grant. This supports including the reviewed diffs in the AGPL Shabbat repository; it is not a blanket certification of every contributor, asset or deployment practice. See [third-party notices](../THIRD_PARTY_NOTICES.md) and the [GNU license text](https://www.gnu.org/licenses/agpl-3.0-body.html).
-
-An exact lock prevents accidental version selection; it cannot guarantee an unseen future Telegram/PHP version will stay compatible. A future upgrade requires an explicit constraint/lock change, reviewed version/commit/schema/file signatures, all behavioral tests, a clean install and an isolated target rehearsal. Unknown versions fail closed. Dependency update proposals and CI do not constitute automatic approval to publish or deploy.
-
-No active bot/container, production data or real Telegram message was changed during the investigation. The final applied state and exact complete-suite/archive results are recorded in [implementation status](IMPLEMENTATION_STATUS.md) and the external checks/PUBLICATION_REPORT.md for this preparation. Historical private validation outputs are not bundled. No task commit, local tag or publication is claimed.
diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md
index fe8ed55..99f2710 100644
--- a/docs/MIGRATION.md
+++ b/docs/MIGRATION.md
@@ -1,12 +1,8 @@
-For the running legacy installation at `/root/shabat`, follow the complete [production upgrade procedure](PRODUCTION_UPGRADE.md), including stopped backups, exact group verification and permission recovery.
-
-# Dev.8 to dev.9
+# Database upgrade and legacy import
-Stop all writers and use the verified backup/migrate sequence in [test deployment](SERVER_TEST_DEPLOYMENT.md). Migration 016 adds dispatch timestamps and indexes without changing prior migration files, permission snapshots or job payload/random IDs. Existing attempts that might have reached Telegram are conservatively marked uncertain. This can suppress additional Tefillin messages on the upgrade day rather than duplicate an unknown old delivery. Existing older unverified permission snapshots retain the dev.8 administrator-review requirement.
+Use the [production runbook](PRODUCTION_UPGRADE.md) ([עברית](PRODUCTION_UPGRADE_HE.md)) to verify whether the real installation is at /root/shabbat or /root/shabat, back up stopped state and preserve the session. Existing 3.0 SQLite deployments keep their data and run the migration/schema gate; they do not run legacy import again. Version 3.1.0 adds no SQL migration and retains migrations 001–016 unchanged.
-Rebuild the image for the reviewed BroadcastManager lifecycle patch. Do not modify a live vendor tree or remove data/session volumes. See [runtime changes and retention](DEV9_DELIVERY_SAFETY.md). Historical migration notes follow.
-
-# Migration from the file-based bot
+## File-based legacy import
Keep the old bot stopped during explicit import and cutover. Do not run old and new writers together or delete the old MadelineProto session. These commands are operator instructions; development tests use isolated fixtures only.
@@ -14,8 +10,22 @@ Keep the old bot stopped during explicit import and cutover. Do not run old and
2. Initialize a new application database: `php bin/migrate.php --db=/path/to/shabbat.sqlite --writers-stopped`. For an existing application DB supply an existing `--backup-dir=/path/to/backups`; it is backed up and verified before any migration.
3. Inspect: `php bin/import-legacy.php --db=/path/to/shabbat.sqlite --legacy=/path/to/old-bot --dry-run`. The source can be the bot root or its `data` directory. With no destination DB, dry-run uses an in-memory database and does not create application records.
4. Compare report counts, templates, original rights, invalid JSON and recovery warnings with sampled legacy records.
-5. Apply: `php bin/import-legacy.php --db=/path/to/shabbat.sqlite --legacy=/path/to/old-bot --apply --writers-stopped --backup-dir=/path/to/backups`.
-6. Run health checks, test backup/restore on a separate path and verify a staging group before starting the new bot.
+5. Save and review the private dry-run JSON, then apply with `php bin/import-legacy.php --db=/path/to/shabbat.sqlite --legacy=/path/to/old-bot --apply --writers-stopped --backup-dir=/path/to/backups --expect-report=/private/path/import-preview.json`.
+6. Check schema/integrity, compare the import result and rehearse restore on a separate path before startup. Live health additionally requires recent scheduler heartbeats; run it after authorized startup.
+
+
+## Preview, comparison and repeatability
+
+Dry-run and apply parse the same group and personal templates. Reports are private: they contain group/user identifiers and source-derived preferences.
+
+- `report_version: 1` identifies the schema; a reviewed preview has `dry_run: true`.
+- `source_sha256`, `destination_sha256` and `plan_sha256` bind the source, affected destination records and planned import. `--expect-report=PATH` refuses a changed source/target/plan before application records are written.
+- `duplicates` records canonical group/audience duplicates. `orphan_group_directories` lists directories not present in the subscription list; they are reported for review, never silently re-subscribed. `group_list_present` distinguishes a missing subscription list.
+- Group comparisons include `source_settings` and `different_settings`. Template/draft comparisons include source/destination value hashes and `matches_source`. Existing destination rows are preserved even when they differ.
+- Successful apply returns `verification.status = passed`, checked/inserted/preserved record counts, integrity and foreign-key results. The CLI also reports the verified `pre_import_backup` path, SHA-256 and integrity.
+- The import is additive but not one all-or-nothing transaction. On failure keep every writer stopped, retain the report and state, inspect or restore the verified pre-import backup, then create a fresh preview before retrying.
+
+To include a genuinely active directory-only group, reconcile it against the operator's subscription evidence in a separate reviewed import copy. Preserve the original snapshot and regenerate the preview; appending every old directory would also reactivate stale groups. Unsupported/malformed files and local extensions require explicit review.
The startup compatibility bridge reads only `data/DBgroups.txt` from `LEGACY_DATA_PATH` and adds missing subscribed group records. Existing groups therefore use `/settings` without re-registering using `/add`. It does not migrate schema, overwrite edited preferences, remove groups or restore permissions. Explicit maintenance import is still required to review templates, drafts, snapshots and old lock state.
@@ -41,10 +51,8 @@ Migration 005 creates `known_broadcast_peers` independently of Shabbat subscript
Run the numbered migration only during stopped-writer maintenance. It adds group-only lock_block_flags (default21, including send_reactions/edit_rank), two holy-message cleanup switches and tefillin_delete_previous, all cleanup switches defaultfalse. It preserves original lock snapshots while keeping an in-flight previous applied mask, and adds durable deletion work plus confirmed tefillin message pointers. Existing group zmanim rich designs are copied once into independent times_alert templates while their original rows/IDs remain. Sent reminders receive separate replayable bookkeeping; no previously sent job is returned to pending to trigger deletion. The earlier seven migration checksums remain immutable. SQLite backups include these tables; restore the full schema/data together.
-## Dev.6 to dev.7
-
-Stop every writer and run the documented verified backup/migration command before starting dev.7. It adds **013_permission_recovery.sql** and **014_diagnostic_panels.sql** while preserving the exact checksums of migrations 001-012, group settings, original permission snapshots, pending conflicts and Telegram session data. The migration does not itself change Telegram permissions or resolve a conflict. Recovery happens only through the reviewed runtime rules or an authorized group-admin confirmation. See [test deployment](SERVER_TEST_DEPLOYMENT.md) and [permission recovery](PERMISSION_RECOVERY.md).
+## Older database and permission state
-## Dev.6/dev.7 to dev.8
+Migrations 013–015 add recovery evidence, diagnostics and snapshot provenance without changing the earlier migration bytes. Older unresolved snapshots remain unverified and require the [administrator recovery procedure](PERMISSION_RECOVERY.md); a matching checksum alone cannot authorize restoration.
-Dev.8 adds migration 015 for snapshot provenance. The first 14 migration files remain unchanged; upgrading dev.6 applies 013-015, while dev.7 applies 015. Stop all writers, preserve the same database/session volumes and run the verified backup/migration command before startup. Migration does not send Telegram requests or alter saved rights. An unresolved older snapshot requires explicit administrator resolution and cannot be automatically restored, even if its checksum is correct. Completed cycles can capture a fresh verified baseline. See the [affected-group procedure](DEV8_PERMISSIONS.md) and [current deployment commands](SERVER_TEST_DEPLOYMENT.md).
+Migration 016 adds dispatch timestamps/indexes and conservatively marks older delivery attempts that might have reached Telegram as uncertain. This can suppress an additional reminder rather than duplicate an unknown old delivery. The independent scheduler and retention behavior are described in [delivery safety](DELIVERY_SAFETY.md). Never delete unresolved recovery or delivery evidence to bypass an upgrade check.
diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md
index c46b9d3..47ba7f7 100644
--- a/docs/OPERATIONS.md
+++ b/docs/OPERATIONS.md
@@ -1,4 +1,41 @@
-# Operator commands and Stars donations
+# Operations
+
+[Bot commands](COMMANDS.md) · [Backup and restore](BACKUP_RESTORE.md) · [Production upgrade](PRODUCTION_UPGRADE.md)
+
+## Operations
+
+Docker commands run **on the host at the same project root/project identity**, with daemon access. PHP commands run **inside the image at /app**, or at the manual root as its service user. Operational output can contain group IDs/state; keep it private.
+
+| Task | Command | Effect / condition |
+|---|---|---|
+| Build | `docker compose build` | Build from source/lock. |
+| Start | `docker compose up -d shabbat` | Start/recreate and connect to Telegram. |
+| Stop | `docker compose stop shabbat` | Graceful stop, 60-second grace; retain volumes. |
+| Restart | `docker compose restart shabbat` | Restart same service; does not rebuild image. |
+| Status | `docker compose ps` | Container/service state. |
+| Logs | `docker compose logs --tail=100 shabbat` | Read logs; add `--follow` to stream, Ctrl+C exits viewer. |
+| Health | `docker compose exec shabbat php bin/health.php` | Schema/connection, both heartbeats and queue/lock metrics. |
+| Deep health | `docker compose exec shabbat php bin/health.php --deep` | Also integrity/foreign-key checks; more expensive. |
+| Release gate | `docker compose run --rm --no-deps shabbat php bin/self-check.php --release` | Offline platform/patch checks. |
+| Write probe | `docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root` | Offline temporary-file probe; may append to existing worker log. |
+
+Both heartbeats must be no older than 180 seconds. Offline/restored DBs can pass structural checks yet return `healthy=false` / exit 1 without schedulers. Never manufacture heartbeat files.
+
+Run direct maintenance below **at project root as service user**. In Docker, prefix PHP commands with `docker compose run --rm --no-deps shabbat` and use container paths. `--writers-stopped` is an attestation, not a stop command.
+
+| Task | Command | Effect / requirement |
+|---|---|---|
+| Migrate | `php bin/migrate.php --writers-stopped --db data/shabbat.sqlite --backup-dir backups` | All writers stopped, existing backup directory. Back up existing DB/apply migrations; omit backup only for new DB. |
+| Backup | `php bin/backup.php --db data/shabbat.sqlite --directory backups --keep 7` | Consistent SQLite copy/manifest; retain seven tool-named backups. Online maintenance allowed. |
+| Restore | `php bin/restore.php --backup backups/CHOSEN.sqlite --db data/shabbat.sqlite --writers-stopped` | Verified chosen backup, stopped writers; previous destination retained. |
+| Inspect legacy | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --dry-run` | Inspect/report, no imported-record writes or Telegram actions. |
+| Import legacy | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --apply --writers-stopped --backup-dir backups` | Existing migrated DB/backup directory, stopped writers; additive import. |
+| Calendar diagnostic | `php bin/check-calendar.php --date=2026-10-15` | Public HTTPS only; no DB, .env or session. `--help` lists coordinates/zone/calendar/language options. |
+| Verify patches | `php scripts/verify-patches.php` | Inspect approved installed bytes. |
+| Apply patches | `composer patches` | Apply/verify; stopped installation only. |
+| Build identity | `php bin/build-metadata.php --commit=YOUR_40_HEX_COMMIT` | Replace placeholder with verified provenance; writes metadata/rejects stale fingerprint. |
+
+## Operator services and Stars donations
The configured operator authorization callback is mandatory for `ManualGroups`. It is a separate bot-operator permission, not a cached group administrator role. Bind it to the project's existing trusted operator IDs and authenticated Telegram sender. Do not expose the service through an ordinary unprotected callback.
@@ -18,12 +55,12 @@ Old three-part `donate|user|amount` payloads had no durable nonce/approved inten
Private database records include payer ID, amount/currency, approved query ID, charge UID and optional service message ID. Charge identifiers and invoice payloads are not returned in the success report or placed in audit/error logs; email and expanded Telegram payment-request information are ignored. Keep the application database and backups private. The `stats` API returns aggregate donation count and Stars only. Define record retention with the operator's accounting needs; this document does not assert legal compliance.
-Implementation was checked against the locked MadelineProto TL schema v225: `inputMediaInvoice` requires DataJSON, `payments.exportInvoice` exports the URL, and `messages.setBotPrecheckoutResults` answers precheckout. Presets/native invoice shape come from the preserved WizardLoop implementation; the project retains its historic MIT copyright/permission notice. New service code is AGPL-3.0-only.
+Implementation was checked against the locked MadelineProto TL schema: `inputMediaInvoice` requires DataJSON, `payments.exportInvoice` exports the URL, and `messages.setBotPrecheckoutResults` answers precheckout. Presets/native invoice shape come from the preserved WizardLoop implementation; the project retains its historic MIT copyright/permission notice. New service code is AGPL-3.0-only.
-Tests use isolated SQLite databases and fake RPC/permission gateways. They cover authorization, snapshot restoration, override expiry, partial failures/cancellation, invoice binding/expiry, replay/conflicting charges, ledger rollback and restart. No Stars charge, real invoice or production Telegram group was used.
+Tests use isolated SQLite databases and fake RPC/permission gateways. They cover authorization, snapshot restoration, override expiry, partial failures/cancellation, invoice binding/expiry, replay/conflicting charges, ledger rollback and restart. No Stars charge, real invoice or production Telegram group was used.
-Invoice titles, descriptions, prompts and recoverable errors use the same six-locale resources as the rest of the private UI. Migration 004 expands the SQL language constraints without rewriting an existing approved intent or ledger record. Test invoice exports remain fake; no live Telegram invoice or Stars payment was made during development.
+Invoice titles, descriptions, prompts and recoverable errors use the same six-locale resources as the rest of the private UI. Migration 004 expands the SQL language constraints without rewriting an existing approved intent or ledger record. Test invoice exports remain fake; no live Telegram invoice or Stars payment was made during development.
Live BroadcastManager status uses the bundled reviewed presentation hook and the six-language `BroadcastStatusFormatter`. Each operator's manager receives its localized initial caption, progress counters/status, and native colored controls with unchanged `bm` operation IDs. The formatter does not send, filter or mutate delivery state. The application verifies operator authorization before control actions. A legacy text-only library summary receives an explicit localized recovery notice rather than being guessed or retranslated; its original file is retained, and structured application progress/audit results remain the current status view. See [patch provenance and installation](../patches/broadcastmanager/README.md).
-Composer/Docker/startup patch verification now covers both the MadelineProto cancellation patch and this separate BroadcastManager presentation patch. With `--no-scripts`, run `php scripts/apply-patches.php` then `php scripts/verify-patches.php` before startup. Installation refuses an active writer or unknown/partially patched source. Reflection tests invoke the actual reviewed library formatting methods without constructing a Telegram API; live status editing/colors still require staging verification.
+Composer/Docker/startup patch verification now covers the active Fresh Peer and BroadcastManager patch sets. With `--no-scripts`, run `php scripts/apply-patches.php` then `php scripts/verify-patches.php` before startup. Installation refuses an active writer or unknown/partially patched source. Reflection tests invoke the actual reviewed library formatting methods without constructing a Telegram API; live status editing/colors still require staging verification.
diff --git a/docs/PATCHES.md b/docs/PATCHES.md
index 40d4b61..dc71ec6 100644
--- a/docs/PATCHES.md
+++ b/docs/PATCHES.md
@@ -1,84 +1,60 @@
# Offline patch installation
-[Review provenance and behavior](../patches/madelineproto/README.md).
-Composer lifecycle scripts and Docker install offline, verify exact hashes,
-and fail on unknown source. Startup verifies only.
-
-With scripts disabled:
-
- composer install --no-dev --no-scripts --prefer-dist
- php scripts/apply-patches.php
- php scripts/verify-patches.php
- php bin/self-check.php
-
-Do not bypass manifest failures or edit a live container. Review upgrades on an
-isolated installation and prefer a tested official correction when available.
-
-Reference runBot implementations were inspected in importchatsbot/src/bot.php
-and SwiftTool/bot.php. Runner reproduces Revolt error-handler installation,
-credentials/Settings setup and startAndLoopBot. The typed error callback is rebound on handler attachment, after the SDK installs its own startup callback. It uses narrow typed checks for
-completed-operation and ReferenceDatabase errors. It does not swallow every error
-whose text says "The operation was cancelled": the explicit cancellation/shutdown
-requirements forbid that behavior. Unexpected errors exit 1; shutdown flags stop
-new application work. SingleInstance protects the shared runtime directory.
-
-Offline loop tests do not prove behavior against Telegram, real network failure,
-or signal delivery in every container runtime. Verify those using an isolated
-staging bot and test groups before production deployment.
-Mutation also acquires the same APP_DB_PATH + .writer.lock used by Runner and
-SQLite maintenance. An active writer makes application fail before a file is
-changed; read-only verification and an already-patched no-op remain available.
-Stop the isolated bot before applying a required patch. The installer only
-creates a lock file on its configured working data path, never starts Telegram.
-
-The same installer requires the reviewed
-[BroadcastManager status-localization patch](../patches/broadcastmanager/README.md),
-[GeoPoint double-coordinate correction](../patches/madelineproto-geopoint/README.md)
-[formatted-date entity correction](../patches/madelineproto-formatted-date/README.md)
-and [fresh full-peer response correction](../patches/madelineproto-fresh-peer/README.md).
-Each manifest identifies its locked package/commit, target, baseline, diff and
-final hashes. All five patch sets are applied before runtime and verified by
-Runner/self-check; missing required evidence or unknown source fails the build.
-Baseline hashes remain checked when installed vendor source is already patched.
-
-The formatted-date set changes the entity factory and adds one independently
-written class; both must match the approved set. Its pinned TL schema and original
-AGPL license are also checked. A partial factory/class installation fails closed.
-The located reference script is not redistributed: its exports lack usable Git
-history and a consistent standalone license grant. This is a new reviewed
-implementation, documented in [the formatted-date review](MADELINE_FORMATTED_DATE.md).
-
-The [GNU AGPLv3](https://www.gnu.org/licenses/agpl-3.0-body.html) permits conveying
-covered modifications, including diffs, with retained notices, identified changes,
-AGPL licensing and applicable source offers. Exact grants and reference limitations
-are recorded in [third-party notices](../THIRD_PARTY_NOTICES.md). Preparing these
-artifacts does not publish them or authorize deployment.
-
-RuntimePaths resolves DATA_DIR, APP_DB_PATH, SESSION_PATH and HEARTBEAT_PATH once
-before startup and exports them for the preserved legacy handlers. Maintenance
-commands use that same DB default and retain explicit --db overrides.
-
-## Native SDK boundaries
-
-The runtime rebinds the typed Revolt error handler in onStart after MadelineProto
-installs its own callback. The gateway uses the declared messages.getForumTopicsByID
-method with peer/topics. Offline tests check reachable gateway, invoice, and menu
-methods against the locked SDK declarations, effective blacklist, and TL schema.
-
-Fresh permissions use the supported getFullInfo helper with fullInfoCacheTime=0
-and the reviewed per-call raw response field. The reader requires complete matching
-Chat/ChatFull evidence; it never substitutes a second cached getInfo result. Direct
-channels.getFullChannel/messages.getFullChat namespace calls are blacklisted and
-are not used. A nonzero cache policy fails closed. Public full-info helper calls
-have the official RPC setting's five-second minimum automatic flood wait; longer
-waits propagate as typed scheduler retries. Direct namespace calls use the
-per-call floodWaitLimit=0. Permission leases and desired state are fenced again
-after awaited reads.
-
-Decimal random_id, query_id and keyboard style.icon values are validated within
-signed int64 and converted to native integers at the outbound boundary. The
-locked TL serializer interprets eight-byte strings as packed binary; real
-serializer regressions cover eight-digit decimals and signed limits. Stored
-identifiers remain decimal strings, preserving database identity.
-
-Fresh permissions use the supported getFullInfo path with full-info caching disabled and verified per-call raw response evidence. See the fresh-peer patch README and dev.8 investigation for the reproduced stale-cache limitation of the earlier two-helper path. Direct full-info namespace calls are blacklisted in the locked SDK. Public full-info helpers use the official five-second minimum flood-wait setting; longer RateLimitError-family waits become typed retries. Ordinary namespace RPCs retain the verified per-call zero-wait option. Native decimal int64 query/random/icon IDs are validated and converted at the outbound boundary; persisted IDs remain decimal strings.
+Only two patch sets are active in 3.1.0:
+
+| Package | Local change | Reviewed source |
+|---|---|---|
+| MadelineProto 8.11.10 | Fresh full-peer response evidence for safe group permission snapshots | [Provenance and tests](../patches/madelineproto-fresh-peer/README.md) |
+| BroadcastManager 3.2.2 | Application delivery hooks and localized status | [Provenance and tests](../patches/broadcastmanager/README.md) |
+
+Composer lifecycle scripts and Docker builds apply local immutable diffs and
+verify exact source/target hashes. Startup verifies only. Unknown versions,
+partial patches or changed artifacts fail closed; an already patched approved
+file succeeds without mutation. Baselines remain verified after application.
+
+With Composer scripts disabled, run from the stopped installation root:
+
+```bash
+composer install --no-dev --no-scripts --prefer-dist
+php scripts/apply-patches.php
+php scripts/verify-patches.php
+php bin/self-check.php
+```
+
+Patch mutation acquires the same `APP_DB_PATH + .writer.lock` as Runner and
+SQLite maintenance. An active writer prevents changes. Read-only verification
+and an already patched no-op remain available. Do not modify an active container,
+ignore a verification error, download a floating patch, or use `composer update`
+as a routine deployment command.
+
+## Official compatibility in 8.11.10
+
+The old local UpdateLoop, GeoPoint and FormattedDate patch trees were removed.
+Official date entities and fractional coordinates now have direct compatibility
+tests. Date payload validation stays at the application template boundary.
+The native update loop recognizes timeout cancellation, but that alone does not
+prove safe shutdown. `UpdateLoopCompatibilityTest` executes the official loop
+and its real parent with controlled RPC boundaries, checking recovery,
+intentional cancellation and a stop concurrent with timeout. These tests exercise one failure followed by recovery; they do not establish
+a global retry/log-rate bound. Parent stop prevents rescheduling but does not cancel
+an in-flight loop body. A separate SDK disconnect/finalize fixture keeps writer
+ownership through a modeled session flush and rejects stale socket reuse.
+`SdkWorkerIsolationTest` exercises the official IPC worker descriptors with a local
+PHP child: Linux checks that it cannot retain the parent lock or listening socket.
+
+`Runner` keeps typed cancellation handling, quiesces application work, and retains
+the process writer lock during SDK session finalization. It does not swallow every
+exception containing the word cancellation. SDK-level retry and shutdown behavior
+is checked separately from application drain and single-writer tests.
+
+Offline tests do not authenticate to Telegram or establish real network, IPC,
+signal or production-load acceptance. Use a separate staging bot after all gates
+pass. Retired patch history remains available in the 3.0.0 Git tag/source release.
+
+## Licensing and corresponding source
+
+Each active manifest binds package version, commit, baseline, reviewed output,
+diff and hashes. The source offer includes these artifacts and modified runtime
+sources with original rights notices. Local modifications are identified without
+changing upstream grants; see [third-party notices](../THIRD_PARTY_NOTICES.md)
+and [licensing](LICENSING.md). Installed vendor is excluded from Git.
diff --git a/docs/PERMISSION_RECOVERY.md b/docs/PERMISSION_RECOVERY.md
index a8933d6..c107360 100644
--- a/docs/PERMISSION_RECOVERY.md
+++ b/docs/PERMISSION_RECOVERY.md
@@ -2,9 +2,9 @@
The group settings panel provides **Resolve permission problem**. Open it from the group's main settings or its Shabbat/permissions category. The private panel names the group, shows the saved state and a bounded comparison of current versus original restrictions, and offers a reviewed confirmation for either **Use current permissions as normal** or **Restore permissions saved before the problem**. Navigation edits the same message.
-## Fresh reads and older snapshots (dev.8)
+## Fresh reads and older snapshots
-All permission reads use the exact matching full-peer response from the supported helper, with a separate immutable patch to pinned MadelineProto 8.7.0. Cached or minimal records cannot authorize capture or readback. Migration 015 preserves older snapshots but labels them unverified. Any unresolved older cycle requires administrator resolution: automatic opening and the restore button cannot use that snapshot. The six-language panel explains how to configure the intended normal permissions in Telegram, refresh and explicitly adopt them outside protected periods. Do not delete the saved row or automatically accept an already opened group. Completed cycles may capture a fresh baseline at the next lock. See [the investigation and recovery steps](DEV8_PERMISSIONS.md).
+All permission reads use the exact matching full-peer response from the supported helper, with the version-matched, hash-verified [Fresh Peer patch](PATCHES.md). Cached or minimal records cannot authorize capture or readback. Migration 015 preserves older snapshots but labels them unverified. Any unresolved older cycle requires administrator resolution: automatic opening and the restore button cannot use that snapshot. The six-language panel explains how to configure the intended normal permissions in Telegram, refresh and explicitly adopt them outside protected periods. Do not delete the saved row or automatically accept an already opened group. Completed cycles may capture a fresh baseline at the next lock.
## Automatic recovery
@@ -26,14 +26,24 @@ A verified calendar deadline also fences the final remote read synchronously, wi
## Upgrade and acceptance
-Dev.7 adds migration 013 for recovery state and evidence. Existing migrations 001-012 and the MadelineProto 8.7.0 dependency/patch lock remain unchanged. Stop all writers and take the verified migration backup before upgrading. See [test deployment](SERVER_TEST_DEPLOYMENT.md).
+Migrations 013 and 015 preserve recovery evidence and snapshot provenance. Stop all writers and take a verified backup before migration. See [production upgrade](PRODUCTION_UPGRADE.md).
Offline tests cover safe automatic recovery, preserved original snapshots, repeated cycles, administrator changes, stale/forged confirmations, role loss, cancellation, timing boundaries and migration preservation. Actual Telegram readback and both recovery choices must also be checked in the isolated test bot. See the versioned validation report for the exact checks that ran.
Native restrictions follow Telegram's [chatBannedRights constructor](https://core.telegram.org/constructor/chatBannedRights) and [default group-rights method](https://core.telegram.org/method/messages.editChatDefaultBannedRights). Individual true flags represent restrictions, so the UI translates them to permitted/blocked rather than showing raw booleans.
-Dev.8 adds migration 015 and a fifth fresh-peer patchset. The first 14 migrations, Composer lock and earlier four patchsets remain unchanged. Follow the current deployment instructions rather than historical version-specific notes.
## Final permission-write checks
Ordinary manual and scheduled changes re-read current permissions after any asynchronous desired-state/calendar evaluation. An administrator change during that wait prevents the write and retains evidence. A synchronous final check verifies the same settings, manual-override expiry, next operational time boundary and shutdown state before dispatch. This reduces stale writes; Telegram still has no compare-and-swap API, so a change after the final read or during the request is not atomic. Readback is required and post-write mismatches are explicitly reported as unverified changes, even when the confirmed-change counter is zero.
+
+## Review an older unverified snapshot
+
+A matching checksum proves saved bytes are consistent, not that the original Telegram read was accurate. An investigated older conflict contained an unexpectedly permissive snapshot, but its exact server-side cause was not established. Never treat that record as authorization to reopen a group.
+
+1. Outside Shabbat/Yom Tov, operational closure and active manual locks, set the intended normal group permissions directly in Telegram.
+2. Open the named group's **Resolve permission problem** panel, then **Refresh**.
+3. Check the current permissions, choose **Use current permissions as normal**, and explicitly confirm.
+4. In a disposable group, test a new close/open cycle with media, invitations and pinning restricted beforehand. Verify those exact restrictions after reopening and restart.
+
+Do not delete recovery rows or adopt a currently locked mask as normal. Missing calendar data, an uncertain read or an active closure prevents adoption. A failed readback after a write can mean Telegram already changed permissions; it does not prove that nothing happened.
diff --git a/docs/PRODUCTION_UPGRADE.md b/docs/PRODUCTION_UPGRADE.md
index 540de0b..a90eb2e 100644
--- a/docs/PRODUCTION_UPGRADE.md
+++ b/docs/PRODUCTION_UPGRADE.md
@@ -1,163 +1,128 @@
-# Production upgrade from the legacy file-based bot
+# Production upgrade to 3.1.0
-[English overview](../README.md) | [עברית](../readme-he.md) | [Import mapping](MIGRATION.md) | [Backup and restore](BACKUP_RESTORE.md) | [Permission recovery](PERMISSION_RECOVERY.md)
+[עברית](PRODUCTION_UPGRADE_HE.md) · [README](../README.md) · [Import mapping](MIGRATION.md) · [Permission recovery](PERMISSION_RECOVERY.md)
-This procedure is for the existing Docker Compose installation at **`/root/shabat`** (one `b`), upgrading the file-based implementation at historical baseline `2976ab8339f489d933c7246e0cb27f3b0e4aa697` to **`3.0.0`**. The final source directory remains `/root/shabat`. `/root/shabbat-test` is a separate test installation and is not a migration source or destination.
+This is a manual runbook, not an executed deployment. Use the released, verified 3.1.0 assets after required checks pass. The requested path is **/root/shabbat**; older instructions used **/root/shabat**. Verify the real container and directory before changing either. Never use the test bot's data.
-**לשרת הקיים `/root/shabat`: בונים את הגרסה החדשה בנפרד, עוצרים את הבוט הישן, מגבים את כל התיקייה, מייבאים ובודקים, ורק אז מחליפים את תיקיית המקור ומפעילים מופע יחיד. הרשאות ישנות עשויות לדרוש אישור ידני של מנהל קבוצה; ייבוא תקין אינו מבטיח שחזור אוטומטי שלהן.**
+Commands cover the legacy whole-project bind mount or standard 3.0 Docker data/session volumes. The 3.0 path probe only reads configuration; it opens no API/session. A custom session name or lock-only remnants stop this procedure. Custom mounts, external storage, symlinks to private data or another writer need a tailored backup first. Run server blocks in one **root Bash session** with Docker/Compose, unzip, GNU coreutils and sufficient storage. Keep backups outside source/build directories. Only the final start connects the new bot to Telegram.
-This targets the stable 3.0.0 release. On dev.9, the owner confirmed live locking, unlocking, original-permission restoration and restart. That confirmation does not cover automatic holy-day transitions, load capacity, a long-running soak or this production import. Complete the remaining checks relevant to your deployment with a separate test bot, and schedule the monitored production window deliberately. These are operator instructions; writing this document does not execute a deployment. The commands below are for **Bash on the Linux server as root**, with Docker daemon access, Compose v2, `curl`, `unzip`, `tar`, `sha256sum` and sufficient free storage. Every `run ... php ...` maintenance command explicitly replaces the image's normal bot command; it does not log in to Telegram. Only the final `up` starts the new bot.
+The new image uses PHP **8.4.27**. Manual runtimes require **8.3.36+, 8.4.27+ or 8.5.12+** within those branches; see the [22 October 2026 security baseline](INSTALLATION.md#php-security-baseline). Preserve the old image for rollback, but do not treat an older interpreter as meeting the new baseline.
-## 1. Understand what moves and what requires review
+## 1. Upload from your computer
-The historical Compose service is named `shabbat` and bind-mounts the entire project directory as `/app`. The old bot reads `.env`, stores group settings below `data/`, starts MadelineProto at `bot.shabbat`, and points BroadcastManager at `data/`. Root files such as `ids.txt`, `state_open.txt` and `*_lock*.txt` also matter. A copy of `data/DBgroups.txt` alone is not a backup.
+Download the deployment ZIP and SHA256SUMS from the matching GitHub release. In the computer's terminal, replace SERVER with your SSH hostname/IP. SFTP can upload the same files to the same protected destination.
-The new Compose service is also `shabbat`, but source/vendor are built into the image. Its separate named volumes hold `/app/data` and `/app/runtime`; the session prefix is `/app/runtime/bot.shabbat`. This procedure uses a distinct production Compose project, so its volumes cannot reuse test or old project state accidentally. All future commands must keep that project name.
+~~~sh
+ssh root@SERVER "install -d -m 700 /root/shabbat-upload-3.1.0"
+scp shabbat-3.1.0.zip SHA256SUMS root@SERVER:/root/shabbat-upload-3.1.0/
+~~~
-| Legacy material | Treatment |
-| --- | --- |
-| Entire old folder, including `.env`, vendor, session files/directories, data and root state | Preserved in a private stopped snapshot and a retained old source directory. |
-| `data/DBgroups.txt` | Unique valid entries become registered groups. Existing new-database settings are preserved on re-import. |
-| Alert flags, opening/closing text, entities, media file IDs and buttons | Imported according to the exact whitelist in [migration](MIGRATION.md); malformed/unsupported records produce warnings. |
-| Root `ids.txt`, operator drafts and supported global draft files | Imported without granting administrator authority. Configure trusted owners through `ADMIN`. |
-| MadelineProto session prefix `bot.shabbat*` | Copied intact to the new session volume while all old writers are stopped. It is not interpreted by the importer. |
-| Entire legacy `data/` | Also copied to the new data volume to retain BroadcastManager history and separate library state. |
-| `chatb1.json` and old global lock/date files | Retained as recovery evidence, never accepted as proof of current Telegram permissions or today's calendar state. |
+## 2. Verify production and set protected paths
-Imported groups keep the legacy Jerusalem/Asia-Jerusalem policy: city-default candle lighting, closure ten minutes before candles, havdalah at 8.5 degrees without an additional opening delay, Hebrew, and existing alert/message flags. They are **active** (`lock` or `lock_messages`); importing is not an automatic switch to off. Daily zmanim, daf, tefillin and Omer remain off for imported groups. Review these defaults if the server contains local modifications to the old implementation.
+On the server, list containers and inspect the selected production container. Replace the ID placeholder and change ORIGINAL_DIR to /root/shabat **only if that is the verified real path**. Assertions reject a different path/layout. Review the displayed mounts; no environment secrets are printed.
-**Permission acceptance is a separate gate.** Any imported `chatb1.json` is `legacy_unverified`. Even an otherwise open group without a snapshot receives `recovery_required` when a global old state file exists, including a leftover `open_lock.txt`. Such groups require an authorized group administrator to set/check the intended normal permissions in Telegram, refresh **Resolve permission problem**, and explicitly adopt current permissions outside Shabbat/Yom Tov and all active closure windows. The bot will not infer that a checksum makes an old snapshot safe. Do not delete recovery records or global state files to bypass this review.
-
-The old Composer specification used `^8.6` for MadelineProto and `*` for BroadcastManager, without a committed lock. Therefore the historical Git commit does not identify the server's actual installed dependency versions. Preserve its vendor and image; session compatibility must be checked during controlled startup. Keep original session bytes for rollback. Do not delete a session or create a second production-connected session as a troubleshooting shortcut.
-
-Review any pending broadcasts before the window. Copied `scheduled-broadcasts.json` and `self-destruct-jobs.json`, when present, are library state, not SQLite import records. Old schedules lack the new creator audit binding: future unattributed schedules block processing, and due unattributed schedules are cancelled rather than replayed as authorized new work. Due self-destruction jobs can act after startup. Preserve this state and review it privately; do not promise that interrupted broadcasts resume or that first startup has no external effects.
-
-## 2. Set paths and identify the actual production container
-
-Run the blocks in the same root Bash session. The timestamp creates new backup/staging destinations. Do not reuse a partially completed attempt without inspecting its state.
-
-```sh
+~~~sh
set -euo pipefail
umask 077
-ORIGINAL_DIR=/root/shabat
-TEST_DIR=/root/shabbat-test
-VERSION=3.0.0
-NEW_PROJECT=shabbat-production
-ARCHIVE="shabbat-${VERSION}.zip"
-test "$VERSION" = 3.0.0
-test "$NEW_PROJECT" = shabbat-production
-STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
-UPLOAD_DIR=/root/shabbat-release-upload
-RELEASE_DIR="/root/shabbat-releases/$VERSION-$STAMP"
-BACKUP_DIR="/root/shabbat-backups/$STAMP"
-RETIRED_DIR="/root/shabat-retired-$STAMP"
-test "$(readlink -f -- "$ORIGINAL_DIR")" = /root/shabat
-test "$ORIGINAL_DIR" != "$TEST_DIR"
-test -f "$ORIGINAL_DIR/docker-compose.yml"
-test -f "$ORIGINAL_DIR/bot.php"
-test -f "$ORIGINAL_DIR/.env"
-test -f "$ORIGINAL_DIR/data/DBgroups.txt"
-test ! -e "$RELEASE_DIR"
-test ! -e "$BACKUP_DIR"
-test ! -e "$RETIRED_DIR"
-df -h /root
-du -sh "$ORIGINAL_DIR"
-docker compose version
docker ps -a --filter label=com.docker.compose.service=shabbat \
--format '{{.ID}} {{.Names}} {{.Status}}'
-```
-
-Choose the existing production container from this list; never choose the test container. The next placeholder must be replaced with its actual ID. The inspection prints only mount paths and Compose labels, not resolved environment secrets.
-
-```sh
-OLD_CONTAINER_ID='REPLACE_WITH_VERIFIED_PRODUCTION_CONTAINER_ID'
+ORIGINAL_DIR=/root/shabbat
+OLD_CONTAINER_ID=REPLACE_WITH_VERIFIED_PRODUCTION_CONTAINER_ID
docker inspect --format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}' "$OLD_CONTAINER_ID"
-docker inspect --format '{{index .Config.Labels "com.docker.compose.project"}} / {{index .Config.Labels "com.docker.compose.service"}}' "$OLD_CONTAINER_ID"
+docker inspect --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$OLD_CONTAINER_ID"
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
+test "$(docker inspect --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$OLD_CONTAINER_ID")" = "$ORIGINAL_DIR"
test "$(docker inspect --format '{{index .Config.Labels "com.docker.compose.service"}}' "$OLD_CONTAINER_ID")" = shabbat
-test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app"}}{{.Type}}:{{.Source}}{{end}}{{end}}' "$OLD_CONTAINER_ID")" = "bind:$ORIGINAL_DIR"
+test -f "$ORIGINAL_DIR/.env"
+test -f "$ORIGINAL_DIR/docker-compose.yml"
OLD_PROJECT="$(docker inspect --format '{{index .Config.Labels "com.docker.compose.project"}}' "$OLD_CONTAINER_ID")"
OLD_IMAGE_ID="$(docker inspect --format '{{.Image}}' "$OLD_CONTAINER_ID")"
OLD_RESTART_POLICY="$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$OLD_CONTAINER_ID")"
+case "$OLD_RESTART_POLICY" in always|unless-stopped|no) ;; *) echo 'Review nonstandard restart policy first.' >&2; exit 1 ;; esac
+APP_MOUNT="$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app"}}{{.Type}}:{{.Source}}{{end}}{{end}}' "$OLD_CONTAINER_ID")"
+MOUNT_DESTINATIONS="$(docker inspect --format '{{range .Mounts}}{{println .Destination}}{{end}}' "$OLD_CONTAINER_ID" | sed '/^$/d' | sort)"
+if [ "$APP_MOUNT" = "bind:$ORIGINAL_DIR" ] && [ "$MOUNT_DESTINATIONS" = /app ]; then
+ LAYOUT=legacy
+ test -s "$ORIGINAL_DIR/data/DBgroups.txt"
+ test ! -e "$ORIGINAL_DIR/data/shabbat.sqlite"
+elif [ -z "$APP_MOUNT" ] && [ "$MOUNT_DESTINATIONS" = "$(printf '/app/data\n/app/runtime')" ]; then
+ LAYOUT=sqlite
+ test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app/data"}}{{.Type}}{{end}}{{end}}' "$OLD_CONTAINER_ID")" = volume
+ test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app/runtime"}}{{.Type}}{{end}}{{end}}' "$OLD_CONTAINER_ID")" = volume
+ test "$(cat "$ORIGINAL_DIR/VERSION")" = 3.0.0
+ docker exec "$OLD_CONTAINER_ID" php -r '
+ require "/app/vendor/autoload.php";
+ $paths=Shabbat\Runtime\RuntimePaths::resolve("/app");
+ if($paths->dataDirectory!=="/app/data"
+ || $paths->databasePath!=="/app/data/shabbat.sqlite"
+ || $paths->sessionPath!=="/app/runtime/bot.shabbat") {
+ throw new RuntimeException("Custom active data/session paths need a reviewed adaptation.");
+ }
+ '
+else
+ echo 'STOP: custom storage layout needs a reviewed backup/cutover.' >&2
+ exit 1
+fi
+VERSION=3.1.0
+NEW_PROJECT=shabbat-production-310
+STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
+UPLOAD_DIR=/root/shabbat-upload-3.1.0
+RELEASE_DIR="/root/shabbat-stage-$VERSION-$STAMP"
+BACKUP_DIR="/root/shabbat-backups/$VERSION-$STAMP"
+RETIRED_DIR="$ORIGINAL_DIR.before-$VERSION-$STAMP"
test -n "$OLD_PROJECT"
test "$OLD_PROJECT" != "$NEW_PROJECT"
-test "$OLD_RESTART_POLICY" = always
-install -d -m 700 "$UPLOAD_DIR" "$BACKUP_DIR"
-```
+test ! -e "$RELEASE_DIR"
+test ! -e "$BACKUP_DIR"
+test ! -e "$RETIRED_DIR"
+df -h /root
+docker system df
+install -d -m 700 "$BACKUP_DIR" "$RELEASE_DIR"
+printf '%s\n' "$ORIGINAL_DIR" "$OLD_CONTAINER_ID" "$OLD_PROJECT" "$OLD_IMAGE_ID" "$OLD_RESTART_POLICY" "$LAYOUT" > "$BACKUP_DIR/old-installation.txt"
+~~~
-Verify that the production container's `/app` mount is a **bind mount from `/root/shabat`**. The baseline uses restart policy `always`; if the final assertion fails, record/review the actual policy instead of blindly changing it. Any extra mounts, external session/database services, symlinks to private storage, a local SQLite database, custom Compose overrides, or additional production writers require a tailored backup before proceeding. This guide covers the inspected file-based layout. Inventory other services/supervisors that could restart the old bot and suspend them for the window. Do not alter the test installation.
+## 3. Verify, configure and build in staging
-Record the old runtime versions while it is still running; this PHP command only reads Composer metadata:
+The checksum must pass. Keep archive build-info.json. Edit the new .env privately: copy the same production API_ID/API_HASH/BOT_TOKEN and trusted ADMIN values; preserve relevant custom application settings and configure GeoNames deliberately; container paths are set below. Never print credentials or copy installed vendor. Keep BUILD_COMMIT absent from .env.
-```sh
-docker exec "$OLD_CONTAINER_ID" php -r '
-require "/app/vendor/autoload.php";
-echo "PHP ", PHP_VERSION, PHP_EOL;
-foreach (["danog/madelineproto", "wizardloop/broadcastmanager"] as $name) {
- echo $name, " ", Composer\InstalledVersions::getPrettyVersion($name), " ",
- Composer\InstalledVersions::getReference($name), PHP_EOL;
-}' > "$BACKUP_DIR/old-runtime-versions.txt"
-printf '%s\n' "$OLD_CONTAINER_ID" > "$BACKUP_DIR/old-container-id.txt"
-printf '%s\n' "$OLD_PROJECT" > "$BACKUP_DIR/old-compose-project.txt"
-printf '%s\n' "$OLD_IMAGE_ID" > "$BACKUP_DIR/old-image-id.txt"
-printf '%s\n' "$OLD_RESTART_POLICY" > "$BACKUP_DIR/old-restart-policy.txt"
-```
-
-Ensure storage can hold the complete old folder twice, its saved image, the new image and new data/session volumes. Keep these backup files private and outside every Docker build context.
-
-## 3. Download, verify and build the reviewed release beside production
-
-The deployment asset is `shabbat-3.0.0.zip`, with files directly at its root and no installed vendor. The separate corresponding-source ZIP is for source inspection; it is not the deployment archive. Use the assets attached to the stable `v3.0.0` release. The checksum block requires exactly one valid SHA-256 record for the expected deployment filename; missing or duplicate records stop the procedure.
-
-```sh
-RELEASE_URL="https://github.com/WizardLoop/shabbat/releases/download/v${VERSION}"
-curl --fail --location --proto '=https' --tlsv1.2 \
- "$RELEASE_URL/$ARCHIVE" -o "$UPLOAD_DIR/$ARCHIVE"
-curl --fail --location --proto '=https' --tlsv1.2 \
- "$RELEASE_URL/SHA256SUMS" -o "$UPLOAD_DIR/SHA256SUMS"
+~~~sh
(
cd "$UPLOAD_DIR"
- awk -v asset="$ARCHIVE" '
- $2 == asset {
- if (NF != 2 || length($1) != 64 || $1 ~ /[^0-9a-f]/) exit 1
- print $1 " " asset
- count++
- }
- END { if (count != 1) exit 1 }
- ' SHA256SUMS > deployment.sha256
+ awk '$2 == "shabbat-3.1.0.zip" {
+ if (NF != 2 || length($1) != 64 || $1 ~ /[^0-9a-f]/) exit 1
+ print; n++
+ } END { if (n != 1) exit 1 }' SHA256SUMS > deployment.sha256
sha256sum --check deployment.sha256
)
-install -d -m 700 "$RELEASE_DIR"
-unzip -q "$UPLOAD_DIR/$ARCHIVE" -d "$RELEASE_DIR"
+unzip -q "$UPLOAD_DIR/shabbat-3.1.0.zip" -d "$RELEASE_DIR"
test "$(cat "$RELEASE_DIR/VERSION")" = "$VERSION"
-test -f "$RELEASE_DIR/composer.lock"
test -f "$RELEASE_DIR/build-info.json"
cp "$RELEASE_DIR/.env.example" "$RELEASE_DIR/.env"
chmod 600 "$RELEASE_DIR/.env"
-```
-
-If uploading manually, upload the same two release assets to `UPLOAD_DIR` and begin with the checksum block. Do not unpack over the running old folder or copy the old installed vendor into the new source. Retain the supplied `build-info.json`; it records the release build's actual source identity. Do not substitute the historical baseline SHA or the test build's metadata. Leave `BUILD_COMMIT` absent from the new `.env`; the build block also unsets an inherited shell value so a stale test commit cannot override the archive identity.
+~~~
-Edit the **new** `.env` privately. Copy the existing production `API_ID`, `API_HASH`, `BOT_TOKEN` and trusted `ADMIN` values from the old private file without printing them or putting them in shell history. Retain the same bot identity. Add the GeoNames account and current configuration deliberately; [configuration](CONFIGURATION.md) documents every field. Use plain `KEY=value` syntax supported by both Compose and the PHP reader. Set these public/container paths exactly:
+Use these public container paths in the new .env alongside private credentials:
-```dotenv
+~~~dotenv
APP_DB_PATH=/app/data/shabbat.sqlite
DATA_DIR=/app/data
SESSION_PATH=/app/runtime/bot.shabbat
HEARTBEAT_PATH=/app/data/scheduler-heartbeat.json
LEGACY_DATA_PATH=.
-SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0
-```
+SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0
+~~~
-Compose explicitly fixes `DATA_DIR` and `SESSION_PATH`; the other paths above avoid a stale host/test path in `.env`. The release page must expose the matching corresponding-source asset before production service. Do not use test bot credentials. Never share `docker compose config` output without `--quiet`.
+After editing, build and run offline checks. The new project must have no existing volumes; inspect an earlier attempt instead of deleting them. These commands do not start the bot. Ensure space for the entire old folder, data/session snapshots, old image and new image.
-```sh
+~~~sh
new_compose() {
- docker compose --project-name "$NEW_PROJECT" \
- --project-directory "$RELEASE_DIR" --file "$RELEASE_DIR/docker-compose.yml" "$@"
+ docker compose --project-name "$NEW_PROJECT" --project-directory "$RELEASE_DIR" \
+ --file "$RELEASE_DIR/docker-compose.yml" "$@"
}
-if docker volume inspect "${NEW_PROJECT}_bot-data" >/dev/null 2>&1 \
- || docker volume inspect "${NEW_PROJECT}_madeline-session" >/dev/null 2>&1; then
- printf '%s\n' 'STOP: this production project already has volumes; inspect the earlier attempt.' >&2
+if docker volume inspect "$NEW_PROJECT"_bot-data >/dev/null 2>&1 \
+ || docker volume inspect "$NEW_PROJECT"_madeline-session >/dev/null 2>&1; then
+ echo 'STOP: destination volumes already exist.' >&2
exit 1
fi
unset BUILD_COMMIT
@@ -166,248 +131,215 @@ new_compose build shabbat
new_compose run --rm --no-deps shabbat php scripts/verify-patches.php
new_compose run --rm --no-deps shabbat php bin/self-check.php --release
new_compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
-new_compose run --rm --no-deps shabbat php bin/check-calendar.php
-```
+~~~
-These checks use the new image/volumes and leave the old bot running. The calendar check contacts public providers, not Telegram. Stop on any failure; no production cutover has happened yet. Do not run `up`, `php bot.php`, or a session diagnostic against the production credentials during this stage.
+## 4. Stop the old writer, then back up everything
-## 4. Stop the single production writer and preserve the entire old installation
+Choose a weekday window outside closure periods with a group administrator available. Review pending broadcasts/self-destruction jobs and stop external supervisors/other writers. From here production is offline. Preserve the old container, image and volumes. A forced/OOM termination requires investigation before continuing.
-Choose a weekday maintenance window outside religious/operational closure periods and pending broadcasts, with a group administrator available for recovery. Complete or review old in-flight work first. From this step until the explicit new startup, production is offline.
-
-```sh
-test "$(readlink -f -- "$ORIGINAL_DIR")" = /root/shabat
-test ! -e "$ORIGINAL_DIR/data/shabbat.sqlite"
+~~~sh
docker update --restart=no "$OLD_CONTAINER_ID"
docker stop --time 120 "$OLD_CONTAINER_ID"
test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
test "$(docker inspect --format '{{.State.Restarting}}' "$OLD_CONTAINER_ID")" = false
-docker inspect --format 'exit={{.State.ExitCode}} oom={{.State.OOMKilled}}' "$OLD_CONTAINER_ID"
-install -d -m 700 "$BACKUP_DIR/legacy"
-cp -a -- "$ORIGINAL_DIR/." "$BACKUP_DIR/legacy/"
+test "$(docker inspect --format '{{.State.OOMKilled}}' "$OLD_CONTAINER_ID")" = false
+test "$(docker inspect --format '{{.State.ExitCode}}' "$OLD_CONTAINER_ID")" != 137
+install -d -m 700 "$BACKUP_DIR/source" "$BACKUP_DIR/data" "$BACKUP_DIR/session"
+cp -a -- "$ORIGINAL_DIR/." "$BACKUP_DIR/source/"
(
cd "$ORIGINAL_DIR"
find . -type f -print0 | sort -z | xargs -0 sha256sum
-) > "$BACKUP_DIR/legacy-files.sha256"
-(
- cd "$BACKUP_DIR/legacy"
- sha256sum --check "$BACKUP_DIR/legacy-files.sha256"
-) > "$BACKUP_DIR/legacy-copy-verification.txt"
+) > "$BACKUP_DIR/source.sha256"
+(cd "$BACKUP_DIR/source"; sha256sum --check "$BACKUP_DIR/source.sha256") > "$BACKUP_DIR/source-check.txt"
+docker cp "$OLD_CONTAINER_ID:/app/data/." "$BACKUP_DIR/data/"
+if [ "$LAYOUT" = legacy ]; then
+ set -- "$BACKUP_DIR/source"/bot.shabbat*
+ test -e "$1"
+ cp -a -- "$@" "$BACKUP_DIR/session/"
+else
+ docker cp "$OLD_CONTAINER_ID:/app/runtime/." "$BACKUP_DIR/session/"
+ test -s "$BACKUP_DIR/data/shabbat.sqlite"
+fi
+if [ -d "$BACKUP_DIR/session/bot.shabbat" ]; then
+ test -s "$BACKUP_DIR/session/bot.shabbat/safe.php"
+elif [ -f "$BACKUP_DIR/session/bot.shabbat" ]; then
+ test -s "$BACKUP_DIR/session/bot.shabbat.safe.php"
+else
+ echo 'STOP: canonical session payload is missing; do not create a new session.' >&2
+ exit 1
+fi
+for part in data session; do
+ (cd "$BACKUP_DIR/$part"; find . -type f -print0 | sort -z | xargs -0 sha256sum) > "$BACKUP_DIR/$part.sha256"
+done
docker image save --output "$BACKUP_DIR/old-image.tar" "$OLD_IMAGE_ID"
sha256sum "$BACKUP_DIR/old-image.tar" > "$BACKUP_DIR/old-image.tar.sha256"
-```
-
-The restart-policy change prevents the old `restart: always` container from returning after a Docker daemon restart during cutover. It does not stop an external supervisor; verify every other writer is stopped too. An OOM/forced termination or a failed snapshot/hash check requires investigation before continuing. The SQLite-absence check deliberately stops this file-based procedure if an application database already exists.
+~~~
-Keep the old stopped container and image. Do not run `down`, remove volumes, prune images, or replace the original folder yet. Back up the protected directory off-server using your private backup mechanism. Its credentials, session, IDs, drafts and permission snapshots must never become release assets or public issue attachments.
+The snapshot includes .env, configuration, installed dependencies, data, database/WAL/SHM, session, root state and BroadcastManager files. Keep a protected off-server copy too. SQLite alone or DBgroups.txt alone is insufficient. No new bot/session has started.
-## 5. Copy stopped state into separate new volumes, then preview the import
+## 5. Copy into fresh volumes and prepare the database
-The root user below is used only for controlled offline copying/import, because the protected legacy snapshot may not be readable by UID 10001. The old snapshot is mounted read-only. Nothing is copied into the new image/build context. The normal bot will run as UID/GID 10001 after ownership is set explicitly.
+The snapshot is mounted read-only. Root is used only for offline copying/maintenance; the bot will run as UID/GID 10001. SHA256 verifies copied data/session before migration.
-```sh
+~~~sh
new_compose run --rm --no-deps --user 0:0 \
- --volume "$BACKUP_DIR/legacy:/legacy:ro" shabbat sh -ec '
+ --volume "$BACKUP_DIR:/review:ro" shabbat sh -ec '
test -z "$(find /app/data -mindepth 1 -maxdepth 1 -print -quit)"
test -z "$(find /app/runtime -mindepth 1 -maxdepth 1 -print -quit)"
- test ! -e /legacy/data/shabbat.sqlite
- test ! -e /legacy/data/upgrade-backups
- cp -a /legacy/data/. /app/data/
- set -- /legacy/bot.shabbat*
- test -e "$1"
- cp -a "$@" /app/runtime/
- mkdir -m 700 /app/data/upgrade-backups
-'
+ cp -a /review/data/. /app/data/
+ cp -a /review/session/. /app/runtime/
+ (cd /app/data; sha256sum --check /review/data.sha256)
+ (cd /app/runtime; sha256sum --check /review/session.sha256)
+ test ! -e /app/data/upgrade-3.1.0
+ mkdir -m 700 /app/data/upgrade-3.1.0
+' > "$BACKUP_DIR/copied-state-check.txt"
+inventory() {
+ new_compose run --rm --no-deps --user 0:0 shabbat php -r '
+ require "/app/vendor/autoload.php";
+ $db=Shabbat\Storage\Database::open("/app/data/shabbat.sqlite");
+ $result=[];
+ $tables=$db->pdo()->prepare("SELECT name FROM sqlite_master WHERE type=? ORDER BY name");
+ $tables->execute(["table"]);
+ foreach($tables->fetchAll(PDO::FETCH_COLUMN) as $name) {
+ if($name==="schema_migrations" || str_starts_with($name,"sqlite_")) continue;
+ if(!preg_match("/^[a-z_][a-z0-9_]*$/D",$name)) throw new RuntimeException("Unexpected table name");
+ $columns=$db->pdo()->query("PRAGMA table_info(\"".$name."\")")->fetchAll(PDO::FETCH_ASSOC);
+ $order=implode(",",array_map(fn($c)=>"\"".str_replace("\"","\"\"",$c["name"])."\"",$columns));
+ $rows=$db->pdo()->query("SELECT * FROM \"".$name."\" ORDER BY ".$order);
+ $hash=hash_init("sha256"); $count=0;
+ while($row=$rows->fetch(PDO::FETCH_ASSOC)) {
+ hash_update($hash,json_encode($row,JSON_THROW_ON_ERROR)."\n"); $count++;
+ }
+ $result[$name]=["rows"=>$count,"sha256"=>hash_final($hash)];
+ }
+ echo json_encode($result,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR),PHP_EOL;
+ '
+}
+if [ "$LAYOUT" = sqlite ]; then
+ inventory > "$BACKUP_DIR/database-before.json"
+fi
new_compose run --rm --no-deps --user 0:0 shabbat \
php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite \
- > "$BACKUP_DIR/migrate.json"
-new_compose run --rm --no-deps --user 0:0 \
- --volume "$BACKUP_DIR/legacy:/legacy:ro" shabbat \
- php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /legacy --dry-run \
- > "$BACKUP_DIR/import-preview.json"
-```
+ --backup-dir /app/data/upgrade-3.1.0 > "$BACKUP_DIR/migrate.json"
+if [ "$LAYOUT" = sqlite ]; then
+ inventory > "$BACKUP_DIR/database-after.json"
+ cmp "$BACKUP_DIR/database-before.json" "$BACKUP_DIR/database-after.json"
+fi
+~~~
-A missing session prefix, non-empty destination volume, unexpected database, unreadable file or importer error is a stop condition. Do not replace these assertions with deletion commands. Inspect the earlier attempt or custom server layout. No real session has been opened by these maintenance commands.
+For 3.0 SQLite, row hashes must match and no legacy import is needed; continue at step 7. For legacy, continue below. No SQL schema change is introduced in 3.1.0; investigate any unexpected difference before startup.
-Read the private JSON preview. Compare its unique group IDs and count with the old subscription list, and sample opening/closing messages, buttons, media IDs, alert flags and private drafts against the snapshot. Inspect **every warning and recovery entry**, not only the count. Invalid IDs, malformed JSON, unsupported buttons, oversized drafts and missing originals must be accounted for. A preview can report the expected fixed Jerusalem timing warning; that does not resolve unrelated warnings. The importer covers the whitelist documented in [migration](MIGRATION.md), not arbitrary local additions to the old bot.
+## 6. Legacy only: review and bind the import
-Dry-run is supported and does not apply application records. It is not a full transaction rehearsal: some normalized private-draft handling occurs only during apply. The apply operation makes a verified pre-import SQLite backup but the complete legacy import is not one all-or-nothing transaction. If apply fails, keep the new bot stopped, preserve its report/state, and review or restore the verified pre-import database before retrying. Re-import preserves existing records; it does not repair a malformed record by overwriting an existing preference.
+Preview every registered group, setting, template, message, alert, draft and permission warning. Duplicates are reported/deduplicated. Directory-only groups are reported, not automatically subscribed: they may be stale. If necessary, reconcile them in a separate reviewed import copy, preserve the original snapshot and generate a fresh preview. The whitelist is documented in [migration](MIGRATION.md); arbitrary local extensions need review.
-## 6. Apply and verify every registered group before starting the bot
+~~~sh
+test "$LAYOUT" = legacy
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat \
+ php bin/import-legacy.php --db /app/data/shabbat.sqlite \
+ --legacy /review/source --dry-run > "$BACKUP_DIR/import-preview.json"
+~~~
-After accepting the preview and planning any required permission review:
+Read the private JSON and accept every source/target difference before the next block. --expect-report rejects changed source or affected target records. Existing settings/templates are preserved. Imported groups are active, with documented Jerusalem/legacy timing and alert defaults; new daily/reminder modules stay off. Review location/mode before normal service.
-```sh
+Apply is not one all-or-nothing transaction. On failure keep the bot stopped, preserve evidence and restore/review the verified pre-import backup before retrying. Do not weaken report matching.
+
+~~~sh
new_compose run --rm --no-deps --user 0:0 \
- --volume "$BACKUP_DIR/legacy:/legacy:ro" shabbat \
- php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /legacy \
- --apply --writers-stopped --backup-dir /app/data/upgrade-backups \
- > "$BACKUP_DIR/import-apply.json"
-```
-
-The next snippet uses the project's real database API to check schema checksums, integrity, foreign keys, exact group-ID equality and one settings row per group. It prints a private inventory for human review and fails on invalid IDs, missing groups, unexpected groups or an empty source list. It does not call Telegram or invent a new application CLI option.
-
-```sh
-new_compose run --rm --no-deps -T --user 0:0 \
- --volume "$BACKUP_DIR:/review:ro" shabbat php \
- > "$BACKUP_DIR/import-verification.json" <<'PHP'
-assertCurrentSchema();
-$checks = $db->integrity();
-if ($checks['integrity_check'] !== ['ok'] || $checks['foreign_key_check'] !== []) {
- throw new RuntimeException('Database integrity or foreign-key check failed.');
-}
-$expected = [];
-foreach (preg_split('/\R/', file_get_contents('/review/legacy/data/DBgroups.txt')) as $line) {
- $id = trim($line);
- if ($id === '') { continue; }
- if (!preg_match('/^-?[0-9]{1,20}$/D', $id)) {
- throw new RuntimeException('Invalid legacy group identifier requires review.');
- }
- $expected[$id] = $id;
-}
-$expected = array_values($expected);
-sort($expected, SORT_STRING);
-$actual = $db->pdo()->query('SELECT group_id FROM groups')->fetchAll(PDO::FETCH_COLUMN);
-sort($actual, SORT_STRING);
-if ($expected === [] || $actual !== $expected) {
- throw new RuntimeException('Imported group IDs do not exactly match the non-empty legacy list.');
-}
-$settings = $db->pdo()->query('SELECT group_id,mode,language,location_name,timezone_id,candle_minutes,havdalah_method,havdalah_value,close_before_candles_minutes,open_after_havdalah_minutes,times_alert_enabled,close_message_enabled,open_message_enabled,zmanim_enabled,daf_enabled,tefillin_enabled,omer_enabled FROM group_settings ORDER BY group_id')->fetchAll();
-if (count($settings) !== count($expected)) {
- throw new RuntimeException('Missing group settings.');
-}
-$counts = [];
-foreach (['groups','group_settings','users','message_templates','admin_state','known_broadcast_peers','legacy_imports'] as $table) {
- $counts[$table] = (int) $db->pdo()->query('SELECT COUNT(*) FROM '.$table)->fetchColumn();
-}
-$recovery = $db->pdo()->query('SELECT group_id,status,snapshot_provenance,last_error FROM group_lock_state ORDER BY group_id')->fetchAll();
-echo Database::encode(['checks'=>$checks,'counts'=>$counts,'group_settings'=>$settings,'permission_review'=>$recovery]), PHP_EOL;
-PHP
-```
+ --volume "$BACKUP_DIR:/review:ro" shabbat \
+ php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /review/source \
+ --apply --writers-stopped --backup-dir /app/data/upgrade-3.1.0 \
+ --expect-report /review/import-preview.json > "$BACKUP_DIR/import-apply.json"
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat php -r '
+ $r=json_decode(file_get_contents("/review/import-apply.json"),true,512,JSON_THROW_ON_ERROR);
+ if(($r["verification"]["status"]??null)!=="passed") throw new RuntimeException("Import verification failed");
+ echo "Import comparison passed.",PHP_EOL;
+'
+~~~
-Review the settings against the source flags and inspect normalized templates through the backed-up database/private reports. Template totals include both group templates and personal drafts, so they need not equal the number of groups or the preview's group-template count. Legacy-selected groups and saved drafts confer no administrator authority. Keep the original files as evidence even after a successful import.
+Old chatb1.json snapshots/global lock files are evidence, not verified current permissions. Administrator review may be required even if the group appears open. Never delete recovery state or automatically restore a permissive old snapshot. See [permission recovery](PERMISSION_RECOVERY.md).
-Preserve a verified post-import SQLite backup without any retention deletion. This snippet calls the existing `BackupService::backup` directly to a new filename; it does not invoke the pruning helper. It also copies the migration/import backups out of the volume and sets ownership on the **new** data/session volumes only.
+## 7. Verify, back up and rehearse restore
-```sh
+These maintenance commands check schema/integrity, make a new SQLite backup without pruning old backups, export it privately and restore to a disposable path. They never open the Telegram session. Offline health needs live heartbeats; use structural checks here and real health after startup.
+
+~~~sh
new_compose run --rm --no-deps --user 0:0 shabbat php -r '
require "/app/vendor/autoload.php";
-$db = Shabbat\Storage\Database::open("/app/data/shabbat.sqlite");
-$result = (new Shabbat\Storage\BackupService())->backup($db, "/app/data/upgrade-backups/post-import.sqlite");
-echo Shabbat\Storage\Database::encode($result), PHP_EOL;
-' > "$BACKUP_DIR/post-import-backup.json"
+$db=Shabbat\Storage\Database::open("/app/data/shabbat.sqlite");
+$db->assertCurrentSchema();
+$checks=$db->integrity();
+if($checks["integrity_check"]!==["ok"] || $checks["foreign_key_check"]!==[]) throw new RuntimeException("Database check failed");
+$result=(new Shabbat\Storage\BackupService())->backup($db,"/app/data/upgrade-3.1.0/ready.sqlite");
+echo Shabbat\Storage\Database::encode($result),PHP_EOL;
+' > "$BACKUP_DIR/ready-backup.json"
install -d -m 700 "$BACKUP_DIR/sqlite"
new_compose run --rm --no-deps --user 0:0 \
--volume "$BACKUP_DIR/sqlite:/export" shabbat sh -ec '
- cp -a /app/data/upgrade-backups/. /export/
+ cp -a /app/data/upgrade-3.1.0/. /export/
chown -R 10001:10001 /app/data /app/runtime
'
-new_compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+new_compose run --rm --no-deps shabbat php bin/restore.php \
+ --backup /app/data/upgrade-3.1.0/ready.sqlite \
+ --db /tmp/restore-rehearsal.sqlite --writers-stopped > "$BACKUP_DIR/restore-rehearsal.json"
new_compose run --rm --no-deps shabbat php scripts/verify-patches.php
new_compose run --rm --no-deps shabbat php bin/self-check.php --release
-```
-
-Rehearse the actual restore into a new disposable destination in a maintenance container. It validates the backup and creates an isolated SQLite copy; it does not replace `/app/data/shabbat.sqlite` or open the bot session.
-
-```sh
-new_compose run --rm --no-deps shabbat php bin/restore.php \
- --backup /app/data/upgrade-backups/post-import.sqlite \
- --db /tmp/shabbat-restore-rehearsal.sqlite --writers-stopped \
- > "$BACKUP_DIR/restore-rehearsal.json"
-```
-
-Accept the restore output and the complete source/private-state backup before proceeding. `health.php`, even with `--deep`, also needs recent live scheduler heartbeats; an offline restore cannot satisfy that live-health gate. Use the structural checks above before startup, then the real live probe afterwards.
+new_compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+~~~
-## 7. Put the reviewed source at `/root/shabat`
+## 8. Swap the source and start exactly one bot
-Proceed only after all offline checks and backups pass, every import warning is understood, and the administrator has a plan for each recovery entry. The old bot remains stopped. The two renames preserve the complete original directory and move the already-built source into the requested final path; they do not overlay old vendor or data with new files.
+Proceed after accepting reports, backup/restore and recovery plans. The old directory is renamed intact, never overlaid. If the second rename fails, stop and restore the retained directory only after verifying ORIGINAL_DIR is absent. Keep the old container stopped while its original bind path holds new source.
-```sh
+~~~sh
test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
test "$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$OLD_CONTAINER_ID")" = no
-test "$(readlink -f -- "$ORIGINAL_DIR")" = /root/shabat
-case "$(readlink -f -- "$RELEASE_DIR")" in
- /root/shabbat-releases/*) ;;
- *) printf '%s\n' 'Unexpected staging path; stop.' >&2; exit 1 ;;
-esac
-case "$RETIRED_DIR" in
- /root/shabat-retired-*) ;;
- *) printf '%s\n' 'Unexpected retained-source path; stop.' >&2; exit 1 ;;
-esac
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
+test "$RELEASE_DIR" = "/root/shabbat-stage-$VERSION-$STAMP"
+test "$RETIRED_DIR" = "$ORIGINAL_DIR.before-$VERSION-$STAMP"
test ! -e "$RETIRED_DIR"
mv -T -- "$ORIGINAL_DIR" "$RETIRED_DIR"
mv -T -- "$RELEASE_DIR" "$ORIGINAL_DIR"
RELEASE_DIR="$ORIGINAL_DIR"
cd "$ORIGINAL_DIR"
new_compose config --quiet
-printf '%s\n' "$RETIRED_DIR" > "$BACKUP_DIR/retired-source-path.txt"
-printf '%s\n' "$NEW_PROJECT" > "$BACKUP_DIR/new-compose-project.txt"
-```
-
-If the second rename fails, stop and inspect both paths. The original is preserved at `RETIRED_DIR`; return it to `/root/shabat` only after verifying that the destination is absent. Do not merge directory contents or use an overwrite operation to conceal a partial cutover.
-
-**The stopped old container still has a bind mount whose source is `/root/shabat`. It must not be started while that path contains the new source.** Its old image/vendor assumptions do not match the new layout. The rollback section restores the old directory before restarting that container.
-
-## 8. Start exactly one production instance and accept it
-
-This step connects to Telegram, sends the existing administrator startup notification, and enables all imported active group behavior. It is not a harmless smoke test. Confirm the bot identity, the reviewed source URL, the maintenance window and the intended permissions once more.
-
-```sh
-test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
+printf '%s\n' "$RETIRED_DIR" "$NEW_PROJECT" > "$BACKUP_DIR/new-installation.txt"
new_compose up -d --no-build shabbat
new_compose ps
new_compose logs --tail=120 shabbat
-```
+~~~
-Keep logs private. Wait for completed permission and notification scheduler passes, then run:
+Starting can act on active groups, send a startup notification and process library work. Old unattributed broadcast schedules may be blocked/cancelled; copied self-destruction work can run. Review preserved BroadcastManager state; never assume an interrupted broadcast is safe to replay.
-```sh
+After startup, check health. In Telegram check /start, home/settings transitions, callbacks, /source identity, group counts, location/timezone, templates and alert preferences. In a disposable group with known pre-existing restrictions, test close/open and restart; do not use bulk /closegroups or /opengroups as a smoke test.
+
+~~~sh
new_compose exec -T shabbat php bin/health.php --deep
new_compose ps
-```
-
-Both heartbeat ages must be current; allow initial startup/provider work to complete and investigate repeated failure. A green health probe establishes the checks it reports, not that every group has resolved its imported permission debt. Do not start a second process to investigate session/authentication errors. Stop the new service and inspect the preserved versions/session state first; rollback remains available.
-
-As the configured bot owner, use `/version` or `/source` privately to verify release identity, `/admin` and its diagnostics to inspect registered groups, then `/settings` for a representative group and every group marked for recovery. Existing imported groups need no `/add`. Confirm group count, local time/location, original notification flags and custom message previews without sending a mass broadcast or using `/closegroups` / `/opengroups` as a test.
-
-For **each** unresolved legacy permission record, a current group administrator must follow [permission recovery](PERMISSION_RECOVERY.md): outside protected periods, configure the actual intended normal group permissions in Telegram; refresh the bot's **Resolve permission problem** panel; review the named group; and explicitly choose **Use current permissions as normal**. A legacy/unverified snapshot cannot be used by the restore button. Adoption does not itself send a restriction update. Re-check diagnostics; leave unexplained mismatches unresolved rather than treating generally open permissions as the intended baseline.
-
-Review copied broadcast history and any cancelled/blocked schedule. Do not recreate an interrupted broadcast without checking which messages Telegram already accepted. Monitor both heartbeats, pending permission recovery, queue age, delivery delay and private logs through startup and the first real scheduled close/open cycle. Investigate missing work, repeated retries, provider failures or growing queues before considering the cutover accepted. Retain the old source/session/private backup until that cycle and recovery behavior have been accepted; the earlier dev.9 manual/live confirmation does not substitute for this observation.
+~~~
-The permanent production commands are now run **from `/root/shabat`, with the recorded project name**:
+A group administrator must resolve every unverified snapshot outside protected periods: set intended normal rights in Telegram, refresh the named recovery panel and explicitly adopt current permissions. Generally open rights are not necessarily the intended baseline. Monitor both heartbeats, queues, permissions and reminders through the first real Shabbat/festival close/open sequence. Earlier 3.0 live checks do not certify 3.1.0, holiday timing or a long soak. Retain rollback material until acceptance.
-```sh
-cd /root/shabat
-docker compose --project-name shabbat-production ps
-docker compose --project-name shabbat-production logs --tail=120 shabbat
-docker compose --project-name shabbat-production exec -T shabbat php bin/health.php --deep
-```
+Future commands run from the verified ORIGINAL_DIR with **--project-name shabbat-production-310**. Keep that project identity and both volumes. Back up matching source, .env, database, session and BroadcastManager state.
-For an intentional later stop, use `docker compose --project-name shabbat-production stop shabbat`; for an approved restart, use `docker compose --project-name shabbat-production restart shabbat`. The new persistent volumes are `shabbat-production_bot-data` and `shabbat-production_madeline-session`. Keep both, the private `.env`, matching source/lock/patches and corresponding-source identity in the normal backup policy. A later SQLite-version upgrade follows the stopped-writer backup/migration instructions, not this legacy import again.
+## 9. Rollback
-## 9. Roll back without mixing old and new state
+**Before either rename/start:** old source/state remain unchanged. If no new service is running and RETIRED_DIR does not exist, restore the recorded restart policy and start the old container:
-Before any new startup, rollback can return the preserved old directory/container directly. **After the new bot has contacted Telegram, rollback also requires a remote-state review:** restoring files does not undo sent messages, updated permissions, broadcast actions or Telegram session changes. Settle any new bot-owned permission changes and stop new activity before restoring older state. Do not copy the new SQLite database or newly written session over the old file-based installation.
-
-If the maintenance attempt stopped **before either rename in step 7**, the original folder is still in place. Verify that no new production service is running and that no retained-source directory was created, then restore the old restart policy and start its existing container:
-
-```sh
+~~~sh
test ! -e "$RETIRED_DIR"
-test "$(readlink -f -- "$ORIGINAL_DIR")" = /root/shabat
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
test -z "$(docker ps --filter label=com.docker.compose.project="$NEW_PROJECT" --filter label=com.docker.compose.service=shabbat --quiet)"
docker update --restart="$OLD_RESTART_POLICY" "$OLD_CONTAINER_ID"
docker start "$OLD_CONTAINER_ID"
-```
-
-For this pre-swap rollback, stop here. The remaining rollback blocks apply after step 7 replaced the directory.
+~~~
-If the new service was started, stop it and disable automatic restart before touching directories. These commands run in the same session, with `RELEASE_DIR=/root/shabat` after the swap:
+Stop here for pre-swap rollback. **After a completed swap/start**, first review remote effects: files cannot undo Telegram permissions/messages/broadcasts. Resolve new bot-owned permission debt before decommissioning, then stop and preserve new state:
-```sh
+~~~sh
NEW_CONTAINER_ID="$(new_compose ps -a -q shabbat)"
if [ -n "$NEW_CONTAINER_ID" ]; then
docker update --restart=no "$NEW_CONTAINER_ID"
@@ -417,44 +349,25 @@ if [ -n "$NEW_CONTAINER_ID" ]; then
test "$(docker inspect --format '{{.State.Running}}' "$NEW_CONTAINER_ID")" = false
fi
test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
-```
-
-Preserve the stopped new volumes for diagnosis. The helper command only reads the volumes and writes private tar files outside the source tree; it does not launch the bot. Use a new destination if this rollback capture has already been taken.
-
-```sh
test ! -e "$BACKUP_DIR/failed-new-state"
install -d -m 700 "$BACKUP_DIR/failed-new-state"
new_compose run --rm --no-deps --user 0:0 \
--volume "$BACKUP_DIR/failed-new-state:/export" shabbat sh -ec '
- tar -cpf /export/new-data.tar -C /app/data .
- tar -cpf /export/new-session.tar -C /app/runtime .
+ tar -cpf /export/data.tar -C /app/data .
+ tar -cpf /export/session.tar -C /app/runtime .
'
-sha256sum "$BACKUP_DIR/failed-new-state/"*.tar \
- > "$BACKUP_DIR/failed-new-state/SHA256SUMS"
-```
-
-After reviewing any remote effects, return the preserved old folder to its original path. This block applies only after the completed step-7 swap; use the separate pre-swap branch above if no rename occurred.
-
-```sh
-FAILED_SOURCE_DIR="/root/shabat-failed-$STAMP"
-test "$(readlink -f -- "$ORIGINAL_DIR")" = /root/shabat
+sha256sum "$BACKUP_DIR/failed-new-state/"*.tar > "$BACKUP_DIR/failed-new-state/SHA256SUMS"
+FAILED_DIR="$ORIGINAL_DIR.failed-$VERSION-$STAMP"
+test "$RETIRED_DIR" = "$ORIGINAL_DIR.before-$VERSION-$STAMP"
test -d "$RETIRED_DIR"
-case "$RETIRED_DIR" in /root/shabat-retired-*) ;; *) exit 1 ;; esac
-case "$FAILED_SOURCE_DIR" in /root/shabat-failed-*) ;; *) exit 1 ;; esac
-test ! -e "$FAILED_SOURCE_DIR"
-mv -T -- "$ORIGINAL_DIR" "$FAILED_SOURCE_DIR"
+test ! -e "$FAILED_DIR"
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+mv -T -- "$ORIGINAL_DIR" "$FAILED_DIR"
mv -T -- "$RETIRED_DIR" "$ORIGINAL_DIR"
test -f "$ORIGINAL_DIR/.env"
-test -f "$ORIGINAL_DIR/data/DBgroups.txt"
docker update --restart="$OLD_RESTART_POLICY" "$OLD_CONTAINER_ID"
docker start "$OLD_CONTAINER_ID"
-docker logs --tail=120 "$OLD_CONTAINER_ID"
-```
-
-This restarts the exact retained old container/image against its original code, vendor, `.env`, data and pre-cutover session. Do not use `compose up --build` or pull the old mutable image for rollback. If the old image/container or retained directory is missing, stop and restore from the private full-folder/image backup with a separately reviewed recovery procedure; do not improvise a partial rollback.
-
-Keep the failed new source, both new volumes and all reports. A new attempt must start with an inspected state and a fresh stopped snapshot; the existing-destination guards are intentional. If authentication or permissions changed on Telegram during the new run, the old runtime still needs explicit review even though its local bytes were preserved.
-
-## Acceptance record
+docker logs --tail=100 "$OLD_CONTAINER_ID"
+~~~
-Record the verified release checksum/commit, the old runtime versions/container/image, backup paths and hashes, import counts/warnings, exact group-ID comparison, schema/integrity/restore results, final Compose project/volume names, live health, and each group's permission-review outcome. Record unresolved limitations honestly. Keep identifiers, session material, private logs, credentials and backup contents outside GitHub and public release assets.
\ No newline at end of file
+The old folder is restored before its bind-mounted container restarts; original volumes/image/session were retained. Never overwrite the old snapshot with the new database/session. Session compatibility and remote Telegram state still require observation. Do not remove either state set, volumes or retained images during this procedure.
diff --git a/docs/PRODUCTION_UPGRADE_HE.md b/docs/PRODUCTION_UPGRADE_HE.md
new file mode 100644
index 0000000..8e39dbe
--- /dev/null
+++ b/docs/PRODUCTION_UPGRADE_HE.md
@@ -0,0 +1,433 @@
+
+
+# שדרוג בטוח ל־3.1.0
+
+[English](PRODUCTION_UPGRADE.md) · [README בעברית](../readme-he.md) · [מיפוי הייבוא](MIGRATION.md) · [התאוששות הרשאות](PERMISSION_RECOVERY.md)
+
+זהו מדריך לביצוע ידני; לא בוצעה פריסה. השתמשו בקובצי 3.1.0 שפורסמו ואומתו לאחר שבדיקות החובה עברו. הנתיב המבוקש הוא **/root/shabbat**; בתיעוד קודם הופיע **/root/shabat**. חובה לאמת את הקונטיינר והתיקייה האמיתיים לפני שינוי. אין להשתמש בנתוני בוט הבדיקה.
+
+הפקודות תומכות בהתקנת legacy שמחברת את כל הפרויקט ובאמצעי האחסון הרגילים של 3.0. בדיקת הנתיבים ב־3.0 קוראת תצורה בלבד; היא אינה פותחת API או סשן. שם סשן מותאם או שרידי נעילה ללא תוכן סשן עוצרים את ההליך. חיבורים מותאמים, אחסון חיצוני, קישורים לנתונים פרטיים או כותב נוסף מחייבים גיבוי מותאם מראש. הריצו את בלוקי השרת באותו **חלון Bash כ־root**, עם Docker/Compose, unzip, כלי GNU ומקום פנוי מספיק. הגיבויים נשמרים מחוץ לקוד ולבנייה. רק ההפעלה בסוף מחברת את הבוט החדש ל־Telegram.
+
+האימג׳ החדש משתמש ב־PHP **8.4.27**. בהתקנה ידנית נדרש **8.3.36+, 8.4.27+ או 8.5.12+** בתוך הענפים האלה; ראו [דרישות אבטחה מ־22 באוקטובר 2026](INSTALLATION.md#php-security-baseline). שמרו את האימג׳ הישן לחזרה לאחור, אך אין לראות במפרש ישן עמידה בדרישות החדשות.
+
+## 1. העלאה מהמחשב
+
+הורידו את ארכיון הפריסה ואת SHA256SUMS משחרור GitHub המתאים. במסוף במחשב החליפו SERVER בשם השרת או בכתובת ה־IP. אפשר להעלות את אותם קבצים גם ב־SFTP לאותו יעד פרטי.
+
+
+
+~~~sh
+ssh root@SERVER "install -d -m 700 /root/shabbat-upload-3.1.0"
+scp shabbat-3.1.0.zip SHA256SUMS root@SERVER:/root/shabbat-upload-3.1.0/
+~~~
+
+
+
+## 2. אימות ההתקנה והנתיבים
+
+בשרת הציגו את הקונטיינרים ובחרו את קונטיינר הייצור. החליפו את מזהה הדוגמה ושנו את ORIGINAL_DIR ל־/root/shabat **רק אם זה הנתיב האמיתי שאומת**. הבדיקות עוצרות בנתיב או במבנה אחר. בדקו את החיבורים המוצגים; סודות מהסביבה אינם מודפסים.
+
+
+
+~~~sh
+set -euo pipefail
+umask 077
+docker ps -a --filter label=com.docker.compose.service=shabbat \
+ --format '{{.ID}} {{.Names}} {{.Status}}'
+ORIGINAL_DIR=/root/shabbat
+OLD_CONTAINER_ID=REPLACE_WITH_VERIFIED_PRODUCTION_CONTAINER_ID
+docker inspect --format '{{range .Mounts}}{{println .Type .Source "->" .Destination}}{{end}}' "$OLD_CONTAINER_ID"
+docker inspect --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$OLD_CONTAINER_ID"
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
+test "$(docker inspect --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}' "$OLD_CONTAINER_ID")" = "$ORIGINAL_DIR"
+test "$(docker inspect --format '{{index .Config.Labels "com.docker.compose.service"}}' "$OLD_CONTAINER_ID")" = shabbat
+test -f "$ORIGINAL_DIR/.env"
+test -f "$ORIGINAL_DIR/docker-compose.yml"
+OLD_PROJECT="$(docker inspect --format '{{index .Config.Labels "com.docker.compose.project"}}' "$OLD_CONTAINER_ID")"
+OLD_IMAGE_ID="$(docker inspect --format '{{.Image}}' "$OLD_CONTAINER_ID")"
+OLD_RESTART_POLICY="$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$OLD_CONTAINER_ID")"
+case "$OLD_RESTART_POLICY" in always|unless-stopped|no) ;; *) echo 'Review nonstandard restart policy first.' >&2; exit 1 ;; esac
+APP_MOUNT="$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app"}}{{.Type}}:{{.Source}}{{end}}{{end}}' "$OLD_CONTAINER_ID")"
+MOUNT_DESTINATIONS="$(docker inspect --format '{{range .Mounts}}{{println .Destination}}{{end}}' "$OLD_CONTAINER_ID" | sed '/^$/d' | sort)"
+if [ "$APP_MOUNT" = "bind:$ORIGINAL_DIR" ] && [ "$MOUNT_DESTINATIONS" = /app ]; then
+ LAYOUT=legacy
+ test -s "$ORIGINAL_DIR/data/DBgroups.txt"
+ test ! -e "$ORIGINAL_DIR/data/shabbat.sqlite"
+elif [ -z "$APP_MOUNT" ] && [ "$MOUNT_DESTINATIONS" = "$(printf '/app/data\n/app/runtime')" ]; then
+ LAYOUT=sqlite
+ test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app/data"}}{{.Type}}{{end}}{{end}}' "$OLD_CONTAINER_ID")" = volume
+ test "$(docker inspect --format '{{range .Mounts}}{{if eq .Destination "/app/runtime"}}{{.Type}}{{end}}{{end}}' "$OLD_CONTAINER_ID")" = volume
+ test "$(cat "$ORIGINAL_DIR/VERSION")" = 3.0.0
+ docker exec "$OLD_CONTAINER_ID" php -r '
+ require "/app/vendor/autoload.php";
+ $paths=Shabbat\Runtime\RuntimePaths::resolve("/app");
+ if($paths->dataDirectory!=="/app/data"
+ || $paths->databasePath!=="/app/data/shabbat.sqlite"
+ || $paths->sessionPath!=="/app/runtime/bot.shabbat") {
+ throw new RuntimeException("Custom active data/session paths need a reviewed adaptation.");
+ }
+ '
+else
+ echo 'STOP: custom storage layout needs a reviewed backup/cutover.' >&2
+ exit 1
+fi
+VERSION=3.1.0
+NEW_PROJECT=shabbat-production-310
+STAMP="$(date -u +%Y%m%dT%H%M%SZ)"
+UPLOAD_DIR=/root/shabbat-upload-3.1.0
+RELEASE_DIR="/root/shabbat-stage-$VERSION-$STAMP"
+BACKUP_DIR="/root/shabbat-backups/$VERSION-$STAMP"
+RETIRED_DIR="$ORIGINAL_DIR.before-$VERSION-$STAMP"
+test -n "$OLD_PROJECT"
+test "$OLD_PROJECT" != "$NEW_PROJECT"
+test ! -e "$RELEASE_DIR"
+test ! -e "$BACKUP_DIR"
+test ! -e "$RETIRED_DIR"
+df -h /root
+docker system df
+install -d -m 700 "$BACKUP_DIR" "$RELEASE_DIR"
+printf '%s\n' "$ORIGINAL_DIR" "$OLD_CONTAINER_ID" "$OLD_PROJECT" "$OLD_IMAGE_ID" "$OLD_RESTART_POLICY" "$LAYOUT" > "$BACKUP_DIR/old-installation.txt"
+~~~
+
+
+
+## 3. אימות, הגדרה ובנייה ב־staging
+
+אימות הקובץ חייב לעבור. שמרו את build-info.json שבארכיון. ערכו את .env החדש בפרטיות: העתיקו את API_ID/API_HASH/BOT_TOKEN של אותו בוט ייצור ואת המנהלים המהימנים; שמרו הגדרות יישום מותאמות רלוונטיות והגדירו GeoNames לפי הצורך; נתיבי הקונטיינר נקבעים בהמשך. אין להדפיס סודות או להעתיק vendor מותקן. השאירו את BUILD_COMMIT מחוץ ל־.env.
+
+
+
+~~~sh
+(
+ cd "$UPLOAD_DIR"
+ awk '$2 == "shabbat-3.1.0.zip" {
+ if (NF != 2 || length($1) != 64 || $1 ~ /[^0-9a-f]/) exit 1
+ print; n++
+ } END { if (n != 1) exit 1 }' SHA256SUMS > deployment.sha256
+ sha256sum --check deployment.sha256
+)
+unzip -q "$UPLOAD_DIR/shabbat-3.1.0.zip" -d "$RELEASE_DIR"
+test "$(cat "$RELEASE_DIR/VERSION")" = "$VERSION"
+test -f "$RELEASE_DIR/build-info.json"
+cp "$RELEASE_DIR/.env.example" "$RELEASE_DIR/.env"
+chmod 600 "$RELEASE_DIR/.env"
+~~~
+
+
+
+הגדירו ב־.env החדש את נתיבי הקונטיינר הציבוריים האלה לצד פרטי ההתחברות הפרטיים:
+
+
+
+~~~dotenv
+APP_DB_PATH=/app/data/shabbat.sqlite
+DATA_DIR=/app/data
+SESSION_PATH=/app/runtime/bot.shabbat
+HEARTBEAT_PATH=/app/data/scheduler-heartbeat.json
+LEGACY_DATA_PATH=.
+SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0
+~~~
+
+
+
+לאחר העריכה בנו ובצעו בדיקות לא מקוונות. לפרויקט החדש אסור שיהיו אמצעי אחסון קיימים; אם נמצא ניסיון קודם, בדקו אותו במקום למחוק. הפקודות אינן מפעילות את הבוט. ודאו מקום לתיקייה הישנה, לנתונים ולסשן, לתמונה הישנה ולתמונה החדשה.
+
+
+
+~~~sh
+new_compose() {
+ docker compose --project-name "$NEW_PROJECT" --project-directory "$RELEASE_DIR" \
+ --file "$RELEASE_DIR/docker-compose.yml" "$@"
+}
+if docker volume inspect "$NEW_PROJECT"_bot-data >/dev/null 2>&1 \
+ || docker volume inspect "$NEW_PROJECT"_madeline-session >/dev/null 2>&1; then
+ echo 'STOP: destination volumes already exist.' >&2
+ exit 1
+fi
+unset BUILD_COMMIT
+new_compose config --quiet
+new_compose build shabbat
+new_compose run --rm --no-deps shabbat php scripts/verify-patches.php
+new_compose run --rm --no-deps shabbat php bin/self-check.php --release
+new_compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+~~~
+
+
+
+## 4. עצירת הכותב הישן וגיבוי מלא
+
+בחרו חלון תחזוקה ביום חול, מחוץ לזמני הסגירה, עם מנהל קבוצה זמין. בדקו שידורים ומחיקות מתוזמנים ועצרו מנהלי תהליכים וכותבים נוספים. מכאן הייצור מושבת. שמרו את הקונטיינר, התמונה ואמצעי האחסון הישנים. עצירה כפויה או OOM מחייבות בירור לפני המשך.
+
+
+
+~~~sh
+docker update --restart=no "$OLD_CONTAINER_ID"
+docker stop --time 120 "$OLD_CONTAINER_ID"
+test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
+test "$(docker inspect --format '{{.State.Restarting}}' "$OLD_CONTAINER_ID")" = false
+test "$(docker inspect --format '{{.State.OOMKilled}}' "$OLD_CONTAINER_ID")" = false
+test "$(docker inspect --format '{{.State.ExitCode}}' "$OLD_CONTAINER_ID")" != 137
+install -d -m 700 "$BACKUP_DIR/source" "$BACKUP_DIR/data" "$BACKUP_DIR/session"
+cp -a -- "$ORIGINAL_DIR/." "$BACKUP_DIR/source/"
+(
+ cd "$ORIGINAL_DIR"
+ find . -type f -print0 | sort -z | xargs -0 sha256sum
+) > "$BACKUP_DIR/source.sha256"
+(cd "$BACKUP_DIR/source"; sha256sum --check "$BACKUP_DIR/source.sha256") > "$BACKUP_DIR/source-check.txt"
+docker cp "$OLD_CONTAINER_ID:/app/data/." "$BACKUP_DIR/data/"
+if [ "$LAYOUT" = legacy ]; then
+ set -- "$BACKUP_DIR/source"/bot.shabbat*
+ test -e "$1"
+ cp -a -- "$@" "$BACKUP_DIR/session/"
+else
+ docker cp "$OLD_CONTAINER_ID:/app/runtime/." "$BACKUP_DIR/session/"
+ test -s "$BACKUP_DIR/data/shabbat.sqlite"
+fi
+if [ -d "$BACKUP_DIR/session/bot.shabbat" ]; then
+ test -s "$BACKUP_DIR/session/bot.shabbat/safe.php"
+elif [ -f "$BACKUP_DIR/session/bot.shabbat" ]; then
+ test -s "$BACKUP_DIR/session/bot.shabbat.safe.php"
+else
+ echo 'STOP: canonical session payload is missing; do not create a new session.' >&2
+ exit 1
+fi
+for part in data session; do
+ (cd "$BACKUP_DIR/$part"; find . -type f -print0 | sort -z | xargs -0 sha256sum) > "$BACKUP_DIR/$part.sha256"
+done
+docker image save --output "$BACKUP_DIR/old-image.tar" "$OLD_IMAGE_ID"
+sha256sum "$BACKUP_DIR/old-image.tar" > "$BACKUP_DIR/old-image.tar.sha256"
+~~~
+
+
+
+הגיבוי כולל .env, תצורה, תלויות מותקנות, data, מסד ו־WAL/SHM, סשן, קובצי מצב בשורש ונתוני BroadcastManager. שמרו גם עותק פרטי מחוץ לשרת. גיבוי SQLite או DBgroups.txt לבדם אינו מספיק. הבוט והסשן החדשים עדיין לא הופעלו.
+
+## 5. העתקה לאחסון חדש והכנת המסד
+
+הגיבוי מחובר לקריאה בלבד. root משמש רק להעתקה ולתחזוקה לא מקוונת; הבוט ירוץ כ־UID/GID 10001. אימות SHA256 בודק את העתקת הנתונים והסשן לפני מיגרציה.
+
+
+
+~~~sh
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat sh -ec '
+ test -z "$(find /app/data -mindepth 1 -maxdepth 1 -print -quit)"
+ test -z "$(find /app/runtime -mindepth 1 -maxdepth 1 -print -quit)"
+ cp -a /review/data/. /app/data/
+ cp -a /review/session/. /app/runtime/
+ (cd /app/data; sha256sum --check /review/data.sha256)
+ (cd /app/runtime; sha256sum --check /review/session.sha256)
+ test ! -e /app/data/upgrade-3.1.0
+ mkdir -m 700 /app/data/upgrade-3.1.0
+' > "$BACKUP_DIR/copied-state-check.txt"
+inventory() {
+ new_compose run --rm --no-deps --user 0:0 shabbat php -r '
+ require "/app/vendor/autoload.php";
+ $db=Shabbat\Storage\Database::open("/app/data/shabbat.sqlite");
+ $result=[];
+ $tables=$db->pdo()->prepare("SELECT name FROM sqlite_master WHERE type=? ORDER BY name");
+ $tables->execute(["table"]);
+ foreach($tables->fetchAll(PDO::FETCH_COLUMN) as $name) {
+ if($name==="schema_migrations" || str_starts_with($name,"sqlite_")) continue;
+ if(!preg_match("/^[a-z_][a-z0-9_]*$/D",$name)) throw new RuntimeException("Unexpected table name");
+ $columns=$db->pdo()->query("PRAGMA table_info(\"".$name."\")")->fetchAll(PDO::FETCH_ASSOC);
+ $order=implode(",",array_map(fn($c)=>"\"".str_replace("\"","\"\"",$c["name"])."\"",$columns));
+ $rows=$db->pdo()->query("SELECT * FROM \"".$name."\" ORDER BY ".$order);
+ $hash=hash_init("sha256"); $count=0;
+ while($row=$rows->fetch(PDO::FETCH_ASSOC)) {
+ hash_update($hash,json_encode($row,JSON_THROW_ON_ERROR)."\n"); $count++;
+ }
+ $result[$name]=["rows"=>$count,"sha256"=>hash_final($hash)];
+ }
+ echo json_encode($result,JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR),PHP_EOL;
+ '
+}
+if [ "$LAYOUT" = sqlite ]; then
+ inventory > "$BACKUP_DIR/database-before.json"
+fi
+new_compose run --rm --no-deps --user 0:0 shabbat \
+ php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite \
+ --backup-dir /app/data/upgrade-3.1.0 > "$BACKUP_DIR/migrate.json"
+if [ "$LAYOUT" = sqlite ]; then
+ inventory > "$BACKUP_DIR/database-after.json"
+ cmp "$BACKUP_DIR/database-before.json" "$BACKUP_DIR/database-after.json"
+fi
+~~~
+
+
+
+בשדרוג SQLite מ־3.0, השוואת שורות המסד חייבת להתאים ואין לבצע ייבוא legacy; המשיכו לשלב 7. במערכת legacy המשיכו לשלב הבא. ב־3.1.0 אין שינוי בסכמת SQL; כל הבדל בלתי צפוי מחייב בירור לפני הפעלה.
+
+## 6. רק ל־legacy: בדיקה וייבוא תואם לדוח
+
+בדקו כל קבוצה רשומה, הגדרה, תבנית, הודעה, התראה, טיוטה ואזהרת הרשאות. כפילויות מדווחות ומנוכות. תיקיות קבוצה שאינן ברשימה מדווחות ואינן נרשמות אוטומטית, כי ייתכן שאינן פעילות. אם צריך לייבאן, התאימו עותק ייבוא נפרד לאחר בירור, שמרו את הגיבוי המקורי והפיקו דוח חדש. הייבוא מכסה את [השדות המתועדים](MIGRATION.md); הרחבות מקומיות מחייבות בדיקה.
+
+
+
+~~~sh
+test "$LAYOUT" = legacy
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat \
+ php bin/import-legacy.php --db /app/data/shabbat.sqlite \
+ --legacy /review/source --dry-run > "$BACKUP_DIR/import-preview.json"
+~~~
+
+
+
+קראו את דוח JSON הפרטי ואשרו כל הבדל בין המקור ליעד לפני הבלוק הבא. האפשרות --expect-report עוצרת אם המקור או רשומות היעד הרלוונטיות השתנו. הגדרות ותבניות קיימות נשמרות. קבוצות מיובאות פעילות, עם ברירות המחדל המתועדות של ירושלים, הזמנים וההתראות הישנים; מודולי התזכורות החדשים נשארים כבויים. בדקו מיקום ומצב לפני עבודה רגילה.
+
+הייבוא אינו טרנזקציה אחת כוללת. בכשל משאירים את הבוט כבוי, שומרים ראיות ובודקים או משחזרים את הגיבוי המאומת שנוצר לפני הייבוא לפני ניסיון נוסף. אין לעקוף את התאמת הדוח.
+
+
+
+~~~sh
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat \
+ php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /review/source \
+ --apply --writers-stopped --backup-dir /app/data/upgrade-3.1.0 \
+ --expect-report /review/import-preview.json > "$BACKUP_DIR/import-apply.json"
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR:/review:ro" shabbat php -r '
+ $r=json_decode(file_get_contents("/review/import-apply.json"),true,512,JSON_THROW_ON_ERROR);
+ if(($r["verification"]["status"]??null)!=="passed") throw new RuntimeException("Import verification failed");
+ echo "Import comparison passed.",PHP_EOL;
+'
+~~~
+
+
+
+צילומי chatb1.json וקובצי נעילה ישנים הם ראיות, ולא הרשאות נוכחיות מאומתות. ייתכן שנדרשת בדיקת מנהל גם אם הקבוצה נראית פתוחה. אין למחוק מצב התאוששות או לשחזר אוטומטית צילום ישן ומתירני. ראו [התאוששות הרשאות](PERMISSION_RECOVERY.md).
+
+## 7. בדיקה, גיבוי ותרגול שחזור
+
+פקודות התחזוקה בודקות סכמה ושלמות, יוצרות גיבוי SQLite חדש בלי למחוק גיבויים ישנים, מייצאות אותו בפרטיות ומשחזרות לנתיב זמני נפרד. הן אינן פותחות סשן Telegram. בריאות דורשת פעימות של בוט פועל; כאן משתמשים בבדיקות מבנה ואחרי ההפעלה בבדיקת בריאות אמיתית.
+
+
+
+~~~sh
+new_compose run --rm --no-deps --user 0:0 shabbat php -r '
+require "/app/vendor/autoload.php";
+$db=Shabbat\Storage\Database::open("/app/data/shabbat.sqlite");
+$db->assertCurrentSchema();
+$checks=$db->integrity();
+if($checks["integrity_check"]!==["ok"] || $checks["foreign_key_check"]!==[]) throw new RuntimeException("Database check failed");
+$result=(new Shabbat\Storage\BackupService())->backup($db,"/app/data/upgrade-3.1.0/ready.sqlite");
+echo Shabbat\Storage\Database::encode($result),PHP_EOL;
+' > "$BACKUP_DIR/ready-backup.json"
+install -d -m 700 "$BACKUP_DIR/sqlite"
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR/sqlite:/export" shabbat sh -ec '
+ cp -a /app/data/upgrade-3.1.0/. /export/
+ chown -R 10001:10001 /app/data /app/runtime
+'
+new_compose run --rm --no-deps shabbat php bin/restore.php \
+ --backup /app/data/upgrade-3.1.0/ready.sqlite \
+ --db /tmp/restore-rehearsal.sqlite --writers-stopped > "$BACKUP_DIR/restore-rehearsal.json"
+new_compose run --rm --no-deps shabbat php scripts/verify-patches.php
+new_compose run --rm --no-deps shabbat php bin/self-check.php --release
+new_compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+~~~
+
+
+
+## 8. החלפת הקוד והפעלת מופע יחיד
+
+המשיכו לאחר קבלת הדוחות, הגיבוי והשחזור ותוכנית ההרשאות. התיקייה הישנה נשמרת בשלמותה בשם אחר, ללא דריסה. אם שינוי השם השני נכשל, עצרו והחזירו את התיקייה השמורה רק אחרי בדיקה ש־ORIGINAL_DIR חסר. הקונטיינר הישן נשאר כבוי כשנתיב הקוד המקורי מכיל את הגרסה החדשה.
+
+
+
+~~~sh
+test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
+test "$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' "$OLD_CONTAINER_ID")" = no
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
+test "$RELEASE_DIR" = "/root/shabbat-stage-$VERSION-$STAMP"
+test "$RETIRED_DIR" = "$ORIGINAL_DIR.before-$VERSION-$STAMP"
+test ! -e "$RETIRED_DIR"
+mv -T -- "$ORIGINAL_DIR" "$RETIRED_DIR"
+mv -T -- "$RELEASE_DIR" "$ORIGINAL_DIR"
+RELEASE_DIR="$ORIGINAL_DIR"
+cd "$ORIGINAL_DIR"
+new_compose config --quiet
+printf '%s\n' "$RETIRED_DIR" "$NEW_PROJECT" > "$BACKUP_DIR/new-installation.txt"
+new_compose up -d --no-build shabbat
+new_compose ps
+new_compose logs --tail=120 shabbat
+~~~
+
+
+
+ההפעלה עשויה לפעול בקבוצות פעילות, לשלוח הודעת אתחול ולעבד משימות ספרייה. שידורים ישנים ללא שיוך מנהל עלולים להיחסם או להתבטל; משימות מחיקה מועתקות עלולות להתבצע. בדקו את מצב BroadcastManager השמור; אין להניח ששידור שנקטע בטוח לשליחה מחדש.
+
+לאחר האתחול בדקו בריאות. ב־Telegram בדקו /start, מעברי הבית וההגדרות, callbacks, זהות /source, מספר קבוצות, מיקום ואזור זמן, תבניות ודגלי התראות. בקבוצת ניסוי עם מגבלות ידועות בדקו סגירה, פתיחה ו־restart; אין להשתמש ב־/closegroups או /opengroups ההמוניות כבדיקת עשן.
+
+
+
+~~~sh
+new_compose exec -T shabbat php bin/health.php --deep
+new_compose ps
+~~~
+
+
+
+מנהל קבוצה צריך לטפל בכל צילום לא מאומת מחוץ לזמנים מוגנים: לקבוע ב־Telegram הרשאות רגילות רצויות, לרענן את פאנל ההתאוששות של הקבוצה ולאשר במפורש את אימוץ ההרשאות הנוכחיות. פתיחה כללית אינה בהכרח ברירת המחדל הרצויה. עקבו אחר שתי הפעימות, התורים, ההרשאות והתזכורות לאורך מחזור שבת/חג אמיתי ראשון. בדיקות 3.0 אינן אישור ל־3.1.0, לתזמון בחג או להרצה ממושכת. שמרו חומרי חזרה לאחור עד לקבלת התוצאה.
+
+פקודות עתידיות מריצים מ־ORIGINAL_DIR המאומת עם **--project-name shabbat-production-310**. שומרים את שם הפרויקט ואת שני אמצעי האחסון. מגבים יחד קוד תואם, .env, מסד, סשן ומצב BroadcastManager.
+
+## 9. חזרה לאחור
+
+**לפני שינויי השם וההפעלה:** הקוד והמצב הישנים לא השתנו. אם השירות החדש אינו פועל ו־RETIRED_DIR לא קיים, החזירו את מדיניות האתחול השמורה והפעילו את הקונטיינר הישן:
+
+
+
+~~~sh
+test ! -e "$RETIRED_DIR"
+test "$(readlink -f -- "$ORIGINAL_DIR")" = "$ORIGINAL_DIR"
+test -z "$(docker ps --filter label=com.docker.compose.project="$NEW_PROJECT" --filter label=com.docker.compose.service=shabbat --quiet)"
+docker update --restart="$OLD_RESTART_POLICY" "$OLD_CONTAINER_ID"
+docker start "$OLD_CONTAINER_ID"
+~~~
+
+
+
+במסלול זה עצרו כאן. **אחרי החלפה והפעלה**, בדקו קודם השפעות ב־Telegram: קבצים אינם מבטלים הרשאות, הודעות ושידורים. טפלו בחובות הרשאות שיצר הבוט החדש לפני הוצאתו משימוש, ואז עצרו ושמרו את מצבו:
+
+
+
+~~~sh
+NEW_CONTAINER_ID="$(new_compose ps -a -q shabbat)"
+if [ -n "$NEW_CONTAINER_ID" ]; then
+ docker update --restart=no "$NEW_CONTAINER_ID"
+fi
+new_compose stop --timeout 120 shabbat
+if [ -n "$NEW_CONTAINER_ID" ]; then
+ test "$(docker inspect --format '{{.State.Running}}' "$NEW_CONTAINER_ID")" = false
+fi
+test "$(docker inspect --format '{{.State.Running}}' "$OLD_CONTAINER_ID")" = false
+test ! -e "$BACKUP_DIR/failed-new-state"
+install -d -m 700 "$BACKUP_DIR/failed-new-state"
+new_compose run --rm --no-deps --user 0:0 \
+ --volume "$BACKUP_DIR/failed-new-state:/export" shabbat sh -ec '
+ tar -cpf /export/data.tar -C /app/data .
+ tar -cpf /export/session.tar -C /app/runtime .
+'
+sha256sum "$BACKUP_DIR/failed-new-state/"*.tar > "$BACKUP_DIR/failed-new-state/SHA256SUMS"
+FAILED_DIR="$ORIGINAL_DIR.failed-$VERSION-$STAMP"
+test "$RETIRED_DIR" = "$ORIGINAL_DIR.before-$VERSION-$STAMP"
+test -d "$RETIRED_DIR"
+test ! -e "$FAILED_DIR"
+case "$ORIGINAL_DIR" in /root/shabbat|/root/shabat) ;; *) exit 1 ;; esac
+mv -T -- "$ORIGINAL_DIR" "$FAILED_DIR"
+mv -T -- "$RETIRED_DIR" "$ORIGINAL_DIR"
+test -f "$ORIGINAL_DIR/.env"
+docker update --restart="$OLD_RESTART_POLICY" "$OLD_CONTAINER_ID"
+docker start "$OLD_CONTAINER_ID"
+docker logs --tail=100 "$OLD_CONTAINER_ID"
+~~~
+
+
+
+התיקייה הישנה מוחזרת לפני הפעלת הקונטיינר שמחובר לנתיב המקורי; אמצעי האחסון, התמונה והסשן הישנים נשמרו. אין לדרוס את הגיבוי הישן במסד או בסשן החדשים. גם אחרי חזרה לאחור בודקים תאימות סשן ומצב ב־Telegram. אין למחוק מצבי נתונים, אמצעי אחסון או תמונות שמורות בתהליך.
+
+
diff --git a/docs/PUBLICATION_STATUS.md b/docs/PUBLICATION_STATUS.md
index ebd9cb4..7a7b50b 100644
--- a/docs/PUBLICATION_STATUS.md
+++ b/docs/PUBLICATION_STATUS.md
@@ -1,59 +1,51 @@
# Publication and release status
-## Stable release 3.0.0
-
-The owner-authorized `v3.0.0` stable release uses the exact reviewed merge commit. Its deployment asset is `shabbat-3.0.0.zip`; `shabbat-3.0.0-corresponding-source.zip` adds the 57 locked runtime package trees and preferred-source supplements below. `SHA256SUMS` and `RELEASE_MANIFEST.json` identify the archives, source fingerprint and scope; the matching Actions run supplies CI evidence. Archive `build-info.json` records the actual commit and `local_changes=false` after exact source equality. See [release notes](RELEASE_NOTES.md) and [production cutover](PRODUCTION_UPGRADE.md).
-
-Stable packaging is now repository tooling: `composer package` / `php scripts/package.php` reads a clean committed Git tree and verifies the locked runtime sources and committed supplement inventory before writing the two ZIPs and metadata to `dist/`. Git and Python 3.9+ are packaging prerequisites. The old three-archive installed-tool path is explicitly `--development` and is not a release source offer. [Release preparation](RELEASE.md) documents the checks and prerequisites.
-
-The owner reported successful dev.9 live locking, unlocking, restoration of original group permissions and restart on 2026-10-16. The stable promotion preserves that runtime behavior; it does not convert those tests into holy-day, load, soak, all-client or production-migration acceptance. The Docker PHP 8.4 base moves to security-patched 8.4.26; Composer stays 2.10.3. Application lock, approved patch bytes and SQL migration bytes remain preserved. Publishing the GitHub release does not deploy or restart the bot.
-
-## Historical local preparation
-
-The earlier local documentation/public-source preparation of **3.0.0-dev.9** preserved runtime behavior and locked dependencies. That preparation itself created no commit, tag, GitHub release or production deployment. Its historical artifact names and metadata are recorded below; use the current release assets above for deployment.
-
-## Historical local delivery layout
-
-| Path in the local delivery | Contents |
-|---|---|
-| `repo/` | Clean files intended for the repository root; no `.git`, installed `vendor`, actual `.env`, databases, sessions, logs, private backups or generated test caches |
-| `artifacts/shabbat-3.0.0-dev.9-publication.zip` | The clean repository source, including dotfiles, tests, resources, immutable migration sources and reviewed patch baselines, plus public archive-only `build-info.json` required for no-Git Docker builds |
-| `artifacts/shabbat-3.0.0-dev.9-corresponding-source.zip` | Application source plus the 57 locked runtime Composer dependency source trees, their notices and approved local modifications; see the archive's source-scope/index |
-| `artifacts/SHA256SUMS` | SHA-256 hashes for the delivered ZIPs |
-| `checks/` | Sanitized implementation inventory, original-source preservation evidence, executed-check reports, archive manifests and documented blockers |
-
-The archive-only `build-info.json` records the verified original baseline commit, `local_changes=true` and the exact publication-source fingerprint. It is excluded from `repo/` and Git; it neither creates nor claims a new commit. Extract the publication ZIP into a new directory, retain that metadata unchanged, and follow the README. It is a source distribution requiring `composer install` or a Docker build, not a preconfigured bot. At that time `scripts/package.php` was a separate three-archive developer packager. Stable 3.0.0 replaces its default with the reviewed two-archive release workflow and retains the old behavior only under `--development`; historical archive names and scope do not describe current release assets.
-
-## Corresponding-source scope
-
-The separate source archive preserves application resources, migration/build/install/test scripts, `composer.lock`, licenses, the five active patch sets, exact upstream baselines and patched runtime dependency sources. Runtime dependency versions/references and files are indexed in its manifest.
-
-The locked `amphp/process` package also distributes two Windows helper executables.
-Their MIT-licensed preferred source is included separately under
-`additional-source/amphp-windows-process-wrapper/` at the immutable
-[v1.2.0 source commit](https://github.com/amphp/windows-process-wrapper/tree/8d5aca0c56b73cba460894d79ee83ec558b41027).
-The version association is supported by official package history and matching
-executable Git blobs. A reproducible rebuild of those binaries was not performed.
-
-The source collection also supplements Composer's MadelineProto distribution with
-pinned upstream TL generator/build inputs, current schema/language inputs and a
-required documentation-template input. Original paths, commits and Git-blob/file
-hashes are indexed in the archive. Generators were not executed; upstream
-documentation/translation workflows that query mutable RPC/Weblate data are not
-claimed to be reproducible offline. Historical schema archives and generated
-upstream documentation are outside this collection.
-
-
-Development tool installations are excluded from this source archive. In particular, a distributed PHPStan PHAR is not labeled as preferred source. Development tools remain reproducible through the committed lock, and their license inventory is retained. PHP, SQLite, operating-system packages and Docker base images are external runtime/build dependencies, not bundled source or a distributed image in this delivery. Dockerfile digests, download checksums and upstream references document those external inputs. No claim is made that this ZIP contains the full source of an entire Linux container or every optional development tool.
-
-See [licensing](LICENSING.md), [third-party notices](../THIRD_PARTY_NOTICES.md), [dependency inventory](DEPENDENCIES.md) and the source archive's scope manifest for exact inclusions, omissions and outstanding provenance findings.
-
-## Review boundaries
-
-- The public README pair is `README.md` and `readme-he.md`; there is no competing `README.he.md`.
-- Original application code, the Composer lock, SQL migration bytes, dependency licenses and approved patch/base bytes are preserved. The release inventory and documentation checker use the requested Hebrew filename; provenance metadata uses portable project-relative identifiers.
-- The public `.env.example` keeps the same key/value placeholders and uses comment-free syntax shared by Compose and PHP INI parsing. Explanations are in the configuration guide.
-- Current acceptance and feature gaps are documented in [implementation status](IMPLEMENTATION_STATUS.md); they are not silently fixed or marketed as complete.
-- Exact test results belong to the final separate checks report. Previously recorded dev.9 results do not replace a clean-install check of this copy.
-
-When publishing manually, use the exact reviewed source and preserve its corresponding-source offer. Do not upload private environment/session/data files. The historical local preparation performed no remote publication or production action; the current authorized stable release is described at the top of this document.
+## 3.1.0 source and release requirements
+
+The upgrade targets MadelineProto 8.11.10 at the exact commit in `composer.lock`.
+Only the rebased Fresh Peer patch and the reviewed BroadcastManager patch remain
+active. Date/location compatibility now uses official SDK implementations;
+inline keyboards are normalized at the transport boundary for TL Layer 232.
+
+Publication requires mandatory PHP, static-analysis, source-inventory, packaging,
+Docker and shutdown compatibility checks to pass on the exact final commit.
+The matching GitHub Actions run and release manifest identify the tested source
+and artifacts. Historical results from another version do not replace those
+checks; a stable tag or release must not bypass a failed mandatory gate.
+
+The runtime baseline requires PHP **8.3.36+, 8.4.27+ or 8.5.12+** within those
+branches; Docker pins **8.4.27**. The [dated security baseline](INSTALLATION.md#php-security-baseline)
+records the upstream fixes reviewed on 22 October 2026. Earlier checks on an older
+interpreter are compatibility evidence, not approval of that deployment runtime.
+
+Shutdown coverage combines the official loop contract with application-owned
+writer exclusion through SDK disconnect/finalization. Loop `stop()` prevents
+rescheduling after the current body returns. Offline fixtures use an in-memory
+transport and modeled flush; they do not establish real session serialization,
+Telegram traffic, IPC-daemon shutdown or Linux-signal acceptance.
+
+## Archives and source scope
+
+The release packager reads a clean committed Git tree and verifies exact locked
+runtime sources plus preferred-source supplements before producing
+`shabbat-3.1.0.zip`, `shabbat-3.1.0-corresponding-source.zip`, `SHA256SUMS`
+and `RELEASE_MANIFEST.json`. Archive `build-info.json` records the exact commit
+and source fingerprint. No real configuration, session, database or log belongs
+in an archive. Unpublished archives are for review and isolated testing; release
+assets must correspond to the final commit whose mandatory gates passed.
+
+The source archive contains application source, active patch baselines/diffs,
+locked runtime dependency sources and their original licenses, plus the pinned
+supplements listed in `resources/release/source-manifest.json`. Development
+binary tools and full operating-system/container source trees are outside its
+scope. See [licensing](LICENSING.md), [third-party notices](../THIRD_PARTY_NOTICES.md)
+and the source manifest for exact inclusions, exclusions and provenance limits.
+
+## Deployment boundary
+
+Publication does not deploy or restart a bot. No live Telegram acceptance or
+production migration is performed by CI. The maintainer must first test the new
+release with a separate bot, then verify the actual production path before
+using the [Hebrew cutover guide](PRODUCTION_UPGRADE_HE.md) or
+[English cutover guide](PRODUCTION_UPGRADE.md). Historical 3.0.0 source and its
+retired patch provenance remain in that version's Git history and release.
diff --git a/docs/RELEASE.md b/docs/RELEASE.md
index 6016a6f..825649b 100644
--- a/docs/RELEASE.md
+++ b/docs/RELEASE.md
@@ -1,16 +1,16 @@
# Release preparation and publication
-The version in [VERSION](../VERSION) is **3.0.0**, stable. The owner confirmed dev.9 live locking, unlocking, original-permission restoration and restart. Broader holy-day, load, soak and feature-specific acceptance remain separate. See [release notes](RELEASE_NOTES.md), [implementation status](IMPLEMENTATION_STATUS.md) and [licensing/source scope](LICENSING.md).
+The version in [VERSION](../VERSION) is **3.1.0**. Publication requires the exact-commit release gates below. The owner confirmed dev.9 live locking, unlocking, original-permission restoration and restart. Broader holy-day, load, soak and feature-specific acceptance remain separate. See [release notes](RELEASE_NOTES.md), [implementation status](IMPLEMENTATION_STATUS.md) and [licensing/source scope](LICENSING.md).
## Review and publication sequence
-Work in an isolated checkout without production credentials or state. Require green checks on the reviewed PR, merge it, and verify the exact resulting commit before creating `v3.0.0` and a stable GitHub release. Release artifacts must identify that actual commit and fingerprint with `local_changes=false`. Tagging and publishing require the owner's authorization; none of the commands below publishes or deploys.
+Work in an isolated checkout without production credentials or state. Require green checks on the reviewed PR, merge it, and verify the exact resulting commit before creating `v3.1.0` and a stable GitHub release. Release artifacts must identify that actual commit and fingerprint with `local_changes=false`. Tagging and publishing require the owner's authorization; none of the commands below publishes or deploys.
-The release provides `shabbat-3.0.0.zip`, `shabbat-3.0.0-corresponding-source.zip`, `RELEASE_MANIFEST.json` and `SHA256SUMS`. The deployment ZIP contains clean repository source plus build identity, without installed vendor. The corresponding-source ZIP adds the locked runtime sources, licenses, reviewed patches and pinned preferred-source supplements. The manifest states the scope and exclusions; no claim covers the complete Docker operating system or all development-tool source.
+The release provides `shabbat-3.1.0.zip`, `shabbat-3.1.0-corresponding-source.zip`, `RELEASE_MANIFEST.json` and `SHA256SUMS`. The deployment ZIP contains clean repository source plus build identity, without installed vendor. The corresponding-source ZIP adds the locked runtime sources, licenses, reviewed patches and pinned preferred-source supplements. The manifest states the scope and exclusions; no claim covers the complete Docker operating system or all development-tool source.
## Reproduce quality checks
-Run at the root of a disposable checkout, as its nonroot owner with write access, with the supported PHP/Composer runtime. The locked installation writes only this checkout's dependencies and applies the approved patches. Never install or patch dependencies inside an active bot tree.
+Run at the root of a disposable checkout, as its nonroot owner with write access, with the supported [patched PHP/Composer runtime](INSTALLATION.md#php-security-baseline): 64-bit PHP 8.3.36+, 8.4.27+ or 8.5.12+ within those branches, and Composer 2.10.3. The locked installation writes only this checkout's dependencies and applies the approved patches. Never install or patch dependencies inside an active bot tree.
```sh
composer validate --strict --no-check-all
@@ -27,7 +27,7 @@ php bin/self-check.php
php bin/self-check.php --release
```
-`--no-check-all` omits generic version-range advice for the deliberate MadelineProto pin while retaining strict manifest/lock validation. Installation/upgrades use `composer install` with the existing lock; dependency changes require separate review. The release self-check enforces the loaded SQLite/target runtime gate. Do not bypass it on an older host runtime.
+The validation command retains strict manifest/lock checking. MadelineProto now uses a reviewed stable version range, while composer.lock pins the exact installed source. Installation/upgrades use `composer install` with the existing lock; dependency changes require separate review. The release self-check enforces the loaded SQLite/target runtime gate. Do not bypass it on an older host runtime.
Record the locked inventory and current advisory evidence from that same installation:
@@ -79,7 +79,7 @@ Exclude `.git`, actual `.env`, sessions, application/runtime databases and WAL/S
## Production remains a separate action
-Use [the complete `/root/shabat` legacy cutover guide](PRODUCTION_UPGRADE.md) for the old file-based production bot. Existing SQLite deployments use [migration](MIGRATION.md) and [backup/restore](BACKUP_RESTORE.md) instead of importing legacy data again. Stable 3.0.0 adds no migration after dev.9; all 16 sources remain required.
+Use the [production upgrade guide](PRODUCTION_UPGRADE.md) ([עברית](PRODUCTION_UPGRADE_HE.md)) to verify the actual /root/shabbat or /root/shabat installation and select its legacy or SQLite path. Existing SQLite deployments must not import legacy data again. Version 3.1.0 retains all 16 immutable migration sources.
Stop all writers before migration, retain matching source/database/session/BroadcastManager state, verify import/settings and restore, and monitor the first real production close/open cycle. Review old permission snapshots through the provenance-aware recovery panel. Keep the exact corresponding source available and set `SOURCE_URL` before public operation. Publication itself does not execute a server command or restart a bot.
diff --git a/docs/RELEASE_NOTES.md b/docs/RELEASE_NOTES.md
index 110c33a..8ad0fde 100644
--- a/docs/RELEASE_NOTES.md
+++ b/docs/RELEASE_NOTES.md
@@ -1,51 +1,44 @@
-# WizardLoop Shabbat 3.0.0
+# Shabbat 3.1.0
-**Stable release `v3.0.0`.** This release retains the dev.9 bot implementation, MadelineProto 8.7.0, SQLite, the locked application dependencies, all five approved patch sets and all 16 migrations. It promotes the reviewed implementation and updates release packaging, identity and deployment documentation. See [CHANGELOG](../CHANGELOG.md), [implementation status](IMPLEMENTATION_STATUS.md) and [production upgrade](PRODUCTION_UPGRADE.md).
+**Release policy: publication requires successful mandatory checks on the exact final commit. Use the matching GitHub Actions run and release manifest to verify the tested source and artifacts.**
-## Acceptance and changes
+Automated release checks and deployment acceptance have separate scopes. See [release requirements](RELEASE.md) and [implementation status](IMPLEMENTATION_STATUS.md).
-On 2026-10-16 the owner confirmed successful live dev.9 group locking, unlocking, original-permission restoration and restart. These results support those paths; they do not establish real Shabbat/Yom Tov timing, a full holiday sequence, Telegram capacity under load, a long-running soak, every client or actual Stars payments. The production import and cutover remain operator actions with their own checks.
+## Changes
-The stable packaging path is now part of the repository: `composer package` or `php scripts/package.php` builds the deployment and scoped corresponding-source archives from an exact clean Git commit. The dependency and preferred-source inventory is pinned, with patch and per-file verification. The former installed-tool packaging path remains explicit `--development` tooling and is not the release source offer. The image retains the PHP 8.4 branch with its security-patched 8.4.26 base; Composer remains pinned to 2.10.3.
+- Raise the supported PHP patch floors to **8.3.36 / 8.4.27 / 8.5.12** and the Docker baseline to **8.4.27**, following the [22 October 2026 security baseline](INSTALLATION.md#php-security-baseline).
+- Update MadelineProto to official stable 8.11.10 / TL layer 232 with a compatible stable Composer range and exact lock.
+- Retire upstreamed UpdateLoop/cancellation, GeoPoint and formatted-date patches; retain the reviewed version-matched Fresh Peer and BroadcastManager changes where still required.
+- Update the keyboard compatibility boundary for new inline constructors while preserving saved templates, callback IDs, styles/icons and distinct reply keyboards.
+- Recognize the current Telegram permission fields. The new `manage_linked_peers` restriction is opt-in, including explicit **All** selection; the existing 21-field default and saved masks are unchanged. Administrator-rights diagnostics cover all 19 current fields.
+- Add comparable dry-run/apply import plans, duplicate/directory-only group reporting, optional reviewed-report binding and post-import verification. Existing destination settings and unverified permission evidence remain protected.
+- Shorten the English/Hebrew README pair and consolidate obsolete development reports into current references. Provide parallel guarded production instructions, including a Hebrew guide.
-The dev.9 publication corrections remain included: PHP 8.3-compatible transaction bookkeeping and native fixtures, immutable migration/resource/fixture bytes across Git line-ending settings, Composer tooling fixes, and reviewed deployment documentation. No existing migration or patch is rewritten.
+Existing group/calendar modules, languages, rich templates, administration, Stars donations, SQLite data, session handling and all 16 immutable migrations remain part of the application. See [keyboard compatibility](KEYBOARD_COMPATIBILITY.md), [implementation status](IMPLEMENTATION_STATUS.md), [changes](../CHANGELOG.md) and [patch documentation](PATCHES.md) for actual boundaries.
-## Included functionality
+## Upgrade manually
-Location-aware Shabbat/Yom Tov closures preserve verified original group permissions. Private/group settings, six interface catalogs, inline/GPS location flows, rich templates, delegated administration, broadcasts, statistics, optional Stars donations and group opt-in zmanim/Daf/Tefillin/Omer modules remain available with the boundaries in [implementation status](IMPLEMENTATION_STATUS.md).
+Follow the [English production guide](PRODUCTION_UPGRADE.md) or [מדריך השדרוג בעברית](PRODUCTION_UPGRADE_HE.md). Verify /root/shabbat versus /root/shabat from the actual production container, stage the image separately, stop the old writer and preserve its whole folder, data, session, configuration, BroadcastManager state and image before cutover.
-Dev.9 delivery safety remains in place: eligibility is rechecked near dispatch; Tefillin spacing/daily caps and Omer restoration gaps use actual delivery evidence; never-dispatched backlogs are bounded; uncertain outcomes remain conservative. Permission, notification and scheduled-broadcast callbacks are independent, with bounded work and separate heartbeats. Configured closing notices remain an intentional quiet-period exception, and a request already accepted by Telegram cannot be recalled by a local check. See [delivery safety](DEV9_DELIVERY_SAFETY.md).
+File-based installations preview/apply the bound import and review each warning. Existing 3.0 SQLite installations keep their data and compare it around the migration/schema check; they do not run legacy import. Old permission snapshots never become trusted solely because they have a valid checksum. Rollback retains old local state but cannot undo Telegram actions already accepted.
-## Dependencies and schema
-
-- MadelineProto: exactly `8.7.0`, commit `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`.
-- BroadcastManager: locked `3.2.2`, commit `f2792a383416b66bb68e55f09414563e540538d6`, with the reviewed local derivative.
-- Five active patch sets: four MadelineProto compatibility patches and one BroadcastManager set, with original baselines, reviewed outputs, diffs and manifests.
-- Migrations 001–016 remain required and checksum-protected. **No new migration is added after dev.9.** Startup validates schema; maintenance applies migrations explicitly.
-
-[Dependency evidence](DEPENDENCIES.md) · [Patch workflow](PATCHES.md) · [Licensing and source scope](LICENSING.md)
-
-## Production upgrade and rollback
-
-The complete [production guide](PRODUCTION_UPGRADE.md) targets the existing file-based bot at `/root/shabat` (one `b`). Build the reviewed source beside production, stop the single old writer, retain the whole private directory and image, copy stopped state into distinct new volumes, preview/apply the explicit legacy import, compare exact group IDs/settings, rehearse restore, then move the reviewed source into `/root/shabat` and start one instance under `shabbat-production`.
-
-Legacy permission snapshots remain unverified until an authorized administrator reviews the intended normal Telegram rights. The guide explains recovery, monitoring and a rollback that restores the original bind path before restarting the retained old container. A file restore does not undo Telegram actions already accepted. Test-bot databases and sessions never replace production state.
-
-Existing SQLite dev.9 deployments need the usual stopped-writer backup and migration/schema check, but no legacy import or new SQL migration. Preserve matching source, database, MadelineProto session and BroadcastManager state. See [backup and restore](BACKUP_RESTORE.md).
-
-## Release artifacts and identity
+## Assets and exact source
| Asset | Purpose |
|---|---|
-| `shabbat-3.0.0.zip` | Clean deployment source and `composer.lock`, plus exact release `build-info.json`; no installed vendor or private runtime state. Docker installs locked runtime dependencies. |
-| `shabbat-3.0.0-corresponding-source.zip` | Application plus 57 locked runtime package trees, licenses, reviewed patches and pinned preferred-source supplements, with exact scope/index. |
-| `RELEASE_MANIFEST.json` | Release commit, version, source fingerprint, package scope and artifact hashes. |
-| `SHA256SUMS` | SHA-256 records for both ZIPs and the release manifest. |
+| `shabbat-3.1.0.zip` | Deployment source, lock and exact release build identity; Docker installs dependencies. No installed vendor or private state. |
+| `shabbat-3.1.0-corresponding-source.zip` | Application, documented locked runtime sources, licenses, active patches and required preferred-source supplements. |
+| `RELEASE_MANIFEST.json` | Actual commit, version, fingerprint, scope and artifact hashes. |
+| `SHA256SUMS` | Checksums for both ZIPs and the manifest. |
+
+Keep archive build-info.json unchanged and leave BUILD_COMMIT out of the private .env when using an unchanged release ZIP. Set SOURCE_URL to https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0 once its corresponding-source asset is available. Modified deployments need their exact source offer.
+
+The source scope excludes the complete operating system/container and optional development-tool source; consult [licensing](LICENSING.md), [third-party notices](../THIRD_PARTY_NOTICES.md) and the source manifest.
-Keep archive build metadata unchanged. It identifies the actual release commit with `local_changes=false`, not the historical legacy baseline. Set `SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0` for this unchanged release after its corresponding-source asset is available. Modified deployments need their own exact source offer.
+## Acceptance limits
-The source collection does not claim to include all operating-system/container or development-tool sources, or a reproducible rebuild of upstream binaries. Existing provenance/license findings remain visible in [third-party notices](../THIRD_PARTY_NOTICES.md) and [publication status](PUBLICATION_STATUS.md). No production `.env`, database/WAL/SHM, session, backup, private log or cache is a release asset.
+Shutdown tests use the official SDK loop and disconnect/finalize paths with an in-memory transport and modeled flush. The loop `stop()` contract prevents rescheduling after the current body returns; safe application shutdown also requires finalization before releasing writer ownership. These fixtures do not establish real session serialization, Telegram delivery, IPC-daemon shutdown or Linux-signal acceptance.
-## Verification boundaries
+The owner reported dev.9 locking, unlocking, original-permission restoration and restart on 2026-10-16. Those are historical results, not new 3.1.0 acceptance. Tests with fake transports cannot establish real client rendering, actual /start and callback delivery, complete holy-day timing, paid operations, sustained load or a long soak. Record final automated/image/archive checks separately and complete relevant isolated live checks before production use.
-The stable release is gated on its own reviewed commit, hosted checks, image validation and final artifact/source comparisons. Exact results belong to the matching Actions run and release evidence; prior test counts are not reused as a result for a different tree. Local Windows PHP's SQLite 3.45.2 remains below the release gate; the Docker target pins SQLite 3.51.3. Publication creates the authorized source/tag/release only. It does not migrate the server, change group permissions or restart the active bot.
+Publishing GitHub assets does not deploy to the server, migrate production, change group permissions or restart the active bot.
diff --git a/docs/SERVER_TEST_DEPLOYMENT.md b/docs/SERVER_TEST_DEPLOYMENT.md
index f607d70..8b6096b 100644
--- a/docs/SERVER_TEST_DEPLOYMENT.md
+++ b/docs/SERVER_TEST_DEPLOYMENT.md
@@ -1,8 +1,8 @@
-# Test stable 3.0.0 with a separate bot
+# Test 3.1.0 with a separate bot
-Use a **new test bot identity and disposable groups**. The fresh-install procedure below uses `/root/shabbat-test-3.0.0` and Compose project `shabbat-staging-300`; it preserves both the existing `/root/shabbat-test` installation and production `/root/shabat`. These are instructions, not an executed deployment. Never run two clients against one bot/session/database.
+Use a **new test bot identity and disposable groups**. The fresh-install procedure below uses `/root/shabbat-test-3.1.0` and Compose project `shabbat-staging-310`; it preserves both the existing `/root/shabbat-test` installation and production at its verified `/root/shabbat` or `/root/shabat` path. These are instructions, not an executed deployment. Never run two clients against one bot/session/database.
-An existing SQLite test deployment should follow the [stopped-writer upgrade](../README.md#upgrade-and-legacy-import) and [complete backup/restore procedure](BACKUP_RESTORE.md), preserving its existing project/volumes. Do not unpack this release over its old files or apply the fresh-volume instructions below to its state. The file-based production bot has its own [full cutover guide](PRODUCTION_UPGRADE.md).
+An existing SQLite test deployment should follow the [stopped-writer upgrade](INSTALLATION.md#updating-an-existing-sqlite-deployment) and [complete backup/restore procedure](BACKUP_RESTORE.md), preserving its existing project/volumes. Do not unpack this release over its old files or apply the fresh-volume instructions below to its state. Production has a separate [guarded cutover guide](PRODUCTION_UPGRADE.md) ([עברית](PRODUCTION_UPGRADE_HE.md)). Check current release/acceptance status before using published assets; a test guide is not a claim that the tests have already run.
## Prepare a fresh isolated source directory
@@ -11,12 +11,12 @@ Run on the Linux test host in the same Bash session, with root/Docker access, Co
```sh
set -euo pipefail
umask 077
-VERSION=3.0.0
+VERSION=3.1.0
ARCHIVE="shabbat-${VERSION}.zip"
-TEST_SOURCE=/root/shabbat-test-3.0.0
-TEST_PROJECT=shabbat-staging-300
+TEST_SOURCE=/root/shabbat-test-3.1.0
+TEST_PROJECT=shabbat-staging-310
UPLOAD_DIR=/root/shabbat-test-release-upload
-test "$TEST_SOURCE" = /root/shabbat-test-3.0.0
+test "$TEST_SOURCE" = /root/shabbat-test-3.1.0
test ! -e "$TEST_SOURCE"
if docker volume inspect "${TEST_PROJECT}_bot-data" >/dev/null 2>&1 \
|| docker volume inspect "${TEST_PROJECT}_madeline-session" >/dev/null 2>&1; then
@@ -52,7 +52,7 @@ chmod 600 .env
For manual upload, transfer the deployment ZIP and `SHA256SUMS` to `UPLOAD_DIR` and use the same exact checksum check before extracting. The separate corresponding-source archive is the source-offer artifact; it is not the deployment ZIP. Retain release `build-info.json` unchanged; it records the actual release commit and fingerprint with `local_changes=false`.
-Edit the new `.env` privately with the new test bot's Telegram credentials, trusted `ADMIN`, GeoNames account and container paths from [configuration](CONFIGURATION.md). Never copy production credentials/data/session. Set `SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0` for this unchanged release and leave `BUILD_COMMIT` absent.
+Edit the new `.env` privately with the new test bot's Telegram credentials, trusted `ADMIN`, GeoNames account and container paths from [configuration](CONFIGURATION.md). Never copy production credentials/data/session. Set `SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0` for this unchanged release and leave `BUILD_COMMIT` absent.
## Build, initialize and start deliberately
@@ -90,7 +90,7 @@ test_compose exec -T shabbat php bin/health.php --deep
test_compose ps
```
-Verify `/source` reports 3.0.0 and the exact release commit/source URL. Health requires recent permission and notification heartbeats; an offline database cannot satisfy it. Stop the test bot when the planned test is finished using `test_compose stop shabbat`. Preserve its project/volumes for diagnosis and later tests.
+Verify `/source` reports 3.1.0 and the exact release commit/source URL. Health requires recent permission and notification heartbeats; an offline database cannot satisfy it. Stop the test bot when the planned test is finished using `test_compose stop shabbat`. Preserve its project/volumes for diagnosis and later tests.
## Permission recovery and acceptance
@@ -102,4 +102,4 @@ The owner already reported successful dev.9 live locking, unlocking, original-pe
4. Inspect `/testzmanim GROUP_ID` and its private export when needed. Do not delete lock-state records or repeatedly force restoration to hide a conflict.
5. Observe both heartbeat ages, oldest due jobs, delivery delay and retry behavior under representative traffic, including a real wall-clock soak. Record what ran and what remains untested.
-Do not use `down -v`, transfer test state into production or run old/new instances on one session. [Rollback](BACKUP_RESTORE.md) needs matching source, database and library/session state; it cannot undo Telegram actions already accepted. See [delivery safety](DEV9_DELIVERY_SAFETY.md), [implementation status](IMPLEMENTATION_STATUS.md) and [publication status](PUBLICATION_STATUS.md).
+Do not use `down -v`, transfer test state into production or run old/new instances on one session. [Rollback](BACKUP_RESTORE.md) needs matching source, database and library/session state; it cannot undo Telegram actions already accepted. See [delivery safety](DELIVERY_SAFETY.md), [implementation status](IMPLEMENTATION_STATUS.md) and [publication status](PUBLICATION_STATUS.md).
diff --git a/docs/THIRD_PARTY_DETAILS.md b/docs/THIRD_PARTY_DETAILS.md
index 55c64e8..d747860 100644
--- a/docs/THIRD_PARTY_DETAILS.md
+++ b/docs/THIRD_PARTY_DETAILS.md
@@ -1,58 +1,47 @@
# Third-party technical provenance
-This companion to [THIRD_PARTY_NOTICES](../THIRD_PARTY_NOTICES.md) retains technical identities, modification history and open findings. The five checked-in patch manifests are authoritative for exact source, output, prerequisite and diff SHA-256 values. Historical hashes below identify earlier reviewed artifacts, not the current output unless stated.
+This companion to [THIRD_PARTY_NOTICES](../THIRD_PARTY_NOTICES.md) records component identity, modifications and open findings. The two active patch manifests are authoritative for exact baseline, approved output, diff and intermediate hashes.
## Original project and reference
-The historical WizardLoop Shabbat baseline is commit `2976ab8339f489d933c7246e0cb27f3b0e4aa697`, Copyright (c) 2024 WizardLoop, originally MIT. Its [complete original grant](../LICENSES/SHABBAT-LEGACY-MIT.txt) remains unchanged. The current application uses AGPL-3.0-only without altering historical grants.
+The original WizardLoop Shabbat baseline is commit 2976ab8339f489d933c7246e0cb27f3b0e4aa697, Copyright (c) 2024 WizardLoop, originally MIT. Its [grant](../LICENSES/SHABBAT-LEGACY-MIT.txt) remains unchanged. The combined application uses AGPL-3.0-only without revoking earlier grants.
-The JewishPulse interface comparison used commit `d7b06eb1acb206543dcff35a7c14ebce4760b4e5` under AGPL-3.0-only. [FEATURE_PARITY](FEATURE_PARITY.md) records that relationship. No JewishPulse graphic branding or hardcoded bot links are imported.
-
-Local reference path labels in the patch provenance identify historical project exports, not files required at installation and not public download URLs. Publication preparation removes the workstation's absolute home/Desktop prefix while retaining project/file identity, hashes and all license findings. Baselines, reviewed PHP, diffs, historical source and approved target hashes are unchanged.
+The JewishPulse comparison used commit d7b06eb1acb206543dcff35a7c14ebce4760b4e5, AGPL-3.0-only. Graphic branding and hardcoded bot links were not imported.
## Active patch identity
-All four MadelineProto patch sets target version **8.7.0**, commit `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`. The BroadcastManager set targets **3.2.2**, commit `f2792a383416b66bb68e55f09414563e540538d6`.
-
-| Set | Upstream baseline SHA-256 | Current approved output SHA-256 |
-|---|---|---|
-| [UpdateLoop](../patches/madelineproto/manifest.json) | `2fbcbb73822258102837f53f4a231b87526d66809be7acd6339156ea778a8c2f` | `8f6cb1a483c879024bddea289e90d4bf2d71dd15716102bc83a1f34a243782e4` |
-| [GeoPoint](../patches/madelineproto-geopoint/manifest.json) | `9ed8054caade6abc96420b0f5b120bec029ee2bc7b7b6aacca56fb7ddc61a27b` | `5633cc441e541e5e919dfa8156192587a68e578e49a496acac91172be5f2549d` |
-| [MessageEntity factory](../patches/madelineproto-formatted-date/manifest.json) | `06a9d438cc198f56cfb745a2a3808932269033671146cf82f84ae88e8d6eae60` | `b265ed707326e1d71c7a8bdf8291f0b8c94a153b98a2c4c45c776fec3b374005` |
-| [PeerHandler](../patches/madelineproto-fresh-peer/manifest.json) | `3e1af3624f2256f53264fe4256475d0a5f353af8761cc9716133b7f0412538d2` | `8188777fc376f2b3cca39963d79f85239fc84141f978128ea2bb591f03891928` |
-| [BroadcastManager](../patches/broadcastmanager/manifest.json) | `2a9a42dc6e3f6d7b51c178e7d9db962a5b5ac424046af18afcfcdb12d41dc6e8` | `d665b24009aabfb5b09e00edad1271f1501bf0ef797d5a2593129da91c8cc435` |
-
-### UpdateLoop cancellation and recovery
+| Set | Locked base | Baseline SHA-256 | Approved output SHA-256 |
+|---|---|---|---|
+| [Fresh full-peer evidence](../patches/madelineproto-fresh-peer/manifest.json) | MadelineProto 8.11.10, 49d3d8460257c7bfb1a7e12708e1bfdd59e898c1 | 6caa058975e7122eeb84409542a7c8241a2da5c63ca4c63e1ec2392c7b3f7314 | 78187d7216c069d47d1c05d8128834603b958b55bc8478576850bce9e86489df |
+| [BroadcastManager](../patches/broadcastmanager/manifest.json) | 3.2.2, f2792a383416b66bb68e55f09414563e540538d6 | 2a9a42dc6e3f6d7b51c178e7d9db962a5b5ac424046af18afcfcdb12d41dc6e8 | d665b24009aabfb5b09e00edad1271f1501bf0ef797d5a2593129da91c8cc435 |
-[The patch review](../patches/madelineproto/README.md) identifies a retained historical PHP patch script and a reproduced reference diff. The script's SHA-256 is `1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9`; identical copies were found in local project exports `newsearch-v2` and `psy new/release-r21-work`. The reference diff is reproduced from that script, not claimed to be a historical Git diff.
+The PeerHandler derivative preserves the upstream public signature and 8.11.10 community/invalid-peer handling, while exposing raw per-call response evidence when full-info caching is disabled. This supports permission validation without treating a stale combined cache record as current RPC evidence. It is a local correction, not an upstream attribution.
-The applied derivative adds shutdown/authorization guards and delayed recovery to the reference cancellation checks. Direct timeouts and timeout-derived cancellation can recover; unrelated cancellation is rethrown and a stopped loop stops. The immutable baseline, script, reference diff, applied diff and manifest remain bundled. The historical standalone script has no license header; its bytes are preserved unchanged. On **2026-10-16**, the WizardLoop project maintainer explicitly stated that they authored this exact helper and authorized its distribution under **AGPL-3.0-only**. The hash-scoped attestation in the patch manifest records that direct maintainer statement. It resolves the previously missing maintainer authorization for this retained helper; it is not an independent authorship/legal certification and does not change upstream MadelineProto grants or the separate formatted-date export findings.
+BroadcastManager retains original source, dev.3 presentation source (3d9425f7911b12c69faae5e87954db134dc3fb7c2f7d654a72f972ebeb84e424), dev.8 transport source (08db35c271f671041257ebe79d1010cdd7c33c4d5868e4553c78612f9e8bf0f3) and guarded transition diffs. The approved derivative includes lifecycle admission/cancellation guards, tracked worker/progress draining and bounded flood handling. These are behavior changes, not merely presentation. Unknown source bytes fail verification.
-### Fractional coordinates
+## Retired patches and historical findings
-The [GeoPoint correction](../patches/madelineproto-geopoint/README.md) changes the two longitude/latitude property types and annotations from integer to float, matching Telegram double coordinates. Access hashes, accuracy radius and surrounding serialization remain unchanged. It is separate from the historical UpdateLoop work; the pinned original file, reviewed output, diff and manifest are retained.
+3.1.0 uses official SDK UpdateLoop, GeoPoint and FormattedDate source. Their former local patch directories, helper and wrapper are absent from this release tree. Retirement does not claim that every upstream shutdown behavior is resolved; [publication status](PUBLICATION_STATUS.md) and actual regression evidence govern that conclusion.
-### Formatted-date entities
+For historical identification only:
-The [factory/class correction](../patches/madelineproto-formatted-date/README.md) adds the native/Bot API factory branches and a new independently authored `FormattedDate` wrapper. Native timestamps, UTF-16 offsets/lengths and flags remain represented; the locked schema and complete upstream license accompany the baseline and diff. The new class SHA-256 is `ffe03d0d78215bc42968cd836c25b1f8a602f161fb55eba189b4102d9b99d5e5`; its copyright is WizardLoop 2026 and its grant is AGPL-3.0-or-later. The unmodified upstream license SHA-256 is `57c8ff33c9c0cfc3ef00e650a1cc910d7ee479a8bc509f6c9209a7c2a11399d6`, identical to the root AGPL text.
+- The earlier standalone UpdateLoop helper SHA-256 was 1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9. On 2026-10-16 the maintainer stated authorship and authorized distribution of those exact bytes under AGPL-3.0-only. Prior release provenance retains that scoped statement; it is not an independent legal certification.
+- Historical formatted-date exports had script SHA-256 c3091f61a401d8022b8ef1d228cf8c5f31a1094982de69a0be108e21885cb967 and wrapper SHA-256 a9e3146e49a88bec469e67e53f5e27cffb1b5127cde547590f2e385ef02dd264. Their MIT/proprietary project declarations conflicted and no standalone grant or recovered Git history was found. Those exports were not redistributed.
+- The separately authored wrapper shipped in earlier releases had SHA-256 ffe03d0d78215bc42968cd836c25b1f8a602f161fb55eba189b4102d9b99d5e5, Copyright WizardLoop 2026, AGPL-3.0-or-later. It is no longer an active source input.
-Two historical exports share script SHA-256 `c3091f61a401d8022b8ef1d228cf8c5f31a1094982de69a0be108e21885cb967` and wrapper SHA-256 `a9e3146e49a88bec469e67e53f5e27cffb1b5127cde547590f2e385ef02dd264`. Their project declarations conflict: MIT in `wizardloop/theisraelis`, proprietary in `psychedelize/psy-bot-suite`. No standalone grant or recoverable Git history was found. Those original exports are not redistributed; [the investigation](MADELINE_FORMATTED_DATE.md) preserves the finding and explains the new implementation's source basis.
+## Current SDK preferred source
-### Fresh full-peer response evidence
+The [source manifest](../resources/release/source-manifest.json) binds 4,095 files from 83 exact runtime distributions, with only the two approved patched outputs differing from upstream. Two public Amp TLS example private keys are omitted by exact hash. All other runtime files, resources and notices remain inventoried; no extension-based source filtering is used.
-The [PeerHandler correction](../patches/madelineproto-fresh-peer/README.md), reviewed 2026-10-16, preserves the public `getFullInfo` signature and exposes per-call raw response evidence when full-info caching is disabled. This supports current permission validation without trusting a stale combined chat/cache record. It is a new local correction, not attributed to a recovered historical patch or an upstream fix. Its baseline was recorded as matching the pinned remote and installed source; original AGPL/copyright headers remain intact.
+The MadelineProto supplement has **84 files** at SDK commit 49d3d8460257c7bfb1a7e12708e1bfdd59e898c1, schema submodule 1d027e48ce9196d86110f8324e23a5c78fc4ef6a and documentation submodule 10ea0769245a3d080c3e501b12603e804ad9f3af. Original Git blobs and SHA-256 values accompany each file. It includes TL/secret parser builders, file-reference-map generators, current TL232/MTProto/secret schemas, all language inputs and the local language generator. The runtime package supplies their referenced parser/runtime classes. No generator was executed.
-### BroadcastManager history and current lifecycle changes
+Full historical schema regeneration, complete generated upstream documentation, its development toolchain and historical mutable RPC responses are outside this collection. No separate license file was present in the pinned schema/documentation submodule trees; their bytes and the parent MadelineProto notices are preserved without inventing a new grant.
-The [BroadcastManager review](../patches/broadcastmanager/README.md) records three stages:
+## RTC source findings
-| Stage | Reviewed-source SHA-256 | Scope |
-|---|---|---|
-| dev.3 | `3d9425f7911b12c69faae5e87954db134dc3fb7c2f7d654a72f972ebeb84e424` | Per-instance status/counter/control presentation. |
-| dev.4 through dev.8 | `08db35c271f671041257ebe79d1010cdd7c33c4d5868e4553c78612f9e8bf0f3` | Optional message-transport hook at native text/media/album/edit/status sites. |
-| dev.9, current | `d665b24009aabfb5b09e00edad1271f1501bf0ef797d5a2593129da91c8cc435` | Runtime authorization/cancellation/admission hooks, cancellation-aware waits, worker/progress joining, cancelled queue persistence and bounded completed progress history. |
+The new RTC PHP packages are locked and included with their original source, notices and Go reference-source files where distributed. danog/php-rtc-av metadata declares MIT while its distributed LICENSE and PHP source headers state BSD-3-Clause; the dependency report preserves the mismatch as **NOT VERIFIED** for the declared MIT grant.
-The older statement that the patch did not change delivery lifecycle applies to the historical presentation stage only. The current derivative includes lifecycle behavior. The native library retains separate persistent state; null optional hooks preserve native call paths, while current future joining is part of the reviewed implementation. The application requests native flood-wait errors for manager-controlled retry. Exact original source, both prior approved sources and all guarded transition diffs remain in the manifest. Unknown intermediate bytes fail verification.
+The AV package contains FFI declaration headers and an optional FFmpeg downloader, not FFmpeg native binaries. The downloader was not run. Native libraries, their optional installation and platform-specific builds are outside the Composer source collection. The eight editable C declaration files match the pinned upstream Git blobs. No separate generator or extraction recipe exists in that tree; whether they are directly maintained preferred source or generated derivatives is unestablished. Their external provenance and any additional notice requirements remain review findings, not a proven missing generator. The pinned AV README is retained as a supplement because Composer dist excludes it; it explicitly states BSD-3-Clause and FFmpeg 9 ABI. The optional downloader repository/tag/release returned HTTP 404 during review, and no native build provenance is claimed.
## Data provenance
diff --git a/docs/ZMANIM_METHODS.md b/docs/ZMANIM_METHODS.md
index b2be932..f398ab3 100644
--- a/docs/ZMANIM_METHODS.md
+++ b/docs/ZMANIM_METHODS.md
@@ -13,7 +13,7 @@ The calendar is fetched separately with explicit `i=on/off`, avoiding a location
Civil dates select Daf Yomi. Omer evening uses the next civil date's structured Omer event; after midnight the current date continues that night. Counting progresses through non-send days. Night messages wait until chosen nightfall and quiet/lock end; daytime completion is separate, disabled by default and omits the blessing.
Sources: [Hebcal calendar](https://www.hebcal.com/home/195/jewish-calendar-rest-api), [zmanim](https://www.hebcal.com/home/1663/zmanim-halachic-times-api), [candle/havdalah](https://www.hebcal.com/home/4463/candle-lighting-havdalah-fast-times).
-
+
Current `is_shabbat` and `is_yom_tov` flags are calculated from active individual day segments. A merged festival/Shabbat sequence keeps one final opening time; its union of event metadata does not imply that every day in the sequence is both Shabbat and Yom Tov. `quiet_now` includes the configured early operational closure, even before the religious interval begins.
Omer phase is explicit: day, twilight or night. At sunset the next civil date's structured Omer event becomes the display count, but nighttime delivery waits for the chosen nightfall. After midnight the current civil date still identifies that counting night until verified dawn. Fixed times before noon are anchored on the following civil morning of the night being planned; a time beyond dawn does not create a night reminder. Optional daytime completion is a separate no-blessing behavior and is suppressed during the group's religious/operational quiet period. Night retry expiry never passes dawn.
@@ -30,7 +30,7 @@ Full night form additionally includes the traditional blessing with localized el
The current tefillin reminder start method is explicitly Hebcal `misheyakir`, 11.5 degrees below the morning horizon. The provider also returns `misheyakirMachmir` (10.2 degrees), but the current reminder form does not offer a selector for that second method. A missing/null selected misheyakir blocks scheduling; the code does not substitute dawn/sunrise or a guessed value. See the [provider method definitions](https://www.hebcal.com/home/1663/zmanim-halachic-times-api).
-Internal language codes are `he`, `en`, `ru`, `fr`, `es`, `pt-br`. Calendar-provider requests map English to Hebcal `s` and Brazilian Portuguese to `pt`; the other four map directly. The [official language documentation](https://www.hebcal.com/home/4534/jewish-calendar-event-language-support) lists the Hebrew/English/Russian/French/Spanish options; the [official calendar form](https://www.hebcal.com/ical/) and a public `lg=pt` API request on 2026-10-13 confirmed Portuguese titles. `title_orig` retains the original event name used for fast/day classification, with original English `title` fallback when the provider omits a redundant original field. A display language change cannot change event restrictions.
+Internal language codes are `he`, `en`, `ru`, `fr`, `es`, `pt-br`. Calendar-provider requests map English to Hebcal `s` and Brazilian Portuguese to `pt`; the other four map directly. The [official language documentation](https://www.hebcal.com/home/4534/jewish-calendar-event-language-support) lists the Hebrew/English/Russian/French/Spanish options; the [official calendar form](https://www.hebcal.com/ical/) and a public `lg=pt` API request on 2026-10-13 confirmed Portuguese titles. `title_orig` retains the original event name used for fast/day classification, with original English `title` fallback when the provider omits a redundant original field. A display language change cannot change event restrictions.
## Complete solar response contract (dev.3)
diff --git a/docs/composer-audit.json b/docs/composer-audit.json
index 22fecbe..2b14cf8 100644
--- a/docs/composer-audit.json
+++ b/docs/composer-audit.json
@@ -1,4 +1,4 @@
-{
- "advisories": [],
- "abandoned": []
+{
+ "advisories": [],
+ "abandoned": []
}
diff --git a/docs/composer-licenses.json b/docs/composer-licenses.json
index 49353f9..6b2a547 100644
--- a/docs/composer-licenses.json
+++ b/docs/composer-licenses.json
@@ -1,507 +1,663 @@
-{
- "name": "wizardloop/shabbat",
- "version": "dev-main",
- "license": [
- "AGPL-3.0-only"
- ],
- "dependencies": {
- "amphp/amp": {
- "version": "v3.1.3",
- "license": [
- "MIT"
- ]
- },
- "amphp/byte-stream": {
- "version": "v2.1.2",
- "license": [
- "MIT"
- ]
- },
- "amphp/cache": {
- "version": "v2.0.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/dns": {
- "version": "v2.4.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/file": {
- "version": "v3.2.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/hpack": {
- "version": "v3.2.2",
- "license": [
- "MIT"
- ]
- },
- "amphp/http": {
- "version": "v2.1.2",
- "license": [
- "MIT"
- ]
- },
- "amphp/http-client": {
- "version": "v5.3.6",
- "license": [
- "MIT"
- ]
- },
- "amphp/http-client-cookies": {
- "version": "v2.0.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/http-server": {
- "version": "v3.4.7",
- "license": [
- "MIT"
- ]
- },
- "amphp/log": {
- "version": "v2.0.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/mysql": {
- "version": "v3.1.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/parallel": {
- "version": "v2.4.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/parser": {
- "version": "v1.1.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/pipeline": {
- "version": "v1.2.7",
- "license": [
- "MIT"
- ]
- },
- "amphp/postgres": {
- "version": "v2.2.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/process": {
- "version": "v2.1.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/redis": {
- "version": "v2.0.4",
- "license": [
- "MIT"
- ]
- },
- "amphp/serialization": {
- "version": "v1.1.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/socket": {
- "version": "v2.4.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/sql": {
- "version": "v2.1.1",
- "license": [
- "MIT"
- ]
- },
- "amphp/sql-common": {
- "version": "v2.0.4",
- "license": [
- "MIT"
- ]
- },
- "amphp/sync": {
- "version": "v2.3.0",
- "license": [
- "MIT"
- ]
- },
- "amphp/websocket": {
- "version": "v2.0.4",
- "license": [
- "MIT"
- ]
- },
- "amphp/websocket-client": {
- "version": "v2.0.2",
- "license": [
- "MIT"
- ]
- },
- "bacon/bacon-qr-code": {
- "version": "v3.1.1",
- "license": [
- "BSD-2-Clause"
- ]
- },
- "danog/async-orm": {
- "version": "1.1.4",
- "license": [
- "Apache-2.0"
- ]
- },
- "danog/better-prometheus": {
- "version": "0.1.1",
- "license": [
- "Apache-2.0"
- ]
- },
- "danog/dns-over-https": {
- "version": "1.0.1",
- "license": [
- "MIT"
- ]
- },
- "danog/ipc": {
- "version": "1.0.1",
- "license": [
- "MIT"
- ]
- },
- "danog/libdns-json": {
- "version": "0.2.1",
- "license": [
- "MIT"
- ]
- },
- "danog/loop": {
- "version": "1.1.1",
- "license": [
- "MIT"
- ]
- },
- "danog/madelineproto": {
- "version": "8.7.0",
- "license": [
- "AGPL-3.0-only"
- ]
- },
- "danog/primemodule": {
- "version": "1.0.13",
- "license": [
- "AGPL-3.0-only"
- ]
- },
- "danog/telegram-entities": {
- "version": "1.0.5",
- "license": [
- "Apache-2.0"
- ]
- },
- "danog/tg-dialog-id": {
- "version": "2.0.0",
- "license": [
- "Apache-2.0"
- ]
- },
- "danog/tg-file-decoder": {
- "version": "1.0.2",
- "license": [
- "AGPL-3.0-only"
- ]
- },
- "dasprid/enum": {
- "version": "1.0.7",
- "license": [
- "BSD-2-Clause"
- ]
- },
- "daverandom/libdns": {
- "version": "v2.1.0",
- "license": [
- "MIT"
- ]
- },
- "kelunik/certificate": {
- "version": "v1.1.3",
- "license": [
- "MIT"
- ]
- },
- "league/uri": {
- "version": "7.8.1",
- "license": [
- "MIT"
- ]
- },
- "league/uri-components": {
- "version": "7.8.1",
- "license": [
- "MIT"
- ]
- },
- "league/uri-interfaces": {
- "version": "7.8.1",
- "license": [
- "MIT"
- ]
- },
- "monolog/monolog": {
- "version": "3.12.1",
- "license": [
- "MIT"
- ]
- },
- "myclabs/deep-copy": {
- "version": "1.14.0",
- "license": [
- "MIT"
- ]
- },
- "nikic/php-parser": {
- "version": "v5.9.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "paragonie/constant_time_encoding": {
- "version": "v3.1.3",
- "license": [
- "MIT"
- ]
- },
- "paragonie/random_compat": {
- "version": "v9.99.100",
- "license": [
- "MIT"
- ]
- },
- "phar-io/manifest": {
- "version": "2.0.4",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phar-io/version": {
- "version": "3.2.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpseclib/phpseclib": {
- "version": "3.0.57",
- "license": [
- "MIT"
- ]
- },
- "phpstan/phpstan": {
- "version": "2.3.1",
- "license": [
- "MIT"
- ]
- },
- "phpunit/php-code-coverage": {
- "version": "12.5.8",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpunit/php-file-iterator": {
- "version": "6.0.2",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpunit/php-invoker": {
- "version": "6.0.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpunit/php-text-template": {
- "version": "5.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpunit/php-timer": {
- "version": "8.0.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "phpunit/phpunit": {
- "version": "12.5.39",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "promphp/prometheus_client_php": {
- "version": "v2.15.1",
- "license": [
- "Apache-2.0"
- ]
- },
- "psr/http-factory": {
- "version": "1.1.0",
- "license": [
- "MIT"
- ]
- },
- "psr/http-message": {
- "version": "2.0",
- "license": [
- "MIT"
- ]
- },
- "psr/log": {
- "version": "3.0.2",
- "license": [
- "MIT"
- ]
- },
- "revolt/event-loop": {
- "version": "v1.0.9",
- "license": [
- "MIT"
- ]
- },
- "sebastian/cli-parser": {
- "version": "4.2.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/comparator": {
- "version": "7.1.8",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/complexity": {
- "version": "5.0.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/diff": {
- "version": "7.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/environment": {
- "version": "8.1.2",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/exporter": {
- "version": "7.0.3",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/global-state": {
- "version": "8.0.3",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/lines-of-code": {
- "version": "4.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/object-enumerator": {
- "version": "7.0.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/object-reflector": {
- "version": "5.0.0",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/recursion-context": {
- "version": "7.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/type": {
- "version": "6.0.4",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "sebastian/version": {
- "version": "6.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "squizlabs/php_codesniffer": {
- "version": "4.0.4",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "staabm/side-effects-detector": {
- "version": "1.0.5",
- "license": [
- "MIT"
- ]
- },
- "symfony/polyfill-mbstring": {
- "version": "v1.43.0",
- "license": [
- "MIT"
- ]
- },
- "symfony/polyfill-php83": {
- "version": "v1.43.0",
- "license": [
- "MIT"
- ]
- },
- "theseer/tokenizer": {
- "version": "2.0.1",
- "license": [
- "BSD-3-Clause"
- ]
- },
- "webmozart/assert": {
- "version": "1.12.1",
- "license": [
- "MIT"
- ]
- },
- "wizardloop/broadcastmanager": {
- "version": "3.2.2",
- "license": [
- "AGPL-3.0-only"
- ]
- }
- }
+{
+ "name": "wizardloop/shabbat",
+ "version": "dev-main 2604d1e",
+ "license": [
+ "AGPL-3.0-only"
+ ],
+ "dependencies": {
+ "amphp/amp": {
+ "version": "v3.1.3",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/byte-stream": {
+ "version": "v2.1.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/cache": {
+ "version": "v2.0.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/dns": {
+ "version": "v2.4.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/file": {
+ "version": "v3.2.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/hpack": {
+ "version": "v3.2.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/http": {
+ "version": "v2.1.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/http-client": {
+ "version": "v5.3.6",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/http-client-cookies": {
+ "version": "v2.0.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/http-server": {
+ "version": "v3.4.7",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/log": {
+ "version": "v2.0.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/mysql": {
+ "version": "v3.1.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/parallel": {
+ "version": "v2.4.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/parser": {
+ "version": "v1.1.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/pipeline": {
+ "version": "v1.2.7",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/postgres": {
+ "version": "v2.2.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/process": {
+ "version": "v2.1.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/redis": {
+ "version": "v2.0.4",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/serialization": {
+ "version": "v1.1.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/socket": {
+ "version": "v2.4.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/sql": {
+ "version": "v2.1.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/sql-common": {
+ "version": "v2.0.4",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/sync": {
+ "version": "v2.3.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/websocket": {
+ "version": "v2.0.4",
+ "license": [
+ "MIT"
+ ]
+ },
+ "amphp/websocket-client": {
+ "version": "v2.0.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "bacon/bacon-qr-code": {
+ "version": "v3.1.1",
+ "license": [
+ "BSD-2-Clause"
+ ]
+ },
+ "brick/math": {
+ "version": "1.0.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/async-orm": {
+ "version": "1.1.6",
+ "license": [
+ "Apache-2.0"
+ ]
+ },
+ "danog/better-prometheus": {
+ "version": "0.1.1",
+ "license": [
+ "Apache-2.0"
+ ]
+ },
+ "danog/dns-over-https": {
+ "version": "1.0.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/ipc": {
+ "version": "1.1.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/libdns-json": {
+ "version": "0.2.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/loop": {
+ "version": "1.1.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/madelineproto": {
+ "version": "8.11.10",
+ "license": [
+ "AGPL-3.0-only"
+ ]
+ },
+ "danog/php-rtc-av": {
+ "version": "1.1.11",
+ "license": [
+ "MIT"
+ ]
+ },
+ "danog/php-rtc-codecs": {
+ "version": "1.1.19",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-datachannel": {
+ "version": "1.1.10",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-dtls": {
+ "version": "2.0.20",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-exception": {
+ "version": "1.1.10",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-ice": {
+ "version": "2.0.18",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-mdns": {
+ "version": "1.1.12",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-mixin": {
+ "version": "2.0.9",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-ntp": {
+ "version": "1.1.15",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-rtcp": {
+ "version": "1.1.11",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-rtp": {
+ "version": "2.0.23",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-rtp-parameter": {
+ "version": "1.1.8",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-sctp": {
+ "version": "2.0.14",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-sdp": {
+ "version": "1.1.12",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-srtp": {
+ "version": "1.1.16",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-stats": {
+ "version": "1.1.7",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-stun": {
+ "version": "2.0.18",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-turn": {
+ "version": "2.0.9",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/php-rtc-webrtc": {
+ "version": "2.0.20",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "danog/primemodule": {
+ "version": "1.0.13",
+ "license": [
+ "AGPL-3.0-only"
+ ]
+ },
+ "danog/telegram-entities": {
+ "version": "1.1.0",
+ "license": [
+ "Apache-2.0"
+ ]
+ },
+ "danog/tg-dialog-id": {
+ "version": "2.0.0",
+ "license": [
+ "Apache-2.0"
+ ]
+ },
+ "danog/tg-file-decoder": {
+ "version": "1.0.2",
+ "license": [
+ "AGPL-3.0-only"
+ ]
+ },
+ "dasprid/enum": {
+ "version": "1.0.7",
+ "license": [
+ "BSD-2-Clause"
+ ]
+ },
+ "daverandom/libdns": {
+ "version": "v2.1.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "kelunik/certificate": {
+ "version": "v1.1.3",
+ "license": [
+ "MIT"
+ ]
+ },
+ "league/uri": {
+ "version": "7.8.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "league/uri-components": {
+ "version": "7.8.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "league/uri-interfaces": {
+ "version": "7.8.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "monolog/monolog": {
+ "version": "3.12.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "myclabs/deep-copy": {
+ "version": "1.14.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "nikic/php-parser": {
+ "version": "v5.9.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "paragonie/constant_time_encoding": {
+ "version": "v3.1.3",
+ "license": [
+ "MIT"
+ ]
+ },
+ "phar-io/manifest": {
+ "version": "2.0.4",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phar-io/version": {
+ "version": "3.2.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpseclib/phpseclib": {
+ "version": "4.0.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "phpstan/phpstan": {
+ "version": "2.3.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "phpunit/php-code-coverage": {
+ "version": "12.5.8",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpunit/php-file-iterator": {
+ "version": "6.0.2",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpunit/php-invoker": {
+ "version": "6.0.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpunit/php-text-template": {
+ "version": "5.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpunit/php-timer": {
+ "version": "8.0.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "phpunit/phpunit": {
+ "version": "12.5.39",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "promphp/prometheus_client_php": {
+ "version": "v2.15.1",
+ "license": [
+ "Apache-2.0"
+ ]
+ },
+ "psr/http-factory": {
+ "version": "1.1.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "psr/http-message": {
+ "version": "2.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "psr/log": {
+ "version": "3.0.2",
+ "license": [
+ "MIT"
+ ]
+ },
+ "ramsey/collection": {
+ "version": "2.1.1",
+ "license": [
+ "MIT"
+ ]
+ },
+ "ramsey/uuid": {
+ "version": "4.9.4",
+ "license": [
+ "MIT"
+ ]
+ },
+ "revolt/event-loop": {
+ "version": "v1.0.9",
+ "license": [
+ "MIT"
+ ]
+ },
+ "sebastian/cli-parser": {
+ "version": "4.2.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/comparator": {
+ "version": "7.1.8",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/complexity": {
+ "version": "5.0.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/diff": {
+ "version": "7.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/environment": {
+ "version": "8.1.2",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/exporter": {
+ "version": "7.0.3",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/global-state": {
+ "version": "8.0.3",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/lines-of-code": {
+ "version": "4.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/object-enumerator": {
+ "version": "7.0.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/object-reflector": {
+ "version": "5.0.0",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/recursion-context": {
+ "version": "7.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/type": {
+ "version": "6.0.4",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "sebastian/version": {
+ "version": "6.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "squizlabs/php_codesniffer": {
+ "version": "4.0.4",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "staabm/side-effects-detector": {
+ "version": "1.0.5",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-iconv": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-mbstring": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-php82": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-php83": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-php84": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-php85": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "symfony/polyfill-php86": {
+ "version": "v1.43.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "theseer/tokenizer": {
+ "version": "2.0.1",
+ "license": [
+ "BSD-3-Clause"
+ ]
+ },
+ "webmozart/assert": {
+ "version": "2.5.0",
+ "license": [
+ "MIT"
+ ]
+ },
+ "wizardloop/broadcastmanager": {
+ "version": "3.2.2",
+ "license": [
+ "AGPL-3.0-only"
+ ]
+ }
+ }
}
diff --git a/docs/composer-show.json b/docs/composer-show.json
index 3ff3f31..f61f3b8 100644
--- a/docs/composer-show.json
+++ b/docs/composer-show.json
@@ -1,751 +1,985 @@
-{
- "locked": [
- {
- "name": "amphp/amp",
- "direct-dependency": true,
- "homepage": "https://amphp.org/amp",
- "source": "https://github.com/amphp/amp/tree/v3.1.3",
- "version": "v3.1.3",
- "description": "A non-blocking concurrency framework for PHP applications.",
- "abandoned": false
- },
- {
- "name": "amphp/byte-stream",
- "direct-dependency": false,
- "homepage": "https://amphp.org/byte-stream",
- "source": "https://github.com/amphp/byte-stream/tree/v2.1.2",
- "version": "v2.1.2",
- "description": "A stream abstraction to make working with non-blocking I/O simple.",
- "abandoned": false
- },
- {
- "name": "amphp/cache",
- "direct-dependency": false,
- "homepage": "https://amphp.org/cache",
- "source": "https://github.com/amphp/cache/tree/v2.0.1",
- "version": "v2.0.1",
- "description": "A fiber-aware cache API based on Amp and Revolt.",
- "abandoned": false
- },
- {
- "name": "amphp/dns",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/dns",
- "source": "https://github.com/amphp/dns/tree/v2.4.1",
- "version": "v2.4.1",
- "description": "Async DNS resolution for Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/file",
- "direct-dependency": true,
- "homepage": "https://github.com/amphp/file",
- "source": "https://github.com/amphp/file/tree/v3.2.0",
- "version": "v3.2.0",
- "description": "Non-blocking access to the filesystem based on Amp and Revolt.",
- "abandoned": false
- },
- {
- "name": "amphp/hpack",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/hpack",
- "source": "https://github.com/amphp/hpack/tree/v3.2.2",
- "version": "v3.2.2",
- "description": "HTTP/2 HPack implementation.",
- "abandoned": false
- },
- {
- "name": "amphp/http",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/amphp/http/tree/v2.1.2",
- "version": "v2.1.2",
- "description": "Basic HTTP primitives which can be shared by servers and clients.",
- "abandoned": false
- },
- {
- "name": "amphp/http-client",
- "direct-dependency": true,
- "homepage": "https://amphp.org/http-client",
- "source": "https://github.com/amphp/http-client/tree/v5.3.6",
- "version": "v5.3.6",
- "description": "An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.",
- "abandoned": false
- },
- {
- "name": "amphp/http-client-cookies",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/http-client-cookies",
- "source": "https://github.com/amphp/http-client-cookies/tree/v2.0.0",
- "version": "v2.0.0",
- "description": "Automatic cookie handling for Amp's HTTP client.",
- "abandoned": false
- },
- {
- "name": "amphp/http-server",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/http-server",
- "source": "https://github.com/amphp/http-server/tree/v3.4.7",
- "version": "v3.4.7",
- "description": "A non-blocking HTTP application server for PHP based on Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/log",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/log",
- "source": "https://github.com/amphp/log/tree/v2.0.0",
- "version": "v2.0.0",
- "description": "Non-blocking logging for PHP based on Amp, Revolt, and Monolog.",
- "abandoned": false
- },
- {
- "name": "amphp/mysql",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/amphp/mysql/tree/v3.1.1",
- "version": "v3.1.1",
- "description": "Asynchronous MySQL client for PHP based on Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/parallel",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/parallel",
- "source": "https://github.com/amphp/parallel/tree/v2.4.0",
- "version": "v2.4.0",
- "description": "Parallel processing component for Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/parser",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/parser",
- "source": "https://github.com/amphp/parser/tree/v1.1.1",
- "version": "v1.1.1",
- "description": "A generator parser to make streaming parsers simple.",
- "abandoned": false
- },
- {
- "name": "amphp/pipeline",
- "direct-dependency": false,
- "homepage": "https://amphp.org/pipeline",
- "source": "https://github.com/amphp/pipeline/tree/v1.2.7",
- "version": "v1.2.7",
- "description": "Asynchronous iterators and operators.",
- "abandoned": false
- },
- {
- "name": "amphp/postgres",
- "direct-dependency": false,
- "homepage": "https://amphp.org",
- "source": "https://github.com/amphp/postgres/tree/v2.2.1",
- "version": "v2.2.1",
- "description": "Asynchronous PostgreSQL client for Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/process",
- "direct-dependency": false,
- "homepage": "https://amphp.org/process",
- "source": "https://github.com/amphp/process/tree/v2.1.0",
- "version": "v2.1.0",
- "description": "A fiber-aware process manager based on Amp and Revolt.",
- "abandoned": false
- },
- {
- "name": "amphp/redis",
- "direct-dependency": false,
- "homepage": "https://amphp.org/redis",
- "source": "https://github.com/amphp/redis/tree/v2.0.4",
- "version": "v2.0.4",
- "description": "Efficient asynchronous communication with Redis servers, enabling scalable and responsive data storage and retrieval.",
- "abandoned": false
- },
- {
- "name": "amphp/serialization",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/serialization",
- "source": "https://github.com/amphp/serialization/tree/v1.1.0",
- "version": "v1.1.0",
- "description": "Serialization tools for IPC and data storage in PHP.",
- "abandoned": false
- },
- {
- "name": "amphp/socket",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/socket",
- "source": "https://github.com/amphp/socket/tree/v2.4.1",
- "version": "v2.4.1",
- "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.",
- "abandoned": false
- },
- {
- "name": "amphp/sql",
- "direct-dependency": false,
- "homepage": "https://amphp.org",
- "source": "https://github.com/amphp/sql/tree/v2.1.1",
- "version": "v2.1.1",
- "description": "Asynchronous SQL client for Amp.",
- "abandoned": false
- },
- {
- "name": "amphp/sql-common",
- "direct-dependency": false,
- "homepage": "https://amphp.org",
- "source": "https://github.com/amphp/sql-common/tree/v2.0.4",
- "version": "v2.0.4",
- "description": "Common classes for non-blocking SQL implementations.",
- "abandoned": false
- },
- {
- "name": "amphp/sync",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/sync",
- "source": "https://github.com/amphp/sync/tree/v2.3.0",
- "version": "v2.3.0",
- "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.",
- "abandoned": false
- },
- {
- "name": "amphp/websocket",
- "direct-dependency": false,
- "homepage": "https://github.com/amphp/websocket",
- "source": "https://github.com/amphp/websocket/tree/v2.0.4",
- "version": "v2.0.4",
- "description": "Shared code for websocket servers and clients.",
- "abandoned": false
- },
- {
- "name": "amphp/websocket-client",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/amphp/websocket-client/tree/v2.0.2",
- "version": "v2.0.2",
- "description": "Async WebSocket client for PHP based on Amp.",
- "abandoned": false
- },
- {
- "name": "bacon/bacon-qr-code",
- "direct-dependency": false,
- "homepage": "https://github.com/Bacon/BaconQrCode",
- "source": "https://github.com/Bacon/BaconQrCode/tree/v3.1.1",
- "version": "v3.1.1",
- "description": "BaconQrCode is a QR code generator for PHP.",
- "abandoned": false
- },
- {
- "name": "danog/async-orm",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/AsyncOrm/tree/1.1.4",
- "version": "1.1.4",
- "description": "Async ORM based on AMPHP v3 and fibers.",
- "abandoned": false
- },
- {
- "name": "danog/better-prometheus",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/better-prometheus/tree/0.1.1",
- "version": "0.1.1",
- "description": "A better Prometheus library for PHP applications",
- "abandoned": false
- },
- {
- "name": "danog/dns-over-https",
- "direct-dependency": false,
- "homepage": "https://github.com/danog/dns-over-https",
- "source": "https://github.com/danog/dns-over-https/tree/1.0.1",
- "version": "1.0.1",
- "description": "Async DNS-over-HTTPS resolution for Amp.",
- "abandoned": false
- },
- {
- "name": "danog/ipc",
- "direct-dependency": false,
- "homepage": "https://github.com/danog/ipc",
- "source": "https://github.com/danog/ipc/tree/1.0.1",
- "version": "1.0.1",
- "description": "IPC component for Amp.",
- "abandoned": false
- },
- {
- "name": "danog/libdns-json",
- "direct-dependency": false,
- "homepage": "https://github.com/danog/libdns-json",
- "source": "https://github.com/danog/LibDNSJson/tree/0.2.1",
- "version": "0.2.1",
- "description": "Encoder/decoder for google's JSON DNS message format based on libdns",
- "abandoned": false
- },
- {
- "name": "danog/loop",
- "direct-dependency": false,
- "homepage": "https://github.com/danog/loop",
- "source": "https://github.com/danog/loop/tree/1.1.1",
- "version": "1.1.1",
- "description": "Loop abstraction for AMPHP.",
- "abandoned": false
- },
- {
- "name": "danog/madelineproto",
- "direct-dependency": true,
- "homepage": "https://docs.madelineproto.xyz",
- "source": "https://github.com/danog/MadelineProto/tree/8.7.0",
- "version": "8.7.0",
- "description": "Async PHP client API for the telegram MTProto protocol.",
- "abandoned": false
- },
- {
- "name": "danog/primemodule",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/PrimeModule/tree/1.0.13",
- "version": "1.0.13",
- "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
- "abandoned": false
- },
- {
- "name": "danog/telegram-entities",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/telegram-entities/tree/1.0.5",
- "version": "1.0.5",
- "description": "A library to work with Telegram UTF-16 styled text entities.",
- "abandoned": false
- },
- {
- "name": "danog/tg-dialog-id",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/tg-dialog-id/tree/2.0.0",
- "version": "2.0.0",
- "description": "A library to work with Telegram bot API dialog IDs",
- "abandoned": false
- },
- {
- "name": "danog/tg-file-decoder",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/danog/tg-file-decoder/tree/1.0.2",
- "version": "1.0.2",
- "description": "Decode Telegram bot API file IDs",
- "abandoned": false
- },
- {
- "name": "dasprid/enum",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/DASPRiD/Enum/tree/1.0.7",
- "version": "1.0.7",
- "description": "PHP 7.1 enum implementation",
- "abandoned": false
- },
- {
- "name": "daverandom/libdns",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0",
- "version": "v2.1.0",
- "description": "DNS protocol implementation written in pure PHP",
- "abandoned": false
- },
- {
- "name": "kelunik/certificate",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/kelunik/certificate/tree/v1.1.3",
- "version": "v1.1.3",
- "description": "Access certificate details and transform between different formats.",
- "abandoned": false
- },
- {
- "name": "league/uri",
- "direct-dependency": false,
- "homepage": "https://uri.thephpleague.com",
- "source": "https://github.com/thephpleague/uri/tree/7.8.1",
- "version": "7.8.1",
- "description": "URI manipulation library",
- "abandoned": false
- },
- {
- "name": "league/uri-components",
- "direct-dependency": false,
- "homepage": "http://uri.thephpleague.com",
- "source": "https://github.com/thephpleague/uri-components/tree/7.8.1",
- "version": "7.8.1",
- "description": "URI components manipulation library",
- "abandoned": false
- },
- {
- "name": "league/uri-interfaces",
- "direct-dependency": false,
- "homepage": "https://uri.thephpleague.com",
- "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1",
- "version": "7.8.1",
- "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
- "abandoned": false
- },
- {
- "name": "monolog/monolog",
- "direct-dependency": false,
- "homepage": "https://github.com/Seldaek/monolog",
- "source": "https://github.com/Seldaek/monolog/tree/3.12.1",
- "version": "3.12.1",
- "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
- "abandoned": false
- },
- {
- "name": "myclabs/deep-copy",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0",
- "version": "1.14.0",
- "description": "Create deep copies (clones) of your objects",
- "abandoned": false
- },
- {
- "name": "nikic/php-parser",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0",
- "version": "v5.9.0",
- "description": "A PHP parser written in PHP",
- "abandoned": false
- },
- {
- "name": "paragonie/constant_time_encoding",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/paragonie/constant_time_encoding",
- "version": "v3.1.3",
- "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
- "abandoned": false
- },
- {
- "name": "paragonie/random_compat",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/paragonie/random_compat",
- "version": "v9.99.100",
- "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
- "abandoned": false
- },
- {
- "name": "phar-io/manifest",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/phar-io/manifest/tree/2.0.4",
- "version": "2.0.4",
- "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
- "abandoned": false
- },
- {
- "name": "phar-io/version",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/phar-io/version/tree/3.2.1",
- "version": "3.2.1",
- "description": "Library for handling version information and constraints",
- "abandoned": false
- },
- {
- "name": "phpseclib/phpseclib",
- "direct-dependency": false,
- "homepage": "http://phpseclib.sourceforge.net",
- "source": "https://github.com/phpseclib/phpseclib/tree/3.0.57",
- "version": "3.0.57",
- "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
- "abandoned": false
- },
- {
- "name": "phpstan/phpstan",
- "direct-dependency": true,
- "homepage": null,
- "source": "https://github.com/phpstan/phpstan-src",
- "version": "2.3.1",
- "description": "PHPStan - PHP Static Analysis Tool",
- "abandoned": false
- },
- {
- "name": "phpunit/php-code-coverage",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.8",
- "version": "12.5.8",
- "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
- "abandoned": false
- },
- {
- "name": "phpunit/php-file-iterator",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.2",
- "version": "6.0.2",
- "description": "FilterIterator implementation that filters files based on a list of suffixes.",
- "abandoned": false
- },
- {
- "name": "phpunit/php-invoker",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/php-invoker/",
- "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0",
- "version": "6.0.0",
- "description": "Invoke callables with a timeout",
- "abandoned": false
- },
- {
- "name": "phpunit/php-text-template",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/php-text-template/",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.1",
- "version": "5.0.1",
- "description": "Simple template engine.",
- "abandoned": false
- },
- {
- "name": "phpunit/php-timer",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/php-timer/",
- "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0",
- "version": "8.0.0",
- "description": "Utility class for timing",
- "abandoned": false
- },
- {
- "name": "phpunit/phpunit",
- "direct-dependency": true,
- "homepage": "https://phpunit.de/",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.39",
- "version": "12.5.39",
- "description": "The PHP Unit Testing framework.",
- "abandoned": false
- },
- {
- "name": "promphp/prometheus_client_php",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/PromPHP/prometheus_client_php/tree/v2.15.1",
- "version": "v2.15.1",
- "description": "Prometheus instrumentation library for PHP applications.",
- "abandoned": false
- },
- {
- "name": "psr/http-factory",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/php-fig/http-factory",
- "version": "1.1.0",
- "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
- "abandoned": false
- },
- {
- "name": "psr/http-message",
- "direct-dependency": false,
- "homepage": "https://github.com/php-fig/http-message",
- "source": "https://github.com/php-fig/http-message/tree/2.0",
- "version": "2.0",
- "description": "Common interface for HTTP messages",
- "abandoned": false
- },
- {
- "name": "psr/log",
- "direct-dependency": false,
- "homepage": "https://github.com/php-fig/log",
- "source": "https://github.com/php-fig/log/tree/3.0.2",
- "version": "3.0.2",
- "description": "Common interface for logging libraries",
- "abandoned": false
- },
- {
- "name": "revolt/event-loop",
- "direct-dependency": true,
- "homepage": null,
- "source": "https://github.com/revoltphp/event-loop/tree/v1.0.9",
- "version": "v1.0.9",
- "description": "Rock-solid event loop for concurrent PHP applications.",
- "abandoned": false
- },
- {
- "name": "sebastian/cli-parser",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/cli-parser",
- "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.1",
- "version": "4.2.1",
- "description": "Library for parsing CLI options",
- "abandoned": false
- },
- {
- "name": "sebastian/comparator",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/comparator",
- "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8",
- "version": "7.1.8",
- "description": "Provides the functionality to compare PHP values for equality",
- "abandoned": false
- },
- {
- "name": "sebastian/complexity",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/complexity",
- "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0",
- "version": "5.0.0",
- "description": "Library for calculating the complexity of PHP code units",
- "abandoned": false
- },
- {
- "name": "sebastian/diff",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/diff",
- "source": "https://github.com/sebastianbergmann/diff/tree/7.0.1",
- "version": "7.0.1",
- "description": "Diff implementation",
- "abandoned": false
- },
- {
- "name": "sebastian/environment",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/environment",
- "source": "https://github.com/sebastianbergmann/environment/tree/8.1.2",
- "version": "8.1.2",
- "description": "Provides functionality to handle HHVM/PHP environments",
- "abandoned": false
- },
- {
- "name": "sebastian/exporter",
- "direct-dependency": false,
- "homepage": "https://www.github.com/sebastianbergmann/exporter",
- "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.3",
- "version": "7.0.3",
- "description": "Provides the functionality to export PHP variables for visualization",
- "abandoned": false
- },
- {
- "name": "sebastian/global-state",
- "direct-dependency": false,
- "homepage": "https://www.github.com/sebastianbergmann/global-state",
- "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.3",
- "version": "8.0.3",
- "description": "Snapshotting of global state",
- "abandoned": false
- },
- {
- "name": "sebastian/lines-of-code",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/lines-of-code",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.1",
- "version": "4.0.1",
- "description": "Library for counting the lines of code in PHP source code",
- "abandoned": false
- },
- {
- "name": "sebastian/object-enumerator",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
- "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0",
- "version": "7.0.0",
- "description": "Traverses array structures and object graphs to enumerate all referenced objects",
- "abandoned": false
- },
- {
- "name": "sebastian/object-reflector",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/object-reflector/",
- "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0",
- "version": "5.0.0",
- "description": "Allows reflection of object attributes, including inherited and non-public ones",
- "abandoned": false
- },
- {
- "name": "sebastian/recursion-context",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/recursion-context",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1",
- "version": "7.0.1",
- "description": "Provides functionality to recursively process PHP variables",
- "abandoned": false
- },
- {
- "name": "sebastian/type",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/type",
- "source": "https://github.com/sebastianbergmann/type/tree/6.0.4",
- "version": "6.0.4",
- "description": "Collection of value objects that represent the types of the PHP type system",
- "abandoned": false
- },
- {
- "name": "sebastian/version",
- "direct-dependency": false,
- "homepage": "https://github.com/sebastianbergmann/version",
- "source": "https://github.com/sebastianbergmann/version/tree/6.0.1",
- "version": "6.0.1",
- "description": "Library that helps with managing the version number of Git-hosted PHP projects",
- "abandoned": false
- },
- {
- "name": "squizlabs/php_codesniffer",
- "direct-dependency": true,
- "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
- "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
- "version": "4.0.4",
- "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.",
- "abandoned": false
- },
- {
- "name": "staabm/side-effects-detector",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5",
- "version": "1.0.5",
- "description": "A static analysis tool to detect side effects in PHP code",
- "abandoned": false
- },
- {
- "name": "symfony/polyfill-mbstring",
- "direct-dependency": false,
- "homepage": "https://symfony.com",
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0",
- "version": "v1.43.0",
- "description": "Symfony polyfill for the Mbstring extension",
- "abandoned": false
- },
- {
- "name": "symfony/polyfill-php83",
- "direct-dependency": false,
- "homepage": "https://symfony.com",
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0",
- "version": "v1.43.0",
- "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
- "abandoned": false
- },
- {
- "name": "theseer/tokenizer",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/theseer/tokenizer/tree/2.0.1",
- "version": "2.0.1",
- "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
- "abandoned": false
- },
- {
- "name": "webmozart/assert",
- "direct-dependency": false,
- "homepage": null,
- "source": "https://github.com/webmozarts/assert/tree/1.12.1",
- "version": "1.12.1",
- "description": "Assertions to validate method input/output with nice error messages.",
- "abandoned": false
- },
- {
- "name": "wizardloop/broadcastmanager",
- "direct-dependency": true,
- "homepage": "https://github.com/WizardLoop/BroadcastManager",
- "source": "https://github.com/WizardLoop/BroadcastManager",
- "version": "3.2.2",
- "description": "High-performance Telegram broadcast manager for MadelineProto",
- "abandoned": false
- }
- ]
+{
+ "locked": [
+ {
+ "name": "amphp/amp",
+ "direct-dependency": true,
+ "homepage": "https://amphp.org/amp",
+ "source": "https://github.com/amphp/amp/tree/v3.1.3",
+ "version": "v3.1.3",
+ "description": "A non-blocking concurrency framework for PHP applications.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/byte-stream",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org/byte-stream",
+ "source": "https://github.com/amphp/byte-stream/tree/v2.1.2",
+ "version": "v2.1.2",
+ "description": "A stream abstraction to make working with non-blocking I/O simple.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/cache",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org/cache",
+ "source": "https://github.com/amphp/cache/tree/v2.0.1",
+ "version": "v2.0.1",
+ "description": "A fiber-aware cache API based on Amp and Revolt.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/dns",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/dns",
+ "source": "https://github.com/amphp/dns/tree/v2.4.1",
+ "version": "v2.4.1",
+ "description": "Async DNS resolution for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/file",
+ "direct-dependency": true,
+ "homepage": "https://github.com/amphp/file",
+ "source": "https://github.com/amphp/file/tree/v3.2.0",
+ "version": "v3.2.0",
+ "description": "Non-blocking access to the filesystem based on Amp and Revolt.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/hpack",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/hpack",
+ "source": "https://github.com/amphp/hpack/tree/v3.2.2",
+ "version": "v3.2.2",
+ "description": "HTTP/2 HPack implementation.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/http",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/amphp/http/tree/v2.1.2",
+ "version": "v2.1.2",
+ "description": "Basic HTTP primitives which can be shared by servers and clients.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/http-client",
+ "direct-dependency": true,
+ "homepage": "https://amphp.org/http-client",
+ "source": "https://github.com/amphp/http-client/tree/v5.3.6",
+ "version": "v5.3.6",
+ "description": "An advanced async HTTP client library for PHP, enabling efficient, non-blocking, and concurrent requests and responses.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/http-client-cookies",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/http-client-cookies",
+ "source": "https://github.com/amphp/http-client-cookies/tree/v2.0.0",
+ "version": "v2.0.0",
+ "description": "Automatic cookie handling for Amp's HTTP client.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/http-server",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/http-server",
+ "source": "https://github.com/amphp/http-server/tree/v3.4.7",
+ "version": "v3.4.7",
+ "description": "A non-blocking HTTP application server for PHP based on Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/log",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/log",
+ "source": "https://github.com/amphp/log/tree/v2.0.0",
+ "version": "v2.0.0",
+ "description": "Non-blocking logging for PHP based on Amp, Revolt, and Monolog.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/mysql",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/amphp/mysql/tree/v3.1.1",
+ "version": "v3.1.1",
+ "description": "Asynchronous MySQL client for PHP based on Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/parallel",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/parallel",
+ "source": "https://github.com/amphp/parallel/tree/v2.4.0",
+ "version": "v2.4.0",
+ "description": "Parallel processing component for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/parser",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/parser",
+ "source": "https://github.com/amphp/parser/tree/v1.1.1",
+ "version": "v1.1.1",
+ "description": "A generator parser to make streaming parsers simple.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/pipeline",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org/pipeline",
+ "source": "https://github.com/amphp/pipeline/tree/v1.2.7",
+ "version": "v1.2.7",
+ "description": "Asynchronous iterators and operators.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/postgres",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org",
+ "source": "https://github.com/amphp/postgres/tree/v2.2.1",
+ "version": "v2.2.1",
+ "description": "Asynchronous PostgreSQL client for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/process",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org/process",
+ "source": "https://github.com/amphp/process/tree/v2.1.0",
+ "version": "v2.1.0",
+ "description": "A fiber-aware process manager based on Amp and Revolt.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/redis",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org/redis",
+ "source": "https://github.com/amphp/redis/tree/v2.0.4",
+ "version": "v2.0.4",
+ "description": "Efficient asynchronous communication with Redis servers, enabling scalable and responsive data storage and retrieval.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/serialization",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/serialization",
+ "source": "https://github.com/amphp/serialization/tree/v1.1.0",
+ "version": "v1.1.0",
+ "description": "Serialization tools for IPC and data storage in PHP.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/socket",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/socket",
+ "source": "https://github.com/amphp/socket/tree/v2.4.1",
+ "version": "v2.4.1",
+ "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/sql",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org",
+ "source": "https://github.com/amphp/sql/tree/v2.1.1",
+ "version": "v2.1.1",
+ "description": "Asynchronous SQL client for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/sql-common",
+ "direct-dependency": false,
+ "homepage": "https://amphp.org",
+ "source": "https://github.com/amphp/sql-common/tree/v2.0.4",
+ "version": "v2.0.4",
+ "description": "Common classes for non-blocking SQL implementations.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/sync",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/sync",
+ "source": "https://github.com/amphp/sync/tree/v2.3.0",
+ "version": "v2.3.0",
+ "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/websocket",
+ "direct-dependency": false,
+ "homepage": "https://github.com/amphp/websocket",
+ "source": "https://github.com/amphp/websocket/tree/v2.0.4",
+ "version": "v2.0.4",
+ "description": "Shared code for websocket servers and clients.",
+ "abandoned": false
+ },
+ {
+ "name": "amphp/websocket-client",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/amphp/websocket-client/tree/v2.0.2",
+ "version": "v2.0.2",
+ "description": "Async WebSocket client for PHP based on Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "bacon/bacon-qr-code",
+ "direct-dependency": false,
+ "homepage": "https://github.com/Bacon/BaconQrCode",
+ "source": "https://github.com/Bacon/BaconQrCode/tree/v3.1.1",
+ "version": "v3.1.1",
+ "description": "BaconQrCode is a QR code generator for PHP.",
+ "abandoned": false
+ },
+ {
+ "name": "brick/math",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/brick/math/tree/1.0.0",
+ "version": "1.0.0",
+ "description": "Arbitrary-precision arithmetic library",
+ "abandoned": false
+ },
+ {
+ "name": "danog/async-orm",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/AsyncOrm/tree/1.1.6",
+ "version": "1.1.6",
+ "description": "Async ORM based on AMPHP v3 and fibers.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/better-prometheus",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/better-prometheus/tree/0.1.1",
+ "version": "0.1.1",
+ "description": "A better Prometheus library for PHP applications",
+ "abandoned": false
+ },
+ {
+ "name": "danog/dns-over-https",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/dns-over-https",
+ "source": "https://github.com/danog/dns-over-https/tree/1.0.1",
+ "version": "1.0.1",
+ "description": "Async DNS-over-HTTPS resolution for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/ipc",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/ipc",
+ "source": "https://github.com/danog/ipc/tree/1.1.0",
+ "version": "1.1.0",
+ "description": "IPC component for Amp.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/libdns-json",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/libdns-json",
+ "source": "https://github.com/danog/LibDNSJson/tree/0.2.1",
+ "version": "0.2.1",
+ "description": "Encoder/decoder for google's JSON DNS message format based on libdns",
+ "abandoned": false
+ },
+ {
+ "name": "danog/loop",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/loop",
+ "source": "https://github.com/danog/loop/tree/1.1.1",
+ "version": "1.1.1",
+ "description": "Loop abstraction for AMPHP.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/madelineproto",
+ "direct-dependency": true,
+ "homepage": "https://docs.madelineproto.xyz",
+ "source": "https://github.com/danog/MadelineProto/tree/8.11.10",
+ "version": "8.11.10",
+ "description": "Async PHP client API for the telegram MTProto protocol.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-av",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-av",
+ "source": "https://github.com/danog/php-rtc-av/tree/1.1.11",
+ "version": "1.1.11",
+ "description": "FFmpeg/libav FFI bindings for PHP media processing. MadelineProto's PHP 8.2+ fork uses lazy, optional FFI, strict ABI checks, and the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-codecs",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-codecs",
+ "source": "https://github.com/danog/php-rtc-codecs/tree/1.1.19",
+ "version": "1.1.19",
+ "description": "WebRTC audio/video codec and RTP packetization utilities. MadelineProto's PHP 8.2+ fork adds optional transcoding FFI, VP9 packetization, and the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-datachannel",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-datachannel",
+ "source": "https://github.com/danog/php-rtc-datachannel/tree/1.1.10",
+ "version": "1.1.10",
+ "description": "A PHP implementation of WebRTC's RTCDataChannel interface. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-dtls",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-dtls",
+ "source": "https://github.com/danog/php-rtc-dtls/tree/2.0.20",
+ "version": "2.0.20",
+ "description": "Pure-PHP DTLS 1.2 for WebRTC, powered by phpseclib and Amp v3.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-exception",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-exception",
+ "source": "https://github.com/danog/php-rtc-exception/tree/1.1.10",
+ "version": "1.1.10",
+ "description": "Lightweight exceptions shared by the WebRTC components. MadelineProto's PHP 8.2+ fork is a Composer-compatible foundation of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-ice",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-ice",
+ "source": "https://github.com/danog/php-rtc-ice/tree/2.0.18",
+ "version": "2.0.18",
+ "description": "WebRTC ICE connectivity in PHP, ported to Amp v3 fibers and sockets. MadelineProto's PHP 8.2+ fork integrates the modular danog/php-rtc STUN, TURN, and mDNS stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-mdns",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-mdns",
+ "source": "https://github.com/danog/php-rtc-mdns/tree/1.1.12",
+ "version": "1.1.12",
+ "description": "An Amp v3 Multicast DNS resolver for WebRTC. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-mixin",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-mixin",
+ "source": "https://github.com/danog/php-rtc-mixin/tree/2.0.9",
+ "version": "2.0.9",
+ "description": "Common PHP classes and traits for WebRTC components. MadelineProto's PHP 8.2+ fork is a Composer-compatible foundation of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-ntp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-ntp",
+ "source": "https://github.com/danog/php-rtc-ntp/tree/1.1.15",
+ "version": "1.1.15",
+ "description": "Pure-PHP NTP timestamp conversion for WebRTC. MadelineProto's PHP 8.2+ fork fixes unsigned 64-bit handling and integrates with the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-rtcp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-rtcp",
+ "source": "https://github.com/danog/php-rtc-rtcp/tree/1.1.11",
+ "version": "1.1.11",
+ "description": "Pure-PHP RTCP packet parsing and generation. MadelineProto's PHP 8.2+ fork fixes unsigned NTP handling and integrates with the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-rtp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-rtp",
+ "source": "https://github.com/danog/php-rtc-rtp/tree/2.0.23",
+ "version": "2.0.23",
+ "description": "RTP packet and media transport handling for PHP, ported to Amp v3. MadelineProto's PHP 8.2+ fork supports optional media FFI in the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-rtp-parameter",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-rtp-parameter",
+ "source": "https://github.com/danog/php-rtc-rtp-parameter/tree/1.1.8",
+ "version": "1.1.8",
+ "description": "RTP codec, payload, SSRC, header-extension, and RTCP parameter objects. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-sctp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-sctp",
+ "source": "https://github.com/danog/php-rtc-sctp/tree/2.0.14",
+ "version": "2.0.14",
+ "description": "SCTP for PHP WebRTC data channels, ported to Amp v3 fibers and timers. MadelineProto's PHP 8.2+ fork is part of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-sdp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-sdp",
+ "source": "https://github.com/danog/php-rtc-sdp/tree/1.1.12",
+ "version": "1.1.12",
+ "description": "SDP parsing and generation for PHP WebRTC. MadelineProto's PHP 8.2+ fork is a Composer-compatible component of the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-srtp",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-srtp",
+ "source": "https://github.com/danog/php-rtc-srtp/tree/1.1.16",
+ "version": "1.1.16",
+ "description": "Pure-PHP SRTP and SRTCP encryption using phpseclib, with AES-CM and AES-GCM profiles. MadelineProto's PHP 8.2+ fork removes the libsrtp/FFI dependency.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-stats",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-stats",
+ "source": "https://github.com/danog/php-rtc-stats/tree/1.1.7",
+ "version": "1.1.7",
+ "description": "WebRTC statistics objects for RTP, DTLS, ICE, and media metrics. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-stun",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-stun",
+ "source": "https://github.com/danog/php-rtc-stun/tree/2.0.18",
+ "version": "2.0.18",
+ "description": "STUN transactions and NAT discovery for PHP, ported to Amp v3 sockets and fibers. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-turn",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-turn",
+ "source": "https://github.com/danog/php-rtc-turn/tree/2.0.9",
+ "version": "2.0.9",
+ "description": "TURN relay transport for PHP WebRTC, ported to Amp v3 TCP, UDP, and fibers. MadelineProto's PHP 8.2+ fork supports the modular danog/php-rtc stack.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/php-rtc-webrtc",
+ "direct-dependency": false,
+ "homepage": "https://github.com/danog/php-rtc-webrtc",
+ "source": "https://github.com/danog/php-rtc-webrtc/tree/2.0.20",
+ "version": "2.0.20",
+ "description": "A modular PHP WebRTC stack for PHP 8.2+, ported to Amp v3 with pure-PHP DTLS/SRTP and optional media FFI. Maintained by danog for MadelineProto.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/primemodule",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/PrimeModule/tree/1.0.13",
+ "version": "1.0.13",
+ "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
+ "abandoned": false
+ },
+ {
+ "name": "danog/telegram-entities",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/telegram-entities/tree/1.1.0",
+ "version": "1.1.0",
+ "description": "A library to work with Telegram UTF-16 styled text entities.",
+ "abandoned": false
+ },
+ {
+ "name": "danog/tg-dialog-id",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/tg-dialog-id/tree/2.0.0",
+ "version": "2.0.0",
+ "description": "A library to work with Telegram bot API dialog IDs",
+ "abandoned": false
+ },
+ {
+ "name": "danog/tg-file-decoder",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/danog/tg-file-decoder/tree/1.0.2",
+ "version": "1.0.2",
+ "description": "Decode Telegram bot API file IDs",
+ "abandoned": false
+ },
+ {
+ "name": "dasprid/enum",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/DASPRiD/Enum/tree/1.0.7",
+ "version": "1.0.7",
+ "description": "PHP 7.1 enum implementation",
+ "abandoned": false
+ },
+ {
+ "name": "daverandom/libdns",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0",
+ "version": "v2.1.0",
+ "description": "DNS protocol implementation written in pure PHP",
+ "abandoned": false
+ },
+ {
+ "name": "kelunik/certificate",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/kelunik/certificate/tree/v1.1.3",
+ "version": "v1.1.3",
+ "description": "Access certificate details and transform between different formats.",
+ "abandoned": false
+ },
+ {
+ "name": "league/uri",
+ "direct-dependency": false,
+ "homepage": "https://uri.thephpleague.com",
+ "source": "https://github.com/thephpleague/uri/tree/7.8.1",
+ "version": "7.8.1",
+ "description": "URI manipulation library",
+ "abandoned": false
+ },
+ {
+ "name": "league/uri-components",
+ "direct-dependency": false,
+ "homepage": "http://uri.thephpleague.com",
+ "source": "https://github.com/thephpleague/uri-components/tree/7.8.1",
+ "version": "7.8.1",
+ "description": "URI components manipulation library",
+ "abandoned": false
+ },
+ {
+ "name": "league/uri-interfaces",
+ "direct-dependency": false,
+ "homepage": "https://uri.thephpleague.com",
+ "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.1",
+ "version": "7.8.1",
+ "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI",
+ "abandoned": false
+ },
+ {
+ "name": "monolog/monolog",
+ "direct-dependency": false,
+ "homepage": "https://github.com/Seldaek/monolog",
+ "source": "https://github.com/Seldaek/monolog/tree/3.12.1",
+ "version": "3.12.1",
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
+ "abandoned": false
+ },
+ {
+ "name": "myclabs/deep-copy",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.14.0",
+ "version": "1.14.0",
+ "description": "Create deep copies (clones) of your objects",
+ "abandoned": false
+ },
+ {
+ "name": "nikic/php-parser",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.9.0",
+ "version": "v5.9.0",
+ "description": "A PHP parser written in PHP",
+ "abandoned": false
+ },
+ {
+ "name": "paragonie/constant_time_encoding",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/paragonie/constant_time_encoding",
+ "version": "v3.1.3",
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
+ "abandoned": false
+ },
+ {
+ "name": "phar-io/manifest",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4",
+ "version": "2.0.4",
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "abandoned": false
+ },
+ {
+ "name": "phar-io/version",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/phar-io/version/tree/3.2.1",
+ "version": "3.2.1",
+ "description": "Library for handling version information and constraints",
+ "abandoned": false
+ },
+ {
+ "name": "phpseclib/phpseclib",
+ "direct-dependency": false,
+ "homepage": "https://phpseclib.com/",
+ "source": "https://github.com/phpseclib/phpseclib/tree/4.0.2",
+ "version": "4.0.2",
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
+ "abandoned": false
+ },
+ {
+ "name": "phpstan/phpstan",
+ "direct-dependency": true,
+ "homepage": null,
+ "source": "https://github.com/phpstan/phpstan-src",
+ "version": "2.3.1",
+ "description": "PHPStan - PHP Static Analysis Tool",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.8",
+ "version": "12.5.8",
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/6.0.2",
+ "version": "6.0.2",
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/6.0.0",
+ "version": "6.0.0",
+ "description": "Invoke callables with a timeout",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/5.0.1",
+ "version": "5.0.1",
+ "description": "Simple template engine.",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/php-timer",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/8.0.0",
+ "version": "8.0.0",
+ "description": "Utility class for timing",
+ "abandoned": false
+ },
+ {
+ "name": "phpunit/phpunit",
+ "direct-dependency": true,
+ "homepage": "https://phpunit.de/",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/12.5.39",
+ "version": "12.5.39",
+ "description": "The PHP Unit Testing framework.",
+ "abandoned": false
+ },
+ {
+ "name": "promphp/prometheus_client_php",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/PromPHP/prometheus_client_php/tree/v2.15.1",
+ "version": "v2.15.1",
+ "description": "Prometheus instrumentation library for PHP applications.",
+ "abandoned": false
+ },
+ {
+ "name": "psr/http-factory",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/php-fig/http-factory",
+ "version": "1.1.0",
+ "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories",
+ "abandoned": false
+ },
+ {
+ "name": "psr/http-message",
+ "direct-dependency": false,
+ "homepage": "https://github.com/php-fig/http-message",
+ "source": "https://github.com/php-fig/http-message/tree/2.0",
+ "version": "2.0",
+ "description": "Common interface for HTTP messages",
+ "abandoned": false
+ },
+ {
+ "name": "psr/log",
+ "direct-dependency": false,
+ "homepage": "https://github.com/php-fig/log",
+ "source": "https://github.com/php-fig/log/tree/3.0.2",
+ "version": "3.0.2",
+ "description": "Common interface for logging libraries",
+ "abandoned": false
+ },
+ {
+ "name": "ramsey/collection",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/ramsey/collection/tree/2.1.1",
+ "version": "2.1.1",
+ "description": "A PHP library for representing and manipulating collections.",
+ "abandoned": false
+ },
+ {
+ "name": "ramsey/uuid",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/ramsey/uuid/tree/4.9.4",
+ "version": "4.9.4",
+ "description": "A PHP library for generating and working with universally unique identifiers (UUIDs).",
+ "abandoned": false
+ },
+ {
+ "name": "revolt/event-loop",
+ "direct-dependency": true,
+ "homepage": null,
+ "source": "https://github.com/revoltphp/event-loop/tree/v1.0.9",
+ "version": "v1.0.9",
+ "description": "Rock-solid event loop for concurrent PHP applications.",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/4.2.1",
+ "version": "4.2.1",
+ "description": "Library for parsing CLI options",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/comparator",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/7.1.8",
+ "version": "7.1.8",
+ "description": "Provides the functionality to compare PHP values for equality",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/complexity",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/5.0.0",
+ "version": "5.0.0",
+ "description": "Library for calculating the complexity of PHP code units",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/diff",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "source": "https://github.com/sebastianbergmann/diff/tree/7.0.1",
+ "version": "7.0.1",
+ "description": "Diff implementation",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/environment",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "source": "https://github.com/sebastianbergmann/environment/tree/8.1.2",
+ "version": "8.1.2",
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/exporter",
+ "direct-dependency": false,
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/7.0.3",
+ "version": "7.0.3",
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/global-state",
+ "direct-dependency": false,
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/8.0.3",
+ "version": "8.0.3",
+ "description": "Snapshotting of global state",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/4.0.1",
+ "version": "4.0.1",
+ "description": "Library for counting the lines of code in PHP source code",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/7.0.0",
+ "version": "7.0.0",
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/5.0.0",
+ "version": "5.0.0",
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/7.0.1",
+ "version": "7.0.1",
+ "description": "Provides functionality to recursively process PHP variables",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/type",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "source": "https://github.com/sebastianbergmann/type/tree/6.0.4",
+ "version": "6.0.4",
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "abandoned": false
+ },
+ {
+ "name": "sebastian/version",
+ "direct-dependency": false,
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "source": "https://github.com/sebastianbergmann/version/tree/6.0.1",
+ "version": "6.0.1",
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "abandoned": false
+ },
+ {
+ "name": "squizlabs/php_codesniffer",
+ "direct-dependency": true,
+ "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer",
+ "version": "4.0.4",
+ "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.",
+ "abandoned": false
+ },
+ {
+ "name": "staabm/side-effects-detector",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5",
+ "version": "1.0.5",
+ "description": "A static analysis tool to detect side effects in PHP code",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-iconv",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-iconv/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill for the Iconv extension",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-mbstring",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill for the Mbstring extension",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-php82",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-php82/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill backporting some PHP 8.2+ features to lower PHP versions",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-php83",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-php84",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-php84/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-php85",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-php85/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
+ "abandoned": false
+ },
+ {
+ "name": "symfony/polyfill-php86",
+ "direct-dependency": false,
+ "homepage": "https://symfony.com",
+ "source": "https://github.com/symfony/polyfill-php86/tree/v1.43.0",
+ "version": "v1.43.0",
+ "description": "Symfony polyfill backporting some PHP 8.6+ features to lower PHP versions",
+ "abandoned": false
+ },
+ {
+ "name": "theseer/tokenizer",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/theseer/tokenizer/tree/2.0.1",
+ "version": "2.0.1",
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "abandoned": false
+ },
+ {
+ "name": "webmozart/assert",
+ "direct-dependency": false,
+ "homepage": null,
+ "source": "https://github.com/webmozarts/assert/tree/2.5.0",
+ "version": "2.5.0",
+ "description": "Assertions to validate method input/output with nice error messages.",
+ "abandoned": false
+ },
+ {
+ "name": "wizardloop/broadcastmanager",
+ "direct-dependency": true,
+ "homepage": "https://github.com/WizardLoop/BroadcastManager",
+ "source": "https://github.com/WizardLoop/BroadcastManager",
+ "version": "3.2.2",
+ "description": "High-performance Telegram broadcast manager for MadelineProto",
+ "abandoned": false
+ }
+ ]
}
diff --git a/docs/dependencies.json b/docs/dependencies.json
index 90f9e57..d7f0c51 100644
--- a/docs/dependencies.json
+++ b/docs/dependencies.json
@@ -1,6 +1,6 @@
{
"schema_version": 1,
- "lock_sha256": "a6a66ad9af4ccd6ef0fa7e62f7a7e28a1ae73cf07e8545552710bc9b8477e9bf",
+ "lock_sha256": "2b5d70795b5a6000769ea87b6f340667d9d743152ac5fefde8f7ae2ff9aecb14",
"packages": [
{
"name": "amphp/amp",
@@ -548,17 +548,38 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
+ {
+ "name": "brick/math",
+ "version": "1.0.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/brick/math.git",
+ "source_commit": "2effe05d2177c451b86c6a073196a4034c02f211",
+ "source_permalink": "https://github.com/brick/math/tree/2effe05d2177c451b86c6a073196a4034c02f211",
+ "license_files": [
+ {
+ "file": "vendor/brick/math/LICENSE",
+ "sha256": "d2625cc652e6ffa9f16827f1dba2d83ac12b050dc8150a38720420dbb810cae3"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "danog/async-orm",
- "version": "1.1.4",
+ "version": "1.1.6",
"direct": false,
"scope": "runtime",
"spdx": [
"Apache-2.0"
],
"source_url": "https://github.com/danog/AsyncOrm.git",
- "source_commit": "495f335d8ddb9dae8b773025911191f31c45e9ea",
- "source_permalink": "https://github.com/danog/AsyncOrm/tree/495f335d8ddb9dae8b773025911191f31c45e9ea",
+ "source_commit": "4a2a7a54c5002bef6cdf80b338085e9e131bf719",
+ "source_permalink": "https://github.com/danog/AsyncOrm/tree/4a2a7a54c5002bef6cdf80b338085e9e131bf719",
"license_files": [
{
"file": "vendor/danog/async-orm/LICENSE",
@@ -621,15 +642,15 @@
},
{
"name": "danog/ipc",
- "version": "1.0.1",
+ "version": "1.1.0",
"direct": false,
"scope": "runtime",
"spdx": [
"MIT"
],
"source_url": "https://github.com/danog/ipc.git",
- "source_commit": "505e672b76af6ec623f7ef78efb2416f62ef8e29",
- "source_permalink": "https://github.com/danog/ipc/tree/505e672b76af6ec623f7ef78efb2416f62ef8e29",
+ "source_commit": "eea6de6a57273f32a4f90a652ae1409786be18a0",
+ "source_permalink": "https://github.com/danog/ipc/tree/eea6de6a57273f32a4f90a652ae1409786be18a0",
"license_files": [
{
"file": "vendor/danog/ipc/LICENSE",
@@ -684,15 +705,15 @@
},
{
"name": "danog/madelineproto",
- "version": "8.7.0",
+ "version": "8.11.10",
"direct": true,
"scope": "runtime",
"spdx": [
"AGPL-3.0-only"
],
"source_url": "https://github.com/danog/MadelineProto.git",
- "source_commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "source_permalink": "https://github.com/danog/MadelineProto/tree/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
+ "source_commit": "49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
+ "source_permalink": "https://github.com/danog/MadelineProto/tree/49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
"license_files": [
{
"file": "vendor/danog/madelineproto/LICENSE",
@@ -705,6 +726,408 @@
"Metadata says AGPL-3.0-only; source headers grant version 3 or later. Preserve upstream grant and report mismatch; application license remains AGPL-3.0-only."
]
},
+ {
+ "name": "danog/php-rtc-av",
+ "version": "1.1.11",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-av.git",
+ "source_commit": "f328e6b5682d7e885dcfab425839921312162008",
+ "source_permalink": "https://github.com/danog/php-rtc-av/tree/f328e6b5682d7e885dcfab425839921312162008",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-av/LICENSE",
+ "sha256": "c855e00eed64bc882f5ff86daa56c03e76495f47e4b4b192b20bb46e924ba0f8"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "NOT VERIFIED",
+ "findings": [
+ "NOT VERIFIED: declared SPDX not confirmed against a distributed root license text; release review required.",
+ "Metadata declares MIT, but distributed LICENSE and PHP source headers state BSD-3-Clause. Preserve both upstream texts; the MIT declaration is not confirmed by the distributed license."
+ ]
+ },
+ {
+ "name": "danog/php-rtc-codecs",
+ "version": "1.1.19",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-codecs.git",
+ "source_commit": "00836382276949099077e19659ff6648b823284f",
+ "source_permalink": "https://github.com/danog/php-rtc-codecs/tree/00836382276949099077e19659ff6648b823284f",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-codecs/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-datachannel",
+ "version": "1.1.10",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-datachannel.git",
+ "source_commit": "3a5ad6f76326514f41a9e1847b41d503e157c459",
+ "source_permalink": "https://github.com/danog/php-rtc-datachannel/tree/3a5ad6f76326514f41a9e1847b41d503e157c459",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-datachannel/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-dtls",
+ "version": "2.0.20",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-dtls.git",
+ "source_commit": "794180b0c3cf54842df44b7bcb44f8fb50f199c8",
+ "source_permalink": "https://github.com/danog/php-rtc-dtls/tree/794180b0c3cf54842df44b7bcb44f8fb50f199c8",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-dtls/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-exception",
+ "version": "1.1.10",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-exception.git",
+ "source_commit": "f9347a5376bb6b7b2fb008e06a8fd9fb6d9febd7",
+ "source_permalink": "https://github.com/danog/php-rtc-exception/tree/f9347a5376bb6b7b2fb008e06a8fd9fb6d9febd7",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-exception/LICENSE",
+ "sha256": "c855e00eed64bc882f5ff86daa56c03e76495f47e4b4b192b20bb46e924ba0f8"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-ice",
+ "version": "2.0.18",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-ice.git",
+ "source_commit": "91c53e982f334cf3bfe64a9e298d874bba51a3f1",
+ "source_permalink": "https://github.com/danog/php-rtc-ice/tree/91c53e982f334cf3bfe64a9e298d874bba51a3f1",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-ice/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-mdns",
+ "version": "1.1.12",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-mdns.git",
+ "source_commit": "ff3f4315339ddcdd4d71bd4e02156903261ef57a",
+ "source_permalink": "https://github.com/danog/php-rtc-mdns/tree/ff3f4315339ddcdd4d71bd4e02156903261ef57a",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-mdns/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-mixin",
+ "version": "2.0.9",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-mixin.git",
+ "source_commit": "e7a086a7fe01875f52e1f08301195db05e7ff9a5",
+ "source_permalink": "https://github.com/danog/php-rtc-mixin/tree/e7a086a7fe01875f52e1f08301195db05e7ff9a5",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-mixin/LICENSE",
+ "sha256": "c855e00eed64bc882f5ff86daa56c03e76495f47e4b4b192b20bb46e924ba0f8"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-ntp",
+ "version": "1.1.15",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-ntp.git",
+ "source_commit": "d70dc01410dba146cb808b9c2bf3c28ed1199d20",
+ "source_permalink": "https://github.com/danog/php-rtc-ntp/tree/d70dc01410dba146cb808b9c2bf3c28ed1199d20",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-ntp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-rtcp",
+ "version": "1.1.11",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-rtcp.git",
+ "source_commit": "f2e7c76d040fb0c4b2e4b62a611d13c6352af145",
+ "source_permalink": "https://github.com/danog/php-rtc-rtcp/tree/f2e7c76d040fb0c4b2e4b62a611d13c6352af145",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-rtcp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-rtp",
+ "version": "2.0.23",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-rtp.git",
+ "source_commit": "e9bee7a5aae91f6abec1fe9a599eefbce219d967",
+ "source_permalink": "https://github.com/danog/php-rtc-rtp/tree/e9bee7a5aae91f6abec1fe9a599eefbce219d967",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-rtp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-rtp-parameter",
+ "version": "1.1.8",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-rtp-parameter.git",
+ "source_commit": "cd1e34df768ddae43fc50c1306c2332cf99f07eb",
+ "source_permalink": "https://github.com/danog/php-rtc-rtp-parameter/tree/cd1e34df768ddae43fc50c1306c2332cf99f07eb",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-rtp-parameter/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-sctp",
+ "version": "2.0.14",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-sctp.git",
+ "source_commit": "741697e355abd7eb8e8134b115fab775bb5ccd06",
+ "source_permalink": "https://github.com/danog/php-rtc-sctp/tree/741697e355abd7eb8e8134b115fab775bb5ccd06",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-sctp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-sdp",
+ "version": "1.1.12",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-sdp.git",
+ "source_commit": "315b9cbaff71625351864c292de0b6ac3b3a39fc",
+ "source_permalink": "https://github.com/danog/php-rtc-sdp/tree/315b9cbaff71625351864c292de0b6ac3b3a39fc",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-sdp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-srtp",
+ "version": "1.1.16",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-srtp.git",
+ "source_commit": "b19959292663d8933a0a48cd1fda05788fb5c542",
+ "source_permalink": "https://github.com/danog/php-rtc-srtp/tree/b19959292663d8933a0a48cd1fda05788fb5c542",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-srtp/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-stats",
+ "version": "1.1.7",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-stats.git",
+ "source_commit": "137934d7d57e97184d5b6b2fb58e571e0d3f9fbd",
+ "source_permalink": "https://github.com/danog/php-rtc-stats/tree/137934d7d57e97184d5b6b2fb58e571e0d3f9fbd",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-stats/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-stun",
+ "version": "2.0.18",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-stun.git",
+ "source_commit": "7f1b48a736e6d7a9ad174e7dc58b794168befed4",
+ "source_permalink": "https://github.com/danog/php-rtc-stun/tree/7f1b48a736e6d7a9ad174e7dc58b794168befed4",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-stun/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-turn",
+ "version": "2.0.9",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-turn.git",
+ "source_commit": "5789c0d4b23c6097c72812fa8f9e9930ac288bc6",
+ "source_permalink": "https://github.com/danog/php-rtc-turn/tree/5789c0d4b23c6097c72812fa8f9e9930ac288bc6",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-turn/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "danog/php-rtc-webrtc",
+ "version": "2.0.20",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "BSD-3-Clause"
+ ],
+ "source_url": "https://github.com/danog/php-rtc-webrtc.git",
+ "source_commit": "58f8a24180cd1e137127214f9bfba3b0a7eff97b",
+ "source_permalink": "https://github.com/danog/php-rtc-webrtc/tree/58f8a24180cd1e137127214f9bfba3b0a7eff97b",
+ "license_files": [
+ {
+ "file": "vendor/danog/php-rtc-webrtc/LICENSE",
+ "sha256": "6e8861d416353fe52e937995140b8d09ff1fa6d8d700b0a1bbcde145dc478690"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "danog/primemodule",
"version": "1.0.13",
@@ -728,15 +1151,15 @@
},
{
"name": "danog/telegram-entities",
- "version": "1.0.5",
+ "version": "1.1.0",
"direct": false,
"scope": "runtime",
"spdx": [
"Apache-2.0"
],
"source_url": "https://github.com/danog/telegram-entities.git",
- "source_commit": "19ab8a48bc4b9519c4493e2c62eb171fba8b58b4",
- "source_permalink": "https://github.com/danog/telegram-entities/tree/19ab8a48bc4b9519c4493e2c62eb171fba8b58b4",
+ "source_commit": "92ca7621594b7a6c4a820c3b557e66ee1d439273",
+ "source_permalink": "https://github.com/danog/telegram-entities/tree/92ca7621594b7a6c4a820c3b557e66ee1d439273",
"license_files": [
{
"file": "vendor/danog/telegram-entities/LICENSE",
@@ -986,38 +1409,17 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
- {
- "name": "paragonie/random_compat",
- "version": "v9.99.100",
- "direct": false,
- "scope": "runtime",
- "spdx": [
- "MIT"
- ],
- "source_url": "https://github.com/paragonie/random_compat.git",
- "source_commit": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
- "source_permalink": "https://github.com/paragonie/random_compat/tree/996434e5492cb4c3edcb9168db6fbb1359ef965a",
- "license_files": [
- {
- "file": "vendor/paragonie/random_compat/LICENSE",
- "sha256": "e79a4c7d03c72850c60b2d5c41c2f92d33448ed2b243bd4686cfa7674e15e3ba"
- }
- ],
- "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
- "status": "LICENSE_TEXT_PRESENT",
- "findings": []
- },
{
"name": "phpseclib/phpseclib",
- "version": "3.0.57",
+ "version": "4.0.2",
"direct": false,
"scope": "runtime",
"spdx": [
"MIT"
],
"source_url": "https://github.com/phpseclib/phpseclib.git",
- "source_commit": "d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
- "source_permalink": "https://github.com/phpseclib/phpseclib/tree/d17e0ddaeaf6f22f7e007cbb437d78792fe2a0e4",
+ "source_commit": "1fe20b9acb08ce810cec24d8a9d02e7c13426e4c",
+ "source_permalink": "https://github.com/phpseclib/phpseclib/tree/1fe20b9acb08ce810cec24d8a9d02e7c13426e4c",
"license_files": [
{
"file": "vendor/phpseclib/phpseclib/LICENSE",
@@ -1112,6 +1514,48 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
+ {
+ "name": "ramsey/collection",
+ "version": "2.1.1",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/ramsey/collection.git",
+ "source_commit": "344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "source_permalink": "https://github.com/ramsey/collection/tree/344572933ad0181accbf4ba763e85a0306a8c5e2",
+ "license_files": [
+ {
+ "file": "vendor/ramsey/collection/LICENSE",
+ "sha256": "aa1e787bd6d05172d2962fa865a592af00ec474984d6b5bcb9a0df91abe8717d"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "ramsey/uuid",
+ "version": "4.9.4",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/ramsey/uuid.git",
+ "source_commit": "75d73f48d02797c2c285a7e9f348fadc0102ffe2",
+ "source_permalink": "https://github.com/ramsey/uuid/tree/75d73f48d02797c2c285a7e9f348fadc0102ffe2",
+ "license_files": [
+ {
+ "file": "vendor/ramsey/uuid/LICENSE",
+ "sha256": "9e8bf008e16a9ee5cc2d3bfe60701ec2351a2ddf29e9092275f71441a6d5a167"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "revolt/event-loop",
"version": "v1.0.9",
@@ -1133,6 +1577,27 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
+ {
+ "name": "symfony/polyfill-iconv",
+ "version": "v1.43.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/symfony/polyfill-iconv.git",
+ "source_commit": "254724d95fe01b679cd97d88786e9623ee00bfb7",
+ "source_permalink": "https://github.com/symfony/polyfill-iconv/tree/254724d95fe01b679cd97d88786e9623ee00bfb7",
+ "license_files": [
+ {
+ "file": "vendor/symfony/polyfill-iconv/LICENSE",
+ "sha256": "eaa5d6e59ff1d5322ae36d3ab9124460df72d2d0c8af60a99222e8a90dcbdf31"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "symfony/polyfill-mbstring",
"version": "v1.43.0",
@@ -1154,6 +1619,27 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
+ {
+ "name": "symfony/polyfill-php82",
+ "version": "v1.43.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/symfony/polyfill-php82.git",
+ "source_commit": "843bbe8b2a7934307b749751eede0f111f5d1cfc",
+ "source_permalink": "https://github.com/symfony/polyfill-php82/tree/843bbe8b2a7934307b749751eede0f111f5d1cfc",
+ "license_files": [
+ {
+ "file": "vendor/symfony/polyfill-php82/LICENSE",
+ "sha256": "6439cc1bba78b7de0c1905b0643679a5a7768ba020a090370d7742030303c6b2"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "symfony/polyfill-php83",
"version": "v1.43.0",
@@ -1175,17 +1661,80 @@
"status": "LICENSE_TEXT_PRESENT",
"findings": []
},
+ {
+ "name": "symfony/polyfill-php84",
+ "version": "v1.43.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/symfony/polyfill-php84.git",
+ "source_commit": "22c6548499cbe5c5bb072fc0c42312dff062a015",
+ "source_permalink": "https://github.com/symfony/polyfill-php84/tree/22c6548499cbe5c5bb072fc0c42312dff062a015",
+ "license_files": [
+ {
+ "file": "vendor/symfony/polyfill-php84/LICENSE",
+ "sha256": "db54a3771e71cada8e5a5dd11e5533e985117354057fc268129898ef415683b1"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "symfony/polyfill-php85",
+ "version": "v1.43.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/symfony/polyfill-php85.git",
+ "source_commit": "86a42cbcc07adc331481a5ab310a4024bfc227f6",
+ "source_permalink": "https://github.com/symfony/polyfill-php85/tree/86a42cbcc07adc331481a5ab310a4024bfc227f6",
+ "license_files": [
+ {
+ "file": "vendor/symfony/polyfill-php85/LICENSE",
+ "sha256": "56e762e45c7d6d7873c19a5dac018ca43f5f9a881f8cd9100d1d08d0182b9544"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
+ {
+ "name": "symfony/polyfill-php86",
+ "version": "v1.43.0",
+ "direct": false,
+ "scope": "runtime",
+ "spdx": [
+ "MIT"
+ ],
+ "source_url": "https://github.com/symfony/polyfill-php86.git",
+ "source_commit": "8840df45b24f33a49dc419fa18dc0057231ae1d8",
+ "source_permalink": "https://github.com/symfony/polyfill-php86/tree/8840df45b24f33a49dc419fa18dc0057231ae1d8",
+ "license_files": [
+ {
+ "file": "vendor/symfony/polyfill-php86/LICENSE",
+ "sha256": "56e762e45c7d6d7873c19a5dac018ca43f5f9a881f8cd9100d1d08d0182b9544"
+ }
+ ],
+ "attribution": "Preserve distributed license and copyright notices; additional source obligations depend on the declared license.",
+ "status": "LICENSE_TEXT_PRESENT",
+ "findings": []
+ },
{
"name": "webmozart/assert",
- "version": "1.12.1",
+ "version": "2.5.0",
"direct": false,
"scope": "runtime",
"spdx": [
"MIT"
],
"source_url": "https://github.com/webmozarts/assert.git",
- "source_commit": "9be6926d8b485f55b9229203f962b51ed377ba68",
- "source_permalink": "https://github.com/webmozarts/assert/tree/9be6926d8b485f55b9229203f962b51ed377ba68",
+ "source_commit": "8a163706bbcac613733dba03f51e13b5eb1bb819",
+ "source_permalink": "https://github.com/webmozarts/assert/tree/8a163706bbcac613733dba03f51e13b5eb1bb819",
"license_files": [
{
"file": "vendor/webmozart/assert/LICENSE",
@@ -1854,106 +2403,22 @@
}
],
"local_patches": [
- {
- "manifest": "patches/madelineproto/manifest.json",
- "sha256": "a2dc6507d5f7dc8d80ec2dd0b5cfdb267ae71d83d3a7131b1023898c626274fd",
- "package": "danog/madelineproto",
- "target": "src/Loop/Update/UpdateLoop.php",
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/UpdateLoop.php",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/Loop/Update/UpdateLoop.php",
- "original_sha256": "2fbcbb73822258102837f53f4a231b87526d66809be7acd6339156ea778a8c2f",
- "patched_sha256": "8f6cb1a483c879024bddea289e90d4bf2d71dd15716102bc83a1f34a243782e4",
- "patch": "update-loop-timeout-cancellation.patch",
- "patch_sha256": "2f5c34d5e2749d3575ef9de1ec80bff60a9ced1240ca61ef8727583ee939f592"
- }
- ],
- "notes": "Locally modified library source and its immutable baseline/diff ship in the corresponding-source archive; preserve upstream notices."
- },
- {
- "manifest": "patches/madelineproto-geopoint/manifest.json",
- "sha256": "30b517d219f0cf7156b59c4e34cd9f0be262fc57bbb5cedb5108e62953900d48",
- "package": "danog/madelineproto",
- "target": "src/EventHandler/Media/GeoPoint.php",
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/GeoPoint.php",
- "reviewed_output": "reviewed/GeoPoint.php",
- "original_sha256": "9ed8054caade6abc96420b0f5b120bec029ee2bc7b7b6aacca56fb7ddc61a27b",
- "patched_sha256": "5633cc441e541e5e919dfa8156192587a68e578e49a496acac91172be5f2549d",
- "patch": "geopoint-double-coordinates.patch",
- "patch_sha256": "b1b830953dce74978ddc64198a958d0ac13d5205d8929daa58a31e86c0541556"
- }
- ],
- "notes": "Locally modified library source and its immutable baseline/diff ship in the corresponding-source archive; preserve upstream notices."
- },
- {
- "manifest": "patches/madelineproto-formatted-date/manifest.json",
- "sha256": "77376a8eef3743583f481d1bd83cb1b1e5384ccf7ce004b5922a3e792a41f807",
- "package": "danog/madelineproto",
- "target": "src/EventHandler/Message/Entities/MessageEntity.php",
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/MessageEntity.php",
- "original_sha256": "06a9d438cc198f56cfb745a2a3808932269033671146cf82f84ae88e8d6eae60",
- "reviewed_output": "reviewed/MessageEntity.php",
- "patched_sha256": "b265ed707326e1d71c7a8bdf8291f0b8c94a153b98a2c4c45c776fec3b374005",
- "patch": "formatted-date-entity.patch",
- "patch_sha256": "5c726acbc73ef6b4994d1c970f74952af007c2eee3c92773cf593e73e834b3d3",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/EventHandler/Message/Entities/MessageEntity.php",
- "license_files": [
- {
- "file": "upstream-LICENSE",
- "sha256": "57c8ff33c9c0cfc3ef00e650a1cc910d7ee479a8bc509f6c9209a7c2a11399d6"
- }
- ],
- "added_files": [
- {
- "target": "src/EventHandler/Message/Entities/FormattedDate.php",
- "original_state": "absent",
- "reviewed_output": "reviewed/FormattedDate.php",
- "patched_sha256": "ffe03d0d78215bc42968cd836c25b1f8a602f161fb55eba189b4102d9b99d5e5",
- "license": "AGPL-3.0-or-later"
- }
- ],
- "prerequisites": [
- {
- "target": "src/TL_telegram_v225.tl",
- "baseline": "baseline/TL_telegram_v225.tl",
- "sha256": "539272f5ad8992ee97b61bd134fcf3a28a41ce720e806d0e7dc0e2e408c581f9",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/TL_telegram_v225.tl"
- }
- ]
- }
- ],
- "notes": "Locally modified library source and its immutable baseline/diff ship in the corresponding-source archive; preserve upstream notices."
- },
{
"manifest": "patches/madelineproto-fresh-peer/manifest.json",
- "sha256": "40d39192dfcb91c64de98daf2eac5910c76e2203a306c656fc4b5b3bc8a5fd3e",
+ "sha256": "e274407689d5d6cad6638fca6edff5429540a99624265882aa7bc374de181119",
"package": "danog/madelineproto",
"target": "src/MTProtoTools/PeerHandler.php",
"approved": [
{
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
+ "version": "8.11.10",
+ "commit": "49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
"mode": "patch",
"baseline": "baseline/PeerHandler.php",
"reviewed_output": "reviewed/PeerHandler.php",
- "original_sha256": "3e1af3624f2256f53264fe4256475d0a5f353af8761cc9716133b7f0412538d2",
- "patched_sha256": "8188777fc376f2b3cca39963d79f85239fc84141f978128ea2bb591f03891928",
+ "original_sha256": "6caa058975e7122eeb84409142a7c8241a2da5c63ca4c63e1ec2392c7b3f7314",
+ "patched_sha256": "78187d7216c069d47d1c05d8128834603b958b55bc8478576850bce9e86489df",
"patch": "fresh-full-peer-response.patch",
- "patch_sha256": "db3099e7bf83550b7a4a4f54da451bc45a1078b8bd9bffc57f26bf52ab2d82e3"
+ "patch_sha256": "0b7c828c49de1e56cf93169560a5d4ba23ec8a1749f676569b6a83592577ed4d"
}
],
"notes": "Locally modified library source and its immutable baseline/diff ship in the corresponding-source archive; preserve upstream notices."
@@ -1996,10 +2461,10 @@
"external_runtime": [
{
"name": "SQLite",
- "php_loaded_version": "3.45.2",
+ "php_loaded_version": "3.53.4",
"license": "public-domain",
"terms": "https://sqlite.org/copyright.html",
- "wal_fix_verified": false,
+ "wal_fix_verified": true,
"docker_source_version": "3.51.3",
"docker_source_url": "https://www.sqlite.org/2026/sqlite-autoconf-3510300.tar.gz",
"docker_source_sha256": "81f5be397049b0cae1b167f2225af7646fc0f82e4a9b3c48c9ea3a533e21d77a",
diff --git a/patches/madelineproto-formatted-date/README.md b/patches/madelineproto-formatted-date/README.md
deleted file mode 100644
index 908f48e..0000000
--- a/patches/madelineproto-formatted-date/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# MadelineProto formatted-date entity compatibility
-
-Prepared 2026-10-14 for exact MadelineProto 8.7.0 commit 7b99dd0f2d964a492c377912ffce9f5ce61aa9ed. This reviewed upstream release is a prerelease; it is not described as the latest stable release. The installed layer 225 schema declares `messageEntityFormattedDate#904ac7c7`, but the unchanged `MessageEntity::fromRawEntity` factory throws `AssertionError` before message dispatch. The public v8 source reviewed on this date still lacked the factory arm, so no tested compatible official version eliminated this local fix.
-
-The immutable [factory source](https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/EventHandler/Message/Entities/MessageEntity.php) was downloaded and byte-matched to the locked installation. Its pristine SHA256 is 06a9d438cc198f56cfb745a2a3808932269033671146cf82f84ae88e8d6eae60. The complete original schema and upstream license are retained beside that baseline. All exact input, output, schema, diff, class and license hashes are in manifest.json.
-
-The single unified diff adds two exact factory arms and a new independently authored `FormattedDate` class. The class preserves inherited readonly UTF-16 offset/length, an integer Unix timestamp and all six native flags. It emits/accepts official BotAPI `date_time` (`unix_time`, `date_time_format`) and retains the native MTProto constructor. Integer fields and boolean flags are validated without lossy numeric coercion. Relative/other flags, simultaneous short/long time and simultaneous short/long date are rejected. Empty format preserves the linked original text. See [native constructor](https://core.telegram.org/constructor/messageEntityFormattedDate) and [official format grammar](https://core.telegram.org/bots/api#date-time-entity-formatting).
-
-The wrapper accepts nonnegative native int32 timestamp/position values. Telegram enforces its own date horizon when a real send is performed; the local wrapper does not use the machine clock to alter an incoming or replayed timestamp. No general unknown-entity fallback is added. Existing entity handlers remain unchanged. The installed generic HTML renderer preserves original text and ordinary surrounding formatting, but does not generate a special date tag; native capture/storage/resend preserves the date entity instead of routing it through HTML.
-
-## Historical reference and licensing
-
-The requested exported script at local-reference/newsearch-v2/docker/patch-madeline-formatted-date.php has SHA256 c3091f61a401d8022b8ef1d228cf8c5f31a1094982de69a0be108e21885cb967. Its wrapper has SHA256 a9e3146e49a88bec469e67e53f5e27cffb1b5127cde547590f2e385ef02dd264. The psy new/release-r21-work exports match those bytes. No recoverable Git history/reference commit was available; their metadata conflict between MIT and proprietary and no standalone grant was found. Those exports are documented as behavioral references and are not redistributed here. This is a new implementation, not the original script or patch.
-
-The unmodified factory/schema and upstream-LICENSE retain their original notices. The new WizardLoop wrapper explicitly grants AGPL-3.0-or-later, consistent with the retained MadelineProto source grant. Application/helper code remains AGPL-3.0-only. Preserve the package metadata/source-header discrepancy documented in THIRD_PARTY_NOTICES; do not flatten dependency grants into the application license. The complete diff, original source and new class ship in all release variants and the corresponding-source offer.
-
-## Installation and refusal states
-
-The installer checks exact installed version/commit, complete baseline/diff/reviewed output/license/schema hashes and contained regular targets. The factory and new class are one state: pristine factory plus absent class may be applied; exact reviewed factory plus exact reviewed class succeeds without change. Either partial combination, changed/unrecognized class/factory, symlink/directory, incorrect schema/version or tampered source artifact stops the build. No unknown hash is called upstream-supported, and partial states are not silently repaired.
-
-Run php scripts/apply-patches.php and php scripts/verify-patches.php before bot startup. Composer and Docker execute the shared five-patch lifecycle; the explicit --no-scripts installation path runs the same two commands. The application writer lock prevents mutation of a running installation. A staged addition is installed exclusively before atomic factory replacement; an interruption between files is a detectable partial state and requires explicit maintenance review. Never patch an active process or container. Vendor is not tracked in Git and no mutable patch is fetched during build.
-
-## Verification
-
-FormattedDatePatchTest covers pristine/repeated/read-only verification, both partial states, unknown class/factory, version/commit/schema, all corresponding artifacts, retained license, target types and active-writer refusal. A symlink fixture may be skipped where Windows cannot create it; report that separately. FormattedDateEntityTest exercises all 19 valid flag configurations with the real locked factory/class and native decoder, all 45 invalid combinations, strict types/format, zero/empty defaults, inherited readonly fields, existing unknown rejection, actual StrTools HTML behavior and private template capture/SQLite storage/UTF-16 expansion/native gateway resend with an injected transport.
-
-Native wire fixtures use the actual constructor descriptor and primitive integer encoder, then the actual TL decoder; they do not claim full serializeParams without its API adapter. No Telegram API, session, client rendering or live formatted-date send was exercised.
-
-Historical local-reference paths are logical project/file identifiers, not public download URLs or installation requirements.
diff --git a/patches/madelineproto-formatted-date/baseline/MessageEntity.php b/patches/madelineproto-formatted-date/baseline/MessageEntity.php
deleted file mode 100644
index 0e7bd57..0000000
--- a/patches/madelineproto-formatted-date/baseline/MessageEntity.php
+++ /dev/null
@@ -1,84 +0,0 @@
- $entities
- * @return list
- */
- public static function fromRawEntities(array $entities): array
- {
- return array_map(self::fromRawEntity(...), $entities);
- }
-
- public static function fromRawEntity(array|self $entity): self
- {
- if ($entity instanceof self) {
- return $entity;
- }
- return match ($entity['_'] ?? $entity['type']) {
- 'mention', 'messageEntityMention' => new Mention($entity['offset'], $entity['length']),
- 'hashtag', 'messageEntityHashtag' => new Hashtag($entity['offset'], $entity['length']),
- 'bot_command', 'messageEntityBotCommand' => new BotCommand($entity['offset'], $entity['length']),
- 'email', 'messageEntityEmail' => new Email($entity['offset'], $entity['length']),
- 'bold', 'messageEntityBold' => new Bold($entity['offset'], $entity['length']),
- 'italic', 'messageEntityItalic' => new Italic($entity['offset'], $entity['length']),
- 'url', 'messageEntityUrl' => new Url($entity['offset'], $entity['length']),
- 'code', 'messageEntityCode' => new Code($entity['offset'], $entity['length']),
- /** @psalm-suppress MixedArgument */
- 'pre', 'messageEntityPre' => new Pre($entity['offset'], $entity['length'], $entity['language'] ?? ''),
- 'text_link', 'messageEntityTextUrl' => new TextUrl($entity['offset'], $entity['length'], $entity['url']),
- 'text_mention', 'messageEntityMentionName' => new MentionName($entity['offset'], $entity['length'], $entity['user_id'] ?? $entity['user']['id']),
- 'inputMessageEntityMentionName' => new InputMentionName($entity['offset'], $entity['length'], $entity['user_id']),
- 'phone_number', 'messageEntityPhone' => new Phone($entity['offset'], $entity['length']),
- 'cashtag', 'messageEntityCashtag' => new Cashtag($entity['offset'], $entity['length']),
- 'underline', 'messageEntityUnderline' => new Underline($entity['offset'], $entity['length']),
- 'strikethrough', 'messageEntityStrike' => new Strike($entity['offset'], $entity['length']),
- 'block_quote', 'messageEntityBlockquote' => new Blockquote($entity['offset'], $entity['length']),
- 'bank_card', 'messageEntityBankCard' => new BankCard($entity['offset'], $entity['length']),
- 'spoiler', 'messageEntitySpoiler' => new Spoiler($entity['offset'], $entity['length']),
- 'custom_emoji', 'messageEntityCustomEmoji' => new CustomEmoji($entity['offset'], $entity['length'], $entity['document_id'] ?? $entity['custom_emoji_id']),
- default => throw new AssertionError("Unknown entity type: ".($entity['_'] ?? $entity['type']))
- };
- }
-
- /**
- * Convert entity to bot API entity.
- */
- abstract public function toBotAPI(): array;
- /**
- * Convert entity to MTProto entity.
- */
- abstract public function toMTProto(): array;
-
- /** @internal */
- #[\Override]
- public function jsonSerialize(): mixed
- {
- $res = ['_' => static::class];
- $refl = new ReflectionClass($this);
- foreach ($refl->getProperties(ReflectionProperty::IS_PUBLIC) as $prop) {
- $res[$prop->getName()] = $prop->getValue($this);
- }
- return $res;
- }
-}
diff --git a/patches/madelineproto-formatted-date/formatted-date-entity.patch b/patches/madelineproto-formatted-date/formatted-date-entity.patch
deleted file mode 100644
index 6189512..0000000
--- a/patches/madelineproto-formatted-date/formatted-date-entity.patch
+++ /dev/null
@@ -1,126 +0,0 @@
---- a/src/EventHandler/Message/Entities/MessageEntity.php
-+++ b/src/EventHandler/Message/Entities/MessageEntity.php
-@@ -57,6 +57,8 @@
- 'bank_card', 'messageEntityBankCard' => new BankCard($entity['offset'], $entity['length']),
- 'spoiler', 'messageEntitySpoiler' => new Spoiler($entity['offset'], $entity['length']),
- 'custom_emoji', 'messageEntityCustomEmoji' => new CustomEmoji($entity['offset'], $entity['length'], $entity['document_id'] ?? $entity['custom_emoji_id']),
-+ 'date_time' => FormattedDate::fromBotAPI($entity),
-+ 'messageEntityFormattedDate' => FormattedDate::fromMTProto($entity),
- default => throw new AssertionError("Unknown entity type: ".($entity['_'] ?? $entity['type']))
- };
- }
---- /dev/null
-+++ b/src/EventHandler/Message/Entities/FormattedDate.php
-@@ -0,0 +1,112 @@
-+ 2147483647) {
-+ throw new \InvalidArgumentException('Formatted-date fields require nonnegative native int32 values.');
-+ }
-+ }
-+ if (($relative && ($shortTime || $longTime || $shortDate || $longDate || $dayOfWeek))
-+ || ($shortTime && $longTime) || ($shortDate && $longDate)) {
-+ throw new \InvalidArgumentException('Contradictory native formatted-date flags.');
-+ }
-+ parent::__construct($offset, $length);
-+ }
-+
-+ public static function fromMTProto(array $entity): self
-+ {
-+ if (($entity['_'] ?? null) !== 'messageEntityFormattedDate') {
-+ throw new \InvalidArgumentException('Expected the native formatted-date constructor.');
-+ }
-+ return new self(
-+ self::integer($entity, 'offset'),
-+ self::integer($entity, 'length'),
-+ self::integer($entity, 'date'),
-+ self::flag($entity, 'relative'),
-+ self::flag($entity, 'short_time'),
-+ self::flag($entity, 'long_time'),
-+ self::flag($entity, 'short_date'),
-+ self::flag($entity, 'long_date'),
-+ self::flag($entity, 'day_of_week')
-+ );
-+ }
-+
-+ public static function fromBotAPI(array $entity): self
-+ {
-+ $format = array_key_exists('date_time_format', $entity) ? $entity['date_time_format'] : '';
-+ if (($entity['type'] ?? null) !== 'date_time' || !is_string($format)
-+ || preg_match('/^(?:r|w?[dD]?[tT]?)$/D', $format) !== 1) {
-+ throw new \InvalidArgumentException('Expected an official date_time entity and valid date_time_format.');
-+ }
-+ return new self(
-+ self::integer($entity, 'offset'),
-+ self::integer($entity, 'length'),
-+ self::integer($entity, 'unix_time'),
-+ $format === 'r',
-+ str_contains($format, 't'),
-+ str_contains($format, 'T'),
-+ str_contains($format, 'd'),
-+ str_contains($format, 'D'),
-+ str_contains($format, 'w')
-+ );
-+ }
-+
-+ #[\Override]
-+ public function toMTProto(): array
-+ {
-+ return ['_' => 'messageEntityFormattedDate', 'offset' => $this->offset, 'length' => $this->length,
-+ 'date' => $this->date, 'relative' => $this->relative, 'short_time' => $this->shortTime,
-+ 'long_time' => $this->longTime, 'short_date' => $this->shortDate,
-+ 'long_date' => $this->longDate, 'day_of_week' => $this->dayOfWeek];
-+ }
-+
-+ #[\Override]
-+ public function toBotAPI(): array
-+ {
-+ $format = $this->relative ? 'r' : ($this->dayOfWeek ? 'w' : '')
-+ . ($this->shortDate ? 'd' : ($this->longDate ? 'D' : ''))
-+ . ($this->shortTime ? 't' : ($this->longTime ? 'T' : ''));
-+ return ['type' => 'date_time', 'offset' => $this->offset, 'length' => $this->length,
-+ 'unix_time' => $this->date, 'date_time_format' => $format];
-+ }
-+
-+ private static function integer(array $entity, string $field): int
-+ {
-+ if (!array_key_exists($field, $entity) || !is_int($entity[$field])) {
-+ throw new \InvalidArgumentException('Formatted-date field must be a native integer: ' . $field);
-+ }
-+ return $entity[$field];
-+ }
-+
-+ private static function flag(array $entity, string $field): bool
-+ {
-+ $value = array_key_exists($field, $entity) ? $entity[$field] : false;
-+ if (!is_bool($value)) {
-+ throw new \InvalidArgumentException('Formatted-date flag must be a native boolean: ' . $field);
-+ }
-+ return $value;
-+ }
-+}
diff --git a/patches/madelineproto-formatted-date/manifest.json b/patches/madelineproto-formatted-date/manifest.json
deleted file mode 100644
index 9121a7d..0000000
--- a/patches/madelineproto-formatted-date/manifest.json
+++ /dev/null
@@ -1,59 +0,0 @@
-{
- "schema_version": 1,
- "package": "danog/madelineproto",
- "target": "src/EventHandler/Message/Entities/MessageEntity.php",
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/MessageEntity.php",
- "original_sha256": "06a9d438cc198f56cfb745a2a3808932269033671146cf82f84ae88e8d6eae60",
- "reviewed_output": "reviewed/MessageEntity.php",
- "patched_sha256": "b265ed707326e1d71c7a8bdf8291f0b8c94a153b98a2c4c45c776fec3b374005",
- "patch": "formatted-date-entity.patch",
- "patch_sha256": "5c726acbc73ef6b4994d1c970f74952af007c2eee3c92773cf593e73e834b3d3",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/EventHandler/Message/Entities/MessageEntity.php",
- "license_files": [
- {
- "file": "upstream-LICENSE",
- "sha256": "57c8ff33c9c0cfc3ef00e650a1cc910d7ee479a8bc509f6c9209a7c2a11399d6"
- }
- ],
- "added_files": [
- {
- "target": "src/EventHandler/Message/Entities/FormattedDate.php",
- "original_state": "absent",
- "reviewed_output": "reviewed/FormattedDate.php",
- "patched_sha256": "ffe03d0d78215bc42968cd836c25b1f8a602f161fb55eba189b4102d9b99d5e5",
- "license": "AGPL-3.0-or-later"
- }
- ],
- "prerequisites": [
- {
- "target": "src/TL_telegram_v225.tl",
- "baseline": "baseline/TL_telegram_v225.tl",
- "sha256": "539272f5ad8992ee97b61bd134fcf3a28a41ce720e806d0e7dc0e2e408c581f9",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/TL_telegram_v225.tl"
- }
- ]
- }
- ],
- "provenance": {
- "prepared_at": "2026-10-14",
- "implementation": "Independently implemented from the locked SDK entity contract and official Telegram layer225/BotAPI specifications.",
- "reference_exports": [
- {
- "path": "local-reference/newsearch-v2/docker/patch-madeline-formatted-date.php",
- "sha256": "c3091f61a401d8022b8ef1d228cf8c5f31a1094982de69a0be108e21885cb967"
- },
- {
- "path": "local-reference/newsearch-v2/docker/madeline-formatted-date/FormattedDate.php",
- "sha256": "a9e3146e49a88bec469e67e53f5e27cffb1b5127cde547590f2e385ef02dd264"
- }
- ],
- "reference_limitations": "Byte-identical psy new/release-r21-work export; no recoverable Git history. Conflicting MIT/proprietary metadata without standalone grant. Historical code is not redistributed. Paths are logical local-reference identifiers, not public download URLs.",
- "upstream_license_file": "upstream-LICENSE",
- "upstream_license_sha256": "57c8ff33c9c0cfc3ef00e650a1cc910d7ee479a8bc509f6c9209a7c2a11399d6"
- }
-}
diff --git a/patches/madelineproto-formatted-date/reviewed/FormattedDate.php b/patches/madelineproto-formatted-date/reviewed/FormattedDate.php
deleted file mode 100644
index a916a33..0000000
--- a/patches/madelineproto-formatted-date/reviewed/FormattedDate.php
+++ /dev/null
@@ -1,112 +0,0 @@
- 2147483647) {
- throw new \InvalidArgumentException('Formatted-date fields require nonnegative native int32 values.');
- }
- }
- if (($relative && ($shortTime || $longTime || $shortDate || $longDate || $dayOfWeek))
- || ($shortTime && $longTime) || ($shortDate && $longDate)) {
- throw new \InvalidArgumentException('Contradictory native formatted-date flags.');
- }
- parent::__construct($offset, $length);
- }
-
- public static function fromMTProto(array $entity): self
- {
- if (($entity['_'] ?? null) !== 'messageEntityFormattedDate') {
- throw new \InvalidArgumentException('Expected the native formatted-date constructor.');
- }
- return new self(
- self::integer($entity, 'offset'),
- self::integer($entity, 'length'),
- self::integer($entity, 'date'),
- self::flag($entity, 'relative'),
- self::flag($entity, 'short_time'),
- self::flag($entity, 'long_time'),
- self::flag($entity, 'short_date'),
- self::flag($entity, 'long_date'),
- self::flag($entity, 'day_of_week')
- );
- }
-
- public static function fromBotAPI(array $entity): self
- {
- $format = array_key_exists('date_time_format', $entity) ? $entity['date_time_format'] : '';
- if (($entity['type'] ?? null) !== 'date_time' || !is_string($format)
- || preg_match('/^(?:r|w?[dD]?[tT]?)$/D', $format) !== 1) {
- throw new \InvalidArgumentException('Expected an official date_time entity and valid date_time_format.');
- }
- return new self(
- self::integer($entity, 'offset'),
- self::integer($entity, 'length'),
- self::integer($entity, 'unix_time'),
- $format === 'r',
- str_contains($format, 't'),
- str_contains($format, 'T'),
- str_contains($format, 'd'),
- str_contains($format, 'D'),
- str_contains($format, 'w')
- );
- }
-
- #[\Override]
- public function toMTProto(): array
- {
- return ['_' => 'messageEntityFormattedDate', 'offset' => $this->offset, 'length' => $this->length,
- 'date' => $this->date, 'relative' => $this->relative, 'short_time' => $this->shortTime,
- 'long_time' => $this->longTime, 'short_date' => $this->shortDate,
- 'long_date' => $this->longDate, 'day_of_week' => $this->dayOfWeek];
- }
-
- #[\Override]
- public function toBotAPI(): array
- {
- $format = $this->relative ? 'r' : ($this->dayOfWeek ? 'w' : '')
- . ($this->shortDate ? 'd' : ($this->longDate ? 'D' : ''))
- . ($this->shortTime ? 't' : ($this->longTime ? 'T' : ''));
- return ['type' => 'date_time', 'offset' => $this->offset, 'length' => $this->length,
- 'unix_time' => $this->date, 'date_time_format' => $format];
- }
-
- private static function integer(array $entity, string $field): int
- {
- if (!array_key_exists($field, $entity) || !is_int($entity[$field])) {
- throw new \InvalidArgumentException('Formatted-date field must be a native integer: ' . $field);
- }
- return $entity[$field];
- }
-
- private static function flag(array $entity, string $field): bool
- {
- $value = array_key_exists($field, $entity) ? $entity[$field] : false;
- if (!is_bool($value)) {
- throw new \InvalidArgumentException('Formatted-date flag must be a native boolean: ' . $field);
- }
- return $value;
- }
-}
diff --git a/patches/madelineproto-formatted-date/reviewed/MessageEntity.php b/patches/madelineproto-formatted-date/reviewed/MessageEntity.php
deleted file mode 100644
index df0e159..0000000
--- a/patches/madelineproto-formatted-date/reviewed/MessageEntity.php
+++ /dev/null
@@ -1,86 +0,0 @@
- $entities
- * @return list
- */
- public static function fromRawEntities(array $entities): array
- {
- return array_map(self::fromRawEntity(...), $entities);
- }
-
- public static function fromRawEntity(array|self $entity): self
- {
- if ($entity instanceof self) {
- return $entity;
- }
- return match ($entity['_'] ?? $entity['type']) {
- 'mention', 'messageEntityMention' => new Mention($entity['offset'], $entity['length']),
- 'hashtag', 'messageEntityHashtag' => new Hashtag($entity['offset'], $entity['length']),
- 'bot_command', 'messageEntityBotCommand' => new BotCommand($entity['offset'], $entity['length']),
- 'email', 'messageEntityEmail' => new Email($entity['offset'], $entity['length']),
- 'bold', 'messageEntityBold' => new Bold($entity['offset'], $entity['length']),
- 'italic', 'messageEntityItalic' => new Italic($entity['offset'], $entity['length']),
- 'url', 'messageEntityUrl' => new Url($entity['offset'], $entity['length']),
- 'code', 'messageEntityCode' => new Code($entity['offset'], $entity['length']),
- /** @psalm-suppress MixedArgument */
- 'pre', 'messageEntityPre' => new Pre($entity['offset'], $entity['length'], $entity['language'] ?? ''),
- 'text_link', 'messageEntityTextUrl' => new TextUrl($entity['offset'], $entity['length'], $entity['url']),
- 'text_mention', 'messageEntityMentionName' => new MentionName($entity['offset'], $entity['length'], $entity['user_id'] ?? $entity['user']['id']),
- 'inputMessageEntityMentionName' => new InputMentionName($entity['offset'], $entity['length'], $entity['user_id']),
- 'phone_number', 'messageEntityPhone' => new Phone($entity['offset'], $entity['length']),
- 'cashtag', 'messageEntityCashtag' => new Cashtag($entity['offset'], $entity['length']),
- 'underline', 'messageEntityUnderline' => new Underline($entity['offset'], $entity['length']),
- 'strikethrough', 'messageEntityStrike' => new Strike($entity['offset'], $entity['length']),
- 'block_quote', 'messageEntityBlockquote' => new Blockquote($entity['offset'], $entity['length']),
- 'bank_card', 'messageEntityBankCard' => new BankCard($entity['offset'], $entity['length']),
- 'spoiler', 'messageEntitySpoiler' => new Spoiler($entity['offset'], $entity['length']),
- 'custom_emoji', 'messageEntityCustomEmoji' => new CustomEmoji($entity['offset'], $entity['length'], $entity['document_id'] ?? $entity['custom_emoji_id']),
- 'date_time' => FormattedDate::fromBotAPI($entity),
- 'messageEntityFormattedDate' => FormattedDate::fromMTProto($entity),
- default => throw new AssertionError("Unknown entity type: ".($entity['_'] ?? $entity['type']))
- };
- }
-
- /**
- * Convert entity to bot API entity.
- */
- abstract public function toBotAPI(): array;
- /**
- * Convert entity to MTProto entity.
- */
- abstract public function toMTProto(): array;
-
- /** @internal */
- #[\Override]
- public function jsonSerialize(): mixed
- {
- $res = ['_' => static::class];
- $refl = new ReflectionClass($this);
- foreach ($refl->getProperties(ReflectionProperty::IS_PUBLIC) as $prop) {
- $res[$prop->getName()] = $prop->getValue($this);
- }
- return $res;
- }
-}
diff --git a/patches/madelineproto-formatted-date/upstream-LICENSE b/patches/madelineproto-formatted-date/upstream-LICENSE
deleted file mode 100644
index dba13ed..0000000
--- a/patches/madelineproto-formatted-date/upstream-LICENSE
+++ /dev/null
@@ -1,661 +0,0 @@
- GNU AFFERO GENERAL PUBLIC LICENSE
- Version 3, 19 November 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU Affero General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
- A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate. Many developers of free software are heartened and
-encouraged by the resulting cooperation. However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
- The GNU Affero General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community. It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server. Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
- An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals. This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing under
-this license.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU Affero General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Remote Network Interaction; Use with the GNU General Public License.
-
- Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your version
-supports such interaction) an opportunity to receive the Corresponding
-Source of your version by providing access to the Corresponding Source
-from a network server at no charge, through some standard or customary
-means of facilitating copying of software. This Corresponding Source
-shall include the Corresponding Source for any work covered by version 3
-of the GNU General Public License that is incorporated pursuant to the
-following paragraph.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU Affero General Public License from time to time. Such new versions
-will be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU Affero General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU Affero General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU Affero General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for the
-specific requirements.
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU AGPL, see
-.
diff --git a/patches/madelineproto-fresh-peer/README.md b/patches/madelineproto-fresh-peer/README.md
index 9e19399..3bd1208 100644
--- a/patches/madelineproto-fresh-peer/README.md
+++ b/patches/madelineproto-fresh-peer/README.md
@@ -1,22 +1,22 @@
-# MadelineProto 8.7.0 fresh full-peer response compatibility patch
+# MadelineProto 8.11.10 fresh full-peer response compatibility patch
-Reviewed: 2026-10-16. This is a new local WizardLoop Shabbat compatibility change, not a recovered historical patch or an upstream release. Package: `danog/madelineproto` 8.7.0, commit `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`.
+Reviewed: 2026-10-22. The local WizardLoop Shabbat compatibility change is verified against the exact new upstream source, which is byte-identical to the previously reviewed 8.11.1 baseline; it is not an upstream release. Package: `danog/madelineproto` 8.11.10, commit `49d3d8460257c7bfb1a7e12708e1bfdd59e898c1`.
## Source and reason
-The immutable [upstream PeerHandler.php](https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/MTProtoTools/PeerHandler.php) was compared byte-for-byte with the installed locked source. Its SHA256 is `3e1af3624f2256f53264fe4256475d0a5f353af8761cc9716133b7f0412538d2`. Baseline and reviewed output are retained in this directory; the manifest binds the unified diff and both hashes.
+The immutable [upstream PeerHandler.php](https://github.com/danog/MadelineProto/blob/49d3d8460257c7bfb1a7e12708e1bfdd59e898c1/src/MTProtoTools/PeerHandler.php) was compared byte-for-byte with the installed locked source. Its SHA256 is `6caa058975e7122eeb84409142a7c8241a2da5c63ca4c63e1ec2392c7b3f7314`. Baseline and reviewed output are retained in this directory; the manifest binds the unified diff and both hashes.
-Upstream `getFullInfo` refreshes the full information but combines it with an earlier Chat object. Re-reading through `getInfo` is insufficient: the pinned minimal-peer branch can return its older local record after refreshing the peer cache. The bot must establish that the default permissions being saved came from the request it just completed.
+Upstream `getFullInfo` refreshes the full information but combines it with an earlier Chat object. Upstream 8.11.10 fixes the earlier minimal-peer re-read defect in `getInfo`, but `getFullInfo` still combines the partial record captured before the full RPC with cached full data. It provides no immediate full-reply provenance to the application. The bot must establish that the default permissions being saved came from the request it just completed.
Direct `channels.getFullChannel` and `messages.getFullChat` namespace calls are blacklisted by the pinned SDK. This patch keeps the public `getFullInfo(mixed $id)` signature and uses its existing internal calls. It does not bypass that API boundary or change dependency versions.
## Change
-When the full-info cache lifetime is zero, bypass cached full information even if its timestamp is in the future. Keep the immediate full-peer RPC response in a namespaced `_shabbat_fresh_full_peer_v1` return field for this call only. Do not persist that field in the peer cache. Other helper fields and normal positive-cache-lifetime behavior remain intact.
+When the full-info cache lifetime is zero, bypass cached full information even if its timestamp is in the future. Keep the immediate full-peer RPC response in a namespaced `_shabbat_fresh_full_peer_v1` return field for this call only. Do not persist that field in the peer cache. Other helper fields and normal positive-cache-lifetime behavior remain intact. The new official `community` peer branch and invalid-peer exception are preserved. Upstream 8.11.10 still discards the raw group RPC reply, so it does not provide equivalent permission evidence.
The application reader validates the returned native constructor, matching signed peer ID, matching ChatFull object and complete non-minimal Chat. Cached records cannot replace the raw Chat, including when fresh complete data legitimately omits optional default restrictions. Malformed, forbidden, migrated, ambiguous and mismatched responses fail before a permission write. Individual restriction bits, including `manage_topics`, are not silently discarded.
-This fixes the reproduced reading defects. It does not prove which historical server event produced the user's broadly permissive dev.6 snapshot. Existing unverified snapshots require explicit administrator resolution; see [the dev.8 investigation](../../docs/DEV8_PERMISSIONS.md).
+This fixes the reproduced reading defects. It does not prove which historical server event produced the user's broadly permissive dev.6 snapshot. Existing unverified snapshots require explicit administrator resolution; see [permission recovery](../../docs/PERMISSION_RECOVERY.md).
## Installation and source offer
diff --git a/patches/madelineproto-fresh-peer/baseline/PeerHandler.php b/patches/madelineproto-fresh-peer/baseline/PeerHandler.php
index 5ead123..cd77ddb 100644
--- a/patches/madelineproto-fresh-peer/baseline/PeerHandler.php
+++ b/patches/madelineproto-fresh-peer/baseline/PeerHandler.php
@@ -27,6 +27,7 @@
use danog\MadelineProto\EventHandler\Message\Entities\MentionName;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
+use danog\MadelineProto\Magic;
use danog\MadelineProto\PeerNotInDbException;
use danog\MadelineProto\RPCError\ChannelPrivateError;
use danog\MadelineProto\RPCError\ChatAdminRequiredError;
@@ -55,9 +56,11 @@ trait PeerHandler
* Set support info.
*
* @internal
+ * @internal
*
* @param array $support Support info
- * @internal
+ *
+ * @psalm-external-mutation-free
*/
public function addSupport(array $support): void
{
@@ -70,7 +73,7 @@ public function addSupport(array $support): void
*/
public function isForum(mixed $peer): bool
{
- return $this->getInfo($peer, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)['forum'] ?? false;
+ return $this->getInfo($peer)['Chat']['forum'] ?? false;
}
/**
@@ -166,11 +169,16 @@ public function getId(mixed $id): int
* @internal
*
* @param mixed $id Peer
+ *
+ * @psalm-mutation-free
*/
public function getIdInternal(mixed $id): ?int
{
if (\is_array($id)) {
switch ($id['_']) {
+ case 'help.promoData':
+ // Its peer is optional.
+ return isset($id['peer']) ? $this->getIdInternal($id['peer']) : null;
case 'updateDialogPinned':
case 'updateDialogUnreadMark':
case 'updateNotifySettings':
@@ -188,12 +196,21 @@ public function getIdInternal(mixed $id): ?int
case 'dialog':
case 'dialogPeer':
case 'notifyPeer':
- case 'help.proxyDataPromo':
case 'folderPeer':
case 'inputDialogPeer':
case 'inputNotifyPeer':
case 'inputFolderPeer':
+ case 'communityPeer':
+ case 'communityPeerRequest':
return $this->getIdInternal($id['peer']);
+ case 'inputNotifyCommunity':
+ case 'inputDialogPeerCommunity':
+ return $this->getIdInternal($id['community']);
+ case 'dialogCommunity':
+ case 'dialogPeerCommunity':
+ case 'notifyCommunity':
+ case 'messageActionChatJoinedViaCommunity':
+ return $id['community_id'];
case 'inputUserSelf':
case 'inputPeerSelf':
return $this->authorization['user']['id'];
@@ -205,6 +222,9 @@ public function getIdInternal(mixed $id): ?int
case 'chat':
case 'chatForbidden':
case 'chatFull':
+ case 'communityFull':
+ case 'community':
+ case 'communityForbidden':
return $id['id'];
case 'inputPeerChat':
case 'peerChat':
@@ -231,6 +251,14 @@ public function getIdInternal(mixed $id): ?int
case 'inputPeerChannel':
case 'inputChannelFromMessage':
case 'inputPeerChannelFromMessage':
+ // Built to be serialized, with the MTProto ID (see genAll), unlike the received constructors below,
+ // whose IDs the deserializer already converted to bot API IDs.
+ if ($id['channel_id'] > 0) {
+ return $id['channel_id'] > Magic::MAX_CHANNEL_ID
+ ? DialogId::fromMonoforumId($id['channel_id'])
+ : DialogId::fromSupergroupOrChannelId($id['channel_id']);
+ }
+ return $id['channel_id'];
case 'updateChannelReadMessagesContents':
case 'updateChannelAvailableMessages':
case 'updateChannel':
@@ -416,10 +444,13 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
$this->caching_full_info[$id] = true;
$this->logger->logger("Only have min peer for {$id} in database, trying to fetch full info");
try {
+ // A min peer may come without an access hash: the serializer replaces the min input constructor
+ // with inputChannelFromMessage/inputUserFromMessage, which don't need one.
+ $input = $this->genAll(['access_hash' => $chat['access_hash'] ?? 0] + $chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR);
if ($id < 0) {
- $this->methodCallAsyncRead('channels.getChannels', ['id' => [$this->genAll($chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)]]);
+ $this->methodCallAsyncRead('channels.getChannels', ['id' => [$input]]);
} else {
- $this->methodCallAsyncRead('users.getUsers', ['id' => [$this->genAll($chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)]]);
+ $this->methodCallAsyncRead('users.getUsers', ['id' => [$input]]);
}
} catch (Exception $e) {
$this->logger->logger($e->getMessage(), Logger::WARNING);
@@ -428,6 +459,7 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
} finally {
unset($this->caching_full_info[$id]);
}
+ $chat = $this->peerDatabase->get($id) ?? $chat;
}
try {
return $this->genAll($chat, $type);
@@ -460,7 +492,14 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
return $this->getInfo($this->supportUser, $type);
}
if ($bot_api_id = $this->peerDatabase->getIdFromUsername($id)) {
- return $this->getInfo($bot_api_id, $type);
+ // Usernames are indexed for min peers too, which may lack an access hash (seen in a forward, a mention,
+ // a group call...): check that the peer can be used (fetching it through the min database if needed)
+ // even when only its ID is requested, or resolve the username again.
+ try {
+ $info = $this->getInfo($bot_api_id);
+ return $type === \danog\MadelineProto\API::INFO_TYPE_ALL ? $info : $this->getInfo($bot_api_id, $type);
+ } catch (PeerNotInDbException) {
+ }
}
if ($bot_api_id = $this->peerDatabase->resolveUsername($id)) {
return $this->getInfo($bot_api_id, $type);
@@ -492,7 +531,7 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'user') {
return ($constructor['self'] ?? false) ? ['_' => 'inputUserSelf'] : ['_' => 'inputUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
- if ($constructor['_'] === 'channel') {
+ if ($constructor['_'] === 'channel' || $constructor['_'] === 'community') {
return ['_' => 'inputChannel', 'channel_id' => DialogId::toMTProtoId($constructor['id']), 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
}
@@ -500,7 +539,7 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'user') {
return ($constructor['self'] ?? false) ? ['_' => 'inputPeerSelf'] : ['_' => 'inputPeerUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
- if ($constructor['_'] === 'channel') {
+ if ($constructor['_'] === 'channel' || $constructor['_'] === 'community') {
return ['_' => 'inputPeerChannel', 'channel_id' => DialogId::toMTProtoId($constructor['id']), 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
@@ -517,6 +556,9 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'channel') {
return $constructor['megagroup'] ?? false ? 'supergroup' : 'channel';
}
+ if ($constructor['_'] === 'community') {
+ return 'community';
+ }
if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
return 'chat';
}
@@ -550,7 +592,17 @@ private function genAll($constructor, int $type): array|int|string
$res['bot_api_id'] = $constructor['id'];
$res['type'] = $constructor['megagroup'] ?? false ? 'supergroup' : 'channel';
break;
+ case 'community':
+ if (!isset($constructor['access_hash'])) {
+ $this->cacheFullDialogs();
+ throw new PeerNotInDbException();
+ }
+ $res['community_id'] = $constructor['id'];
+ $res['bot_api_id'] = $constructor['id'];
+ $res['type'] = 'community';
+ break;
case 'channelForbidden':
+ case 'communityForbidden':
throw new PeerNotInDbException();
default:
throw new Exception('Invalid constructor given '.$constructor['_']);
@@ -667,9 +719,12 @@ public function getFullInfo(mixed $id): array
$this->methodCallAsyncRead('messages.getFullChat', $partial);
break;
case 'channel':
+ case 'community':
case 'supergroup':
$this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['bot_api_id']]);
break;
+ default:
+ throw new Exception('Invalid peer type '.$partial['type']);
}
return array_merge($partial, $this->peerDatabase->getFull($partial['bot_api_id']));
}
@@ -753,6 +808,21 @@ public function getPwrChat(mixed $id, bool $fullfetch = true): array
$res['invite'] = $full['full']['exported_invite']['link'];
}
break;
+ case 'community':
+ foreach (['title', 'creator', 'left', 'admin_rights', 'default_banned_rights'] as $key) {
+ if (isset($full['Chat'][$key])) {
+ $res[$key] = $full['Chat'][$key];
+ }
+ }
+ foreach (['about', 'linked_peers', 'admins_count', 'kicked_count', 'peer_link_requests_pending'] as $key) {
+ if (isset($full['full'][$key])) {
+ $res[$key] = $full['full'][$key];
+ }
+ }
+ if (isset($full['full']['chat_photo'])) {
+ $res['photo'] = $full['full']['chat_photo'];
+ }
+ break;
}
if (isset($res['participants']) && $fullfetch) {
foreach ($res['participants'] as $key => $participant) {
@@ -818,7 +888,7 @@ private function recurseAlphabetSearchParticipants(int $channel, string $filter,
}
++$depth;
$promises = [];
- for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x++) {
+ for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x = str_increment($x)) {
$promises []= async(function () use ($channel, $filter, $q, $x, $total_count, &$res, $depth) {
return $this->recurseAlphabetSearchParticipants($channel, $filter, $q.$x, $total_count, $res, $depth);
});
@@ -916,6 +986,8 @@ private function fetchParticipants(int $channel, string $filter, string $q, int
}
/**
* Key for participatns cache.
+ *
+ * @psalm-pure
*/
private static function participantsKey(int $channelId, string $filter, string $q, int $offset, int $limit): string
{
diff --git a/patches/madelineproto-fresh-peer/fresh-full-peer-response.patch b/patches/madelineproto-fresh-peer/fresh-full-peer-response.patch
index d04ab91..5a9f689 100644
--- a/patches/madelineproto-fresh-peer/fresh-full-peer-response.patch
+++ b/patches/madelineproto-fresh-peer/fresh-full-peer-response.patch
@@ -1,56 +1,34 @@
--- a/src/MTProtoTools/PeerHandler.php
+++ b/src/MTProtoTools/PeerHandler.php
-@@ -651,25 +651,33 @@
-- public function getFullInfo(mixed $id): array
-- {
-- $partial = $this->getInfo($id);
-- if (DialogId::isSecretChat($partial['bot_api_id'])) {
-- return $partial;
-- }
-- $full = $this->peerDatabase->getFull($partial['bot_api_id']);
+@@ -707,26 +707,34 @@
+ return $partial;
+ }
+ $full = $this->peerDatabase->getFull($partial['bot_api_id']);
- if (time() - ($full['inserted'] ?? 0) < $this->getSettings()->getPeer()->getFullInfoCacheTime()) {
-- return array_merge($partial, $full);
-- }
-- switch ($partial['type']) {
-- case 'user':
-- case 'bot':
-- $this->methodCallAsyncRead('users.getFullUser', ['id' => $partial['bot_api_id']]);
-- break;
-- case 'chat':
-- $this->methodCallAsyncRead('messages.getFullChat', $partial);
-- break;
-- case 'channel':
-- case 'supergroup':
-- $this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['bot_api_id']]);
-- break;
-- }
-- return array_merge($partial, $this->peerDatabase->getFull($partial['bot_api_id']));
-- }
-+ public function getFullInfo(mixed $id): array
-+ {
-+ $partial = $this->getInfo($id);
-+ if (DialogId::isSecretChat($partial['bot_api_id'])) {
-+ return $partial;
-+ }
-+ $full = $this->peerDatabase->getFull($partial['bot_api_id']);
+ $cacheTime = $this->getSettings()->getPeer()->getFullInfoCacheTime();
+ if ($cacheTime > 0 && time() - ($full['inserted'] ?? 0) < $cacheTime) {
-+ return array_merge($partial, $full);
-+ }
+ return array_merge($partial, $full);
+ }
+ $freshReply = null;
-+ switch ($partial['type']) {
-+ case 'user':
-+ case 'bot':
-+ $this->methodCallAsyncRead('users.getFullUser', ['id' => $partial['bot_api_id']]);
-+ break;
-+ case 'chat':
+ switch ($partial['type']) {
+ case 'user':
+ case 'bot':
+ $this->methodCallAsyncRead('users.getFullUser', ['id' => $partial['bot_api_id']]);
+ break;
+ case 'chat':
+- $this->methodCallAsyncRead('messages.getFullChat', $partial);
+ $freshReply = $this->methodCallAsyncRead('messages.getFullChat', $partial);
-+ break;
-+ case 'channel':
-+ case 'supergroup':
+ break;
+ case 'channel':
+ case 'community':
+ case 'supergroup':
+- $this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['bot_api_id']]);
+ $freshReply = $this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['bot_api_id']]);
-+ break;
-+ }
+ break;
+ default:
+ throw new Exception('Invalid peer type '.$partial['type']);
+ }
+- return array_merge($partial, $this->peerDatabase->getFull($partial['bot_api_id']));
+ $result = array_merge($partial, $this->peerDatabase->getFull($partial['bot_api_id']));
+ // Shabbat local compatibility patch: never persist this per-call RPC evidence.
+ // Keep the public helper signature and ordinary cache semantics unchanged.
@@ -58,4 +36,6 @@
+ $result['_shabbat_fresh_full_peer_v1'] = $freshReply;
+ }
+ return $result;
-+ }
+ }
+ /**
+ * Get full info about peer (including full list of channel members), returns a Chat object.
diff --git a/patches/madelineproto-fresh-peer/manifest.json b/patches/madelineproto-fresh-peer/manifest.json
index 1d74345..e54459a 100644
--- a/patches/madelineproto-fresh-peer/manifest.json
+++ b/patches/madelineproto-fresh-peer/manifest.json
@@ -1,26 +1,27 @@
{
"schema_version": 1,
- "reviewed_at": "2026-10-16",
+ "reviewed_at": "2026-10-22",
"package": "danog/madelineproto",
"target": "src/MTProtoTools/PeerHandler.php",
"provenance": {
- "kind": "new-local-authoritative-full-peer-response",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/MTProtoTools/PeerHandler.php",
+ "kind": "ported-local-authoritative-full-peer-response",
+ "source_url": "https://github.com/danog/MadelineProto/blob/49d3d8460257c7bfb1a7e12708e1bfdd59e898c1/src/MTProtoTools/PeerHandler.php",
"source_verified_against_locked_installed_file": true,
"source_verified_against_pinned_remote_bytes": true,
- "source_verified_sha256": "3e1af3624f2256f53264fe4256475d0a5f353af8761cc9716133b7f0412538d2"
+ "source_verified_sha256": "6caa058975e7122eeb84409142a7c8241a2da5c63ca4c63e1ec2392c7b3f7314",
+ "note": "Reviewed against official 8.11.10. PeerHandler is byte-identical to the reviewed 8.11.1 baseline. Upstream getFullInfo still discards the raw group RPC reply and can merge cached partial data; no equivalent authoritative evidence accessor was found."
},
"approved": [
{
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
+ "version": "8.11.10",
+ "commit": "49d3d8460257c7bfb1a7e12708e1bfdd59e898c1",
"mode": "patch",
"baseline": "baseline/PeerHandler.php",
"reviewed_output": "reviewed/PeerHandler.php",
- "original_sha256": "3e1af3624f2256f53264fe4256475d0a5f353af8761cc9716133b7f0412538d2",
- "patched_sha256": "8188777fc376f2b3cca39963d79f85239fc84141f978128ea2bb591f03891928",
+ "original_sha256": "6caa058975e7122eeb84409142a7c8241a2da5c63ca4c63e1ec2392c7b3f7314",
+ "patched_sha256": "78187d7216c069d47d1c05d8128834603b958b55bc8478576850bce9e86489df",
"patch": "fresh-full-peer-response.patch",
- "patch_sha256": "db3099e7bf83550b7a4a4f54da451bc45a1078b8bd9bffc57f26bf52ab2d82e3"
+ "patch_sha256": "0b7c828c49de1e56cf93169560a5d4ba23ec8a1749f676569b6a83592577ed4d"
}
],
"official_versions": []
diff --git a/patches/madelineproto-fresh-peer/reviewed/PeerHandler.php b/patches/madelineproto-fresh-peer/reviewed/PeerHandler.php
index 254eddb..8139df6 100644
--- a/patches/madelineproto-fresh-peer/reviewed/PeerHandler.php
+++ b/patches/madelineproto-fresh-peer/reviewed/PeerHandler.php
@@ -27,6 +27,7 @@
use danog\MadelineProto\EventHandler\Message\Entities\MentionName;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
+use danog\MadelineProto\Magic;
use danog\MadelineProto\PeerNotInDbException;
use danog\MadelineProto\RPCError\ChannelPrivateError;
use danog\MadelineProto\RPCError\ChatAdminRequiredError;
@@ -55,9 +56,11 @@ trait PeerHandler
* Set support info.
*
* @internal
+ * @internal
*
* @param array $support Support info
- * @internal
+ *
+ * @psalm-external-mutation-free
*/
public function addSupport(array $support): void
{
@@ -70,7 +73,7 @@ public function addSupport(array $support): void
*/
public function isForum(mixed $peer): bool
{
- return $this->getInfo($peer, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)['forum'] ?? false;
+ return $this->getInfo($peer)['Chat']['forum'] ?? false;
}
/**
@@ -166,11 +169,16 @@ public function getId(mixed $id): int
* @internal
*
* @param mixed $id Peer
+ *
+ * @psalm-mutation-free
*/
public function getIdInternal(mixed $id): ?int
{
if (\is_array($id)) {
switch ($id['_']) {
+ case 'help.promoData':
+ // Its peer is optional.
+ return isset($id['peer']) ? $this->getIdInternal($id['peer']) : null;
case 'updateDialogPinned':
case 'updateDialogUnreadMark':
case 'updateNotifySettings':
@@ -188,12 +196,21 @@ public function getIdInternal(mixed $id): ?int
case 'dialog':
case 'dialogPeer':
case 'notifyPeer':
- case 'help.proxyDataPromo':
case 'folderPeer':
case 'inputDialogPeer':
case 'inputNotifyPeer':
case 'inputFolderPeer':
+ case 'communityPeer':
+ case 'communityPeerRequest':
return $this->getIdInternal($id['peer']);
+ case 'inputNotifyCommunity':
+ case 'inputDialogPeerCommunity':
+ return $this->getIdInternal($id['community']);
+ case 'dialogCommunity':
+ case 'dialogPeerCommunity':
+ case 'notifyCommunity':
+ case 'messageActionChatJoinedViaCommunity':
+ return $id['community_id'];
case 'inputUserSelf':
case 'inputPeerSelf':
return $this->authorization['user']['id'];
@@ -205,6 +222,9 @@ public function getIdInternal(mixed $id): ?int
case 'chat':
case 'chatForbidden':
case 'chatFull':
+ case 'communityFull':
+ case 'community':
+ case 'communityForbidden':
return $id['id'];
case 'inputPeerChat':
case 'peerChat':
@@ -231,6 +251,14 @@ public function getIdInternal(mixed $id): ?int
case 'inputPeerChannel':
case 'inputChannelFromMessage':
case 'inputPeerChannelFromMessage':
+ // Built to be serialized, with the MTProto ID (see genAll), unlike the received constructors below,
+ // whose IDs the deserializer already converted to bot API IDs.
+ if ($id['channel_id'] > 0) {
+ return $id['channel_id'] > Magic::MAX_CHANNEL_ID
+ ? DialogId::fromMonoforumId($id['channel_id'])
+ : DialogId::fromSupergroupOrChannelId($id['channel_id']);
+ }
+ return $id['channel_id'];
case 'updateChannelReadMessagesContents':
case 'updateChannelAvailableMessages':
case 'updateChannel':
@@ -416,10 +444,13 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
$this->caching_full_info[$id] = true;
$this->logger->logger("Only have min peer for {$id} in database, trying to fetch full info");
try {
+ // A min peer may come without an access hash: the serializer replaces the min input constructor
+ // with inputChannelFromMessage/inputUserFromMessage, which don't need one.
+ $input = $this->genAll(['access_hash' => $chat['access_hash'] ?? 0] + $chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR);
if ($id < 0) {
- $this->methodCallAsyncRead('channels.getChannels', ['id' => [$this->genAll($chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)]]);
+ $this->methodCallAsyncRead('channels.getChannels', ['id' => [$input]]);
} else {
- $this->methodCallAsyncRead('users.getUsers', ['id' => [$this->genAll($chat, \danog\MadelineProto\API::INFO_TYPE_CONSTRUCTOR)]]);
+ $this->methodCallAsyncRead('users.getUsers', ['id' => [$input]]);
}
} catch (Exception $e) {
$this->logger->logger($e->getMessage(), Logger::WARNING);
@@ -428,6 +459,7 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
} finally {
unset($this->caching_full_info[$id]);
}
+ $chat = $this->peerDatabase->get($id) ?? $chat;
}
try {
return $this->genAll($chat, $type);
@@ -460,7 +492,14 @@ public function getInfo(mixed $id, int $type = \danog\MadelineProto\API::INFO_TY
return $this->getInfo($this->supportUser, $type);
}
if ($bot_api_id = $this->peerDatabase->getIdFromUsername($id)) {
- return $this->getInfo($bot_api_id, $type);
+ // Usernames are indexed for min peers too, which may lack an access hash (seen in a forward, a mention,
+ // a group call...): check that the peer can be used (fetching it through the min database if needed)
+ // even when only its ID is requested, or resolve the username again.
+ try {
+ $info = $this->getInfo($bot_api_id);
+ return $type === \danog\MadelineProto\API::INFO_TYPE_ALL ? $info : $this->getInfo($bot_api_id, $type);
+ } catch (PeerNotInDbException) {
+ }
}
if ($bot_api_id = $this->peerDatabase->resolveUsername($id)) {
return $this->getInfo($bot_api_id, $type);
@@ -492,7 +531,7 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'user') {
return ($constructor['self'] ?? false) ? ['_' => 'inputUserSelf'] : ['_' => 'inputUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
- if ($constructor['_'] === 'channel') {
+ if ($constructor['_'] === 'channel' || $constructor['_'] === 'community') {
return ['_' => 'inputChannel', 'channel_id' => DialogId::toMTProtoId($constructor['id']), 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
}
@@ -500,7 +539,7 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'user') {
return ($constructor['self'] ?? false) ? ['_' => 'inputPeerSelf'] : ['_' => 'inputPeerUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
- if ($constructor['_'] === 'channel') {
+ if ($constructor['_'] === 'channel' || $constructor['_'] === 'community') {
return ['_' => 'inputPeerChannel', 'channel_id' => DialogId::toMTProtoId($constructor['id']), 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min'] ?? false];
}
if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
@@ -517,6 +556,9 @@ private function genAll($constructor, int $type): array|int|string
if ($constructor['_'] === 'channel') {
return $constructor['megagroup'] ?? false ? 'supergroup' : 'channel';
}
+ if ($constructor['_'] === 'community') {
+ return 'community';
+ }
if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
return 'chat';
}
@@ -550,7 +592,17 @@ private function genAll($constructor, int $type): array|int|string
$res['bot_api_id'] = $constructor['id'];
$res['type'] = $constructor['megagroup'] ?? false ? 'supergroup' : 'channel';
break;
+ case 'community':
+ if (!isset($constructor['access_hash'])) {
+ $this->cacheFullDialogs();
+ throw new PeerNotInDbException();
+ }
+ $res['community_id'] = $constructor['id'];
+ $res['bot_api_id'] = $constructor['id'];
+ $res['type'] = 'community';
+ break;
case 'channelForbidden':
+ case 'communityForbidden':
throw new PeerNotInDbException();
default:
throw new Exception('Invalid constructor given '.$constructor['_']);
@@ -669,9 +721,12 @@ public function getFullInfo(mixed $id): array
$freshReply = $this->methodCallAsyncRead('messages.getFullChat', $partial);
break;
case 'channel':
+ case 'community':
case 'supergroup':
$freshReply = $this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['bot_api_id']]);
break;
+ default:
+ throw new Exception('Invalid peer type '.$partial['type']);
}
$result = array_merge($partial, $this->peerDatabase->getFull($partial['bot_api_id']));
// Shabbat local compatibility patch: never persist this per-call RPC evidence.
@@ -761,6 +816,21 @@ public function getPwrChat(mixed $id, bool $fullfetch = true): array
$res['invite'] = $full['full']['exported_invite']['link'];
}
break;
+ case 'community':
+ foreach (['title', 'creator', 'left', 'admin_rights', 'default_banned_rights'] as $key) {
+ if (isset($full['Chat'][$key])) {
+ $res[$key] = $full['Chat'][$key];
+ }
+ }
+ foreach (['about', 'linked_peers', 'admins_count', 'kicked_count', 'peer_link_requests_pending'] as $key) {
+ if (isset($full['full'][$key])) {
+ $res[$key] = $full['full'][$key];
+ }
+ }
+ if (isset($full['full']['chat_photo'])) {
+ $res['photo'] = $full['full']['chat_photo'];
+ }
+ break;
}
if (isset($res['participants']) && $fullfetch) {
foreach ($res['participants'] as $key => $participant) {
@@ -826,7 +896,7 @@ private function recurseAlphabetSearchParticipants(int $channel, string $filter,
}
++$depth;
$promises = [];
- for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x++) {
+ for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x = str_increment($x)) {
$promises []= async(function () use ($channel, $filter, $q, $x, $total_count, &$res, $depth) {
return $this->recurseAlphabetSearchParticipants($channel, $filter, $q.$x, $total_count, $res, $depth);
});
@@ -924,6 +994,8 @@ private function fetchParticipants(int $channel, string $filter, string $q, int
}
/**
* Key for participatns cache.
+ *
+ * @psalm-pure
*/
private static function participantsKey(int $channelId, string $filter, string $q, int $offset, int $limit): string
{
diff --git a/patches/madelineproto-geopoint/README.md b/patches/madelineproto-geopoint/README.md
deleted file mode 100644
index b09d4ea..0000000
--- a/patches/madelineproto-geopoint/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# MadelineProto GeoPoint double-coordinate correction
-
-This is a **new local patch**, reviewed on 2026-10-13. It is separate from the historical UpdateLoop cancellation patch and is not presented as that original artifact.
-
-The locked package is `danog/madelineproto` 8.7.0 at commit `7b99dd0f2d964a492c377912ffce9f5ce61aa9ed`. The pristine `src/EventHandler/Media/GeoPoint.php` bytes were downloaded from that immutable [upstream commit](https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/EventHandler/Media/GeoPoint.php) and matched the installed source exactly (SHA256 `9ed8054caade6abc96420b0f5b120bec029ee2bc7b7b6aacca56fb7ddc61a27b`).
-
-Telegram's native `geoPoint` constructor declares `long` and `lat` as doubles. The locked SDK GeoPoint wrapper instead declared both readonly properties as integers. Assigning a fractional coordinate such as latitude 31.778 and longitude 35.235 throws a TypeError; InlineQuery constructs this wrapper before either typed or raw event dispatch.
-
-The unified diff changes only those two property types and their matching PHPDoc annotations from `int` to `float`. The constructor, access hash, accuracy radius, JSON serialization and all other source bytes remain unchanged. Integer zero coordinates remain valid because PHP permits integer-to-float assignment. No coordinates are rounded or guessed. The application separately validates finite geographical bounds.
-
-The target upstream file contains no standalone copyright header; its remaining source is retained byte for byte. MadelineProto's package copyright notices and AGPL-3.0-or-later license remain in the corresponding source/dependency notices. `baseline/GeoPoint.php`, `reviewed/GeoPoint.php`, the immutable source reference, unified diff and manifest are included in the source offer for the bot. No entire vendor directory is tracked.
-
-Installation uses the shared exact-source patch manager through `php scripts/apply-patches.php` and `php scripts/verify-patches.php`, including Composer and Docker before bot startup. For `composer install --no-scripts`, run those two commands explicitly while writers are stopped. The installer verifies version/commit and baseline/diff/output hashes, applies only pristine approved bytes, succeeds without mutation when already corrected, and stops on unknown, partial or incompatible source. It never fetches a patch during build. The shared writer lock prevents mutation of an active installation.
-
-Tests reproduce the pristine fractional-coordinate TypeError using the bundled baseline alone, exercise the actual installed corrected constructor with positive, negative, fractional and zero coordinates, and verify precision through JSON serialization/roundtrip. Installer tests cover clean/repeated/verify-only operation, mismatched version/commit, unknown/partial source, artifact tampering and an active writer. These are isolated local tests; no Telegram connection, live inline request or running container was used. No later official version is admitted without a separate source and behavior review.
diff --git a/patches/madelineproto-geopoint/baseline/GeoPoint.php b/patches/madelineproto-geopoint/baseline/GeoPoint.php
deleted file mode 100644
index c2f7482..0000000
--- a/patches/madelineproto-geopoint/baseline/GeoPoint.php
+++ /dev/null
@@ -1,37 +0,0 @@
-long = $rawGeoPoint['long'];
- $this->lat = $rawGeoPoint['lat'];
- $this->accessHash = $rawGeoPoint['access_hash'];
- $this->accuracyRadius = $rawGeoPoint['accuracy_radius'] ?? null;
- }
-
- /** @internal */
- #[\Override]
- public function jsonSerialize(): mixed
- {
- $v = get_object_vars($this);
- $v['_'] = static::class;
- return $v;
- }
-}
diff --git a/patches/madelineproto-geopoint/geopoint-double-coordinates.patch b/patches/madelineproto-geopoint/geopoint-double-coordinates.patch
deleted file mode 100644
index ef13dd0..0000000
--- a/patches/madelineproto-geopoint/geopoint-double-coordinates.patch
+++ /dev/null
@@ -1,12 +0,0 @@
---- a/src/EventHandler/Media/GeoPoint.php
-+++ b/src/EventHandler/Media/GeoPoint.php
-@@ -9,2 +9,2 @@
-- /** @var int Longitude */
-- public readonly int $long;
-+ /** @var float Longitude */
-+ public readonly float $long;
-@@ -12,2 +12,2 @@
-- /** @var int Latitude */
-- public readonly int $lat;
-+ /** @var float Latitude */
-+ public readonly float $lat;
diff --git a/patches/madelineproto-geopoint/manifest.json b/patches/madelineproto-geopoint/manifest.json
deleted file mode 100644
index a8b9600..0000000
--- a/patches/madelineproto-geopoint/manifest.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
- "schema_version": 1,
- "reviewed_at": "2026-10-13",
- "package": "danog/madelineproto",
- "target": "src/EventHandler/Media/GeoPoint.php",
- "provenance": {
- "kind": "new-local-tl-double-type-correction",
- "note": "New reviewed correction for this upgrade, distinct from the historical UpdateLoop cancellation patch. The locked GeoPoint constructor assigns TL double coordinates to integer properties before inline dispatch.",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/EventHandler/Media/GeoPoint.php",
- "source_verified_against_locked_installed_file": true,
- "source_verified_sha256": "9ed8054caade6abc96420b0f5b120bec029ee2bc7b7b6aacca56fb7ddc61a27b"
- },
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/GeoPoint.php",
- "reviewed_output": "reviewed/GeoPoint.php",
- "original_sha256": "9ed8054caade6abc96420b0f5b120bec029ee2bc7b7b6aacca56fb7ddc61a27b",
- "patched_sha256": "5633cc441e541e5e919dfa8156192587a68e578e49a496acac91172be5f2549d",
- "patch": "geopoint-double-coordinates.patch",
- "patch_sha256": "b1b830953dce74978ddc64198a958d0ac13d5205d8929daa58a31e86c0541556"
- }
- ],
- "official_versions": []
-}
diff --git a/patches/madelineproto-geopoint/reviewed/GeoPoint.php b/patches/madelineproto-geopoint/reviewed/GeoPoint.php
deleted file mode 100644
index c3c5adc..0000000
--- a/patches/madelineproto-geopoint/reviewed/GeoPoint.php
+++ /dev/null
@@ -1,37 +0,0 @@
-long = $rawGeoPoint['long'];
- $this->lat = $rawGeoPoint['lat'];
- $this->accessHash = $rawGeoPoint['access_hash'];
- $this->accuracyRadius = $rawGeoPoint['accuracy_radius'] ?? null;
- }
-
- /** @internal */
- #[\Override]
- public function jsonSerialize(): mixed
- {
- $v = get_object_vars($this);
- $v['_'] = static::class;
- return $v;
- }
-}
diff --git a/patches/madelineproto/README.md b/patches/madelineproto/README.md
deleted file mode 100644
index e55c651..0000000
--- a/patches/madelineproto/README.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# UpdateLoop cancellation patch
-
-Reviewed 2026-10-13. Locked MadelineProto **8.7.0** at
-[7b99dd0f2d964a492c377912ffce9f5ce61aa9ed](https://github.com/danog/MadelineProto/tree/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed).
-
-Original local implementation: local-reference/newsearch-v2/docker/patch-madeline-update-loop.php,
-also identical in local-reference/psy new/release-r21-work/docker/patch-madeline-update-loop.php.
-Both SHA256: 1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9.
-The original script is preserved in original-reference.php. It adds the Amp
-CancelledException import and two union catches guarded by getPrevious() instanceof
-TimeoutException. It rethrows other cancellation. Historical source was a script;
-original-reference.patch is a reproduced unified diff, not a historical diff.
-
-On **2026-10-16**, the WizardLoop project maintainer stated that they authored this
-historical UpdateLoop helper and explicitly authorized its distribution under
-**AGPL-3.0-only**. The attestation applies to the exact script hash above and is
-recorded in the manifest. The original headerless script bytes remain unchanged;
-the statement does not relicense upstream MadelineProto source or certify
-independent authorship/legal review. See [licensing](../../docs/LICENSING.md).
-
-The applied update-loop-timeout-cancellation.patch is a **new reviewed derivative**.
-Both difference branches retain those guards, check isRunning()/authorization,
-and return the existing 10-second interval on a transient timeout. This lets the
-parent loop honor stop() and prevents immediate retry/report loops. A stopped
-loop returns STOP; unrelated cancellation while running is rethrown.
-
-The reviewed locked version is 8.7.0; the recorded GitHub release is a prerelease. MTProtoTools/CallHandler delegates to
-MTProtoSession/CallHandler, which creates TimeoutCancellation and awaits the send
-future using it. Amp emits CancelledException with TimeoutException as previous.
-No conversion exists there; upstream UpdateLoop still has two TimeoutException-only
-catches. danog/loop 1.1.1 stop() marks running=false, completing after loop() returns.
-No official fixed release is currently approved in the manifest.
-
-The manifest pins exact version, commit, baseline/output/patch SHA256. Installation
-applies exact unified-diff context, then verifies output SHA256 and syntax.
-Unknown files, partial patches and unknown commits fail. No dynamic patch downloads,
-no broad source regex replacements, no silent skipping. Already patched succeeds
-without a write. A future approved mode=official entry checks its exact sha256 and
-applies no patch; no such version is listed today.
-
-Composer invokes apply then verify. For --no-scripts:
-
- composer install --no-scripts
- php scripts/apply-patches.php
- php scripts/verify-patches.php
- php bin/self-check.php
-
-Never patch an active process/container. Runner only verifies. Build a new image.
-Tests exercise first/repeated application, unknown version/file, partial patch,
-direct timeout, timeout-derived cancellation, deliberate cancellation, shutdown,
-and recovery in both actual loop branches using a fake Telegram transport.
-They do not contact Telegram. See [operational details](../../docs/PATCHES.md).
-
-All baseline copyright/license notices are unmodified. Upstream metadata says
-AGPL-3.0-only; source headers permit version 3 or later. Preserve and report this
-discrepancy. Baseline, original script, diffs and manifest ship in source archives.
-
-Regenerate against the fixed baseline with php patches/madelineproto/generate-artifacts.php.
-Regeneration does not approve an upgrade; review source and rerun behavioral tests.
-Historical local-reference paths are logical project/file identifiers, not public download URLs or installation requirements.
diff --git a/patches/madelineproto/baseline/UpdateLoop.php b/patches/madelineproto/baseline/UpdateLoop.php
deleted file mode 100644
index bc54fca..0000000
--- a/patches/madelineproto/baseline/UpdateLoop.php
+++ /dev/null
@@ -1,263 +0,0 @@
-.
- *
- * @author Daniil Gentili
- * @copyright 2016-2025 Daniil Gentili
- * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
- * @link https://docs.madelineproto.xyz MadelineProto documentation
- */
-
-namespace danog\MadelineProto\Loop\Update;
-
-use Amp\TimeoutException;
-use danog\Loop\Loop;
-use danog\MadelineProto\API;
-use danog\MadelineProto\Exception;
-use danog\MadelineProto\Logger;
-use danog\MadelineProto\Loop\InternalLoop;
-use danog\MadelineProto\MTProto;
-use danog\MadelineProto\MTProto\LoginState;
-use danog\MadelineProto\MTProto\SpecialMethodType;
-use danog\MadelineProto\PeerNotInDbException;
-use danog\MadelineProto\PTSException;
-use danog\MadelineProto\Reactive\SimpleSubscriber;
-use danog\MadelineProto\RPCError\ChannelInvalidError;
-use danog\MadelineProto\RPCError\ChannelPrivateError;
-use danog\MadelineProto\RPCError\ChatForbiddenError;
-use danog\MadelineProto\RPCError\TimeoutError;
-use danog\MadelineProto\RPCError\UserBannedInChannelError;
-
-use Revolt\EventLoop;
-use function Amp\delay;
-
-/**
- * Update loop.
- *
- * @internal
- *
- * @author Daniil Gentili
- *
- * @implements SimpleSubscriber
- */
-final class UpdateLoop extends Loop implements SimpleSubscriber
-{
- use InternalLoop {
- __construct as private init;
- }
- /**
- * Main loop ID.
- */
- public const GENERIC = 0;
-
- private const DEFAULT_TIMEOUT = 10.0;
-
- /**
- * Feed loop.
- */
- private ?FeedLoop $feeder = null;
- private ?int $authorizedDc = null;
- /**
- * Constructor.
- */
- public function __construct(MTProto $API, private int $channelId)
- {
- $this->init($API);
- $API->loginState->subscribe($this);
- }
- public function __sleep(): array
- {
- return ['channelId', 'API', 'feeder', 'authorizedDc'];
- }
- #[\Override]
- public function onSimpleStateChange($state): void
- {
- if ($state->state !== API::LOGGED_IN) {
- $this->authorizedDc = null;
- return;
- }
- if (null !== $this->authorizedDc = $state->authorizedDc) {
- if ($this->isRunning()) {
- $this->resume(true);
- } else {
- $this->start();
- }
- }
- }
-
- /**
- * Main loop.
- */
- #[\Override]
- public function loop(): ?float
- {
- if ($this->authorizedDc === null) {
- return self::PAUSE;
- }
- $this->API->feeders[$this->channelId] ??= new FeedLoop($this->API, $this->channelId);
- $this->API->updaters[$this->channelId] ??= new UpdateLoop($this->API, $this->channelId);
-
- $this->feeder = $this->API->feeders[$this->channelId];
- $state = $this->channelId === self::GENERIC ? $this->API->loadUpdateState() : $this->API->loadChannelState($this->channelId);
-
- $result = [];
- while (true) {
- if ($this->channelId) {
- $this->API->logger('Resumed and fetching '.$this->channelId.' difference...', Logger::ULTRA_VERBOSE);
- if ($state->pts() <= 1) {
- $limit = 10;
- } elseif ($this->API->authorization['user']['bot']) {
- $limit = 100000;
- } else {
- $limit = 100;
- }
- $request_pts = $state->pts();
- try {
- $difference = $this->API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true, 'floodWaitLimit' => 86400]);
- } catch (ChannelPrivateError|ChatForbiddenError|ChannelInvalidError|UserBannedInChannelError) {
- $this->feeder->stop();
- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
- $this->API->getChannelStates()->remove($this->channelId);
- $this->API->logger("Channel private, exiting {$this}");
- return self::STOP;
- } catch (TimeoutError $e) {
- delay(1.0);
- continue;
- } catch (PeerNotInDbException) {
- $this->feeder->stop();
- $this->API->getChannelStates()->remove($this->channelId);
- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
- $this->API->logger("Channel private, exiting {$this}");
- return self::STOP;
- } catch (PTSException $e) {
- $this->feeder->stop();
- $this->API->getChannelStates()->remove($this->channelId);
- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
- $this->API->logger("Got PTS exception, exiting update loop for $this: $e", Logger::FATAL_ERROR);
- return self::STOP;
- } catch (TimeoutException) {
- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
- continue;
- }
- $timeout = min(self::DEFAULT_TIMEOUT, $difference['timeout'] ?? self::DEFAULT_TIMEOUT);
- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
- switch ($difference['_']) {
- case 'updates.channelDifferenceEmpty':
- $state->update($difference);
- unset($difference);
- break 2;
- case 'updates.channelDifference':
- if ($request_pts >= $difference['pts'] && $request_pts > 1) {
- $this->API->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), Logger::VERBOSE);
- $difference['pts'] = $request_pts + 1;
- }
- $result += ($this->feeder->feed($difference['other_updates']));
- $state->update($difference);
- if ($difference['new_messages']) {
- $result[$this->channelId] = true;
- }
- $this->feeder->saveMessages($difference['new_messages']);
- if (!$difference['final']) {
- unset($difference);
- break;
- }
- unset($difference);
- break 2;
- case 'updates.channelDifferenceTooLong':
- if (isset($difference['dialog']['pts'])) {
- $difference['pts'] = $difference['dialog']['pts'];
- }
- $state->update($difference);
- if ($difference['messages']) {
- $result[$this->channelId] = true;
- }
- $this->feeder->saveMessages($difference['messages']);
- unset($difference);
- break;
- default:
- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
- }
- } else {
- $this->API->logger('Resumed and fetching normal difference...', Logger::ULTRA_VERBOSE);
- do {
- try {
- $difference = $this->API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts(), 'specialMethodType' => SpecialMethodType::USER_RELATED], $this->authorizedDc);
- break;
- } catch (TimeoutError) {
- delay(1.0);
- } catch (TimeoutException) {
- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
- }
- } while (true);
- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
- $timeout = self::DEFAULT_TIMEOUT;
- switch ($difference['_']) {
- case 'updates.differenceEmpty':
- $state->update($difference);
- unset($difference);
- break 2;
- case 'updates.difference':
- $state->qts($difference['state']['qts']);
- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
- }
- $result += ($this->feeder->feed($difference['other_updates']));
- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
- $state->update($difference['state']);
- if ($difference['new_messages']) {
- $result[$this->channelId] = true;
- }
- $this->feeder->saveMessages($difference['new_messages']);
- unset($difference);
- break 2;
- case 'updates.differenceSlice':
- $state->qts($difference['intermediate_state']['qts']);
- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
- }
- $result += ($this->feeder->feed($difference['other_updates']));
- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
- $state->update($difference['intermediate_state']);
- if ($difference['new_messages']) {
- $result[$this->channelId] = true;
- }
- $this->feeder->saveMessages($difference['new_messages']);
- unset($difference);
- break;
- case 'updates.differenceTooLong':
- $state->update($difference);
- unset($difference);
- break;
- default:
- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
- }
- }
- }
- $this->API->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
- foreach ($result as $channelId => $_) {
- $this->API->feeders[$channelId]?->resume();
- }
- $this->API->logger("Finished parsing updates in {$this}, pausing for $timeout seconds", Logger::ULTRA_VERBOSE);
-
- return $timeout;
- }
- /**
- * Get loop name.
- */
- public function __toString(): string
- {
- return $this->channelId ?
- "getUpdate loop channel {$this->channelId}" :
- 'getUpdate loop generic';
- }
-}
diff --git a/patches/madelineproto/generate-artifacts.php b/patches/madelineproto/generate-artifacts.php
deleted file mode 100644
index a4201c0..0000000
--- a/patches/madelineproto/generate-artifacts.php
+++ /dev/null
@@ -1,69 +0,0 @@
-getPrevious() instanceof TimeoutException)) {';
-foreach ([20, 24] as $indent) {
- $space = str_repeat(' ', $indent);
- $patched = str_replace("\n" . $space . $guard, "\n" . $space . 'if (!$this->isRunning() || $this->authorizedDc === null) {' . "\n" . $space . ' return self::STOP;' . "\n" . $space . '}' . "\n" . $space . $guard, $patched, $count);
- if ($count !== 1) {
- throw new RuntimeException('Unexpected reference patch layout.');
- }
-}
-$report = 'EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");';
-$patched = str_replace(' ' . $report . "\n" . ' continue;', ' ' . $report . "\n" . ' return self::DEFAULT_TIMEOUT;', $patched, $count);
-if ($count !== 1) {
- throw new RuntimeException('Unexpected channel recovery layout.');
-}
-$patched = str_replace(' ' . $report . "\n", ' ' . $report . "\n" . ' return self::DEFAULT_TIMEOUT;' . "\n", $patched, $count);
-if ($count !== 1) {
- throw new RuntimeException('Unexpected generic recovery layout.');
-}
-$diff = static function (string $before, string $after): string {
- $old = explode("\n", rtrim($before, "\n"));
- $new = explode("\n", rtrim($after, "\n"));
- return "--- a/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php\n+++ b/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php\n"
- . '@@ -1,' . count($old) . ' +1,' . count($new) . " @@\n"
- . implode("\n", array_map(static fn (string $line): string => '-' . $line, $old)) . "\n"
- . implode("\n", array_map(static fn (string $line): string => '+' . $line, $new)) . "\n";
-};
-file_put_contents(__DIR__ . '/original-reference.patch', $diff($source, $reference));
-$patch = $diff($source, $patched);
-file_put_contents(__DIR__ . '/update-loop-timeout-cancellation.patch', $patch);
-$manifest = ['schema_version' => 1, 'reviewed_at' => '2026-10-13', 'package' => 'danog/madelineproto', 'target' => 'src/Loop/Update/UpdateLoop.php',
- 'original_reference' => ['path' => 'local-reference/newsearch-v2/docker/patch-madeline-update-loop.php', 'also_found' => 'local-reference/psy new/release-r21-work/docker/patch-madeline-update-loop.php', 'sha256' => hash_file('sha256', __DIR__ . '/original-reference.php'), 'note' => 'Historical artifact was a guarded PHP patch script; reference unified diff is reproduced from that script. Paths are logical local-reference identifiers, not public download URLs.'],
- 'approved' => [['version' => '8.7.0', 'commit' => '7b99dd0f2d964a492c377912ffce9f5ce61aa9ed', 'mode' => 'patch', 'baseline' => 'baseline/UpdateLoop.php',
- 'source_url' => 'https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/Loop/Update/UpdateLoop.php',
- 'original_sha256' => hash('sha256', $source), 'patched_sha256' => hash('sha256', $patched), 'patch' => 'update-loop-timeout-cancellation.patch', 'patch_sha256' => hash('sha256', $patch)]],
- 'official_versions' => [], 'notes' => 'No released official solution was verified. New versions require source, call-chain and behavioral review before admission.'];
-$manifest['original_reference']['maintainer_attestation'] = array (
- 'date' => '2026-10-16',
- 'by' => 'WizardLoop project maintainer',
- 'scope' => 'patches/madelineproto/original-reference.php',
- 'sha256' => '1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9',
- 'authorship' => 'The maintainer states that they authored this historical UpdateLoop helper.',
- 'distribution_authorization' => 'The maintainer explicitly authorizes distribution of this helper under the project license AGPL-3.0-only.',
- 'license' => 'AGPL-3.0-only',
- 'evidence' => 'Explicit maintainer instruction during preparation of the 3.0.0 release.',
- 'limits' => 'Records the maintainer attestation; not an independent authorship or legal certification. Original helper bytes and upstream dependency notices remain unchanged.',
-);
-file_put_contents(__DIR__ . '/manifest.json', json_encode($manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR) . "\n");
-echo "Reviewed patch artifacts regenerated.\n";
\ No newline at end of file
diff --git a/patches/madelineproto/manifest.json b/patches/madelineproto/manifest.json
deleted file mode 100644
index be4b1dd..0000000
--- a/patches/madelineproto/manifest.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "schema_version": 1,
- "reviewed_at": "2026-10-13",
- "package": "danog/madelineproto",
- "target": "src/Loop/Update/UpdateLoop.php",
- "original_reference": {
- "path": "local-reference/newsearch-v2/docker/patch-madeline-update-loop.php",
- "also_found": "local-reference/psy new/release-r21-work/docker/patch-madeline-update-loop.php",
- "sha256": "1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9",
- "note": "Historical artifact was a guarded PHP patch script; reference unified diff is reproduced from that script. Paths are logical local-reference identifiers, not public download URLs.",
- "maintainer_attestation": {
- "date": "2026-10-16",
- "by": "WizardLoop project maintainer",
- "scope": "patches/madelineproto/original-reference.php",
- "sha256": "1ec2691498e878d28ca8e9cde94b00c803d9ccba789096ffc8471156dfb429e9",
- "authorship": "The maintainer states that they authored this historical UpdateLoop helper.",
- "distribution_authorization": "The maintainer explicitly authorizes distribution of this helper under the project license AGPL-3.0-only.",
- "license": "AGPL-3.0-only",
- "evidence": "Explicit maintainer instruction during preparation of the 3.0.0 release.",
- "limits": "Records the maintainer attestation; not an independent authorship or legal certification. Original helper bytes and upstream dependency notices remain unchanged."
- }
- },
- "approved": [
- {
- "version": "8.7.0",
- "commit": "7b99dd0f2d964a492c377912ffce9f5ce61aa9ed",
- "mode": "patch",
- "baseline": "baseline/UpdateLoop.php",
- "source_url": "https://github.com/danog/MadelineProto/blob/7b99dd0f2d964a492c377912ffce9f5ce61aa9ed/src/Loop/Update/UpdateLoop.php",
- "original_sha256": "2fbcbb73822258102837f53f4a231b87526d66809be7acd6339156ea778a8c2f",
- "patched_sha256": "8f6cb1a483c879024bddea289e90d4bf2d71dd15716102bc83a1f34a243782e4",
- "patch": "update-loop-timeout-cancellation.patch",
- "patch_sha256": "2f5c34d5e2749d3575ef9de1ec80bff60a9ced1240ca61ef8727583ee939f592"
- }
- ],
- "official_versions": [],
- "notes": "No released official solution was verified. New versions require source, call-chain and behavioral review before admission."
-}
diff --git a/patches/madelineproto/original-reference.patch b/patches/madelineproto/original-reference.patch
deleted file mode 100644
index 03fa67b..0000000
--- a/patches/madelineproto/original-reference.patch
+++ /dev/null
@@ -1,536 +0,0 @@
---- a/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php
-+++ b/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php
-@@ -1,263 +1,270 @@
--.
-- *
-- * @author Daniil Gentili
-- * @copyright 2016-2025 Daniil Gentili
-- * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
-- * @link https://docs.madelineproto.xyz MadelineProto documentation
-- */
--
--namespace danog\MadelineProto\Loop\Update;
--
--use Amp\TimeoutException;
--use danog\Loop\Loop;
--use danog\MadelineProto\API;
--use danog\MadelineProto\Exception;
--use danog\MadelineProto\Logger;
--use danog\MadelineProto\Loop\InternalLoop;
--use danog\MadelineProto\MTProto;
--use danog\MadelineProto\MTProto\LoginState;
--use danog\MadelineProto\MTProto\SpecialMethodType;
--use danog\MadelineProto\PeerNotInDbException;
--use danog\MadelineProto\PTSException;
--use danog\MadelineProto\Reactive\SimpleSubscriber;
--use danog\MadelineProto\RPCError\ChannelInvalidError;
--use danog\MadelineProto\RPCError\ChannelPrivateError;
--use danog\MadelineProto\RPCError\ChatForbiddenError;
--use danog\MadelineProto\RPCError\TimeoutError;
--use danog\MadelineProto\RPCError\UserBannedInChannelError;
--
--use Revolt\EventLoop;
--use function Amp\delay;
--
--/**
-- * Update loop.
-- *
-- * @internal
-- *
-- * @author Daniil Gentili
-- *
-- * @implements SimpleSubscriber
-- */
--final class UpdateLoop extends Loop implements SimpleSubscriber
--{
-- use InternalLoop {
-- __construct as private init;
-- }
-- /**
-- * Main loop ID.
-- */
-- public const GENERIC = 0;
--
-- private const DEFAULT_TIMEOUT = 10.0;
--
-- /**
-- * Feed loop.
-- */
-- private ?FeedLoop $feeder = null;
-- private ?int $authorizedDc = null;
-- /**
-- * Constructor.
-- */
-- public function __construct(MTProto $API, private int $channelId)
-- {
-- $this->init($API);
-- $API->loginState->subscribe($this);
-- }
-- public function __sleep(): array
-- {
-- return ['channelId', 'API', 'feeder', 'authorizedDc'];
-- }
-- #[\Override]
-- public function onSimpleStateChange($state): void
-- {
-- if ($state->state !== API::LOGGED_IN) {
-- $this->authorizedDc = null;
-- return;
-- }
-- if (null !== $this->authorizedDc = $state->authorizedDc) {
-- if ($this->isRunning()) {
-- $this->resume(true);
-- } else {
-- $this->start();
-- }
-- }
-- }
--
-- /**
-- * Main loop.
-- */
-- #[\Override]
-- public function loop(): ?float
-- {
-- if ($this->authorizedDc === null) {
-- return self::PAUSE;
-- }
-- $this->API->feeders[$this->channelId] ??= new FeedLoop($this->API, $this->channelId);
-- $this->API->updaters[$this->channelId] ??= new UpdateLoop($this->API, $this->channelId);
--
-- $this->feeder = $this->API->feeders[$this->channelId];
-- $state = $this->channelId === self::GENERIC ? $this->API->loadUpdateState() : $this->API->loadChannelState($this->channelId);
--
-- $result = [];
-- while (true) {
-- if ($this->channelId) {
-- $this->API->logger('Resumed and fetching '.$this->channelId.' difference...', Logger::ULTRA_VERBOSE);
-- if ($state->pts() <= 1) {
-- $limit = 10;
-- } elseif ($this->API->authorization['user']['bot']) {
-- $limit = 100000;
-- } else {
-- $limit = 100;
-- }
-- $request_pts = $state->pts();
-- try {
-- $difference = $this->API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true, 'floodWaitLimit' => 86400]);
-- } catch (ChannelPrivateError|ChatForbiddenError|ChannelInvalidError|UserBannedInChannelError) {
-- $this->feeder->stop();
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->getChannelStates()->remove($this->channelId);
-- $this->API->logger("Channel private, exiting {$this}");
-- return self::STOP;
-- } catch (TimeoutError $e) {
-- delay(1.0);
-- continue;
-- } catch (PeerNotInDbException) {
-- $this->feeder->stop();
-- $this->API->getChannelStates()->remove($this->channelId);
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->logger("Channel private, exiting {$this}");
-- return self::STOP;
-- } catch (PTSException $e) {
-- $this->feeder->stop();
-- $this->API->getChannelStates()->remove($this->channelId);
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->logger("Got PTS exception, exiting update loop for $this: $e", Logger::FATAL_ERROR);
-- return self::STOP;
-- } catch (TimeoutException) {
-- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-- continue;
-- }
-- $timeout = min(self::DEFAULT_TIMEOUT, $difference['timeout'] ?? self::DEFAULT_TIMEOUT);
-- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-- switch ($difference['_']) {
-- case 'updates.channelDifferenceEmpty':
-- $state->update($difference);
-- unset($difference);
-- break 2;
-- case 'updates.channelDifference':
-- if ($request_pts >= $difference['pts'] && $request_pts > 1) {
-- $this->API->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), Logger::VERBOSE);
-- $difference['pts'] = $request_pts + 1;
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $state->update($difference);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- if (!$difference['final']) {
-- unset($difference);
-- break;
-- }
-- unset($difference);
-- break 2;
-- case 'updates.channelDifferenceTooLong':
-- if (isset($difference['dialog']['pts'])) {
-- $difference['pts'] = $difference['dialog']['pts'];
-- }
-- $state->update($difference);
-- if ($difference['messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['messages']);
-- unset($difference);
-- break;
-- default:
-- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-- }
-- } else {
-- $this->API->logger('Resumed and fetching normal difference...', Logger::ULTRA_VERBOSE);
-- do {
-- try {
-- $difference = $this->API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts(), 'specialMethodType' => SpecialMethodType::USER_RELATED], $this->authorizedDc);
-- break;
-- } catch (TimeoutError) {
-- delay(1.0);
-- } catch (TimeoutException) {
-- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-- }
-- } while (true);
-- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-- $timeout = self::DEFAULT_TIMEOUT;
-- switch ($difference['_']) {
-- case 'updates.differenceEmpty':
-- $state->update($difference);
-- unset($difference);
-- break 2;
-- case 'updates.difference':
-- $state->qts($difference['state']['qts']);
-- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-- $state->update($difference['state']);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- unset($difference);
-- break 2;
-- case 'updates.differenceSlice':
-- $state->qts($difference['intermediate_state']['qts']);
-- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-- $state->update($difference['intermediate_state']);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- unset($difference);
-- break;
-- case 'updates.differenceTooLong':
-- $state->update($difference);
-- unset($difference);
-- break;
-- default:
-- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-- }
-- }
-- }
-- $this->API->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
-- foreach ($result as $channelId => $_) {
-- $this->API->feeders[$channelId]?->resume();
-- }
-- $this->API->logger("Finished parsing updates in {$this}, pausing for $timeout seconds", Logger::ULTRA_VERBOSE);
--
-- return $timeout;
-- }
-- /**
-- * Get loop name.
-- */
-- public function __toString(): string
-- {
-- return $this->channelId ?
-- "getUpdate loop channel {$this->channelId}" :
-- 'getUpdate loop generic';
-- }
--}
-+.
-+ *
-+ * @author Daniil Gentili
-+ * @copyright 2016-2025 Daniil Gentili
-+ * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
-+ * @link https://docs.madelineproto.xyz MadelineProto documentation
-+ */
-+
-+namespace danog\MadelineProto\Loop\Update;
-+
-+use Amp\CancelledException;
-+use Amp\TimeoutException;
-+use danog\Loop\Loop;
-+use danog\MadelineProto\API;
-+use danog\MadelineProto\Exception;
-+use danog\MadelineProto\Logger;
-+use danog\MadelineProto\Loop\InternalLoop;
-+use danog\MadelineProto\MTProto;
-+use danog\MadelineProto\MTProto\LoginState;
-+use danog\MadelineProto\MTProto\SpecialMethodType;
-+use danog\MadelineProto\PeerNotInDbException;
-+use danog\MadelineProto\PTSException;
-+use danog\MadelineProto\Reactive\SimpleSubscriber;
-+use danog\MadelineProto\RPCError\ChannelInvalidError;
-+use danog\MadelineProto\RPCError\ChannelPrivateError;
-+use danog\MadelineProto\RPCError\ChatForbiddenError;
-+use danog\MadelineProto\RPCError\TimeoutError;
-+use danog\MadelineProto\RPCError\UserBannedInChannelError;
-+
-+use Revolt\EventLoop;
-+use function Amp\delay;
-+
-+/**
-+ * Update loop.
-+ *
-+ * @internal
-+ *
-+ * @author Daniil Gentili
-+ *
-+ * @implements SimpleSubscriber
-+ */
-+final class UpdateLoop extends Loop implements SimpleSubscriber
-+{
-+ use InternalLoop {
-+ __construct as private init;
-+ }
-+ /**
-+ * Main loop ID.
-+ */
-+ public const GENERIC = 0;
-+
-+ private const DEFAULT_TIMEOUT = 10.0;
-+
-+ /**
-+ * Feed loop.
-+ */
-+ private ?FeedLoop $feeder = null;
-+ private ?int $authorizedDc = null;
-+ /**
-+ * Constructor.
-+ */
-+ public function __construct(MTProto $API, private int $channelId)
-+ {
-+ $this->init($API);
-+ $API->loginState->subscribe($this);
-+ }
-+ public function __sleep(): array
-+ {
-+ return ['channelId', 'API', 'feeder', 'authorizedDc'];
-+ }
-+ #[\Override]
-+ public function onSimpleStateChange($state): void
-+ {
-+ if ($state->state !== API::LOGGED_IN) {
-+ $this->authorizedDc = null;
-+ return;
-+ }
-+ if (null !== $this->authorizedDc = $state->authorizedDc) {
-+ if ($this->isRunning()) {
-+ $this->resume(true);
-+ } else {
-+ $this->start();
-+ }
-+ }
-+ }
-+
-+ /**
-+ * Main loop.
-+ */
-+ #[\Override]
-+ public function loop(): ?float
-+ {
-+ if ($this->authorizedDc === null) {
-+ return self::PAUSE;
-+ }
-+ $this->API->feeders[$this->channelId] ??= new FeedLoop($this->API, $this->channelId);
-+ $this->API->updaters[$this->channelId] ??= new UpdateLoop($this->API, $this->channelId);
-+
-+ $this->feeder = $this->API->feeders[$this->channelId];
-+ $state = $this->channelId === self::GENERIC ? $this->API->loadUpdateState() : $this->API->loadChannelState($this->channelId);
-+
-+ $result = [];
-+ while (true) {
-+ if ($this->channelId) {
-+ $this->API->logger('Resumed and fetching '.$this->channelId.' difference...', Logger::ULTRA_VERBOSE);
-+ if ($state->pts() <= 1) {
-+ $limit = 10;
-+ } elseif ($this->API->authorization['user']['bot']) {
-+ $limit = 100000;
-+ } else {
-+ $limit = 100;
-+ }
-+ $request_pts = $state->pts();
-+ try {
-+ $difference = $this->API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true, 'floodWaitLimit' => 86400]);
-+ } catch (ChannelPrivateError|ChatForbiddenError|ChannelInvalidError|UserBannedInChannelError) {
-+ $this->feeder->stop();
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ $this->API->logger("Channel private, exiting {$this}");
-+ return self::STOP;
-+ } catch (TimeoutError $e) {
-+ delay(1.0);
-+ continue;
-+ } catch (PeerNotInDbException) {
-+ $this->feeder->stop();
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->logger("Channel private, exiting {$this}");
-+ return self::STOP;
-+ } catch (PTSException $e) {
-+ $this->feeder->stop();
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->logger("Got PTS exception, exiting update loop for $this: $e", Logger::FATAL_ERROR);
-+ return self::STOP;
-+ } catch (TimeoutException|CancelledException $e) {
-+ if ($e instanceof CancelledException && !($e->getPrevious() instanceof TimeoutException)) {
-+ throw $e;
-+ }
-+ EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-+ continue;
-+ }
-+ $timeout = min(self::DEFAULT_TIMEOUT, $difference['timeout'] ?? self::DEFAULT_TIMEOUT);
-+ $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-+ switch ($difference['_']) {
-+ case 'updates.channelDifferenceEmpty':
-+ $state->update($difference);
-+ unset($difference);
-+ break 2;
-+ case 'updates.channelDifference':
-+ if ($request_pts >= $difference['pts'] && $request_pts > 1) {
-+ $this->API->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), Logger::VERBOSE);
-+ $difference['pts'] = $request_pts + 1;
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $state->update($difference);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ if (!$difference['final']) {
-+ unset($difference);
-+ break;
-+ }
-+ unset($difference);
-+ break 2;
-+ case 'updates.channelDifferenceTooLong':
-+ if (isset($difference['dialog']['pts'])) {
-+ $difference['pts'] = $difference['dialog']['pts'];
-+ }
-+ $state->update($difference);
-+ if ($difference['messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['messages']);
-+ unset($difference);
-+ break;
-+ default:
-+ throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-+ }
-+ } else {
-+ $this->API->logger('Resumed and fetching normal difference...', Logger::ULTRA_VERBOSE);
-+ do {
-+ try {
-+ $difference = $this->API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts(), 'specialMethodType' => SpecialMethodType::USER_RELATED], $this->authorizedDc);
-+ break;
-+ } catch (TimeoutError) {
-+ delay(1.0);
-+ } catch (TimeoutException|CancelledException $e) {
-+ if ($e instanceof CancelledException && !($e->getPrevious() instanceof TimeoutException)) {
-+ throw $e;
-+ }
-+ EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-+ }
-+ } while (true);
-+ $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-+ $timeout = self::DEFAULT_TIMEOUT;
-+ switch ($difference['_']) {
-+ case 'updates.differenceEmpty':
-+ $state->update($difference);
-+ unset($difference);
-+ break 2;
-+ case 'updates.difference':
-+ $state->qts($difference['state']['qts']);
-+ foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-+ $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-+ $state->update($difference['state']);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ unset($difference);
-+ break 2;
-+ case 'updates.differenceSlice':
-+ $state->qts($difference['intermediate_state']['qts']);
-+ foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-+ $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-+ $state->update($difference['intermediate_state']);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ unset($difference);
-+ break;
-+ case 'updates.differenceTooLong':
-+ $state->update($difference);
-+ unset($difference);
-+ break;
-+ default:
-+ throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-+ }
-+ }
-+ }
-+ $this->API->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
-+ foreach ($result as $channelId => $_) {
-+ $this->API->feeders[$channelId]?->resume();
-+ }
-+ $this->API->logger("Finished parsing updates in {$this}, pausing for $timeout seconds", Logger::ULTRA_VERBOSE);
-+
-+ return $timeout;
-+ }
-+ /**
-+ * Get loop name.
-+ */
-+ public function __toString(): string
-+ {
-+ return $this->channelId ?
-+ "getUpdate loop channel {$this->channelId}" :
-+ 'getUpdate loop generic';
-+ }
-+}
diff --git a/patches/madelineproto/original-reference.php b/patches/madelineproto/original-reference.php
deleted file mode 100644
index e484f93..0000000
--- a/patches/madelineproto/original-reference.php
+++ /dev/null
@@ -1,148 +0,0 @@
-getPrevious() instanceof TimeoutException)) {';
- $report = 'EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");';
-
- $originalChannel = implode($newline, [
- ' } catch (TimeoutException) {',
- ' ' . $report,
- ' continue;',
- ' }',
- ]);
- $patchedChannel = implode($newline, [
- ' } catch (TimeoutException|CancelledException $e) {',
- ' ' . $guard,
- ' throw $e;',
- ' }',
- ' ' . $report,
- ' continue;',
- ' }',
- ]);
- $originalGeneric = implode($newline, [
- ' } catch (TimeoutException) {',
- ' ' . $report,
- ' }',
- ]);
- $patchedGeneric = implode($newline, [
- ' } catch (TimeoutException|CancelledException $e) {',
- ' ' . $guard,
- ' throw $e;',
- ' }',
- ' ' . $report,
- ' }',
- ]);
-
- $commonLayoutIsExpected = substr_count($source, $timeoutImport) === 1
- && substr_count($source, "methodCallAsyncRead('updates.getChannelDifference'") === 1
- && substr_count($source, "methodCallAsyncRead('updates.getDifference'") === 1
- && substr_count($source, $report) === 2;
- if (!$commonLayoutIsExpected) {
- throw new RuntimeException('Unsupported MadelineProto UpdateLoop layout; expected imports, difference calls, or timeout reports changed.');
- }
-
- $isFullyPatched = substr_count($source, $cancelledImport) === 1
- && substr_count($source, $plainCatch) === 0
- && substr_count($source, $unionCatch) === 2
- && substr_count($source, $guard) === 2
- && substr_count($source, $patchedChannel) === 1
- && substr_count($source, $patchedGeneric) === 1;
- if ($isFullyPatched) {
- return 'already-patched';
- }
-
- $isExactOriginal = substr_count($source, $cancelledImport) === 0
- && substr_count($source, $plainCatch) === 2
- && substr_count($source, $unionCatch) === 0
- && substr_count($source, $guard) === 0
- && substr_count($source, $originalChannel) === 1
- && substr_count($source, $originalGeneric) === 1;
- if (!$isExactOriginal) {
- throw new RuntimeException('MadelineProto UpdateLoop is partially patched or has an unsupported upstream layout; refusing an ambiguous patch.');
- }
-
- $patched = str_replace(
- $timeoutImport,
- $cancelledImport . $newline . $timeoutImport,
- $source,
- $importReplacements,
- );
- $patched = str_replace($originalChannel, $patchedChannel, $patched, $channelReplacements);
- $patched = str_replace($originalGeneric, $patchedGeneric, $patched, $genericReplacements);
- if ($importReplacements !== 1 || $channelReplacements !== 1 || $genericReplacements !== 1) {
- throw new RuntimeException('MadelineProto UpdateLoop compatibility patch did not replace every guarded anchor exactly once.');
- }
-
- if (substr_count($patched, $cancelledImport) !== 1
- || substr_count($patched, $plainCatch) !== 0
- || substr_count($patched, $unionCatch) !== 2
- || substr_count($patched, $guard) !== 2
- || substr_count($patched, $patchedChannel) !== 1
- || substr_count($patched, $patchedGeneric) !== 1
- ) {
- throw new RuntimeException('MadelineProto UpdateLoop compatibility patch failed its postconditions.');
- }
-
- try {
- token_get_all($patched, TOKEN_PARSE);
- } catch (ParseError $error) {
- throw new RuntimeException('Patched MadelineProto UpdateLoop is not valid PHP: ' . $error->getMessage(), 0, $error);
- }
-
- newSearchWriteUpdateLoopCompatibilityFile($updateLoopFile, $patched);
- return 'patched';
-}
-
-function newSearchWriteUpdateLoopCompatibilityFile(string $path, string $contents): void
-{
- $temporary = $path . '.newsearch-' . bin2hex(random_bytes(6)) . '.tmp';
- try {
- $bytes = file_put_contents($temporary, $contents, LOCK_EX);
- if ($bytes !== strlen($contents)) {
- throw new RuntimeException('Unable to write complete UpdateLoop compatibility file: ' . $path);
- }
- if (!rename($temporary, $path)) {
- throw new RuntimeException('Unable to atomically install UpdateLoop compatibility file: ' . $path);
- }
- } finally {
- if (is_file($temporary)) {
- @unlink($temporary);
- }
- }
-}
-
-if (isset($_SERVER['SCRIPT_FILENAME']) && realpath((string) $_SERVER['SCRIPT_FILENAME']) === __FILE__) {
- try {
- $vendorRoot = $argv[1] ?? dirname(__DIR__) . '/vendor';
- $result = newSearchPatchMadelineUpdateLoop($vendorRoot);
- fwrite(STDOUT, "MadelineProto UpdateLoop timeout compatibility: {$result}\n");
- } catch (Throwable $error) {
- fwrite(STDERR, 'ERROR: MadelineProto UpdateLoop timeout compatibility patch failed: ' . $error->getMessage() . "\n");
- exit(1);
- }
-}
diff --git a/patches/madelineproto/update-loop-timeout-cancellation.patch b/patches/madelineproto/update-loop-timeout-cancellation.patch
deleted file mode 100644
index 5a7928d..0000000
--- a/patches/madelineproto/update-loop-timeout-cancellation.patch
+++ /dev/null
@@ -1,543 +0,0 @@
---- a/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php
-+++ b/vendor/danog/madelineproto/src/Loop/Update/UpdateLoop.php
-@@ -1,263 +1,277 @@
--.
-- *
-- * @author Daniil Gentili
-- * @copyright 2016-2025 Daniil Gentili
-- * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
-- * @link https://docs.madelineproto.xyz MadelineProto documentation
-- */
--
--namespace danog\MadelineProto\Loop\Update;
--
--use Amp\TimeoutException;
--use danog\Loop\Loop;
--use danog\MadelineProto\API;
--use danog\MadelineProto\Exception;
--use danog\MadelineProto\Logger;
--use danog\MadelineProto\Loop\InternalLoop;
--use danog\MadelineProto\MTProto;
--use danog\MadelineProto\MTProto\LoginState;
--use danog\MadelineProto\MTProto\SpecialMethodType;
--use danog\MadelineProto\PeerNotInDbException;
--use danog\MadelineProto\PTSException;
--use danog\MadelineProto\Reactive\SimpleSubscriber;
--use danog\MadelineProto\RPCError\ChannelInvalidError;
--use danog\MadelineProto\RPCError\ChannelPrivateError;
--use danog\MadelineProto\RPCError\ChatForbiddenError;
--use danog\MadelineProto\RPCError\TimeoutError;
--use danog\MadelineProto\RPCError\UserBannedInChannelError;
--
--use Revolt\EventLoop;
--use function Amp\delay;
--
--/**
-- * Update loop.
-- *
-- * @internal
-- *
-- * @author Daniil Gentili
-- *
-- * @implements SimpleSubscriber
-- */
--final class UpdateLoop extends Loop implements SimpleSubscriber
--{
-- use InternalLoop {
-- __construct as private init;
-- }
-- /**
-- * Main loop ID.
-- */
-- public const GENERIC = 0;
--
-- private const DEFAULT_TIMEOUT = 10.0;
--
-- /**
-- * Feed loop.
-- */
-- private ?FeedLoop $feeder = null;
-- private ?int $authorizedDc = null;
-- /**
-- * Constructor.
-- */
-- public function __construct(MTProto $API, private int $channelId)
-- {
-- $this->init($API);
-- $API->loginState->subscribe($this);
-- }
-- public function __sleep(): array
-- {
-- return ['channelId', 'API', 'feeder', 'authorizedDc'];
-- }
-- #[\Override]
-- public function onSimpleStateChange($state): void
-- {
-- if ($state->state !== API::LOGGED_IN) {
-- $this->authorizedDc = null;
-- return;
-- }
-- if (null !== $this->authorizedDc = $state->authorizedDc) {
-- if ($this->isRunning()) {
-- $this->resume(true);
-- } else {
-- $this->start();
-- }
-- }
-- }
--
-- /**
-- * Main loop.
-- */
-- #[\Override]
-- public function loop(): ?float
-- {
-- if ($this->authorizedDc === null) {
-- return self::PAUSE;
-- }
-- $this->API->feeders[$this->channelId] ??= new FeedLoop($this->API, $this->channelId);
-- $this->API->updaters[$this->channelId] ??= new UpdateLoop($this->API, $this->channelId);
--
-- $this->feeder = $this->API->feeders[$this->channelId];
-- $state = $this->channelId === self::GENERIC ? $this->API->loadUpdateState() : $this->API->loadChannelState($this->channelId);
--
-- $result = [];
-- while (true) {
-- if ($this->channelId) {
-- $this->API->logger('Resumed and fetching '.$this->channelId.' difference...', Logger::ULTRA_VERBOSE);
-- if ($state->pts() <= 1) {
-- $limit = 10;
-- } elseif ($this->API->authorization['user']['bot']) {
-- $limit = 100000;
-- } else {
-- $limit = 100;
-- }
-- $request_pts = $state->pts();
-- try {
-- $difference = $this->API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true, 'floodWaitLimit' => 86400]);
-- } catch (ChannelPrivateError|ChatForbiddenError|ChannelInvalidError|UserBannedInChannelError) {
-- $this->feeder->stop();
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->getChannelStates()->remove($this->channelId);
-- $this->API->logger("Channel private, exiting {$this}");
-- return self::STOP;
-- } catch (TimeoutError $e) {
-- delay(1.0);
-- continue;
-- } catch (PeerNotInDbException) {
-- $this->feeder->stop();
-- $this->API->getChannelStates()->remove($this->channelId);
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->logger("Channel private, exiting {$this}");
-- return self::STOP;
-- } catch (PTSException $e) {
-- $this->feeder->stop();
-- $this->API->getChannelStates()->remove($this->channelId);
-- unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-- $this->API->logger("Got PTS exception, exiting update loop for $this: $e", Logger::FATAL_ERROR);
-- return self::STOP;
-- } catch (TimeoutException) {
-- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-- continue;
-- }
-- $timeout = min(self::DEFAULT_TIMEOUT, $difference['timeout'] ?? self::DEFAULT_TIMEOUT);
-- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-- switch ($difference['_']) {
-- case 'updates.channelDifferenceEmpty':
-- $state->update($difference);
-- unset($difference);
-- break 2;
-- case 'updates.channelDifference':
-- if ($request_pts >= $difference['pts'] && $request_pts > 1) {
-- $this->API->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), Logger::VERBOSE);
-- $difference['pts'] = $request_pts + 1;
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $state->update($difference);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- if (!$difference['final']) {
-- unset($difference);
-- break;
-- }
-- unset($difference);
-- break 2;
-- case 'updates.channelDifferenceTooLong':
-- if (isset($difference['dialog']['pts'])) {
-- $difference['pts'] = $difference['dialog']['pts'];
-- }
-- $state->update($difference);
-- if ($difference['messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['messages']);
-- unset($difference);
-- break;
-- default:
-- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-- }
-- } else {
-- $this->API->logger('Resumed and fetching normal difference...', Logger::ULTRA_VERBOSE);
-- do {
-- try {
-- $difference = $this->API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts(), 'specialMethodType' => SpecialMethodType::USER_RELATED], $this->authorizedDc);
-- break;
-- } catch (TimeoutError) {
-- delay(1.0);
-- } catch (TimeoutException) {
-- EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-- }
-- } while (true);
-- $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-- $timeout = self::DEFAULT_TIMEOUT;
-- switch ($difference['_']) {
-- case 'updates.differenceEmpty':
-- $state->update($difference);
-- unset($difference);
-- break 2;
-- case 'updates.difference':
-- $state->qts($difference['state']['qts']);
-- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-- $state->update($difference['state']);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- unset($difference);
-- break 2;
-- case 'updates.differenceSlice':
-- $state->qts($difference['intermediate_state']['qts']);
-- foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-- $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-- }
-- $result += ($this->feeder->feed($difference['other_updates']));
-- $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-- $state->update($difference['intermediate_state']);
-- if ($difference['new_messages']) {
-- $result[$this->channelId] = true;
-- }
-- $this->feeder->saveMessages($difference['new_messages']);
-- unset($difference);
-- break;
-- case 'updates.differenceTooLong':
-- $state->update($difference);
-- unset($difference);
-- break;
-- default:
-- throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-- }
-- }
-- }
-- $this->API->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
-- foreach ($result as $channelId => $_) {
-- $this->API->feeders[$channelId]?->resume();
-- }
-- $this->API->logger("Finished parsing updates in {$this}, pausing for $timeout seconds", Logger::ULTRA_VERBOSE);
--
-- return $timeout;
-- }
-- /**
-- * Get loop name.
-- */
-- public function __toString(): string
-- {
-- return $this->channelId ?
-- "getUpdate loop channel {$this->channelId}" :
-- 'getUpdate loop generic';
-- }
--}
-+.
-+ *
-+ * @author Daniil Gentili
-+ * @copyright 2016-2025 Daniil Gentili
-+ * @license https://opensource.org/licenses/AGPL-3.0 AGPLv3
-+ * @link https://docs.madelineproto.xyz MadelineProto documentation
-+ */
-+
-+namespace danog\MadelineProto\Loop\Update;
-+
-+use Amp\CancelledException;
-+use Amp\TimeoutException;
-+use danog\Loop\Loop;
-+use danog\MadelineProto\API;
-+use danog\MadelineProto\Exception;
-+use danog\MadelineProto\Logger;
-+use danog\MadelineProto\Loop\InternalLoop;
-+use danog\MadelineProto\MTProto;
-+use danog\MadelineProto\MTProto\LoginState;
-+use danog\MadelineProto\MTProto\SpecialMethodType;
-+use danog\MadelineProto\PeerNotInDbException;
-+use danog\MadelineProto\PTSException;
-+use danog\MadelineProto\Reactive\SimpleSubscriber;
-+use danog\MadelineProto\RPCError\ChannelInvalidError;
-+use danog\MadelineProto\RPCError\ChannelPrivateError;
-+use danog\MadelineProto\RPCError\ChatForbiddenError;
-+use danog\MadelineProto\RPCError\TimeoutError;
-+use danog\MadelineProto\RPCError\UserBannedInChannelError;
-+
-+use Revolt\EventLoop;
-+use function Amp\delay;
-+
-+/**
-+ * Update loop.
-+ *
-+ * @internal
-+ *
-+ * @author Daniil Gentili
-+ *
-+ * @implements SimpleSubscriber
-+ */
-+final class UpdateLoop extends Loop implements SimpleSubscriber
-+{
-+ use InternalLoop {
-+ __construct as private init;
-+ }
-+ /**
-+ * Main loop ID.
-+ */
-+ public const GENERIC = 0;
-+
-+ private const DEFAULT_TIMEOUT = 10.0;
-+
-+ /**
-+ * Feed loop.
-+ */
-+ private ?FeedLoop $feeder = null;
-+ private ?int $authorizedDc = null;
-+ /**
-+ * Constructor.
-+ */
-+ public function __construct(MTProto $API, private int $channelId)
-+ {
-+ $this->init($API);
-+ $API->loginState->subscribe($this);
-+ }
-+ public function __sleep(): array
-+ {
-+ return ['channelId', 'API', 'feeder', 'authorizedDc'];
-+ }
-+ #[\Override]
-+ public function onSimpleStateChange($state): void
-+ {
-+ if ($state->state !== API::LOGGED_IN) {
-+ $this->authorizedDc = null;
-+ return;
-+ }
-+ if (null !== $this->authorizedDc = $state->authorizedDc) {
-+ if ($this->isRunning()) {
-+ $this->resume(true);
-+ } else {
-+ $this->start();
-+ }
-+ }
-+ }
-+
-+ /**
-+ * Main loop.
-+ */
-+ #[\Override]
-+ public function loop(): ?float
-+ {
-+ if ($this->authorizedDc === null) {
-+ return self::PAUSE;
-+ }
-+ $this->API->feeders[$this->channelId] ??= new FeedLoop($this->API, $this->channelId);
-+ $this->API->updaters[$this->channelId] ??= new UpdateLoop($this->API, $this->channelId);
-+
-+ $this->feeder = $this->API->feeders[$this->channelId];
-+ $state = $this->channelId === self::GENERIC ? $this->API->loadUpdateState() : $this->API->loadChannelState($this->channelId);
-+
-+ $result = [];
-+ while (true) {
-+ if ($this->channelId) {
-+ $this->API->logger('Resumed and fetching '.$this->channelId.' difference...', Logger::ULTRA_VERBOSE);
-+ if ($state->pts() <= 1) {
-+ $limit = 10;
-+ } elseif ($this->API->authorization['user']['bot']) {
-+ $limit = 100000;
-+ } else {
-+ $limit = 100;
-+ }
-+ $request_pts = $state->pts();
-+ try {
-+ $difference = $this->API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true, 'floodWaitLimit' => 86400]);
-+ } catch (ChannelPrivateError|ChatForbiddenError|ChannelInvalidError|UserBannedInChannelError) {
-+ $this->feeder->stop();
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ $this->API->logger("Channel private, exiting {$this}");
-+ return self::STOP;
-+ } catch (TimeoutError $e) {
-+ delay(1.0);
-+ continue;
-+ } catch (PeerNotInDbException) {
-+ $this->feeder->stop();
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->logger("Channel private, exiting {$this}");
-+ return self::STOP;
-+ } catch (PTSException $e) {
-+ $this->feeder->stop();
-+ $this->API->getChannelStates()->remove($this->channelId);
-+ unset($this->API->updaters[$this->channelId], $this->API->feeders[$this->channelId]);
-+ $this->API->logger("Got PTS exception, exiting update loop for $this: $e", Logger::FATAL_ERROR);
-+ return self::STOP;
-+ } catch (TimeoutException|CancelledException $e) {
-+ if (!$this->isRunning() || $this->authorizedDc === null) {
-+ return self::STOP;
-+ }
-+ if ($e instanceof CancelledException && !($e->getPrevious() instanceof TimeoutException)) {
-+ throw $e;
-+ }
-+ EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-+ return self::DEFAULT_TIMEOUT;
-+ }
-+ $timeout = min(self::DEFAULT_TIMEOUT, $difference['timeout'] ?? self::DEFAULT_TIMEOUT);
-+ $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-+ switch ($difference['_']) {
-+ case 'updates.channelDifferenceEmpty':
-+ $state->update($difference);
-+ unset($difference);
-+ break 2;
-+ case 'updates.channelDifference':
-+ if ($request_pts >= $difference['pts'] && $request_pts > 1) {
-+ $this->API->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested ".$state->pts().', using '.($state->pts() + 1), Logger::VERBOSE);
-+ $difference['pts'] = $request_pts + 1;
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $state->update($difference);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ if (!$difference['final']) {
-+ unset($difference);
-+ break;
-+ }
-+ unset($difference);
-+ break 2;
-+ case 'updates.channelDifferenceTooLong':
-+ if (isset($difference['dialog']['pts'])) {
-+ $difference['pts'] = $difference['dialog']['pts'];
-+ }
-+ $state->update($difference);
-+ if ($difference['messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['messages']);
-+ unset($difference);
-+ break;
-+ default:
-+ throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-+ }
-+ } else {
-+ $this->API->logger('Resumed and fetching normal difference...', Logger::ULTRA_VERBOSE);
-+ do {
-+ try {
-+ $difference = $this->API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts(), 'specialMethodType' => SpecialMethodType::USER_RELATED], $this->authorizedDc);
-+ break;
-+ } catch (TimeoutError) {
-+ delay(1.0);
-+ } catch (TimeoutException|CancelledException $e) {
-+ if (!$this->isRunning() || $this->authorizedDc === null) {
-+ return self::STOP;
-+ }
-+ if ($e instanceof CancelledException && !($e->getPrevious() instanceof TimeoutException)) {
-+ throw $e;
-+ }
-+ EventLoop::queue($this->API->report(...), "Network issues detected, please check logs!");
-+ return self::DEFAULT_TIMEOUT;
-+ }
-+ } while (true);
-+ $this->API->logger('Got '.$difference['_'], Logger::ULTRA_VERBOSE);
-+ $timeout = self::DEFAULT_TIMEOUT;
-+ switch ($difference['_']) {
-+ case 'updates.differenceEmpty':
-+ $state->update($difference);
-+ unset($difference);
-+ break 2;
-+ case 'updates.difference':
-+ $state->qts($difference['state']['qts']);
-+ foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-+ $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-+ $state->update($difference['state']);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ unset($difference);
-+ break 2;
-+ case 'updates.differenceSlice':
-+ $state->qts($difference['intermediate_state']['qts']);
-+ foreach ($difference['new_encrypted_messages'] as &$encrypted) {
-+ $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
-+ }
-+ $result += ($this->feeder->feed($difference['other_updates']));
-+ $result += ($this->feeder->feed($difference['new_encrypted_messages']));
-+ $state->update($difference['intermediate_state']);
-+ if ($difference['new_messages']) {
-+ $result[$this->channelId] = true;
-+ }
-+ $this->feeder->saveMessages($difference['new_messages']);
-+ unset($difference);
-+ break;
-+ case 'updates.differenceTooLong':
-+ $state->update($difference);
-+ unset($difference);
-+ break;
-+ default:
-+ throw new Exception('Unrecognized update difference received: '.var_export($difference, true));
-+ }
-+ }
-+ }
-+ $this->API->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
-+ foreach ($result as $channelId => $_) {
-+ $this->API->feeders[$channelId]?->resume();
-+ }
-+ $this->API->logger("Finished parsing updates in {$this}, pausing for $timeout seconds", Logger::ULTRA_VERBOSE);
-+
-+ return $timeout;
-+ }
-+ /**
-+ * Get loop name.
-+ */
-+ public function __toString(): string
-+ {
-+ return $this->channelId ?
-+ "getUpdate loop channel {$this->channelId}" :
-+ 'getUpdate loop generic';
-+ }
-+}
diff --git a/readme-he.md b/readme-he.md
index f8bf0b2..5a80639 100644
--- a/readme-he.md
+++ b/readme-he.md
@@ -1,119 +1,116 @@
-# 🕯️ בוט השבת של WizardLoop
+# 🕯️ בוט שבת
-בוט Telegram המבוסס על PHP, MadelineProto ו־SQLite לניהול זמני שקט בקבוצות בשבתות ובחגים, להצגת הלוח היהודי ולתזכורות בהפעלה מפורשת.
+בוט Telegram לניהול שקט בקבוצות בשבתות ובחגים, להצגת מידע מהלוח היהודי ולתזכורות לבחירה. מבוסס על PHP, MadelineProto ו־SQLite.
[English](README.md) | [עברית](readme-he.md)
-[](LICENSE)
+[](LICENSE)
[](composer.json)
-[](composer.lock)
-[](VERSION)
+[](composer.lock)
-**הגרסה הנוכחית:
3.0.0, גרסה יציבה.** השתמשו ב[קובצי השחרור המתאימים](https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0) או בעותק מהתג ושמרו את נתוני הזיהוי שלו. בעל הפרויקט אישר שב־dev.9 עברו בדיקות חיות של נעילה, פתיחה, שחזור ההרשאות המקוריות והפעלה מחדש. אישור זה אינו מכסה תזמון בחג, קיבולת בעומס או הרצה ממושכת; בדיקות אוטומטיות ובדיקות בסביבת היעד נשארות נפרדות. במעבר מבוט קיים פעלו לפי [מדריך השדרוג והחזרה לגרסה קודמת](docs/PRODUCTION_UPGRADE.md) לפני החלפת קבצים או הפעלת מופע נוסף. ראו [מצב הפרסום](docs/PUBLICATION_STATUS.md), [שינויים](CHANGELOG.md) ו[בטיחות מסירה](docs/DEV9_DELIVERY_SAFETY.md). התגים מתארים את תצורת המקור ואינם אישור לתקינות בסביבת production.
+**גרסה 3.1.0.** דרישות השחרור ומגבלות האימות מתוארות ב[מצב המימוש](docs/IMPLEMENTATION_STATUS.md). להתקנה קיימת התחילו ב[מדריך השדרוג בעברית](docs/PRODUCTION_UPGRADE_HE.md) ([English](docs/PRODUCTION_UPGRADE.md)); הפקודות שבהמשך יוצרות מסד נתונים חדש.
-## תוכן עניינים
-
-[יכולות](#features) · [דרישות](#requirements) · [התקנת Docker](#docker-installation) · [התקנה ידנית](#manual-installation) · [תצורה](#configuration) · [הכנת Telegram](#telegram-setup) · [הוספת קבוצה](#group-setup) · [מיקום ושפות](#location-and-languages) · [מודולי הלוח](#calendar-modules) · [פקודות הבוט](#bot-commands) · [תפעול](#operations) · [שדרוג וייבוא](#upgrade-and-legacy-import) · [גיבוי וחזרה לגרסה קודמת](#backup-and-rollback) · [פתרון תקלות](#troubleshooting) · [מבנה ופיתוח](#project-and-development) · [רישוי וקרדיטים](#license-and-credits)
+[יכולות](#features) · [דרישות](#requirements) · [התקנה](#install) · [הגדרה](#configure) · [שימוש ראשון](#first-use) · [תפעול ועדכון](#operate) · [תיעוד](#documentation) · [רישיון](#license)
-## יכולות
-
-| תחום | ההתנהגות הממומשת |
-|---|---|
-| שבת וחגים | מיקום לכל קבוצה, לוח ישראל/חו״ל, שיטות נרות והבדלה, היסטים תפעוליים וסגירה רצופה בימים קדושים סמוכים. |
-| מצבים | כבוי, הודעות בלבד, נעילה בלבד או נעילה והודעות; שבת וחגים נבחרים בנפרד. |
-| שחזור הרשאות | צילום מקורי של 22 דגלים, קריאה טרייה מאומתת, מצב שחזור שמור ופאנל לטיפול מורשה בהתנגשויות. מסכת הנעילה הרגילה כוללת 21 הגבלות חברים לבחירה; סמכויות מנהלים נפרדות. |
-| שליטה בפרטי | קבוצות מוכרות, הגדרות מודרכות, העדפות אישיות נפרדות, תצוגה מקדימה ואישור. |
-| לוח ותזכורות | זמני היום, דף יומי, תפילין ועומר עונתי בהפעלה מפורשת ובהגדרות נפרדות לכל קבוצה. |
-| עיצוב הודעות | טקסט, ישויות Telegram, מדיה לשימוש חוזר וכפתורי ברירת מחדל/מותאמים/ללא כפתורים; תבניות נפרדות לסגירה, פתיחה, הודעת זמנים ומודולים. ניקוי הודעות כבוי כברירת מחדל. |
-| ניהול | מנהלים מלאים/מוגבלים/לצפייה בלבד, ספריית מנויים, שידורים, סטטיסטיקות, אבחון, קישורי מערכת ומעקב. |
-| אחסון ותפעול | מיגרציות וגיבויי SQLite, משימות מסירה שמורות, פעימות מתזמן נפרדות, כותב יישום יחיד וכלי תחזוקה מפורשים. |
-| תרומות ומקור | תרומות Telegram Stars לבחירה, לרבות סכום שלם מותאם 1–10000; גרסה, רישיון וקישור מפעיל למקור המדויק. |
-
-גרסה 3.0.0 שומרת על השיפורים שנוספו ב־dev.9: בדיקת זכאות בזמן המסירה, הגבלת תזכורות שהצטברו, אכיפת מרווחים ושעות שקט בפועל והפרדה בין עבודת הרשאות, הודעות ושידורים. MadelineProto נשאר ב־8.7.0 ונשמר קובץ התלויות הנעול. ערך שמש חסר מדווח כחסר, ללא המצאת חלופה לאזורי קוטב. הזמנים והנוסחים נועדו למידע, והמנהל בוחר את שיטות החישוב.
+## מה הבוט עושה
-
-## דרישות
+- סוגר ופותח קבוצות בשבתות ובחגים, תוך שמירת הרשאות מקור מאומתות והתאוששות מבוקרת.
+- מאפשר לבחור לכל קבוצה מיקום, אזור זמן, לוח ישראל/חו״ל ושיטות לנרות ולהבדלה.
+- מציג זמני היום ודף יומי; מאפשר לתזמן תזכורות לזמנים, לדף יומי, לתפילין ולעומר.
+- מנהל קבוצות דרך פאנל פרטי, עם התאמת הודעות, מדיה וכפתורים.
+- כולל מנהלי בוט עם הרשאות נפרדות, שידורים, סטטיסטיקה ותרומות אופציונליות בכוכבי Telegram.
-| רכיב | דרישה |
-|---|---|
-| פריסה מומלצת | Linux, Docker Engine ו־Compose v2, גישה יוצאת ל־HTTPS ול־Telegram ואחסון מתמשך. |
-| הרצה ידנית | PHP 8.3/8.4/8.5 ב־64 ביט ו־Composer 2. ב־Docker נעולים PHP 8.4.26 ו־Composer 2.10.3. |
-| הרחבות | PDO/PDO SQLite, mbstring, XML, DOM, fileinfo ו־zlib; ZIP לכלי האריזה האופציונלי לפיתוח. בדקו את כל דרישות ה־lock באמצעות `composer check-platform-reqs`. ב־Docker נבנות גם pcntl ו־sockets. |
-| SQLite | מינימום יישום 3.35. בדיקת שחרור מקבלת 3.51.3 ומעלה או 3.44.6 / 3.50.7 שנבדקו. חשוב לבדוק את הספרייה ש־PHP טוען. Docker בונה 3.51.3 עם אימות SHA-256. |
-| Telegram | פרטי יישום API ID/hash, טוקן BotFather ומזהי משתמש או שמות משתמש ניתנים לפענוח עבור המפעילים. |
-| GeoNames | חשבון שלכם עם webservices פעילים לחיפוש עיר ואזור זמן אוטומטי. ערים מוכרות וקואורדינטות מפורשות זמינות גם בלעדיו. |
-| מערכת קבצים | נתוני יישום מתמשכים וסשן MadelineProto נפרד. נדרשת גם כתיבה בתיקיית העבודה ללוג תהליך הספרייה ולקובצי PrimeModule. |
+כלולים קטלוגי ממשק בעברית, באנגלית, ברוסית, בצרפתית, בספרדית ובפורטוגזית ברזילאית. תוכן חיצוני וטקסטים ליטורגיים בעברית עשויים להישאר בשפת המקור. לפרטים ראו [הגדרות קבוצה](docs/GROUP_SETTINGS.md).
-הבדיקות האוטומטיות משתמשות בתחליפי Telegram ובנתוני בדיקה של ספקים, ללא פרטי התחברות. בדקו שוב שחזור הרשאות והפעלה מחדש בסביבת היעד, וכן נושאים, תצוגת לקוחות, אינליין/GPS, כוכבים ותפריטי פקודות לפי השימוש. ראו את [רישום הבדיקות המדויק](docs/IMPLEMENTATION_STATUS.md).
+
+## לפני שמתחילים
-
-## התקנת Docker
+נדרש שרת Linux עם אחסון קבוע, גישה לאינטרנט, **Docker Engine ותוסף Docker Compose**, וכן:
-דוגמאות המעטפת מיועדות למסוף Linux/POSIX. פקודות Docker מריצים **במחשב המארח, בשורש הפרויקט שחולץ**, עם הרשאה לשירות Docker. התהליך בתמונה רץ כ־`shabbat`, עם UID/GID `10001`. אין שירות Composer נפרד.
+| פריט | מאיפה מקבלים |
+|---|---|
+| API ID ו־API Hash של Telegram | [ניהול אפליקציות Telegram](https://my.telegram.org/apps) |
+| טוקן הבוט | יצירה או בחירה של בוט דרך [BotFather](https://t.me/BotFather) |
+| מזהה המנהל | מזהה משתמש Telegram מהימן; מספר מזהים מופרדים בפסיקים |
+| שם משתמש GeoNames | [חשבון GeoNames](https://www.geonames.org/login) עם Web Services פעילים, לחיפוש ערים ואזור זמן אוטומטי |
-1. קבלו את המקור שנבדק. עבור ארכיון השחרור להתקנה:
+התקינו [Docker Engine לפי הפצת Linux](https://docs.docker.com/engine/install/) ואת [תוסף Compose](https://docs.docker.com/compose/install/linux/), ובדקו:
~~~sh
-unzip shabbat-3.0.0.zip -d shabbat
-cd shabbat
-unset BUILD_COMMIT
+docker --version
+docker compose version
~~~
-הארכיון מכיל מקור ו־`composer.lock`, ללא `vendor/` מותקן. Docker מתקין את תלויות ההרצה הנעולות. **שמרו את `build-info.json` שבארכיון.** ארכיון השחרור מתעד את ה־commit המדויק שנבדק, `local_changes=false` וטביעת מקור היישום. אל תוסיפו `BUILD_COMMIT` ל־`.env`; הדוגמה לארכיון מנקה ערך שהתקבל מהמעטפת כדי שלא יחליף את הזיהוי. אם משתמשים בעותק Git שנבדק, מסרו לפני הבנייה את ה־commit האמיתי שלו:
-
-
-
-~~~sh
-export BUILD_COMMIT="$(git rev-parse HEAD)"
-~~~
-
-
+Docker מספק PHP 8.4.27, Composer, SQLite ואת התלויות הנעולות. בהתקנה ידנית נדרש PHP ב־64 ביט: **8.3.36+, 8.4.27+ או 8.5.12+**, בתוך הענפים הנתמכים האלה. ראו [דרישות אבטחה מ־22 באוקטובר 2026](docs/INSTALLATION.md#php-security-baseline) ו[התקנה ידנית](docs/INSTALLATION.md#manual-installation).
-השתמשו בארכיון שחרור שלא שונה או בעותק Git נקי ותואם. אין להחליף את ה־commit בערך לא קשור או לשמור נתוני ארכיון לאחר שינוי המקור שלו.
+
+## 1. חילוץ התקנה חדשה
-2. צרו פעם אחת תצורה פרטית בהתקנה החדשה:
+הורידו את `shabbat-3.1.0.zip` ואת `SHA256SUMS` מ[שחרור GitHub המתאים](https://github.com/WizardLoop/shabbat/releases). הריצו ב־**Bash בשרת**, מתיקיית ההעלאה ועם גישה ל־Docker. אימות הקובץ חייב להחזיר `OK`.
~~~sh
+set -euo pipefail
+umask 077
+awk '$2 == "shabbat-3.1.0.zip" {
+ if (NF != 2 || length($1) != 64 || $1 ~ /[^0-9a-f]/) exit 1
+ print; n++
+} END { if (n != 1) exit 1 }' SHA256SUMS > deployment.sha256
+sha256sum --check deployment.sha256
+test ! -e shabbat-3.1.0
+unzip -q shabbat-3.1.0.zip -d shabbat-3.1.0
+cd shabbat-3.1.0
cp .env.example .env
chmod 600 .env
+unset BUILD_COMMIT
~~~
-ערכו את `.env`: החליפו את דוגמאות Telegram, הגדירו `ADMIN`, חשבון GeoNames לפי הצורך ו־`SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.0.0` לשחרור הזה ללא שינויים, שקובץ המקור התואם שלו חייב להיות זמין. לפריסה ששונתה יש לספק את המקור המדויק שלה. שמרו על תחביר פשוט של `KEY=value`, המתאים ל־PHP raw INI ול־Compose. הקובץ המוגדר אינו מיועד להעלאה למאגר.
+שמרו את `build-info.json` המצורף. בארכיון שחרור שלא שונה אין להוסיף `BUILD_COMMIT` לקובץ `.env`. אין לחלץ עדכון על התקנה פועלת.
+
+
+## 2. הגדרת הבוט
-3. בנו ובדקו את התמונה. השלבים מתקינים ומתקנים תלויות וכותבים נתוני זיהוי בתוך התמונה, בלי להפעיל את הבוט:
+ערכו את `.env` באופן פרטי. החליפו את פרטי הדוגמה ואת מזהה המנהל:
-~~~sh
-docker compose build
-docker compose run --rm --no-deps shabbat php bin/self-check.php --release
-docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
+~~~dotenv
+API_ID=123456
+API_HASH=replace_with_your_32_character_api_hash
+BOT_TOKEN=replace_with_your_bot_token
+ADMIN=123456789
+GEONAMES_USERNAME=your_geonames_username
+SOURCE_URL=https://github.com/WizardLoop/shabbat/releases/tag/v3.1.0
~~~
-4. אתחלו **מסד חדש וריק**, כשהשירות עצור. למסד קיים נדרש נוהל שדרוג וגיבוי.
+שמרו את שאר ערכי `.env.example` אלא אם נדרשת הגדרה מתקדמת. אין לפרסם את הקובץ או להשתמש בפרטי בוט בדיקה ב־production. קישור המקור חייב להציע את המקור המדויק של ההתקנה, כולל ארכיון Corresponding Source. ראו [כל משתני התצורה](docs/CONFIGURATION.md).
+
+משורש התיקייה שחולצה, בנו ובדקו את התמונה ואתחלו **מסד נתונים חדש וריק**. הפקודות האלה אינן מפעילות את הבוט:
~~~sh
+docker compose build shabbat
+docker compose run --rm --no-deps shabbat php bin/self-check.php --release
+docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root
docker compose run --rm --no-deps shabbat php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite
~~~
-5. הפעילו כשמוכנים לחיבור אמיתי ל־Telegram ולפעילות בקבוצות הרשומות:
+כשתהיו מוכנים לחיבור ל־Telegram, הפעילו:
@@ -126,414 +123,56 @@ docker compose exec shabbat php bin/health.php
-שם השירות: `shabbat`. כרכים: `bot-data` ב־`/app/data`, ו־`madeline-session` ב־`/app/runtime`; השמות בפועל כוללים את שם פרויקט Compose. שמרו את זהות הפרויקט והכרכים בשדרוג. Compose כופה `DATA_DIR=/app/data` ו־`SESSION_PATH=/app/runtime/bot.shabbat`. בדיקת הבריאות הראשונית ממתינה לשני המתזמנים; תקופת ההתחלה המוגדרת היא 90 שניות.
-
-[התקנה מפורטת](docs/INSTALLATION.md) · [סביבת בדיקה נפרדת](docs/SERVER_TEST_DEPLOYMENT.md)
+בדיקת הבריאות עשויה להזדקק לתקופת האתחול הראשונית, שאורכה 90 שניות. שם השירות הוא `shabbat`. אמצעי האחסון `bot-data` ו־`madeline-session` שומרים את נתוני היישום והסשן; שמם המלא כולל את שם פרויקט Compose.
-
-## התקנה ידנית
+
+## 3. Telegram והקבוצה הראשונה
-השתמשו במקור נפרד ובחשבון שירות שאינו root ושיכול לכתוב לתיקיות העבודה, הנתונים והסשן. הריצו **משורש הפרויקט הזה**, לאחר העתקת והגדרת `.env` כמתואר:
+1. ב־BotFather אפשרו הצטרפות לקבוצות. הפעילו `/setinline` לחיפוש מיקום ולוח באינליין.
+2. שלחו `/start` בפרטי. בדקו את כפתורי הבית, `/preferences` ואת השפה.
+3. הוסיפו את הבוט כמנהל בקבוצה עם הרשאה להגביל חברים. מחיקה ונעיצה דורשות את ההרשאות המתאימות.
+4. כמנהל קבוצה, שלחו `/add` **בתוך הקבוצה**. קבוצה חדשה נוצרת במצב **כבוי**, וההגדרה נפתחת בפרטי.
+5. בדקו מיקום, אזור זמן, לוח, מצב ושיטות נרות והבדלה. הפעילו רק תזכורות רצויות. חוזרים דרך `/groups` בפרטי או `/settings` בקבוצה.
-
+להקמה ראשונה השתמשו ב־`/add`: רישום ישיר דרך `/settings` מקבל כיום ברירת מחדל של נעילה. בדקו את הערכים לפני הפעלת קבוצה אמיתית. הרשאות מנהל הבוט ומנהל הקבוצה נפרדות.
-~~~sh
-composer install --no-dev --no-interaction --prefer-dist --optimize-autoloader
-composer check-platform-reqs --no-dev
-mkdir -p data/session
-php bin/self-check.php --release
-php bin/runtime-permissions.php --require-non-root
-php bin/migrate.php --writers-stopped --db data/shabbat.sqlite
-php bot.php
-~~~
+[כל פקודות הבוט](docs/COMMANDS.md) · [הגדרות קבוצה](docs/GROUP_SETTINGS.md) · [מיקום וחיפוש אינליין](docs/INLINE_GEONAMES.md)
-
+
+## תפעול שוטף ועדכון
-הפקודה האחרונה מפעילה את הבוט בחזית ומתחברת ל־Telegram. עצרו באמצעות Ctrl+C והמתינו לסיום; הפעלה חוזרת נעשית ב־`php bot.php`. ניהול תהליך ידני באחריות המפעיל; אין בפרויקט יחידת systemd מוכנה. Windows מתאים לרבות מהבדיקות הלא־מקוונות, אך בדיקת POSIX של משתמש שאינו root ובדיקת פריסת Linux דורשות מארח מתאים.
+הריצו **בשרת, משורש ההתקנה**, עם גישה ל־Docker ובאותו שם פרויקט Compose:
-Composer מחיל ומאמת את התיקונים המקומיים בהתקנה רגילה. אם הסקריפטים בוטלו, הריצו **בהתקנה העצורה**:
-
-
-
-~~~sh
-composer install --no-dev --no-scripts --no-interaction --prefer-dist
-php scripts/apply-patches.php
-php scripts/verify-patches.php
-~~~
-
-
-
-תוכן תלות לא מוכר או תיקון חלקי גורמים לכישלון אימות. החלה חוזרת אינה משנה מקור שכבר תוקן כראוי. אין לתקן ספרייה מותקנת בזמן שהבוט משתמש בה.
-
-
-## תצורה
-
-הבוט קורא את `.env` שבשורש כ־raw INI. ערכי סביבה לא ריקים קודמים לקובץ בחיפוש פרטי התחברות ונתיבים; הימנעו מהגדרות כפולות וריקות. גם כלי התחזוקה קוראים את `.env` לפתרון נתיבים; `--db` מפורש בוחר את מסד היעד. נתיבים יחסיים מתחילים בשורש הפרויקט.
-
-| משתנה | ברירת מחדל / דרישה | תפקיד |
+| פעולה | פקודה | השפעה |
|---|---|---|
-| `API_ID` | מספר שלם חיובי, חובה | מזהה יישום Telegram. |
-| `API_HASH` | 32 תווים הקסדצימליים, חובה | סוד יישום Telegram. |
-| `BOT_TOKEN` | חובה | טוקן BotFather של ההתקנה. |
-| `ADMIN` | יש להגדיר לגישת מפעילים | מזהים/שמות ניתנים לפענוח, מופרדים בפסיק; מזהים מספריים מונעים עמימות. הבעלים המוגדרים שומרים גישת התאוששות והפעלה מחדש. |
-| `DATA_DIR` | `data` בפרויקט | נתוני היישום ו־BroadcastManager; ב־Compose מוחלף ב־`/app/data`. |
-| `APP_DB_PATH` | `DATA_DIR/shabbat.sqlite` | מסד היישום; בדוגמה מוגדר במפורש `data/shabbat.sqlite`. |
-| `SESSION_PATH` | `bot.shabbat` בפרויקט | סשן MadelineProto; בדוגמה `data/session/bot.shabbat`, וב־Compose `/app/runtime/bot.shabbat`. |
-| `HEARTBEAT_PATH` | `DATA_DIR/scheduler-heartbeat.json` | קובץ פעימות מתזמני ההרשאות וההודעות. |
-| `LEGACY_DATA_PATH` | שורש הפרויקט | שורש מקור ישן לקריאה בלבד עם `data/DBgroups.txt`; בעת עלייה נוספים רק רישומי קבוצות חסרים. |
-| `GEONAMES_USERNAME` | ריק | חשבון webservices שלכם; demo אינו נתמך. |
-| `GEONAMES_ENDPOINT` | `https://secure.geonames.org` | נקודת HTTPS מאומתת, ללא מעבר ל־HTTP. |
-| `CUSTOM_EMOJI_ENABLED` | `1` | `0` בוחר אימוג׳ים בסיסיים; גם דחיית זכאות ודאית מפעילה חלופה מבוקרת. |
-| `SOURCE_URL` | ריק; יש להגדיר לפני פריסה | URL ב־HTTPS למקור המדויק. חוסר בהגדרה מדווח, אך אינו חוסם עלייה. |
-| `BUILD_COMMIT` | נתוני הארכיון או commit בן 40 תווי hex | זהות בנייה/ריצה ופרמטר בניית Compose. שומרים גם טביעות מקור לשינויים מקומיים. |
-
-[תצורה מפורטת](docs/CONFIGURATION.md) · [פרטיות](docs/PRIVACY.md)
-
-
-## הכנת Telegram
-
-1. קבלו פרטי API דרך [ניהול יישומי Telegram](https://my.telegram.org/apps).
-2. צרו או בחרו את הבוט ב־[BotFather](https://t.me/BotFather), קבלו טוקן ואפשרו הוספה לקבוצות.
-3. פתחו את הבוט בפרטי באמצעות `/start`. הוסיפו אותו לקבוצה עם הרשאות להגבלת חברים ולשינוי הרשאות ברירת מחדל. מחיקה ונעיצה אופציונליות דורשות את הרשאות Telegram המתאימות.
-4. הפעילו `/setinline` ב־BotFather לחיפוש ושיתוף באינליין. טקסט מוצע: `shabbat · zmanim · daf · omer · loc city`. חיפוש בשם עיר אינו דורש `/setinlinegeo` או `/setinlinefeedback`; שיתוף GPS מפורש.
-5. עם הרשאת שינוי תפריטים, שלחו בפרטי `/setcommands all all preview` לצפייה בכמות התפריטים; `/setcommands all all` מעדכן אותם ב־Telegram. מנהל קבוצה אינו מקבל מכך הרשאה זו.
-
-ניקוי אופציונלי מטפל רק בעדכונים ש־Telegram מוסר לבוט. לקבלת הודעות כלליות מבוטים אחרים, הבוט המקבל צריך **Bot-to-Bot Communication Mode** פעיל דרך BotFather, הרשאת מנהל בקבוצה ו־**Group Privacy Mode** כבוי, כמפורט ב[תיעוד Telegram לתקשורת בין בוטים](https://core.telegram.org/api/bots/bot-to-bot). המחיקה עדיין דורשת הרשאה מתאימה; אין בכך הבטחה לקבלת כל הודעה.
+| הפעלה | `docker compose up -d shabbat` | הפעלה וחיבור הבוט |
+| עצירה | `docker compose stop shabbat` | עצירת הבוט ושמירת אמצעי האחסון |
+| הפעלה מחדש | `docker compose restart shabbat` | הפעלה מחדש של התמונה הנוכחית |
+| מצב | `docker compose ps` | הצגת מצב השירות |
+| לוגים | `docker compose logs --tail=100 -f shabbat` | מעקב אחר לוגים; Ctrl+C סוגר את התצוגה |
+| בריאות | `docker compose exec shabbat php bin/health.php --deep` | בדיקת התזמון ומסד הנתונים של הבוט הפועל |
-
-## הוספת קבוצה
+**עדכון מחייב גיבוי לאחר עצירת הכותבים ובדיקת מיגרציות.** פעלו לפי [מדריך השדרוג](docs/PRODUCTION_UPGRADE_HE.md) ([English](docs/PRODUCTION_UPGRADE.md)) לאימות הנתיבים, הכנת staging, ייבוא או עדכון SQLite, שמירת הסשן וחזרה לאחור. בנייה בלבד אינה מבצעת מיגרציה; `restart` בלבד אינו מתקין תמונה חדשה. אין להריץ `composer update` בעדכון שגרתי או להסיר אמצעי אחסון.
-1. שלחו `/add` **בקבוצה, כמנהלי הקבוצה**. קבוצה חדשה שמתווספת כך מתחילה **כבויה**, וההגדרות נפתחות בפרטי.
-2. אשרו את שם הקבוצה, המיקום, אזור IANA ולוח ישראל/חו״ל. יש לבדוק את ערכי ברירת המחדל של ירושלים; הם אינם מיקום שנקבע אוטומטית.
-3. בחרו מצב ומדיניות שבת/חג, ואחר כך שיטות נרות/הבדלה והיסטים תפעוליים.
-4. הפעילו במפורש את מודולי היום/דף/תפילין/עומר הרצויים. צפו בתצוגה מקדימה בפרטי; בדיקה בקבוצה דורשת אישור נפרד ומוגבלת בקצב.
-5. חזרו דרך `/groups` בפרטי או `/settings` בקבוצה. הגדרות אישיות וקבוצתיות נפרדות.
+
+## מידע נוסף
-**הסתייגות במימוש הרישום הנוכחי:** גם `/settings` יכול לרשום קבוצה לא מוכרת אחרי אימות המנהל, ונתיב זה יורש מהמסד מצב **נעילה**. השתמשו ב־`/add` למסלול המתחיל במצב כבוי ובדקו מיד מיקום ומצב. `/settings` אינו מפעיל מחדש קבוצה שהוסרה; `/add` יכול. זו ההתנהגות הקיימת, והיא לא שונתה בסתר במסגרת הכנת הפרסום.
-
-הפאנלים מציגים ערכים קיימים, עבודה קרובה ומצב התאוששות. שינוי דורש הרשאה עדכנית ואישור הקשור למשתמש, לקבוצה ולגרסת ההגדרות. נושא פורום חסר או סגור יוצר שגיאה, ולא הפניה לנושא אחר. השחזור משתמש בהרשאות המקוריות; צילום חסר, לא מאומת או מתנגש דורש פתרון מורשה. ניקוי הודעות חברים ובוטים מתחיל כבוי. חוב שחזור לא פתור חוסם הסרת קבוצה.
-
-[הגדרות](docs/GROUP_SETTINGS.md) · [ממשק מודרך](docs/USER_EXPERIENCE.md) · [שחזור הרשאות](docs/PERMISSION_RECOVERY.md)
-
-
-## מיקום ושפות
-
-קיימים שישה קטלוגי שפה: עברית `he`, אנגלית `en`, רוסית `ru`, צרפתית `fr`, ספרדית `es` ופורטוגזית ברזילאית `pt-br`. נבדקים מפתחות ומצייני ערכים; אין בכך הבטחה לתרגום כל שגיאת צד שלישי או ממשק ישן. נוסח התפילה העברי נשאר עברי, לצד טקסט הסבר כאשר הוא מסופק. תפריטי Telegram משתמשים ב־`pt`; שפת התפריט לפי הלקוח ושפת הבוט השמורה הן הגדרות נפרדות.
-
-השתמשו ב־`/preferences` או `/language` בפרטי; `/language` בקבוצה מחייב ניהול קבוצה. לחיפוש עיר, פתחו [חשבון GeoNames](https://www.geonames.org/login), הפעילו free webservices והגדירו `GEONAMES_USERNAME`.
-
-בפאנל המתאים: **מיקום ואזור זמן → חיפוש עיר באינליין → עיר/מדינה/אזור → בדיקת קואורדינטות ואזור זמן → אישור היעד ששמו מוצג**. קיימים גם חיפוש פרטי, ערים מוכרות, קואורדינטות, חיפוש אזור IANA ותשובת GPS לפי בקשה. הבחירה זמנית, שייכת למשתמש אחד וחד־פעמית. שינוי אזור זמן אינו מזיז קואורדינטות.
-
-חיפוש אינליין ציבורי `loc city` או שם עיר בלבד מאפשר חיפוש ושיתוף מיקום. חיפוש אזור זמן ציבורי אפשרי באמצעות `tz Jerusalem` או `Asia/Jerusalem`, ללא שינוי הגדרות. שאילתות ההגדרה `location CITY` ו־`timezone QUERY` דורשות בקשת מיקום או אזור זמן פעילה בפרטי ומובילות לאישור. המצבים הנוספים: `shabat`, `shabbat`, `שבת`, `zmanim`, `daf`, `omer`. בדקו את המיקום המוצג: שיתוף אישי ותצוגה מורשית בהקשר קבוצה עשויים להשתמש בהגדרות שונות. תקלות חשבון ומכסה נשארות שגיאות גלויות.
-
-[אינליין ו־GeoNames](docs/INLINE_GEONAMES.md)
-
-
-## מודולי הלוח
-
-| מודול | הגדרות ומגבלות ממומשות |
+| נושא | מדריך |
|---|---|
-| שבת וחגים | מנהג נרות של עיר או בדיוק 10/15/18/20/22/30/40 דקות או ערך מותאם. ברירת המחדל העירונית של ירושלים היא 40; בחירת 18 נשארת 18. הבדלה: 8.5° או 42/50/72 דקות קבועות או ערך מותאם. 72 קבועות אינן כל שיטות רבנו תם. |
-| תזמון קבוצתי | היסטי סגירה לפני נרות ופתיחה לאחר הבדלה נפרדים. רצף ימים קדושים נשאר סגור. ישראל/חו״ל נבחר במפורש. הודעת הזמנים כוללת תזמון ועיצוב עצמאיים, תאריכים עבריים ומידע על הפרשה. |
-| זמני היום | תאריך אזרחי ואזור IANA; עלות, משיכיר, הנץ, שמע ותפילה לגר״א/מג״א, חצות, מנחה, פלג, שקיעה, צאת וחצות לילה כשזמינים. נתון חסר נשאר לא זמין. |
-| דף יומי | חישוב לפי תאריך אזרחי וקישור לימוד מהספק; דילוג על שליחה אינו עוצר את המחזור. |
-| תפילין | שעות קבועות, מרווחים והיסטים משקיעה, מניעת כפילויות, מכסות, מרווח מינימלי, שקט והשהיה. תחילת הזמן משתמשת ב־`misheyakir` של 11.5°; שדה הספק המחמיר אינו מוצע לבחירה. אין שליחה בשבת/יום טוב; מדיניות מפורשת לחול המועד ולתשעה באב בפועל. שעת הסיום נבדקת שוב במסירה. אישור הנחה אופציונלי סופר משתמשים ייחודיים וניתן לביטול בלחיצה חוזרת. |
-| עומר | 49 ימי העונה מתקדמים גם בימים ללא שליחה ובין שנים. לילה ממתין לצאת שנבחר ולסוף השקט הקבוצתי; השלמת יום אופציונלית ללא ברכה. ממומשים `ashkenaz` ורצף `sephard` המתועד, ולא כל מנהגי הקהילות. הנוסח המלא כולל הכנה ותוספות מסורתיות לפי הבחירה. |
-
-ההנחיה לברכה מתייחסת לזכאות אישית; היסטוריית הודעות אינה היסטוריית הספירה של אדם. ראו [הגדרות שיטות](docs/ZMANIM_METHODS.md), [תצוגת הלוח](docs/CALENDAR_PRESENTATION.md) ו[מקורות הנוסחים](THIRD_PARTY_NOTICES.md).
-
-
-## פקודות הבוט
-
-את הפקודות שולחים **ב־Telegram**. התפריט הוא קיצור דרך ולא מפרט הרשאות מלא. `[...]` מציין פרמטר אופציונלי.
-
-### משתמשים
-
-| פקודה | מקום והרשאה | השפעה |
-|---|---|---|
-| `/start`, `/help` | בפרטי; כל משתמש | תפריט הבית ועזרה. |
-| `/preferences` | בפרטי; העדפות אישיות | מיקום, לוח ושיטות אישיים. |
-| `/language`, `/lang` | בפרטי; העדפות אישיות | שפה אישית; שימוש בקבוצה דורש ניהול קבוצה. |
-| `/groups [search]` | בפרטי; אימות ניהול עדכני | רשימה וחיפוש בקבוצות מוכרות שניתן לנהל. |
-| `/shabat [YYYY-MM-DD]`, `/shabbat [YYYY-MM-DD]` | בפרטי או בקבוצה רשומה; כל משתמש | זמני שבת/חג לפי ההקשר. |
-| `/zmanim [YYYY-MM-DD]` | בפרטי או בקבוצה רשומה; כל משתמש | זמני היום. |
-| `/daf [YYYY-MM-DD]` | בפרטי או בקבוצה רשומה; כל משתמש | דף יומי. |
-| `/omer [YYYY-MM-DD]` | בפרטי או בקבוצה רשומה; כל משתמש | ספירה או מידע על העונה בתאריך שנבחר. |
-| `/stats` | בפרטי או בקבוצה; כל משתמש | נתונים מצרפיים ציבוריים, ללא זהויות מנויים. |
-| `/donate` | בפרטי; כל משתמש | אפשרויות תמיכה בכוכבים; תשלום מחייב אישור ב־Telegram. |
-| `/source`, `/license`, `/version` | בפרטי או בקבוצה; כל משתמש | הצעת מקור, רישוי וזיהוי גרסה. |
-
-### מנהלי קבוצות
-
-| פקודה | מקום והרשאה | השפעה |
-|---|---|---|
-| `/add` | בקבוצה; מנהל נוכחי | רישום/הפעלה מחדש ופתיחת ההגדרות. |
-| `/remove` | בקבוצה; מנהל נוכחי | השבתת הרישום; חוב שחזור חוסם הסרה. |
-| `/settings` | בקבוצה; מנהל נוכחי | הגדרות קבוצה בפרטי; ראו הסתייגות רישום לעיל. |
-| `/settings [GROUP_ID]` | בפרטי; מנהל נוכחי בקבוצת היעד | פתיחת יעד, או רשימת קבוצות ללא מזהה. |
-| `/language`, `/lang` | בקבוצה; מנהל נוכחי | בחירת שפת קבוצה בפרטי. |
-
-טפסים מתקדמים **בפרטי** מחייבים את הטוקן המדויק שהפאנל הנפיק, את בעליו וההקשר/גרסה התקפים, וכן הרשאת קבוצה עדכנית ליעד קבוצתי. העדיפו את הכפתורים המודרכים.
-
-| טופס | השפעה |
-|---|---|
-| `/city TOKEN QUERY` | חיפוש המיקום שבבחירה. |
-| `/coordinates TOKEN LATITUDE LONGITUDE IANA_ZONE [NAME]` | תצוגה מקדימה לקואורדינטות ואזור זמן. |
-| `/location TOKEN IANA_ZONE` או `/location TOKEN auto` | בקשת תשובת GPS; auto דורש GeoNames. |
-| `/timezone TOKEN QUERY` | חיפוש אזורי IANA. |
-| `/configure TOKEN FORM` | תצוגה מקדימה של טופס ההגדרות הנתמך בפאנל. |
-| `/viewdate TOKEN YYYY-MM-DD` | תאריך לתצוגת הלוח. |
-| `/template TOKEN` + שורה חדשה + תוכן | סקירת תבנית קבוצה מוצעת. |
-| `/buttons TOKEN` + שורה חדשה + תוכן כפתורים | סקירת כפתורים בפורמט JSON או בפורמט הישן. |
-
-### מנהלי הבוט
-
-כל הפקודות להלן **בפרטי**. תפקידי ניהול הבוט נפרדים מניהול קבוצה; צפייה בלבד אינה מתירה שינוי.
-
-| פקודה | הרשאה נדרשת | השפעה |
-|---|---|---|
-| `/admin` | מנהל בוט | פאנל הניהול. |
-| `/adminstats` | סטטיסטיקות | נתונים מצרפיים ניהוליים. |
-| `/testzmanim [GROUP_ID]` | סטטיסטיקות | אבחון מדופדף, סינון וחיפוש וייצוא JSON פרטי לפי בחירה. |
-| `/subscribers` | מנויים | ספריית נמענים מוכרים ופרופילים. |
-| `/broadcast` | שידורים | טיוטות ומשימות; שליחה, עריכה ומחיקה דורשות הרשאת שינוי ואישור מתאים. |
-| `/managers` | ניהול מנהלים | תפקידים מואצלים במסגרת סמכות המבצע. |
-| `/systemlinks` | קישורי מערכת | קישורי ניווט, שאינם מעניקים הרשאות. |
-| `/trackinglinks` | קישורי מעקב | ספירת הפעלות וניהול; שינוי דורש הרשאת שינוי. |
-| `/setcommands [LANGUAGE] [SCOPE] [preview]` | הרשאת שינוי תפריטים, גם לתצוגה | צפייה או עדכון תפריטי Telegram. |
-| `/closegroups`, `/opengroups` | הרשאת שינוי בפעולות קבוצות | החלת חריגה ידנית לשעה מיד על קבוצות פעילות רשומות; שמירת נעילות קודמות ודיווח התנגשויות. אלה פעולות הרשאה אמיתיות. |
-| `/restart` | בעלים מוגדר ב־`ADMIN` בלבד | הפעלה מחדש מסודרת של הבוט. |
-
-שפות לתפריטים: `all|he|en|ru|fr|es|pt-br`; תחומים: `all|private|operators|groups|group_admins`; ברירת מחדל: `all all`. דוגמה: `/setcommands ru group_admins preview`. בתפריטי הקבוצות מופיע כרגע `/settings`; אפשר להקליד פקודות נתמכות נוספות.
-
-[ניהול הבוט](docs/ADMIN_PANEL.md) · [אבחון](docs/DIAGNOSTICS.md)
-
-
-## תפעול
-
-פקודות Docker רצות **במארח, באותו שורש ובאותה זהות פרויקט**, עם גישה לשירות Docker. פקודות PHP רצות **בתמונה ב־/app**, או בשורש התקנה ידנית כמשתמש השירות. פלט תפעולי עלול לכלול מזהי קבוצות ומצב; שמרו אותו בפרטיות.
-
-| פעולה | פקודה | השפעה או תנאי |
-|---|---|---|
-| בנייה | `docker compose build` | בנייה מהמקור ומה־lock. |
-| הפעלה | `docker compose up -d shabbat` | הפעלה/יצירה מחדש וחיבור ל־Telegram. |
-| עצירה | `docker compose stop shabbat` | עצירה מסודרת עם 60 שניות חסד; הכרכים נשמרים. |
-| הפעלה מחדש | `docker compose restart shabbat` | הפעלת אותו שירות מחדש; ללא בניית תמונה. |
-| מצב | `docker compose ps` | מצב השירות והמכולה. |
-| לוגים | `docker compose logs --tail=100 shabbat` | צפייה בלוגים; `--follow` למעקב, Ctrl+C מסיים את הצופה. |
-| בריאות | `docker compose exec shabbat php bin/health.php` | סכמה וחיבור, שתי פעימות ומדדי תורים/נעילות. |
-| בריאות מעמיקה | `docker compose exec shabbat php bin/health.php --deep` | גם שלמות ומפתחות זרים; פעולה יקרה יותר. |
-| בדיקת שחרור | `docker compose run --rm --no-deps shabbat php bin/self-check.php --release` | בדיקות פלטפורמה ותיקונים ללא חיבור לבוט. |
-| בדיקת כתיבה | `docker compose run --rm --no-deps shabbat php bin/runtime-permissions.php --require-non-root` | בדיקת קבצים זמניים; עשויה להוסיף שורה ללוג תהליך קיים. |
-
-שתי פעימות המתזמן חייבות להיות בנות 180 שניות לכל היותר. מסד משוחזר או מנותק עשוי לעבור בדיקות מבנה ובכל זאת להחזיר `healthy=false` וקוד יציאה 1 ללא מתזמנים. אין ליצור פעימות מלאכותיות.
-
-כלי התחזוקה הישירים מופעלים **משורש הפרויקט כמשתמש השירות**. ב־Docker מקדימים לפקודת PHP `docker compose run --rm --no-deps shabbat` ומשתמשים בנתיבי המכולה. `--writers-stopped` הוא הצהרת המפעיל ולא פקודת עצירה.
-
-| פעולה | פקודה | השפעה או דרישה |
-|---|---|---|
-| מיגרציה | `php bin/migrate.php --writers-stopped --db data/shabbat.sqlite --backup-dir backups` | כל הכותבים עצורים ותיקיית גיבוי קיימת; גיבוי מסד קיים והחלת מיגרציות. מוותרים על הגיבוי רק למסד חדש. |
-| גיבוי | `php bin/backup.php --db data/shabbat.sqlite --directory backups --keep 7` | העתק SQLite עקבי ומניפסט, שמירת שבעה גיבויים בשם הכלי. אפשר בתחזוקה בזמן פעילות. |
-| שחזור | `php bin/restore.php --backup backups/CHOSEN.sqlite --db data/shabbat.sqlite --writers-stopped` | גיבוי נבחר ומאומת, כותבים עצורים; היעד הקודם נשמר. |
-| בדיקת ייבוא | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --dry-run` | בדיקה ודוח, ללא כתיבת רשומות מיובאות או פעולות Telegram. |
-| החלת ייבוא | `php bin/import-legacy.php --db data/shabbat.sqlite --legacy /path/to/legacy-copy --apply --writers-stopped --backup-dir backups` | מסד שעבר מיגרציות, תיקיית גיבוי וכותבים עצורים; ייבוא תוספתי. |
-| אבחון לוח | `php bin/check-calendar.php --date=2026-10-15` | HTTPS ציבורי בלבד; ללא DB, .env או סשן. `--help` מציג קואורדינטות/אזור/לוח/שפה. |
-| אימות תיקונים | `php scripts/verify-patches.php` | בדיקת התוכן המותקן המאושר. |
-| החלת תיקונים | `composer patches` | החלה ואימות; בהתקנה עצורה בלבד. |
-| זיהוי בנייה | `php bin/build-metadata.php --commit=YOUR_40_HEX_COMMIT` | מחליפים את מציין המקום במקור מאומת; כתיבת זיהוי ודחיית טביעה לא תואמת. |
-
-
-## שדרוג וייבוא מהגרסה הישנה
-
-שמרו תצורה פרטית, נתונים וסשן ואת זהות פרויקט Compose. השתמשו במקור ו־lock שנבדקו; עצרו כל כותב לפני שינוי סכמה או תלויות מותקנות. שדרוג רגיל נעשה עם `composer install`, ולא עם `composer update`.
-
-למסד Compose קיים, מתוך הפרויקט המוכן המחובר ל־**אותם כרכים**:
-
-
-
-~~~sh
-docker compose build
-docker compose stop shabbat
-docker compose run --rm --no-deps shabbat mkdir -p /app/data/backups
-docker compose run --rm --no-deps shabbat php bin/backup.php --db /app/data/shabbat.sqlite --directory /app/data/backups --keep 7
-~~~
-
-
-
-השלימו גיבוי סשן ו־BroadcastManager כשהם עצורים ותרגול שחזור, כמתואר בהמשך, **לפני המשך העבודה**. לאחר מכן הריצו את המיגרציה ובדיקת השחרור:
-
-
-
-~~~sh
-docker compose run --rm --no-deps shabbat php bin/migrate.php --writers-stopped --db /app/data/shabbat.sqlite --backup-dir /app/data/backups
-docker compose run --rm --no-deps shabbat php bin/self-check.php --release
-~~~
-
-
-
-`docker compose up -d shabbat` מפעיל לאחר מכן את התמונה שנבדקה; בדקו לוגים ובריאות. הסדר בהתקנה ידנית: עצירה, גיבוי, התקנה מה־lock, מיגרציה, בדיקה והפעלה.
-
-גרסה 3.0.0 אינה מוסיפה מיגרציה מעבר ל־dev.9. המעבר מ־dev.8 ל־dev.9 הוסיף `016_delivery_safety.sql`. מ־dev.6 נדרשות גם 013–015; גרסאות מוקדמות מחילות אוטומטית את כל החסרות. אין לערוך SQL שכבר הוחל. ניסיונות מסירה קודמים שלא הוכרעו מטופלים בזהירות; צילומי הרשאות ישנים שאינם מאומתים עדיין דורשים בדיקת מנהל.
-
-במעבר מהבוט הישן מבוסס הקבצים: שמרו עותק מוגן, עצרו את הכותבים הישנים לייבוא הסופי ולמעבר, אתחלו מסד חדש, בצעו dry-run, השוו ספירות/תבניות/הרשאות/אזהרות ואז החילו עם כותבים עצורים ותיקיית גיבוי. הפקודות המדויקות מופיעות לעיל. ב־Docker חברו רק את העותק המוגן לקריאה בלבד:
-
-
-
-~~~sh
-docker compose run --rm --no-deps --volume /absolute/path/legacy-copy:/legacy:ro shabbat php bin/import-legacy.php --db /app/data/shabbat.sqlite --legacy /legacy --dry-run
-~~~
-
-
-
-ייבוא מפורש משמר לפי הנתונים קבוצות, תבניות/ישויות/מדיה/כפתורים, טיוטות, נמענים מוכרים ועדויות הרשאות, ללא קריאות Telegram. המודולים החדשים נשארים כבויים; צילום חסר או פגום נשאר לטיפול. הגשר של `DBgroups.txt` בעת עלייה מוסיף רישומים בלבד ואינו מחליף ייבוא מלא. אין להחליף נתוני ייצור במסד או בסשן של בוט בדיקה.
-
-[מעבר](docs/MIGRATION.md) · [סכמה](docs/DATABASE.md) · [צילומים ישנים](docs/DEV8_PERMISSIONS.md)
-
-
-## גיבוי וחזרה לגרסה קודמת
-
-גיבוי SQLite משתמש ב־`VACUUM INTO`, מאמת שלמות, מפתחות זרים והיסטוריית סכמה וכותב נתוני SHA-256. העתקת הקובץ הראשי החי בלבד עלולה להשמיט נתונים שכבר נכתבו ל־WAL. שמירת הגיבויים מוחקת רק שמות מדויקים של הכלי בתיקייה שנבחרה; בחרו `--keep` במכוון.
-
-SQLite **אינו** כולל את הסשן ואת כל קובצי BroadcastManager. עצרו את הכותבים ושמרו בנפרד נתיבים אלה, תצורה פרטית וקוד/lock תואמים לצד גיבוי המסד. דוגמת Docker **לאחר עצירת השירות**, משורש הפרויקט במארח. השתמשו בתיקיית עותק חדשה וריקה לכל גיבוי (החליפו את `../shabbat-private-backup` באופן עקבי):
-
-
-
-~~~sh
-mkdir -p ../shabbat-private-backup
-chmod 700 ../shabbat-private-backup
-docker compose cp shabbat:/app/data ../shabbat-private-backup/data
-docker compose cp shabbat:/app/runtime ../shabbat-private-backup/runtime
-cp .env ../shabbat-private-backup/config.env
-chmod 600 ../shabbat-private-backup/config.env
-~~~
-
-
-
-כך מועתקות תיקיות הנתונים המתמשכים כשהתהליך עצור לתיקייה מקבילה מחוץ להקשר הבנייה של Docker. שמרו אותן בפרטיות ומחוץ לחומר הפרסום. בהתקנה ידנית העתיקו את נתיבי הנתונים והסשן האמיתיים כשהכותבים עצורים. אמתו גיבויים לפני החלפה.
-
-צרו תיקיית תרגול נפרדת ושחזרו אליה גיבוי SQLite נבחר ומאומת:
-
-
-
-~~~sh
-mkdir -p ../shabbat-rehearsal
-php bin/restore.php --backup backups/CHOSEN.sqlite --db ../shabbat-rehearsal/restored.sqlite --writers-stopped
-php bin/health.php --db ../shabbat-rehearsal/restored.sqlite --deep
-~~~
-
-
-
-החליפו `CHOSEN.sqlite` בשם האמיתי. בדקו שדות מבנה, סכמה ודגימת רשומות; בדיקת הבריאות הכוללת עשויה לצאת ב־1 ללא פעימות חיות.
-
-חזרה לגרסה קודמת: עצרו כותבים, שמרו גיבוי התאוששות עדכני, פתרו או תעדו חובות הרשאה ב־Telegram, שחזרו מסד/קוד/lock/סשן/מצב BroadcastManager תואמים, הפעילו עותק יחיד ובדקו התאמה להרשאות מרוחקות טריות. שחזור מסד אינו מבטל שינוי שכבר התקבל ב־Telegram. כלי השחזור מאמת קלט ומניפסט, מקבל נעילת כותב ושומר `*.before-restore-*`. כותב עסוק או סכמה לא תואמת דורשים בדיקה, ולא מחיקת נעילות או כרכים.
-
-[גיבוי ושחזור מפורטים](docs/BACKUP_RESTORE.md)
-
-
-## פתרון תקלות
-
-| תסמין | פעולה |
-|---|---|
-| commit חסר או מקור ששונה בזמן הבנייה | שמרו נתוני ארכיון מאומתים או מסרו זהות אמיתית של עותק שנבדק. לאחר שינוי מקור מפיקים מחדש נתוני ארכיון. |
-| בדיקת שחרור SQLite נכשלת | השתמשו בתמונה הנעולה או בסביבה מתוקנת ומתקבלת; אזהרת פיתוח אינה אישור ייצור. |
-| סכמה חסרה או ישנה | עצרו כותבים, גבו והריצו מיגרציה לנתיב מפורש. העלייה אינה מבצעת מיגרציה. |
-| כישלון תיקון | בדקו lock ומניפסטים והתקינו בעותק נקי ועצור; אין להחליש אימות. |
-| קבוצה חדשה לא שולחת | בדקו מצב, מיקום, הפעלת מודול ותזמון; `/add` מתחיל כבוי. |
-| הגדרות חסומות או פגו | פתחו שיחה פרטית ופאנל `/settings` חדש כמנהלי הקבוצה הנוכחיים. |
-| חיפוש עיר נכשל | בדקו הפעלת GeoNames, חשבון, מכסה ו־HTTPS; השתמשו בעיר מוכרת או בקואורדינטות לפי הצורך. |
-| מצב לא בריא | בדקו גיל שתי הפעימות, סכמה, תור ולוגים; מתזמן עצור אינו מעדכן פעימה. |
-| קבוצה לא נפתחת | השתמשו בהתאוששות ובאבחון לצילומים חסרים/לא מאומתים/מתנגשים ושמרו הגבלות מקוריות. |
-| תזכורת חסרה או מאוחרת | בדקו אזור זמן/תאריך, שקט, מדיניות חג וסיום, מודול ונושא. הזכאות נבדקת במסירה. |
-| דחיית אימוג׳י מותאם | הגדירו `CUSTOM_EMOJI_ENABLED=0`; גם דחיית זכאות ודאית מפעילה חלופה. |
-| שגיאת הרשאות קבצים | בדקו UID/GID 10001 ונתיבי עבודה/נתונים/סשן, והריצו בדיקת כתיבה. הימנעו מהרשאת כתיבה לכולם. |
-
-[תקלות נוספות](docs/TROUBLESHOOTING.md) · [פרטיות](docs/PRIVACY.md) · [דיווח אבטחה](.github/SECURITY.md)
-
-
-## מבנה הפרויקט ופיתוח
-
-| נתיב | תוכן |
-|---|---|
-| `bot.php`, `src/` | כניסה לבוט ושירותי לוח, ממשק, תזמון, אחסון, Telegram וריצה. |
-| `bin/`, `migrations/` | תחזוקה ושינויי סכמה ממוספרים שאינם משתנים אחרי החלה. |
-| `resources/` | שש שפות, מקורות עומר מיוחסים ותצורת PHP. |
-| `patches/` | מקורות בסיס ותוכן מתוקן שנבדקו, diffs, מקור וחתימות SHA-256. |
-| `tests/` | בדיקות ונתוני JSON/TXT/PHP חיוניים. |
-| `scripts/` | תיקונים, איכות, תלויות ואריזה מקומית. |
-| `docs/`, `LICENSES/` | מדריכים, מקור ורישיונות. |
-| `.github/` | תהליכי CI ושחרור ותבניות תרומה ואבטחה. |
-
-הריצו **בשורש עותק פיתוח נפרד, כחשבון המפתח**, ללא נתוני ייצור או סודות. ההתקנה כוללת כלי בדיקה; הבדיקות משתמשות במצב זמני מבודד.
-
-
-
-~~~sh
-composer install --no-interaction --prefer-dist
-composer validate --strict --no-check-all
-composer check-platform-reqs
-php scripts/verify-patches.php
-composer test
-composer lint
-composer style
-composer analyse
-composer check-locales
-composer check-docs
-composer self-check
-~~~
-
-
-
-האפשרות `--no-check-all` מדלגת על עצת טווח גרסאות כללית בשל נעילת MadelineProto המדויקת; בדיקות סכמה ו־lock מחמירות נשארות. `lint` בודק תחביר ואיכות, `style` אוכף שגיאות PHPCS ו־`analyse` מפעיל PHPStan. `composer style-review` מציג דוח סגנון רחב יותר; `composer style-fix` **משכתב קבצים**, ולכן מיועד לעותק פיתוח מבוקר בלבד.
-
-באותו שורש פיתוח:
-
-
-
-~~~sh
-composer show --locked --format=json
-composer licenses --format=json
-composer audit --locked --format=json
-composer dependencies
-~~~
-
-
-
-הפקודות מדווחות על חבילות נעולות, רישיונות מותקנים והתראות עדכניות; audit פונה לשירותי התראות. `dependencies` כותב עדויות ב־`docs/`; בדקו וסננו אותן לפני הכללה. אין להחליף lock כדי להשתיק בדיקה.
-
-הפקת תיקונים מחדש למפתחים בלבד, משורש עותק הפיתוח:
-
-
-
-~~~sh
-php patches/madelineproto/generate-artifacts.php
-php patches/broadcastmanager/generate-artifacts.php
-~~~
-
-
-
-הפקודות משכתבות תוצרי תיקון ומניפסטים מהמקורות המצורפים שנבדקו. הן מיועדות לסקירת תיקון יזומה, ולא להתקנה רגילה. בדקו חתימות ו־diffs ששונו והריצו לאחר מכן את כל בדיקות התיקונים. סקריפטי ההחלה והאימות ב־PHP מקבלים גם פרמטר מיקום ראשון אופציונלי לתיקיית vendor; השאירו אותו ריק לשימוש רגיל ב־`vendor/`.
-
-לאריזת שחרור מעותק Git נקי שכל שינוייו נשמרו ב־commit, עם Git, Python 3.9+ ותלויות הפיתוח הנעולות:
-
-
-
-~~~sh
-php scripts/package.php
-~~~
-
-
-
-הכלי כותב אל `dist/` את `shabbat-3.0.0.zip`, את `shabbat-3.0.0-corresponding-source.zip`, את `RELEASE_MANIFEST.json` ואת `SHA256SUMS`, ללא פרסום. חבילת המקור כוללת תלויות ריצה נעולות, תיקונים שנבדקו והשלמות מקור מגרסאות נעולות. הכלי הישן המפיק שלושה ארכיונים זמין לפיתוח מקומי בלבד באמצעות `php scripts/package.php --development`, עם פלט ברירת מחדל ב־`dist/development/`; הפצות כלי הפיתוח המותקנות שלו אינן הצעת מקור תואם לשחרור. ראו [הכנת שחרור](docs/RELEASE.md) לדרישות, לתכולת המקור ולבדיקת התוצרים.
-
-[ארכיטקטורה](docs/ARCHITECTURE.md) · [תלויות](docs/DEPENDENCIES.md) · [תיקונים](docs/PATCHES.md) · [הכנת שחרור](docs/RELEASE.md) · [תרומה](.github/CONTRIBUTING.md) · [קוד התנהגות](.github/CODE_OF_CONDUCT.md)
-
-
-## רישוי וקרדיטים
+| התקנה מפורטת והתקנת PHP ידנית | [התקנה](docs/INSTALLATION.md) |
+| משתני סביבה והעדפות | [תצורה](docs/CONFIGURATION.md) |
+| פקודות וניהול | [פקודות](docs/COMMANDS.md), [תפעול](docs/OPERATIONS.md), [פאנל מנהלים](docs/ADMIN_PANEL.md) |
+| שדרוג, ייבוא ושחזור | [English](docs/PRODUCTION_UPGRADE.md), [עברית](docs/PRODUCTION_UPGRADE_HE.md), [מיפוי ייבוא](docs/MIGRATION.md), [גיבוי ושחזור](docs/BACKUP_RESTORE.md) |
+| הרשאות, זמנים ותזכורות | [התאוששות הרשאות](docs/PERMISSION_RECOVERY.md), [שיטות חישוב](docs/ZMANIM_METHODS.md), [בטיחות מסירה](docs/DELIVERY_SAFETY.md) |
+| תקלות ואבחון | [פתרון תקלות](docs/TROUBLESHOOTING.md), [אבחון](docs/DIAGNOSTICS.md) |
+| פיתוח ובדיקות | [תרומה](.github/CONTRIBUTING.md), [ארכיטקטורה](docs/ARCHITECTURE.md), [מצב הבדיקות](docs/IMPLEMENTATION_STATUS.md) |
+| גרסאות ואריזת מקור | [שינויים](CHANGELOG.md), [הערות שחרור](docs/RELEASE_NOTES.md), [תהליך שחרור](docs/RELEASE.md) |
-היישום המשולב הוא **AGPL-3.0-only**: [הרישיון](LICENSE), [מדיניות רישוי](docs/LICENSING.md). הודעות MIT והרשאות היסטוריות נשמרות. רישיונות התלויות, הנתונים והתעתיקים נפרדים; הכותרות וההודעות שלהם נשמרות.
+
+## רישיון וקרדיטים
-קרדיט ל־[WizardLoop](https://github.com/WizardLoop), [MadelineProto](https://github.com/danog/MadelineProto), [BroadcastManager](https://github.com/WizardLoop/BroadcastManager), [Hebcal](https://www.hebcal.com/), [GeoNames](https://www.geonames.org/) ולמקורות התפילה המיוחסים מוויקיטקסט. רכיבים, רישיונות, גרסאות מקור קבועות, שינויים וייחוס מתועדים ב־[THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md), במניפסטי תלויות ובנתוני המקור של המשאבים.
+היישום מופץ ברישיון **AGPL-3.0-only**. יש לשמור את [הרישיון](LICENSE), הודעות זכויות היוצרים ההיסטוריות ו[הודעות צד שלישי](THIRD_PARTY_NOTICES.md). רישיונות התלויות נפרדים. שם נכלל הייחוס ל־MadelineProto, BroadcastManager, Hebcal, GeoNames ולמקורות המשאבים.
-מפעילים ו־forks צריכים להעמיד **מקור תואם בדיוק לגרסה שנפרסה**, כולל שינויים מקומיים ביישום ובתלויות וחומר בנייה נחוץ, ולהגדיר `SOURCE_URL`. קישור ל־`main` ציבורי שונה אינו מספיק. חומר הפרסום מחריג תצורה פרטית, DB/WAL/SHM חיים, סשנים, גיבויים, לוגים ו־caches, ושומר מקור נחוץ, בדיקות ונתוניהן, מקורות בסיס לתיקונים ורישיונות.
+מפעילים חייבים להציע את המקור התואם המדויק של שינויים שהם מפעילים. ארכיון Corresponding Source הנפרד כולל את היישום ואת מקורות הריצה המתועדים, בלי טענה למקור מלא של מערכת ההפעלה או כל כלי הפיתוח. ראו [רישוי](docs/LICENSING.md).
diff --git a/resources/locales/en.json b/resources/locales/en.json
index 5622054..851dd62 100644
--- a/resources/locales/en.json
+++ b/resources/locales/en.json
@@ -313,6 +313,7 @@
"permission_send_plain": "Send plain text",
"permission_edit_rank": "Edit member titles",
"permission_send_reactions": "Send reactions",
+ "permission_manage_linked_peers": "Manage linked chats",
"bot_permissions": "🛡 Bot administrator rights",
"bot_permissions_intro": "Read-only Telegram permission diagnostics. Grant required rights through the group's administrator settings; the bot cannot grant rights to itself.",
"bot_role_creator": "Group owner",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "Delete stories",
"admin_right_manage_direct_messages": "Manage channel direct messages",
"admin_right_manage_ranks": "Manage member ranks",
+ "admin_right_manage_linked_peers": "Manage linked chats",
+ "admin_right_manage_welcome_messages": "Manage welcome messages",
"welcome": "✡️ Shabbat Guardian\nShabbat and holiday times, daily zmanim, Daf Yomi and the Omer, for your location.\n\nChoose what to view, or open your preferences to manage your language and location.\n\nGroup administrators can manage each group through “My groups”.",
"help": "ℹ️ Information and help",
"home": "🏠 Main menu",
diff --git a/resources/locales/es.json b/resources/locales/es.json
index ac1c03f..c11b904 100644
--- a/resources/locales/es.json
+++ b/resources/locales/es.json
@@ -313,6 +313,7 @@
"permission_send_plain": "Enviar texto simple",
"permission_edit_rank": "Editar los títulos de los miembros",
"permission_send_reactions": "Enviar reacciones",
+ "permission_manage_linked_peers": "Gestionar chats vinculados",
"bot_permissions": "🛡 Permisos de administrador del bot",
"bot_permissions_intro": "Diagnóstico de permisos de Telegram de solo lectura. Concede los permisos necesarios en los ajustes de administradores del grupo; el bot no puede concederse permisos a sí mismo.",
"bot_role_creator": "Propietario del grupo",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "Eliminar historias",
"admin_right_manage_direct_messages": "Gestionar mensajes directos del canal",
"admin_right_manage_ranks": "Gestionar los rangos de miembros",
+ "admin_right_manage_linked_peers": "Gestionar chats vinculados",
+ "admin_right_manage_welcome_messages": "Gestionar mensajes de bienvenida",
"welcome": "✡️ Guardián del Shabat\nHorarios de Shabat y fiestas, zmanim, Daf Yomi y cuenta del Ómer según tu ubicación.\n\nElige qué consultar o abre tus preferencias para ajustar el idioma y la ubicación.\n\nLos administradores pueden gestionar cada grupo desde «Mis grupos».",
"help": "ℹ️ Información y ayuda",
"home": "🏠 Menú principal",
diff --git a/resources/locales/fr.json b/resources/locales/fr.json
index bc08449..fb5e7d0 100644
--- a/resources/locales/fr.json
+++ b/resources/locales/fr.json
@@ -313,6 +313,7 @@
"permission_send_plain": "Envoyer du texte simple",
"permission_edit_rank": "Modifier les titres des membres",
"permission_send_reactions": "Envoyer des réactions",
+ "permission_manage_linked_peers": "Gérer les discussions liées",
"bot_permissions": "🛡 Droits d’administration du bot",
"bot_permissions_intro": "Diagnostic des permissions Telegram en lecture seule. Accordez les droits nécessaires dans les réglages des administrateurs du groupe ; le bot ne peut pas s’accorder lui-même des droits.",
"bot_role_creator": "Propriétaire du groupe",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "Supprimer des stories",
"admin_right_manage_direct_messages": "Gérer les messages directs du canal",
"admin_right_manage_ranks": "Gérer les rangs des membres",
+ "admin_right_manage_linked_peers": "Gérer les discussions liées",
+ "admin_right_manage_welcome_messages": "Gérer les messages de bienvenue",
"welcome": "✡️ Gardien du Chabbat\nHoraires du Chabbat et des fêtes, zmanim, Daf Yomi et compte du Omer selon votre lieu.\n\nChoisissez une rubrique ou ouvrez vos préférences pour régler la langue et le lieu.\n\nLes administrateurs peuvent gérer chaque groupe dans « Mes groupes ».",
"help": "ℹ️ Informations et aide",
"home": "🏠 Menu principal",
diff --git a/resources/locales/he.json b/resources/locales/he.json
index c2a03e3..b3dc402 100644
--- a/resources/locales/he.json
+++ b/resources/locales/he.json
@@ -313,6 +313,7 @@
"permission_send_plain": "שליחת טקסט רגיל",
"permission_edit_rank": "עריכת תארי חברים",
"permission_send_reactions": "הוספת תגובות",
+ "permission_manage_linked_peers": "ניהול צ׳אטים מקושרים",
"bot_permissions": "🛡 הרשאות מנהל של הבוט",
"bot_permissions_intro": "אבחון הרשאות טלגרם לקריאה בלבד. הרשאות נדרשות מעניקים בהגדרות מנהלי הקבוצה; הבוט אינו יכול להעניק לעצמו הרשאות.",
"bot_role_creator": "בעל הקבוצה",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "מחיקת סיפורים",
"admin_right_manage_direct_messages": "ניהול הודעות ישירות בערוץ",
"admin_right_manage_ranks": "ניהול תארי חברים",
+ "admin_right_manage_linked_peers": "ניהול צ׳אטים מקושרים",
+ "admin_right_manage_welcome_messages": "ניהול הודעות קבלת פנים",
"welcome": "✡️ שומר שבת\nזמני שבת וחג, זמני היום, דף יומי וספירת העומר, לפי המיקום שלך.\n\nבחרו מה להציג, או פתחו את ההעדפות שלכם לניהול השפה והמיקום.\n\nמנהלי קבוצות יכולים לנהל כל קבוצה דרך ״הקבוצות שלי״.",
"help": "ℹ️ מידע ועזרה",
"home": "🏠 תפריט ראשי",
diff --git a/resources/locales/pt-br.json b/resources/locales/pt-br.json
index 91af90d..572c4d6 100644
--- a/resources/locales/pt-br.json
+++ b/resources/locales/pt-br.json
@@ -313,6 +313,7 @@
"permission_send_plain": "Enviar texto simples",
"permission_edit_rank": "Editar títulos de membros",
"permission_send_reactions": "Enviar reações",
+ "permission_manage_linked_peers": "Gerenciar chats vinculados",
"bot_permissions": "🛡 Direitos de administrador do bot",
"bot_permissions_intro": "Diagnóstico de permissões do Telegram somente para leitura. Conceda os direitos nas configurações dos administradores do grupo; o bot não pode concedê-los a si mesmo.",
"bot_role_creator": "Dono do grupo",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "Excluir stories",
"admin_right_manage_direct_messages": "Gerenciar mensagens diretas do canal",
"admin_right_manage_ranks": "Gerenciar títulos de membros",
+ "admin_right_manage_linked_peers": "Gerenciar chats vinculados",
+ "admin_right_manage_welcome_messages": "Gerenciar mensagens de boas-vindas",
"welcome": "✡️ Guardião do Shabat\nHorários de Shabat e festas, zmanim, Daf Yomi e contagem do Ômer para sua localização.\n\nEscolha o que consultar ou abra suas preferências para ajustar o idioma e a localização.\n\nAdministradores podem gerenciar cada grupo em “Meus grupos”.",
"help": "ℹ️ Informações e ajuda",
"home": "🏠 Menu principal",
diff --git a/resources/locales/ru.json b/resources/locales/ru.json
index 948e895..ec53997 100644
--- a/resources/locales/ru.json
+++ b/resources/locales/ru.json
@@ -313,6 +313,7 @@
"permission_send_plain": "Отправка обычного текста",
"permission_edit_rank": "Изменение званий участников",
"permission_send_reactions": "Отправка реакций",
+ "permission_manage_linked_peers": "Управление связанными чатами",
"bot_permissions": "🛡 Права администратора бота",
"bot_permissions_intro": "Диагностика прав Telegram только для чтения. Нужные права выдаются в настройках администраторов группы; бот не может выдать их себе.",
"bot_role_creator": "Владелец группы",
@@ -334,6 +335,8 @@
"admin_right_delete_stories": "Удаление историй",
"admin_right_manage_direct_messages": "Управление личными сообщениями канала",
"admin_right_manage_ranks": "Управление званиями участников",
+ "admin_right_manage_linked_peers": "Управление связанными чатами",
+ "admin_right_manage_welcome_messages": "Управление приветственными сообщениями",
"welcome": "✡️ Хранитель Шаббата\nВремя Шаббата и праздников, зманим, Даф Йоми и счёт Омера для вашего местоположения.\n\nВыберите раздел или откройте настройки, чтобы изменить язык и местоположение.\n\nАдминистраторы могут управлять каждой группой через «Мои группы».",
"help": "ℹ️ Информация и помощь",
"home": "🏠 Главное меню",
diff --git a/resources/release/README.md b/resources/release/README.md
index 68a6f37..d3d65a7 100644
--- a/resources/release/README.md
+++ b/resources/release/README.md
@@ -1,17 +1,15 @@
# Pinned corresponding-source inputs
-This directory contains release-packaging inputs, not installed dependencies or runtime state.
+This directory holds release source inputs, not installed dependencies or runtime state.
-- [source-manifest.json](source-manifest.json) pins **2,960 runtime dependency files** from the 57 locked Composer packages and **92 preferred-source supplements**.
-- The amphp-windows-process-wrapper collection retains 18 original upstream files for the distributed Windows helpers, including their MIT license.
-- The madelineproto-build-inputs collection retains 74 pinned generator/build, schema, language and template inputs with their original notices.
+[source-manifest.json](source-manifest.json) pins **4,095 runtime files from 83 locked Composer packages** and **103 preferred-source files**. The supplements contain 18 upstream Windows helper files, 84 MadelineProto 8.11.10 generator/current-schema/language inputs and the pinned RTC AV README, preserving original licenses and Git-blob/SHA-256 evidence.
-The manifest maps each supplementary archive path to its checked-in file below preferred-source/additional-source. The packager copies these bytes to additional-source in the corresponding-source archive and verifies installed runtime package files against the same approved inventory. It rejects a different Composer lock or unknown source bytes. Application files and the final release identity come from the reviewed Git tree, not from the historical artifact identity in this manifest.
+The runtime inventory was compared with each exact locked Composer distribution. Only the fresh-peer and BroadcastManager outputs differ, matching their approved manifests. It excludes two public Amp TLS example private keys by exact hash, installed development tools and generated Composer autoload/bin metadata. Unknown, missing or changed runtime files fail packaging.
-These inputs were reverified against the published v3.0.0-dev.9 source asset and its upstream provenance records. Source URLs, revisions, Git blobs and file hashes remain in the manifest. The Git attributes prevent line-ending conversion of the preferred-source files; upstream attributes are stored as .gitattributes.source with the original archive path in the manifest. Do not edit upstream files or license notices to make a hash check pass; review and repin an intentional upstream change.
+Each supplementary archive path maps to its checked-in file below preferred-source/additional-source. Upstream attributes are stored as .gitattributes.source to prevent them overriding immutable checkout bytes, then restored to their original archive name. Do not edit upstream bytes to satisfy a hash check; review and repin intentional changes.
-The two approved upstream documentation symlinks are recorded explicitly in source_symlinks: danog/async-orm and danog/telegram-entities each link docs/index.md to ../README.md within the same locked package. The historical Windows extraction stored the link-target text as regular files; its approved SHA-256 values remain unchanged. Packaging accepts only these exact target bytes, whether read from native symlinks or those materialized files, and writes them with the original Unix symlink mode 120777 in the corresponding-source ZIP. Unlisted symlinks and targets outside their package are rejected. The deployment application ZIP contains no dependency symlinks.
+The two approved dependency documentation symlinks map docs/index.md to ../README.md inside danog/async-orm and danog/telegram-entities. Packaging validates exact target bytes whether represented as native symlinks or Windows materialized pointers, then retains Unix mode 120777. Unlisted/escaping links are rejected.
-The two public upstream Amp HTTP Server development TLS private-key examples are omitted by exact approved hash. Their recorded omissions remain in the manifest. Installed development tools, generated Composer autoload/bin metadata, PHP, SQLite and operating-system/base-image source remain outside this runtime source collection.
+The Windows helper source association is established, but no reproducible binary rebuild is claimed. TL232/current file-reference-map and language inputs are included; full historical schema/doc generation and mutable RPC responses are not claimed reproducible. No generator was run. PHP, SQLite, optional native FFmpeg libraries and system/base-image source are outside this scope.
-The Windows helper association is supported by original release/history evidence, but its binaries were not reproducibly rebuilt. The supplied MadelineProto generators were not executed; upstream translation/documentation steps that depend on mutable remote services are not claimed reproducible offline. See [licensing](../../docs/LICENSING.md) and [technical provenance](../../docs/THIRD_PARTY_DETAILS.md) for the exact scope and remaining findings.
+See [licensing](../../docs/LICENSING.md) and [technical provenance](../../docs/THIRD_PARTY_DETAILS.md) for metadata/license conflicts and remaining provenance findings.
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitattributes.source b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitattributes.source
index 700a7ff..d6a33f6 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitattributes.source
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitattributes.source
@@ -6,3 +6,7 @@ CHANGELOG.md export-ignore
psalm-baseline.xml export-ignore
langs/ export-ignore
+webui/ export-ignore
+src/WebUI/templates/assets/tweb/app.js linguist-generated
+src/WebUI/templates/assets/tweb/app.css linguist-generated
+src/WebUI/templates/assets/tweb/tgs/** linguist-vendored
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitmodules b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitmodules
new file mode 100644
index 0000000..cebef61
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/.gitmodules
@@ -0,0 +1,15 @@
+[submodule "examples/magnaluna"]
+ path = examples/magnaluna
+ url = https://github.com/danog/magnaluna.git
+[submodule "examples/pipesbot"]
+ path = examples/pipesbot
+ url = https://github.com/danog/pipesbot.git
+[submodule "schemas"]
+ path = schemas
+ url = https://github.com/danog/schemas.git
+[submodule "docs"]
+ path = docs
+ url = https://github.com/danog/MadelineProtoDocs.git
+[submodule "examples/downloadRenameBot"]
+ path = examples/downloadRenameBot
+ url = https://github.com/danog/downloadRenameBot
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/README.md b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/README.md
index a2f818f..12d32f7 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/README.md
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/README.md
@@ -45,6 +45,10 @@ if (!$me['bot']) {
} catch (\danog\MadelineProto\RPCErrorException $e) {
$MadelineProto->logger($e);
}
+
+ // Video call @magicalcrazypony, the MadelineProto video webradio, playing a WebM video (works on webhosts, NO ffmpeg needed!)
+ // See https://docs.madelineproto.xyz/docs/CALLS.html for group calls, livestreams, recording and more.
+ $MadelineProto->requestCall('@magicalcrazypony', video: true)->play(new \danog\MadelineProto\RemoteUrl('https://paste.daniil.it/oncall.webm'));
}
$MadelineProto->echo('OK, done!');
```
@@ -91,7 +95,9 @@ Some of MadelineProto's core components are also available as separate, standalo
* [QR code login (user)](https://docs.madelineproto.xyz/docs/LOGIN.html#qr-code-user)
* [Features](https://docs.madelineproto.xyz/docs/FEATURES.html) - MadelineProto can do everything official clients can do, and more!
* [Requirements](https://docs.madelineproto.xyz/docs/REQUIREMENTS.html) - MadelineProto requires the mbstring, xml, json, fileinfo, gmp, openssl, iconv, gd extensions to function properly.
-* [MadelineProto on Docker](https://docs.madelineproto.xyz/docs/DOCKER.html) - MadelineProto offers an official MadelineProto docker image for the linux/amd64, linux/arm64 and linux/riscv64 platforms @ hub.madelineproto.xyz/danog/madelineproto.
+* [MadelineProto on Docker](https://docs.madelineproto.xyz/docs/DOCKER.html) - MadelineProto offers an official MadelineProto docker image for the linux/amd64 and linux/arm64 platforms @ hub.madelineproto.xyz/danog/madelineproto.
+ * [Tags](https://docs.madelineproto.xyz/docs/DOCKER.html#tags)
+ * [User and permissions](https://docs.madelineproto.xyz/docs/DOCKER.html#user-and-permissions)
* [Getting started](https://docs.madelineproto.xyz/docs/DOCKER.html#getting-started)
* [CLI bot (recommended)](https://docs.madelineproto.xyz/docs/DOCKER.html#cli-bot-recommended)
* [Databases on docker](https://docs.madelineproto.xyz/docs/DOCKER.html#databases-on-docker)
@@ -130,6 +136,19 @@ Some of MadelineProto's core components are also available as separate, standalo
* [danog\MadelineProto\EventHandler\AbstractStory »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/AbstractStory.html) - Represents a Telegram Story.
* [danog\MadelineProto\EventHandler\BotCommands »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/BotCommands.html) - The [command set](https://core.telegram.org/api/bots/commands) of a certain bot in a certain chat has changed.
* [danog\MadelineProto\EventHandler\CallbackQuery »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/CallbackQuery.html) - Represents a query sent by the user by clicking on a button.
+ * [danog\MadelineProto\EventHandler\Calls\AbstractGroupCall »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/AbstractGroupCall.html) - What a [video chat/livestream »](https://core.telegram.org/api/group-calls#video-chats-livestreams)
+ * [danog\MadelineProto\EventHandler\Calls\AbstractGroupCallMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/AbstractGroupCallMessage.html) - What an in-call message of a video chat ({@see GroupCallMessage}) and of a live story
+ * [danog\MadelineProto\EventHandler\Calls\CallStreams »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/CallStreams.html) - The streams a participant of a call sends (their microphone, camera and screen share, see
+ * [danog\MadelineProto\EventHandler\Calls\ConferenceCall »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/ConferenceCall.html) - This update represents a Telegram [end-to-end encrypted conference call »](https://core.telegram.org/api/end-to-end/group-calls).
+ * [danog\MadelineProto\EventHandler\Calls\ConferenceCallMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/ConferenceCallMessage.html) - An end-to-end encrypted [in-call message or reaction »](https://core.telegram.org/api/end-to-end/group-calls#conference-in-call-messages)
+ * [danog\MadelineProto\EventHandler\Calls\GroupCall »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/GroupCall.html) - This update represents a Telegram [video chat or livestream »](https://core.telegram.org/api/group-calls#video-chats-livestreams):
+ * [danog\MadelineProto\EventHandler\Calls\GroupCallMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/GroupCallMessage.html) - An [in-call message or reaction »](https://core.telegram.org/api/group-calls#in-call-messages) sent in a [video chat or livestream »](https://core.telegram.org/api/group-calls#video-chats-livestreams)
+ * [danog\MadelineProto\EventHandler\Calls\GroupCallMessagesDeleted »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/GroupCallMessagesDeleted.html) - Some [in-call messages »](https://core.telegram.org/api/group-calls#in-call-messages) of a group call
+ * [danog\MadelineProto\EventHandler\Calls\GroupCallParticipants »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/GroupCallParticipants.html) - Participants of a group call joined, left, or changed state (muted, video, volume, raised hand...),
+ * [danog\MadelineProto\EventHandler\Calls\LiveStory »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/LiveStory.html) - This update represents a Telegram [live story »](https://core.telegram.org/api/group-calls#live-stories):
+ * [danog\MadelineProto\EventHandler\Calls\LiveStoryMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/LiveStoryMessage.html) - An [in-call message or reaction »](https://core.telegram.org/api/group-calls#in-call-messages) sent in a [live story »](https://core.telegram.org/api/group-calls#live-stories) ({@see LiveStory}).
+ * [danog\MadelineProto\EventHandler\Calls\MultiCallMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/MultiCallMessage.html) - An [in-call message or reaction »](https://core.telegram.org/api/group-calls#in-call-messages) sent in a multi-party call, shown as an overlay by the participants' clients (there is no chat history).
+ * [danog\MadelineProto\EventHandler\Calls\PrivateCall »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/PrivateCall.html) - This update represents a private (one-to-one) VoIP Telegram call.
* [danog\MadelineProto\EventHandler\Channel\ChannelParticipant »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Channel/ChannelParticipant.html) - A participant has left, joined, was banned or admin'd in a [channel or supergroup](https://core.telegram.org/api/channel).
* [danog\MadelineProto\EventHandler\Channel\MessageForwards »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Channel/MessageForwards.html) - Indicates that the forward counter of a message in a channel has changed.
* [danog\MadelineProto\EventHandler\Channel\MessageViewsChanged »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Channel/MessageViewsChanged.html) - Indicates that the view counter of a message in a channel has changed.
@@ -141,6 +160,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* [danog\MadelineProto\EventHandler\Delete\DeleteChannelMessages »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Delete/DeleteChannelMessages.html) - Some messages in a [supergroup/channel](https://core.telegram.org/api/channel) were deleted.
* [danog\MadelineProto\EventHandler\Delete\DeleteMessages »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Delete/DeleteMessages.html) - Some messages were deleted in a private chat or simple group.
* [danog\MadelineProto\EventHandler\Delete\DeleteScheduledMessages »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Delete/DeleteScheduledMessages.html) - Some [scheduled messages](https://core.telegram.org/api/scheduled-messages) were deleted from the schedule queue of a chat.
+ * [danog\MadelineProto\EventHandler\GroupOrChannelMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/GroupOrChannelMessage.html) - Represents a group or channel message.
* [danog\MadelineProto\EventHandler\InlineQuery »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/InlineQuery.html) - An incoming inline query.
* [danog\MadelineProto\EventHandler\Message »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message.html) - Represents an incoming or outgoing message.
* [danog\MadelineProto\EventHandler\Message\ChannelMessage »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/ChannelMessage.html) - Represents an incoming or outgoing channel message.
@@ -155,6 +175,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* [danog\MadelineProto\EventHandler\Message\Service\DialogChannelMigrateFrom »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogChannelMigrateFrom.html) - Indicates the channel was [migrated](https://core.telegram.org/api/channel) from the specified chat.
* [danog\MadelineProto\EventHandler\Message\Service\DialogChatJoinedByLink »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogChatJoinedByLink.html) - A user joined the chat via an invite link.
* [danog\MadelineProto\EventHandler\Message\Service\DialogChatMigrateTo »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogChatMigrateTo.html) - Indicates the chat was [migrated](https://core.telegram.org/api/channel) to the specified supergroup.
+ * [danog\MadelineProto\EventHandler\Message\Service\DialogConferenceCall »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogConferenceCall.html) - A service message about an [end-to-end encrypted conference call »](https://core.telegram.org/api/group-calls#conference-calls):
* [danog\MadelineProto\EventHandler\Message\Service\DialogContactSignUp »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogContactSignUp.html) - A contact just signed up to telegram.
* [danog\MadelineProto\EventHandler\Message\Service\DialogCreated »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogCreated.html) - A chat or channel was created.
* [danog\MadelineProto\EventHandler\Message\Service\DialogDeleteMessages »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Message/Service/DialogDeleteMessages.html) - Deleted messages.
@@ -221,7 +242,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* [danog\MadelineProto\EventHandler\User\Status\Online »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/User/Status/Online.html) - Online status of the user.
* [danog\MadelineProto\EventHandler\User\Status\Recently »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/User/Status/Recently.html) - Online status: last seen recently.
* [danog\MadelineProto\EventHandler\User\Username »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/User/Username.html) - Changes were made to the user’s first name, last name or username.
- * [danog\MadelineProto\VoIP »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/VoIP.html) - This update represents a VoIP Telegram call.
+ * [danog\MadelineProto\VoIP »](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/VoIP.html) - This update represents a private (one-to-one) VoIP Telegram call.
* [Filters](https://docs.madelineproto.xyz/docs/FILTERS.html) - MadelineProto offers a very simple and intuitive message filtering system, based on PHP's type system and attributes.
* [Simple filters](https://docs.madelineproto.xyz/docs/FILTERS.html#simple-filters)
* [Attribute filters](https://docs.madelineproto.xyz/docs/FILTERS.html#attribute-filters)
@@ -271,11 +292,24 @@ Some of MadelineProto's core components are also available as separate, standalo
* [Getting the TL trace](https://docs.madelineproto.xyz/docs/EXCEPTIONS.html#getting-the-tl-trace)
* [Avoiding FLOOD_WAITs](https://docs.madelineproto.xyz/docs/FLOOD_WAIT.html) - If you make too many requests to telegram, you might get FLOOD_WAITed for a while. To avoid these flood waits, you must calculate the flood wait rate.
* [Logging](https://docs.madelineproto.xyz/docs/LOGGING.html) - MadelineProto provides a unified class for logging messages to the logging destination defined in settings.
-* [Telegram VoIP phone calls](https://docs.madelineproto.xyz/docs/CALLS.html) - MadelineProto provides an easy wrapper to work with phone calls.
+* [Telegram voice/video/group calls](https://docs.madelineproto.xyz/docs/CALLS.html) - MadelineProto can make and receive voice and video calls, stream and record video chats and livestreams, and take part in end-to-end encrypted conference calls.
+ * [Call types](https://docs.madelineproto.xyz/docs/CALLS.html#call-types)
* [Requesting a call](https://docs.madelineproto.xyz/docs/CALLS.html#requesting-a-call)
- * [Playing audio files](https://docs.madelineproto.xyz/docs/CALLS.html#playing-audio-files)
- * [Webhost support!](https://docs.madelineproto.xyz/docs/CALLS.html#webhost-support)
* [Accepting calls](https://docs.madelineproto.xyz/docs/CALLS.html#accepting-calls)
+ * [Playing video files](https://docs.madelineproto.xyz/docs/CALLS.html#playing-video-files)
+ * [Playing audio files](https://docs.madelineproto.xyz/docs/CALLS.html#playing-audio-files)
+ * [Supported formats](https://docs.madelineproto.xyz/docs/CALLS.html#supported-formats)
+ * [Playlists and screen sharing](https://docs.madelineproto.xyz/docs/CALLS.html#playlists-and-screen-sharing)
+ * [Recording calls](https://docs.madelineproto.xyz/docs/CALLS.html#recording-calls)
+ * [Group calls (video chats and livestreams)](https://docs.madelineproto.xyz/docs/CALLS.html#group-calls-video-chats-and-livestreams)
+ * [Livestreams, RTMP and stream mode](https://docs.madelineproto.xyz/docs/CALLS.html#livestreams-rtmp-and-stream-mode)
+ * [Live stories](https://docs.madelineproto.xyz/docs/CALLS.html#live-stories)
+ * [Conference calls](https://docs.madelineproto.xyz/docs/CALLS.html#conference-calls)
+ * [Restarts](https://docs.madelineproto.xyz/docs/CALLS.html#restarts)
+ * [PrivateCall](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/PrivateCall.html): a one-to-one voice or video call (`danog\MadelineProto\VoIP` is an alias kept for backwards compatibility)
+ * [GroupCall](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/GroupCall.html)
+ * [LiveStory](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/LiveStory.html)
+ * [ConferenceCall](https://docs.madelineproto.xyz/PHP/danog/MadelineProto/EventHandler/Calls/ConferenceCall.html)
* [Uploading and downloading files](https://docs.madelineproto.xyz/docs/FILES.html) - MadelineProto provides fully parallelized wrapper methods to upload and download files that support bot API file ids, direct upload by URL and file renaming.
* [Bot API file IDs](https://docs.madelineproto.xyz/docs/FILES.html#bot-api-file-ids)
* [Uploading & sending files](https://docs.madelineproto.xyz/docs/FILES.html#sending-files)
@@ -427,6 +461,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Change the photo of a channel/supergroup: channels.editPhoto
* Change the reaction notification settings »: account.setReactionsNotifySettings
* Change the set of message reactions » that can be used in a certain group, supergroup or channel: messages.setChatAvailableReactions
+ * Change the title of a group call: setGroupCallTitle
* Changes chat name and sends a service message on it: messages.editChatTitle
* Changes chat photo and sends a service message on it: messages.editChatPhoto
* Changes the absolute position of a sticker in the set to which it belongs. The sticker set must have been created by the current user/bot: stickers.changeStickerPosition
@@ -492,11 +527,13 @@ Some of MadelineProto's core components are also available as separate, standalo
* Convert value to unsigned base256 int: packUnsignedInt
* Converts a string into an async amphp stream: stringToStream
* Create a business chat deep link »: account.createBusinessChatLink
+ * Create a group call (video chat or livestream) in the specified group or channel: createGroupCall
* Create a group call or livestream: phone.createGroupCall
* Create a star gift collection »: payments.createStarGiftCollection
* Create a stickerset: stickers.createStickerSet
* Create a supergroup/channel: channels.createChannel
* Create a theme: account.createTheme
+ * Create and join a new end-to-end encrypted conference call, with ourselves as the only: createConferenceCall
* Create and optionally join a new conference call: phone.createConferenceCall
* Create and upload a new wallpaper: account.uploadWallPaper
* Create array: arr
@@ -507,6 +544,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Creates and returns a prometheus gauge: getPromGauge
* Creates and returns a prometheus histogram: getPromHistogram
* Creates and returns a prometheus summary: getPromSummary
+ * Decline an invitation to a conference call: declineConferenceCallInvite
* Declines a conference call invite: phone.declineConferenceCallInvite
* Delete a business chat deep link »: account.deleteBusinessChatLink
* Delete a channel/supergroup: channels.deleteChannel
@@ -586,6 +624,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Enable/disable message signatures in channels: channels.toggleSignatures
* Enable/disable top peers: contacts.toggleTopPeers
* Enables or disables the reception of notifications every time a gift » is received by the specified channel, can only be invoked by admins with post_messages admin rights: payments.toggleChatStarGiftNotifications
+ * End a group call for all participants: discardGroupCall
* Escape string for MadelineProto's HTML entity converter: htmlEscape
* Escape string for URL: markdownUrlEscape
* Escape string for markdown code section: markdownCodeEscape
@@ -594,6 +633,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Executes a custom broadcast action with all peers (users, chats, channels) of the bot: broadcastCustom
* Export a folder », creating a chat folder deep link »: chatlists.exportChatlistInvite
* Export an invite link for a chat: messages.exportChatInvite
+ * Export an invite link for a group call: exportGroupCallInvite
* Export authorization: exportAuthorization
* Extract Update constructors from an Updates constructor: extractUpdates
* Extract a message ID from an Updates constructor: extractMessageId
@@ -630,6 +670,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Fetch updated information about paid media, see here » for the full flow: messages.getExtendedMedia
* Fetches all star gift collections » of a peer: payments.getStarGiftCollections
* Fetches an updatePaidReactionPrivacy update with the current default paid reaction privacy, see here » for more info: messages.getPaidReactionPrivacy
+ * Files to play on hold in a group call: groupCallPlayOnHold
* Find out if a media message's caption can be edited: messages.getMessageEditData
* Finish an SMS job (official clients only): smsjobs.finishJob
* Fork a new green thread and execute the passed function in the background: callFork
@@ -644,11 +685,11 @@ Some of MadelineProto's core components are also available as separate, standalo
* Get RTMP URL and stream key for RTMP livestreams. Can be used even before creating the actual RTMP livestream with phone.createGroupCall (the rtmp_stream flag must be set): phone.getGroupCallStreamRtmpUrl
* Get SMS jobs status (official clients only): smsjobs.getStatus
* Get TL namespaces: getMethodNamespaces
- * Get TL serializer: getTL
* Get Telegram Premium promotion information: help.getPremiumPromo
* Get Telegram Star revenue statistics »: payments.getStarsRevenueStats
* Get Telegram UTF-8 length of string: mbStrlen
* Get a document by its SHA256 hash, mainly used for gifs: messages.getDocumentByHash
+ * Get a group call from its: getGroupCallBySlug
* Get a list of available gifts, see here » for more info: payments.getStarGifts
* Get a list of bots owned by the current user: bots.getAdminedBots
* Get a list of channels/supergroups we left, requires a takeout session, see here » for more info: channels.getLeftChannels
@@ -656,6 +697,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Get a list of default suggested emoji statuses: account.getDefaultEmojiStatuses
* Get a list of peers that can be used to join a group call, presenting yourself as a specific user/channel: phone.getGroupCallJoinAs
* Get a list of sponsored messages for a peer, see here » for more info: messages.getSponsoredMessages
+ * Get a live end-to-end encrypted conference call this session is in, by its call id: getConferenceCall
* Get a message to show to the user when starting the bot: getWebMessage
* Get a payment form: payments.getPaymentForm
* Get a set of suggested custom emoji stickers that can be used as group picture: account.getDefaultGroupPhotoEmojis
@@ -665,10 +707,12 @@ Some of MadelineProto's core components are also available as separate, standalo
* Get all archived stickers: messages.getArchivedStickers
* Get all available chat themes »: account.getChatThemes
* Get all contacts, requires a takeout session, see here » for more info: contacts.getSaved
+ * Get all group calls (video chats, livestreams and live stories) we're currently tracking, indexed by their ID: getAllGroupCalls
* Get all groups that can be used as discussion groups: channels.getGroupsForDiscussion
* Get all installed stickers: messages.getAllStickers
* Get all pending and running calls, indexed by user ID: getAllCalls
* Get all saved Telegram Passport documents, for more info see the passport docs »: account.getAllSecureValues
+ * Get an [end-to-end encrypted conference call »](https://core.telegram.org/api/group-calls#conference-calls): getConferenceCallBySlug
* Get an invite link for a group call or livestream: phone.exportGroupCallInvite
* Get and increase the view counter of a message sent or forwarded from a channel: messages.getMessagesViews
* Get app-specific configuration, see client configuration for more info on the result: help.getAppConfig
@@ -791,19 +835,25 @@ Some of MadelineProto's core components are also available as separate, standalo
* Get supergroup statistics: stats.getMegagroupStats
* Get temporary payment password: account.getTmpPassword
* Get the IDs of the maximum read stories for a set of peers: stories.getPeerMaxIDs
+ * Get the RTMP URL and stream key to publish an [RTMP livestream »](https://core.telegram.org/api/group-calls#creating-and-publishing-an-rtmp-livestream): getGroupCallStreamRtmpUrl
* Get the admin log of a channel/supergroup: channels.getAdminLog
* Get the current Telegram Stars balance of the current account (with peer=inputPeerSelf), or the stars balance of the bot specified in peer: payments.getStarsStatus
* Get the current reaction notification settings »: account.getReactionsNotifySettings
* Get the exact read date of one of our messages, sent to a private chat with another user: messages.getOutboxReadDate
+ * Get the file that is currently being played in a group call: groupCallGetCurrent
* Get the file that is currently being played: callGetCurrent
+ * Get the group call (video chat or livestream) currently active in a group or channel: getGroupCall
+ * Get the media state of the other party of a call, as reported by their client: getCallRemoteMediaState
* Get the number of results that would be found by a messages.search call with the same parameters: messages.getSearchCounters
* Get the number of stars we have received from the specified user thanks to paid messages »; the received amount will be equal to the sent amount multiplied by stars_paid_message_commission_permille divided by 1000: account.getPaidMessagesRevenue
+ * Get the participants of a group call, indexed by their bot API peer ID: getGroupCallParticipants
* Get the participants of a supergroup/channel: channels.getParticipants
* Get the phone call with the specified user ID: getCallByPeer
* Get the progress of a currently running broadcast: getBroadcastProgress
* Get the reaction and interaction list of a story posted to a channel, along with the sender of each reaction: stories.getStoryReactionsList
* Get the set of accent color palettes » that can be used for message accents: help.getPeerColors
* Get the set of accent color palettes » that can be used in profile page backgrounds: help.getPeerProfileColors
+ * Get the state of a group call: getGroupCallState
* Get the telegram IDs of all contacts.: contacts.getContactIDs
* Get theme information: account.getTheme
* Get type of peer: getType
@@ -859,6 +909,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Invite a set of users to a group call: phone.inviteToGroupCall
* Invite a user to a conference call: phone.inviteConferenceCallParticipant
* Invite users to a channel/supergroup: channels.inviteToChannel
+ * Invite users to a group call: inviteToGroupCall
* Invoke a method using a Telegram Business Bot connection, see here » for more info, including a list of the methods that can be wrapped in this constructor: invokeWithBusinessConnection
* Invoke a method within a takeout session, see here » for more info: invokeWithTakeout
* Invoke a request without subscribing the used connection for updates (this is enabled by default for file queries): invokeWithoutUpdates
@@ -869,10 +920,15 @@ Some of MadelineProto's core components are also available as separate, standalo
* Join a bot's affiliate program, becoming an affiliate »: payments.connectStarRefBot
* Join a channel/supergroup: channels.joinChannel
* Join a group call: phone.joinGroupCall
+ * Join an end-to-end encrypted conference call from its conference link slug: joinConferenceCallBySlug
+ * Join an end-to-end encrypted conference call from the service message that invited us to it: joinConferenceCallByInviteMessage
+ * Join an existing end-to-end encrypted conference call: joinConferenceCall
* Join channels and supergroups recently added to a chat folder deep link »: chatlists.joinChatlistUpdates
+ * Join the group call currently active in a group or channel: joinGroupCall
* Launch a prepaid giveaway »: payments.launchPrepaidGiveaway
* Leave a bot's affiliate program »: payments.editConnectedStarRefBot
* Leave a channel/supergroup: channels.leaveChannel
+ * Leave a group call, without ending it for the other participants: leaveGroupCall
* Leave a group call: phone.leaveGroupCall
* List all chat folder deep links » associated to a folder: chatlists.getExportedInvites
* List all created business chat deep links »: account.getBusinessChatLinks
@@ -913,6 +969,8 @@ Some of MadelineProto's core components are also available as separate, standalo
* Method for fetching previously featured stickers: messages.getOldFeaturedStickers
* Modify autosave settings: account.saveAutoSaveSettings
* Modify the admin rights of a user in a supergroup/channel: channels.editAdmin
+ * Mute or unmute our own audio stream in a call: setCallMuted
+ * Mute or unmute our own audio stream in a group call: setGroupCallMuted
* Notifies the sender about the recipient having listened a voice message or watched a video, emitting an updateReadMessagesContents: messages.readMessageContents
* Notify the other user in a private chat that a screenshot of the chat was taken: messages.sendScreenshotNotification
* Notify the user that the sent passport data contains some errors The user will not be able to re-submit their Passport data to you until the errors are fixed (the contents of the field for which you returned the error must change): users.setSecureValueErrors
@@ -944,7 +1002,6 @@ Some of MadelineProto's core components are also available as separate, standalo
* Obtain information about a chat folder deep link »: chatlists.checkChatlistInvite
* Obtain information about a direct link Mini App: messages.getBotApp
* Obtain information about specific saved message dialogs » or monoforum topics »: messages.getSavedDialogsByID
- * Obtain the API ID UI template: getWebAPITemplate
* Obtain the latest read story ID for all peers when first logging in, returned as a list of updateReadStories updates, see here » for more info: stories.getAllReadPeerStories
* Obtain the list of users that have viewed a specific story we posted: stories.getStoryViewsList
* Obtain user info from a temporary profile link: contacts.importContactToken
@@ -968,6 +1025,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Optional: notify the server that the user is currently busy in a call: this will automatically refuse all incoming phone calls until the current phone call is ended: phone.receivedCall
* Parse, update and store settings: updateSettings
* Pause or unpause a specific chat, temporarily disconnecting it from all business bots »: account.toggleConnectedBotPaused
+ * Pause playback of the current audio file in a group call: groupCallPausePlay
* Pauses playback of the current audio file in the call: pausePlay
* Perform static analysis on a certain event handler class, to make sure it satisfies some performance requirements: validateEventHandlerClass
* Permanently disconnect a specific chat from all business bots » (equivalent to specifying it in recipients.exclude_users during initial configuration with account.updateConnectedBot »); to reconnect of a chat disconnected using this method the user must reconnect the entire bot by invoking account.updateConnectedBot »: account.disablePeerConnectedBot
@@ -977,11 +1035,12 @@ Some of MadelineProto's core components are also available as separate, standalo
* Pin some stories to the top of the profile, see here » for more info: stories.togglePinnedToTop
* Pin/unpin a dialog: messages.toggleDialogPin
* Pins a received gift on top of the profile of the user or owned channels by using payments.toggleStarGiftsPinnedToTop: payments.toggleStarGiftsPinnedToTop
+ * Play a file in a group call: groupCallPlay
* Play file in call: callPlay
* Play files on hold in call: callPlayOnHold
* Positive modulo: posmod
* Press an inline callback button and get a callback answer from the bot: messages.getBotCallbackAnswer
- * Provide a buffered reader for a file, URL or amp stream: openBuffered
+ * Provide a buffered reader for a file, URL or amp stream, optionally starting at a byte offset: openBuffered
* Provide a stream for a file, URL or amp stream: getStream
* Query an inline bot: messages.getInlineBotResults
* Rate a call, returns info about the rating message sent to the official VoIP bot: phone.setCallRating
@@ -989,6 +1048,10 @@ Some of MadelineProto's core components are also available as separate, standalo
* Re-join a private channel associated to an active Telegram Star subscription »: payments.fulfillStarsSubscription
* React to a story: stories.sendReaction
* React to message: messages.sendReaction
+ * Record group call media into a directory: every transmitting participant (or only the given: groupCallSetOutputFolder
+ * Record one participant of a group call (or, in stream mode, its mixed stream) into a single file: groupCallSetOutput
+ * Record the incoming media of a call into a directory, one numbered file per combination of: callSetOutputFolder
+ * Record the incoming media of a call into one file (or stream) with a fixed set of tracks, see: callSetOutput
* Refresh full peer cache for a certain peer: refreshFullPeerCache
* Refresh peer cache for a certain peer: refreshPeerCache
* Refund a Telegram Stars transaction, see here » for more info: payments.refundStarsCharge
@@ -1029,7 +1092,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Represents a list of emoji categories, to be used when selecting custom emojis to set as custom emoji status: messages.getEmojiStatusGroups
* Represents a list of emoji categories, to be used when selecting custom emojis to set as profile picture: messages.getEmojiProfilePhotoGroups
* Represents a list of emoji categories: messages.getEmojiGroups
- * Request VoIP call: requestCall
+ * Request a one-to-one voice or video call: requestCall
* Request an SMS code via Firebase: auth.requestFirebaseSms
* Request recovery code of a 2FA password, only for accounts with a recovery email configured: auth.requestPasswordRecovery
* Request secret chat: requestSecretChat
@@ -1044,6 +1107,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Resolve a business chat deep link »: account.resolveBusinessChatLink
* Resolve a phone number to get user info, if their privacy settings allow it: contacts.resolvePhone
* Restart update loop: restart
+ * Resume playback of the current audio file in a group call: groupCallResumePlay
* Resumes playback of the current audio file in the call: resumePlay
* Rethrow exception into event loop: rethrow
* Return all message drafts.: messages.getAllDrafts
@@ -1087,6 +1151,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Save a theme: account.saveTheme
* Save or remove saved notification sound: account.saveRingtone
* Save phone call debug information: phone.saveCallLog
+ * Save the peer we join the video chats and livestreams of a group or channel as by default: saveDefaultGroupCallJoinAs
* Saves logs of application on the server: help.saveAppLog
* Search for custom emoji stickersets »: messages.searchEmojiStickerSets
* Search for messages and peers globally: messages.searchGlobal
@@ -1141,11 +1206,9 @@ Some of MadelineProto's core components are also available as separate, standalo
* Set localized name, about text and description of a bot (or of the current account, if called by a bot): bots.setBotInfo
* Set maximum Time-To-Live of all messages in the specified chat: messages.setHistoryTTL
* Set or remove the Telegram Business introduction »: account.updateBusinessIntro
- * Set output file or stream for incoming OPUS audio packets in a call: callSetOutput
* Set peer(s) where to send errors occurred in the event loop: setReportPeers
* Set sensitive content settings (for viewing or hiding NSFW content): account.setContentSettings
* Set stickerset thumbnail: stickers.setStickerSetThumb
- * Set the API ID UI template: setWebApiTemplate
* Set the callback answer to a user button press (bots only): messages.setBotCallbackAnswer
* Set the default peer that will be used to join a group call in a specific dialog: phone.saveDefaultGroupCallJoinAs
* Set the default suggested admin rights for bots being added as admins to channels, see here for more info on how to handle them »: bots.setBotBroadcastDefaultAdminRights
@@ -1157,13 +1220,16 @@ Some of MadelineProto's core components are also available as separate, standalo
* Sets the menu button action » for a given user or for all users: bots.setBotMenuButton
* Should be called after the user hides the report spam/add as contact bar of a new chat, effectively prevents the user from executing the actions specified in the action bar »: messages.hidePeerSettingsBar
* Show or hide the real-time chat translation popup for a certain chat: messages.togglePeerTranslations
+ * Skip to the next file in the playlist of a group call: groupCallSkipPlay
* Specify a set of Telegram Business opening hours.: account.updateBusinessWorkHours
+ * Start a [live story »](https://core.telegram.org/api/group-calls#live-stories): a livestream posted: startLive
* Start a conversation with a bot using a deep linking parameter: messages.startBot
* Start a scheduled group call: phone.startScheduledGroupCall
* Start multiple instances of MadelineProto and the event handlers (enables async): startAndLoopMulti
* Start or stop recording a group call: the recorded audio and video streams will be automatically sent to Saved messages (the chat with ourselves): phone.toggleGroupCallRecord
* Start screen sharing in a call: phone.joinGroupCallPresentation
* Stop getting notifications about discussion replies of a certain user in @replies: contacts.blockFromReplies
+ * Stop playing all files in a group call, clearing the main and the hold playlist: groupCallStopPlay
* Stop screen sharing in a group call: phone.leaveGroupCallPresentation
* Stop update loop: stop
* Stops playing all files in the call, clears the main and the hold playlist: stopPlay
@@ -1179,6 +1245,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Terminate webview interaction started with messages.requestWebView, sending the specified message to the chat on behalf of the user: messages.sendWebViewResultMessage
* Terminates all user's authorized sessions except for the current one: auth.resetAuthorizations
* Test fibers: testFibers
+ * The peers we may join the video chats and livestreams of a group or channel as: ourselves, the: getGroupCallJoinAs
* Toggle autotranslation in a channel, for all users: see here » for more info: channels.toggleAutotranslation
* Toggle contact sign up notifications: account.setContactSignUpNotification
* Toggle supergroup slow mode: if enabled, users will only be able to send one message every seconds seconds: channels.toggleSlowMode
@@ -1206,6 +1273,7 @@ Some of MadelineProto's core components are also available as separate, standalo
* Updates online user status: account.updateStatus
* Updates user profile: account.updateProfile
* Upgrade a gift to a collectible gift: can only be used if the upgrade was already paid by the gift sender; see here » for more info on the full flow (including the different flow to use in case the upgrade was not paid by the gift sender): payments.upgradeStarGift
+ * Upgrade a one-to-one call to an [end-to-end encrypted conference call »](https://core.telegram.org/api/group-calls#conference-calls):: migrateCallToConference
* Upload a custom profile picture for a contact, or suggest a new profile picture to a contact: photos.uploadContactProfilePhoto
* Upload a file and associate it to a chat (without actually sending it to the chat): messages.uploadMedia
* Upload a media file associated with an imported chat, click here for more info »: messages.uploadImportedMedia
@@ -1244,7 +1312,10 @@ Some of MadelineProto's core components are also available as separate, standalo
* When called, skips to the next file in the playlist: skipPlay
* When client-side passcode lock feature is enabled, will not show message texts in incoming PUSH notifications: account.updateDeviceLocked
* When was full info for this chat last cached: fullChatLastUpdated
+ * Whether our own audio stream is muted in a call: isCallMuted
+ * Whether our own audio stream is muted in a group call: isGroupCallMuted
* Whether the currently playing audio file is paused: isPlayPaused
+ * Whether the currently playing audio file of a group call is paused: isGroupCallPlayPaused
* Whether the user will receive notifications when contacts sign up: account.getContactSignUpNotification
* Whether this is altervista: isAltervista
* Whether we can convert any audio/video file to a VoIP OGG OPUS file, or the files must be preconverted using @libtgvoipbot: canConvertOgg
@@ -1257,10 +1328,15 @@ Some of MadelineProto's core components are also available as separate, standalo
* Wrap a Pin constructor into an abstract Pinned object: wrapPin
* Wrap a media constructor into an abstract Media object: wrapMedia
* Wrap an Update constructor into an abstract Update object: wrapUpdate
+ * account.confirmBotConnection
* account.deletePasskey
+ * account.deleteWebBrowserSettingsExceptions
* account.getPasskeys
+ * account.getWebBrowserSettings
* account.initPasskeyRegistration
* account.registerPasskey
+ * account.toggleWebBrowserSettingsException
+ * account.updateWebBrowserSettings
* aicompose.createTone
* aicompose.deleteTone
* aicompose.getTone
@@ -1268,21 +1344,48 @@ Some of MadelineProto's core components are also available as separate, standalo
* aicompose.getTones
* aicompose.saveTone
* aicompose.updateTone
+ * auth.cancelWebTokenAuthorization
* auth.checkPaidAuth
+ * auth.finishFirebasePnvLogin
* auth.finishPasskeyLogin
+ * auth.firebasePnvSignUp
+ * auth.initFirebasePnvLogin
* auth.initPasskeyLogin
* base64URL decode: base64urlDecode
+ * bots.addUsername
* bots.checkUsername
* bots.createBot
* bots.editAccessSettings
* bots.exportBotToken
* bots.getAccessSettings
* bots.getRequestedWebViewButton
+ * bots.removeUsername
* bots.requestWebViewButton
+ * bots.setJoinChatResults
+ * communities.create
+ * communities.getJoinedCommunities
+ * communities.getParticipantJoinedChats
+ * communities.getPeerLinkRequests
+ * communities.toggleAllPeerLinkRequestApproval
+ * communities.toggleCommunityCollapsedInDialogs
+ * communities.toggleParticipantBanned
+ * communities.togglePeerLink
+ * communities.togglePeerLinkRequestApproval
+ * contacts.exportNoPaidMessagesToken
+ * contacts.importNoPaidMessagesToken
* contacts.updateContactNote
+ * ephemeral.deleteAllWelcomeMessages
+ * ephemeral.deleteMessage
+ * ephemeral.deleteWelcomeMessage
+ * ephemeral.editMessage
+ * ephemeral.getCallbackAnswer
+ * ephemeral.getWelcomeMessages
+ * ephemeral.reportMessage
+ * ephemeral.sendMessage
* messages.addPollAnswer
* messages.checkUrlAuthMatchCode
* messages.composeMessageWithAI
+ * messages.composeRichMessageWithAI
* messages.createForumTopic
* messages.declineUrlAuth
* messages.deleteParticipantReaction
@@ -1297,24 +1400,40 @@ Some of MadelineProto's core components are also available as separate, standalo
* messages.getForumTopicsByID
* messages.getFutureChatCreatorAfterLeave
* messages.getPersonalChannelHistory
+ * messages.getRichMessage
+ * messages.getShareThemeBackdrops
* messages.getUnreadPollVotes
* messages.readPollVotes
* messages.reorderPinnedForumTopics
* messages.reportMusicListen
* messages.reportReadMetrics
+ * messages.requestChatJoinWebView
* messages.setBotGuestChatResult
+ * messages.setShareTheme
* messages.summarizeText
+ * messages.translateRichMessage
* messages.updatePinnedForumTopic
* null-byte RLE decode: rleDecode
* null-byte RLE encode: rleEncode
* payments.craftStarGift
+ * payments.createOnrampSession
+ * payments.deleteStarGift
+ * payments.depositStarGift
+ * payments.displayStarGift
* payments.getCraftStarGifts
+ * payments.getCurrencyRates
+ * payments.getOnrampAvailability
+ * payments.getOnrampBaseCurrencies
+ * payments.getOnrampLimits
+ * payments.getOnrampProviders
+ * payments.getOnrampQuote
* payments.getStarGiftActiveAuctions
* payments.getStarGiftAuctionAcquiredGifts
* payments.getStarGiftAuctionState
* payments.getStarGiftUpgradeAttributes
* payments.resolveStarGiftOffer
* payments.sendStarGiftOffer
+ * payments.withdrawStarGift
* phone.deleteGroupCallMessages
* phone.deleteGroupCallParticipantMessages
* phone.getGroupCallStars
@@ -1323,7 +1442,35 @@ Some of MadelineProto's core components are also available as separate, standalo
* phone.sendGroupCallMessage
* stats.getPollStats
* stories.startLive
+ * toncenter.getStreamingUrl
+ * toncenter.performApiRequest
* users.suggestBirthday
+ * wallet.disableBackup
+ * wallet.enableBackup
+ * wallet.exportSecretPhrase
+ * wallet.fetchEncryptedSecretPhrasePart
+ * wallet.getBackupHolderDcs
+ * wallet.getExistingWaltBalance
+ * wallet.getGaslessInfo
+ * wallet.getNfts
+ * wallet.getProofChallenge
+ * wallet.getState
+ * wallet.getTransactions
+ * wallet.getTransactionsByIDs
+ * wallet.getTransactionsByMsgHash
+ * wallet.getUserAddresses
+ * wallet.replaceWallet
+ * wallet.sendTransfer
+ * wallet.setCardStickers
+ * wallet.tonConnectClaimRequest
+ * wallet.tonConnectCloseSession
+ * wallet.tonConnectCreateSession
+ * wallet.tonConnectGetPending
+ * wallet.tonConnectGetSessions
+ * wallet.tonConnectNextEventId
+ * wallet.tonConnectRegisterKey
+ * wallet.tonConnectSubmitConnectResult
+ * wallet.tonConnectSubmitResponse
* [Contributing](https://docs.madelineproto.xyz/docs/CONTRIB.html) - You can contribute in various ways.
* [Translation](https://docs.madelineproto.xyz/docs/CONTRIB.html#translation)
* [Contribution guide](https://docs.madelineproto.xyz/docs/CONTRIB.html#contribution-guide)
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/composer.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/composer.json
index 799799b..01cc625 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/composer.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/composer.json
@@ -25,7 +25,7 @@
"require": {
"php-64bit": ">=8.2",
"danog/primemodule": "^1.0.13",
- "symfony/polyfill-mbstring": ">=1.32",
+ "symfony/polyfill-mbstring": ">=1.38.2",
"ext-json": "*",
"ext-xml": "*",
"ext-dom": "*",
@@ -33,60 +33,84 @@
"ext-hash": "*",
"ext-zlib": "*",
"ext-fileinfo": "*",
- "amphp/amp": "^3.1.1",
- "amphp/http-client": "^5.3.4",
+ "amphp/amp": "^3.1.3",
+ "amphp/http-client": "^5.3.6",
"amphp/websocket-client": "^2.0.2",
"amphp/http": "^2.1.2",
- "amphp/socket": "^2.3.1",
- "amphp/dns": "^2.4.0",
+ "amphp/socket": "^2.4.1",
+ "amphp/dns": "^2.4.1",
"amphp/byte-stream": "^2.1.2",
"amphp/file": "^3.2.0",
- "amphp/mysql": "^3",
- "amphp/postgres": "^2.1.1",
+ "amphp/mysql": "^3.1.1",
+ "amphp/postgres": "^2.2.1",
+ "amphp/process": "^2.1",
"danog/dns-over-https": "^1.0.1",
"amphp/http-client-cookies": "^2",
"danog/tg-file-decoder": "^1.0.2",
- "league/uri": "^7.5.1",
- "danog/ipc": "^1.0.1",
+ "league/uri": "^7.8.1",
+ "danog/ipc": "^1.1.0",
"amphp/log": "^2",
"danog/loop": "^1.1.1",
- "phpseclib/phpseclib": "^3.0.47",
- "amphp/redis": "^2.0.3",
+ "phpseclib/phpseclib": "^4.0.1",
+ "amphp/redis": "^2.0.4",
"psr/http-factory": "^1.1.0",
"psr/log": "^3.0.2",
- "webmozart/assert": "^1.12.1",
- "bacon/bacon-qr-code": "^3.0.1",
- "nikic/php-parser": "^5.6.2",
- "revolt/event-loop": "^1.0.7",
- "danog/async-orm": "^1.1.4",
- "danog/telegram-entities": "^1.0.5",
+ "webmozart/assert": "^2.4.1",
+ "bacon/bacon-qr-code": "^3.1.1",
+ "nikic/php-parser": "^5.9.0",
+ "revolt/event-loop": "^1.0.9",
+ "danog/async-orm": "^1.1.6",
+ "danog/telegram-entities": "^1.1.0",
"danog/better-prometheus": "^0.1.1",
- "amphp/http-server": "^3.4.3",
+ "amphp/http-server": "^3.4.6",
"danog/tg-dialog-id": "^2",
- "symfony/polyfill-php83": "^1.32"
+ "symfony/polyfill-php83": "^1.41",
+ "danog/php-rtc-av": "^1.1.11",
+ "danog/php-rtc-codecs": "^1.1.19",
+ "danog/php-rtc-dtls": "^2.0.19",
+ "danog/php-rtc-ice": "^2.0.18",
+ "danog/php-rtc-ntp": "^1.1.14",
+ "danog/php-rtc-rtcp": "^1.1.11",
+ "danog/php-rtc-rtp": "^2.0.23",
+ "danog/php-rtc-sctp": "^2.0.14",
+ "danog/php-rtc-srtp": "^1.1.16",
+ "danog/php-rtc-stun": "^2.0.18",
+ "danog/php-rtc-webrtc": "^2.0.19",
+ "danog/php-rtc-datachannel": "^1.1.10",
+ "danog/php-rtc-sdp": "^1.1.12",
+ "danog/php-rtc-stats": "^1.1.7",
+ "danog/php-rtc-turn": "^2.0.9",
+ "danog/php-rtc-mdns": "^1.1.12",
+ "danog/php-rtc-exception": "^1.1.10",
+ "danog/php-rtc-mixin": "^2.0.9",
+ "danog/php-rtc-rtp-parameter": "^1.1.8",
+ "symfony/polyfill-iconv": "^1.37",
+ "symfony/polyfill-php84": "^1.38",
+ "symfony/polyfill-php85": "^1.41",
+ "symfony/polyfill-php86": "^1.41"
},
"require-dev": {
- "quasarstream/webrtc": "^1.0",
"ext-ctype": "*",
"danog/phpdoc": "^0.1.24",
- "phpunit/phpunit": "^9.6.29",
+ "phpunit/phpunit": "^9.6.36",
"amphp/phpunit-util": "^3",
- "bamarni/composer-bin-plugin": "1.8.2",
- "symfony/yaml": "^6.4.26",
- "revolt/event-loop-adapter-react": "^1.1.1",
+ "bamarni/composer-bin-plugin": "1.9.1",
+ "symfony/yaml": "^6.4.45",
"dg/bypass-finals": "dev-master",
"brianium/paratest": "^6.11.1",
"vimeo/psalm": "dev-master",
- "sebastian/diff": "^4.0"
+ "sebastian/diff": "^4.0.6"
},
"suggest": {
"ext-primemodule": "Install the primemodule and FFI extensions to speed up MadelineProto (https://prime.madelineproto.xyz)",
- "ext-ffi": "Install the primemodule and FFI extensions to speed up MadelineProto (https://prime.madelineproto.xyz)",
+ "ext-ffi": "Install the FFI extension (with libopus, libvpx and ffmpeg) to transcode audio and video in realtime; not required to play and record video and audio inside calls",
"ext-pdo": "Install the pdo extension to store session data on MySQL",
"ext-openssl": "Install the openssl extension for faster crypto",
+ "ext-sodium": "Install the sodium extension for faster crypto",
"ext-uv": "Install the uv extension to greatly speed up MadelineProto!",
"ext-gmp": "Install the gmp extension to speed up authorization",
- "ext-bcmath": "Install the bcmath extension to speed up authorization"
+ "ext-bcmath": "Install the bcmath extension to speed up authorization",
+ "ext-sockets": "Install the sockets extension on Windows to use UNIX sockets for IPC (otherwise TCP on 127.0.0.1 is used, which any local user can connect to)"
},
"authors": [
{
@@ -120,11 +144,11 @@
"@cs-fix",
"@fuzz",
"@file_ref_map",
- "@psalm",
"@test-light"
],
"test": [
- "@paratest"
+ "@paratest",
+ "@test-session"
],
"test-light": [
"@paratest-light"
@@ -135,11 +159,16 @@
"fuzz": "php tools/fuzzer.php",
"file_ref_map": "php tools/gen_filerefmap.php",
"docs-fix": "tools/fix_docs.sh",
- "paratest": "@php -dzend.assertions=1 ./vendor/bin/paratest -fv",
- "paratest-light": "@php -dzend.assertions=1 ./vendor/bin/paratest -fvc phpunit-light.xml",
+ "paratest": "@php -dzend.assertions=1 ./vendor/bin/paratest -v --exclude-group session",
+ "test-session": "tests/session_tests.sh",
+ "paratest-light": "@php -dzend.assertions=1 ./vendor/bin/paratest -vc phpunit-light.xml --exclude-group session",
"bin": "echo 'bin not installed'",
- "post-install-cmd": ["@composer bin all install --ansi"],
- "post-update-cmd": ["@composer bin all update --ansi"]
+ "post-install-cmd": [
+ "@composer bin all install --ansi"
+ ],
+ "post-update-cmd": [
+ "@composer bin all update --ansi"
+ ]
},
"config": {
"allow-plugins": {
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ar.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ar.json
new file mode 100644
index 0000000..660f1a4
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ar.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "تم ضبط قيد basedir: قد يؤثر ذلك على الأداء ويسبب بعض المشكلات، يُرجى تعطيله إن أمكن!",
+ "noReportPeers": "تحذير: لم يتم تعيين أي جهات لاستلام التقارير (report peers)، يُرجى إضافة الدالة التالية إلى معالج الأحداث الخاص بك",
+ "manualAdminActionRequired": "!!!!!!!!! يلزم تدخل يدوي من مسؤول النظام !!!!!!!!!",
+ "mmapErrorPart1": "تم بلوغ الحد الأقصى لعدد مناطق الذاكرة المعيّنة (mmap) (%s): يُرجى زيادة إعداد النواة vm.max_map_count إلى 262144 لإصلاح ذلك.",
+ "mmapErrorPart2": "للإصلاح، نفّذ الأمر التالي بصلاحيات root: %s",
+ "mmapErrorPart3": "للإبقاء على التغيير بعد إعادة التشغيل: %s",
+ "mmapErrorPart4": "على Windows وWSL، قد تساعد زيادة حجم ملف الصفحات (pagefile)؛ يُرجى الانتقال إلى Linux أصلي إذا استمرت المشكلة.",
+ "botAlreadyRunning": "البوت قيد التشغيل بالفعل!",
+ "extensionRequired": "يتطلب MadelineProto الامتداد %s ليعمل. %s",
+ "extensionRequiredInstallWithApt": "جرّب تنفيذ sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "اتبع التعليمات على %s لتثبيته.",
+ "extensionRecommended": "تحذير: الامتداد %s غير مثبّت، يُرجى تثبيته لتسريع MadelineProto!",
+ "go": "متابعة",
+ "apiChooseManualAutoTip": "لاحظ أنه يمكنك أيضًا توفير API ID/hash مباشرةً في الشيفرة باستخدام الإعدادات: %s",
+ "apiChooseManualAutoTipWeb": "لاحظ أنه يمكنك أيضًا توفير API ID/hash مباشرةً في الشيفرة باستخدام الإعدادات.",
+ "apiChoosePrompt": "اختيارك (m/a): ",
+ "apiManualInstructions0": "سجّل الدخول إلى https://my.telegram.org",
+ "apiManualInstructions1": "انتقل إلى API development tools",
+ "apiManualInstructions2": "انقر على create application",
+ "apiAppInstructionsManual0": "اسم تطبيقك، يمكن أن يكون أي شيء",
+ "apiAppInstructionsManual1": "الاسم المختصر لتطبيقك، أحرف وأرقام، من 5 إلى 32 حرفًا",
+ "apiAppInstructionsManual2": "عنوان URL لتطبيقك/موقعك، أو t.me/yourusername",
+ "apiAppInstructionsManual3": "أي شيء",
+ "apiAppInstructionsManual4": "صِف تطبيقك هنا",
+ "apiManualWeb": "أدخل API ID وAPI hash الخاصين بك",
+ "apiManualPrompt0": "أدخل API ID الخاص بك: ",
+ "apiManualPrompt1": "أدخل API hash الخاص بك: ",
+ "apiAutoWeb": "أدخل رقم هاتف مسجّلًا مسبقًا في Telegram للحصول على API ID",
+ "apiAutoPrompt0": "أدخل رقم هاتف مسجّلًا مسبقًا في Telegram: ",
+ "apiAutoPrompt1": "أدخل رمز التحقق الذي تلقيته في Telegram: ",
+ "apiAppWeb": "أدخل معلومات API",
+ "apiAppInstructionsAuto0": "أدخل اسم التطبيق، يمكن أن يكون أي شيء: ",
+ "apiAppInstructionsAuto1": "أدخل الاسم المختصر للتطبيق، أحرف وأرقام، من 5 إلى 32 حرفًا: ",
+ "apiAppInstructionsAuto2": "أدخل عنوان URL للتطبيق/الموقع، أو t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "أدخل منصة التطبيق: ",
+ "apiAppInstructionsAuto4": "صِف تطبيقك: ",
+ "apiAppInstructionsAutoTypeOther": "أخرى (حدّدها في الوصف)",
+ "apiParamsError": "لم تقدّم جميع المعاملات المطلوبة!",
+ "apiError": "خطأ: %s. حاول مرة أخرى.",
+ "loginChoosePromptWeb": "هل تريد تسجيل الدخول كمستخدم أم كبوت؟",
+ "loginWebQr": "يمكنك أيضًا تسجيل الدخول تلقائيًا بفتح Telegram على هاتفك، والانتقال إلى الإعدادات > الأجهزة > ربط جهاز سطح المكتب، ثم مسح رمز QR التالي:",
+ "loginWebQr1": "افتح Telegram على هاتفك",
+ "loginWebQr2": "انتقل إلى الإعدادات > الأجهزة > ربط جهاز سطح المكتب",
+ "loginWebQr3": "وجّه هاتفك نحو هذه الشاشة لتأكيد تسجيل الدخول",
+ "loginOptionBot": "بوت",
+ "loginOptionUser": "مستخدم",
+ "loginBot": "أدخل توكن البوت: ",
+ "loginUser": "أدخل رقم هاتفك: ",
+ "loginQr": "افتح Telegram على هاتفك، وانتقل إلى الإعدادات > الأجهزة > ربط جهاز سطح المكتب، ثم امسح رمز QR أعلاه لتسجيل الدخول تلقائيًا.",
+ "loginQrCodeSuccessful": "تم تسجيل الدخول برمز QR بنجاح!",
+ "loginQrCodeExpired": "انتهت صلاحية رمز QR، جارٍ إنشاء رمز جديد...",
+ "loginManual": "بدلًا من ذلك، يمكنك أيضًا إدخال توكن بوت أو رقم هاتف لتسجيل الدخول يدويًا: ",
+ "loginUserCode": "أدخل الرمز: ",
+ "loginUserPass": "أدخل كلمة المرور (التلميح: %s): ",
+ "loginUserPassWeb": "أدخل كلمة المرور: ",
+ "loginUserPassHint": "التلميح: %s",
+ "signupFirstName": "أدخل اسمك الأول: ",
+ "signupLastName": "أدخل اسم العائلة (يمكن تركه فارغًا): ",
+ "signupWeb": "يُرجى التسجيل",
+ "signupFirstNameWeb": "الاسم الأول",
+ "signupLastNameWeb": "اسم العائلة",
+ "loginNoCode": "لم تُدخل رمز التحقق!",
+ "loginNoPass": "لم تُدخل كلمة المرور!",
+ "loginNoName": "لم تُدخل الاسم الأول!",
+ "loginBotTokenWeb": "توكن البوت",
+ "loginUserPhoneWeb": "رقم الهاتف",
+ "loginUserPhoneCodeWeb": "الرمز",
+ "done": "تم!",
+ "nearest_dc": "نحن في %s، وأقرب DC هو %d.",
+ "serialization_ofd": "التسلسل (serialization) قديم، جارٍ إعادة بناء الكائن!",
+ "api_not_set": "يجب توفير api key وapi id، احصل عليهما من my.telegram.org",
+ "session_corrupted": "الجلسة تالفة!",
+ "value_bigger_than_2147483647": "القيمة المقدّمة %s أكبر من 2147483647",
+ "value_smaller_than_2147483648": "القيمة المقدّمة %s أصغر من -2147483648",
+ "value_bigger_than_9223372036854775807": "القيمة المقدّمة %s أكبر من 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "القيمة المقدّمة %s أصغر من -9223372036854775808",
+ "value_bigger_than_4294967296": "القيمة المقدّمة %s أكبر من 4294967296",
+ "value_smaller_than_0": "القيمة المقدّمة %s أصغر من 0",
+ "encode_double_error": "تعذّر ترميز double بشكل صحيح",
+ "file_not_exist": "الملف غير موجود",
+ "deserialization_error": "حدث خطأ أثناء إلغاء التسلسل (deserialization)",
+ "rpc_tg_error": "أعاد Telegram خطأ RPC: %s (%s)، بسبب %s:%s%sتتبع TL:",
+ "madelineproto_ready": "MadelineProto جاهز!",
+ "logout_ok": "تم تسجيل الخروج بنجاح!",
+ "already_loggedIn": "نسخة MadelineProto هذه مسجّلة الدخول بالفعل!",
+ "login_ok": "تم تسجيل الدخول بنجاح!",
+ "login_user": "جارٍ تسجيل الدخول كمستخدم عادي...",
+ "login_bot": "جارٍ تسجيل الدخول كبوت...",
+ "login_code_sending": "جارٍ إرسال الرمز...",
+ "login_code_sent": "تم إرسال الرمز بنجاح! بعد استلام الرمز، استخدم الدالة completePhoneLogin.",
+ "login_code_uncalled": "لست في انتظار الرمز! يُرجى استدعاء الدالة phoneLogin أولًا",
+ "login_2fa_enabled": "المصادقة الثنائية (2FA) مفعّلة، سيتعيّن عليك استدعاء الدالة complete2falogin...",
+ "login_need_signup": "لم يتم إنشاء حساب لهذا الرقم، سيتعيّن عليك استدعاء الدالة completeSignup...",
+ "login_auth_key": "جارٍ تسجيل الدخول باستخدام مفتاح التفويض (auth key)...",
+ "not_loggedIn": "لم يتم تسجيل الدخول!",
+ "signup_uncalled": "لست في انتظار التسجيل! يُرجى استدعاء الدالتين phoneLogin وcompletePhoneLogin أولًا!",
+ "signing_up": "جارٍ التسجيل كمستخدم عادي...",
+ "signup_ok": "تم التسجيل بنجاح!",
+ "2fa_uncalled": "لست في انتظار كلمة المرور! يُرجى استدعاء الدالتين phoneLogin وcompletePhoneLogin أولًا!",
+ "peer_not_in_db": "هذا الـ peer غير موجود في قاعدة بيانات الـ peers الداخلية",
+ "call_error_1": "تعذّر العثور على المكالمة %s وقبولها",
+ "accepting_call": "جارٍ قبول المكالمة من %s...",
+ "call_already_accepted": "المكالمة %s مقبولة بالفعل",
+ "call_already_declined": "المكالمة %s مرفوضة بالفعل",
+ "call_error_2": "تعذّر العثور على المكالمة %s وتأكيدها",
+ "call_confirming": "جارٍ تأكيد المكالمة من %s...",
+ "call_error_3": "تعذّر العثور على المكالمة %s وإكمال إنشائها",
+ "call_completing": "جارٍ إكمال إنشاء المكالمة من %s...",
+ "fingerprint_invalid": "بصمة المفتاح غير صالحة!",
+ "call_discarding": "جارٍ إنهاء المكالمة %s...",
+ "file_parsing": "جارٍ تحليل %s...",
+ "src_file_invalid": "تم تقديم ملف مصدر غير صالح: ",
+ "bool_error": "تعذّر استخراج القيمة المنطقية (boolean)",
+ "not_numeric": "القيمة المعطاة ليست رقمية",
+ "long_not_16": "طول القيمة المعطاة ليس 16 بايت",
+ "long_not_32": "طول القيمة المعطاة ليس 32 بايت",
+ "long_not_64": "طول القيمة المعطاة ليس 64 بايت",
+ "array_invalid": "لم تقدّم مصفوفة صالحة",
+ "predicate_not_set": "لم يتم تعيين الـ predicate (القيمة تحت _)!",
+ "update_madelineproto": "أنت تستخدم إصدارًا قديمًا من MadelineProto، والتحديث مطلوب: الإصدار الحالي هو %s، لكن أحدث إصدار مع العديد من إصلاحات الأخطاء والميزات الجديدة هو %s!",
+ "type_extract_error": "تعذّر استخراج النوع \"%s\"، يجب عليك تحديث MadelineProto!",
+ "method_not_found": "تعذّر العثور على الدالة: ",
+ "params_missing": "معامل مطلوب مفقود",
+ "sec_peer_not_in_db": "هذا الـ peer السري غير موجود في قاعدة بيانات الـ peers الداخلية",
+ "stream_handle_invalid": "تم تقديم مقبض تدفق (stream handle) غير صالح.",
+ "length_too_big": "الطول كبير جدًا",
+ "string_required": "كان من المتوقع سلسلة نصية (string)!",
+ "waveform_must_have_100_values": "يجب أن تحتوي مصفوفة waveform على 100 قيمة!",
+ "waveform_value": "يجب أن تكون قيمة waveform بين 0 و31!",
+ "could_not_convert_object": "تعذّر تحويل كائن من النوع %s",
+ "type_extract_error_id": "تعذّر استخراج النوع: %s بالمعرّف %s، يجب عليك تحديث MadelineProto!",
+ "constructor_not_found": "لم يتم العثور على constructor للنوع: ",
+ "botapi_conversion_error": "لا يمكن تحويل %s إلى كائن bot API",
+ "non_text_conversion": "لا يمكن تحويل الرسائل غير النصية بعد!",
+ "file_type_invalid": "تم اكتشاف نوع ملف غير صالح (%s)",
+ "static_analysis_minor": "تمت مصادفة مشكلة بسيطة أثناء التحليل الثابت لـ %s: %s",
+ "static_analysis_severe": "تمت مصادفة مشكلة خطيرة أثناء التحليل الثابت لـ %s: %s",
+ "secret_chat_skipping": "المحادثة السرية %s غير موجودة في قاعدة البيانات، جارٍ تخطي الرسالة...",
+ "must_have_declare_types": "لأسباب تتعلق بالأداء، يجب أن تكون العبارة الأولى في ملف معالج الأحداث \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "يجب عدم حذف ملف MadelineProto.log أبدًا، يُرجى بدلًا من ذلك تعيين حد أقصى مخصص للحجم في الإعدادات!",
+ "do_not_remove_MadelineProto.log_phar": "يُرجى عدم حذف madeline.phar أو madeline.php، وإلا سيتعطل MadelineProto. إذا واجهت أي مشكلة مع MadelineProto، فأبلغ عنها على https://github.com/danog/MadelineProto أو https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "لأسباب تتعلق بالأداء، لا يجوز لمعالجات الأحداث استخدام الدالة الحاجبة المتزامنة (غير async) %s، يُرجى استخدام %s بدلًا منها",
+ "do_not_use_blocking_class": "لأسباب تتعلق بالأداء، لا يجوز للمعالجات استخدام الصنف الحاجب (غير async) %s، يُرجى استخدام %s بدلًا منه",
+ "do_not_use_deprecated_function": "الدالة %s مهملة (deprecated)، يُرجى استخدام %s بدلًا منها",
+ "do_not_use_non_root_require_in_event_handler": "لأسباب تتعلق بالأداء، يجب عدم استخدام require أو include داخل صنف معالج الأحداث، يُسمح فقط بـ require على مستوى الجذر.",
+ "do_not_use_yield": "لا يتطلب MadelineProto 8 استخدام yield في الدوال غير المتزامنة ولا يدعمه، يجب عليك إزالة جميع كلمات yield المفتاحية المستخدمة سابقًا لاستدعاءات الدوال غير المتزامنة",
+ "recommend_not_use_filesystem_function": "لا يُنصح باستخدام الدالة %s، لأن الوصول إلى نظام الملفات أثناء معالجة التحديثات سيبطئ البوت الخاص بك، يُرجى مراجعة https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions للاطلاع على قائمة بالطرق البديلة لتخزين البيانات التي لن تبطئ البوت!",
+ "plugins_do_not_use_require": "لأسباب تتعلق بالأداء، لا يمكن للإضافات تضمين (include أو require) ملفات أخرى موجودة في مجلد الإضافات تلقائيًا إلا عبر تشغيل المحمّل التلقائي PSR-4 (وليس باستدعاء require() يدويًا).",
+ "plugins_must_have_exactly_one_class": "يجب أن تعرّف الإضافة صنفًا واحدًا بالضبط! لتعريف عدة أصناف أو واجهات أو traits، أنشئ ملفات منفصلة، وسيحمّلها MadelineProto تلقائيًا.",
+ "cli_need_dl.php_link": "يُرجى تحديد عنوان URL لسكربت التنزيل عند استخدام getDownloadLink عبر CLI!",
+ "invalid_dl.php_session": "%s ليس سكربت تنزيل صالحًا لأن معرّف جلسته مختلف (المتوقع %s، الفعلي %s)",
+ "need_dl.php": "تعذّر إنشاء سكربت التنزيل الافتراضي (%s)، يُرجى إنشاء ملف dl.php بالمحتوى التالي: %s وتمرير عنوان URL الخاص به إلى المعامل الثاني لـ getDownloadLink",
+ "dl.php_powered_by_madelineproto": "خادم تنزيل ملفات Telegram (حتى 4 غيغابايت)، مدعوم بواسطة MadelineProto!
انقر هنا لمزيد من المعلومات حول كيفية إعداد خادم تنزيل ملفات Telegram الخاص بك!",
+ "dl.php_check_logs_make_sure_session_running": "إما أن بوت MadelineProto EventHandler المرتبط أو خادم MadelineProto IPC غير متصل، يُرجى التحقق من السجلات والتأكد من تشغيل واحد منهما على الأقل!",
+ "account_banned": "!!!!!!! تحذير !!!!!!!\nعلّق نظام منع الإغراق (flood) في Telegram هذا الحساب.\nللمتابعة، يلزم التحقق اليدوي.\nأرسل بريدًا إلكترونيًا إلى recover@telegram.org تطلب فيه رفع الحظر عن رقم الهاتف %s، وصِف باختصار ما ستفعله بهذا الرقم.\nثم سجّل الدخول مرة أخرى.\nإذا حذفت هذا الحساب عمدًا، فتجاهل هذه الرسالة.",
+ "plugin_path_does_not_exist": "مسار الإضافة %s غير موجود!",
+ "could_not_connect_to_MadelineProto": "تعذّر الاتصال بـ MadelineProto، يُرجى تفعيل proc_open وإزالة قيود open_basedir أو تعطيل إعادة كتابة المسارات في خادم الويب لإصلاح ذلك! إذا كنت قد فعلت ذلك بالفعل، فتأكد من أن إصدار CLI من PHP مطابق تمامًا لإصدار الويب (نفس الإصدار والامتدادات وما إلى ذلك)، وراجع ملف MadelineProto.log لمزيد من المعلومات حول الخطأ الذي منع خادم IPC من البدء.",
+ "translate_madelineproto_web": "يمكن ترجمة MadelineProto إلى لغتك (تقدّم الترجمة الحالي: %d%%)، انقر هنا للمساهمة في الترجمة!",
+ "translate_madelineproto_cli": "يمكن ترجمة MadelineProto إلى لغتك (تقدّم الترجمة الحالي: %d%%)، انتقل إلى https://github.com/danog/MadelineProto/tree/v8/langs للمساهمة في الترجمة!",
+ "apiInvalidWeb": "API ID رقم، وAPI hash طوله 32 حرفًا: انسخهما مرة أخرى من my.telegram.org.",
+ "webDoneLead": "يواصل MadelineProto العمل على الخادم: يمكنك إغلاق هذه الصفحة.",
+ "apiChooseManualAuto": "هل تريد الحصول على API ID وhash تلقائيًا من my.telegram.org (a)، أم إدخالهما يدويًا (m)؟",
+ "apiAutoFallbackManual": "أدخل API ID وhash يدويًا بدلًا من ذلك.",
+ "apiSetupTitleWeb": "احصل على API ID وhash",
+ "apiSetupLeadWeb": "يحتاج كل تطبيق Telegram إلى API ID وhash. يمكن لـ MadelineProto الحصول عليهما لك من my.telegram.org، باستخدام رقم هاتف حساب Telegram موجود.",
+ "apiAutoPhoneHintWeb": "يرسل my.telegram.org رمز تسجيل الدخول إلى تطبيق Telegram لديك، وليس عبر SMS.",
+ "apiSendCodeWeb": "إرسال الرمز",
+ "apiChooseManualWeb": "لدي API ID بالفعل",
+ "apiChooseAutoWeb": "الحصول عليهما تلقائيًا",
+ "apiStartOverWeb": "البدء من جديد",
+ "apiAutoCodeTitleWeb": "أدخل الرمز الوارد من Telegram",
+ "apiAutoCodeLeadWeb": "أرسل my.telegram.org رمز تسجيل دخول إلى تطبيق Telegram لديك، في المحادثة مع Telegram (وليس عبر SMS).",
+ "apiAutoCodeLabelWeb": "رمز تسجيل الدخول",
+ "apiCreateTitleWeb": "أنشئ تطبيقك",
+ "apiCreateLeadWeb": "لا يملك هذا الحساب أي تطبيق على my.telegram.org بعد. تظهر هذه التفاصيل لك فقط، ويمكن تغييرها لاحقًا.",
+ "apiAppTitleLabelWeb": "اسم التطبيق",
+ "apiAppShortNameLabelWeb": "الاسم المختصر",
+ "apiAppUrlLabelWeb": "عنوان URL",
+ "apiAppDescLabelWeb": "الوصف",
+ "apiCreateWeb": "إنشاء التطبيق",
+ "apiSaveWeb": "حفظ ومتابعة",
+ "apiAutoErrorTitle": "أعاد my.telegram.org خطأً",
+ "apiCreateErrorTitle": "لم يُنشئ my.telegram.org التطبيق",
+ "apiCreateVpsWarning": "لا يسمح Telegram بإنشاء تطبيقات جديدة على my.telegram.org من نطاقات IP الخاصة بخوادم VPS وشبكات VPN ومراكز البيانات الأخرى، وقد أُرسل الطلب من عنوان IP للجهاز الذي يشغّل MadelineProto. أنشئ التطبيق يدويًا على https://my.telegram.org من اتصال منزلي (مثل هاتفك عبر بيانات الجوال)، ثم أدخل API ID وhash.",
+ "loginTitleWeb": "تسجيل الدخول إلى Telegram",
+ "loginLeadWeb": "اختر الحساب أو البوت الذي ستعمل به نسخة MadelineProto هذه.",
+ "loginTypeWeb": "تسجيل الدخول كـ",
+ "loginUserPhoneHintWeb": "مع رمز الدولة، مثل +39 123 456 7890.",
+ "loginBotTokenHintWeb": "التوكن الذي أعطاك إياه @BotFather عند إنشاء البوت.",
+ "loginCodeTitleWeb": "أدخل رمز تسجيل الدخول",
+ "loginCodeLeadWeb": "أرسل Telegram رمز تسجيل الدخول إلى تطبيق Telegram لديك، أو عبر SMS إن لم تكن مسجّلًا الدخول في أي مكان آخر.",
+ "loginPasswordTitleWeb": "التحقق بخطوتين",
+ "loginPasswordLeadWeb": "هذا الحساب محمي بكلمة مرور، مُعيّنة في الإعدادات > الخصوصية والأمان > التحقق بخطوتين.",
+ "loginPasswordLabelWeb": "كلمة المرور",
+ "signupTitleWeb": "أنشئ حسابك",
+ "signupLeadWeb": "رقم الهاتف هذا غير مسجّل في Telegram بعد: اختر اسم الحساب الجديد.",
+ "webContinue": "متابعة",
+ "webLogin": "تسجيل الدخول",
+ "webError": "%s. تحقّق منه وحاول مرة أخرى.",
+ "webStepApp": "API ID وhash",
+ "webStepAccount": "الحساب",
+ "webStepVerify": "التحقق",
+ "webStepDone": "قيد التشغيل",
+ "webProgress": "تقدّم الإعداد",
+ "webDocs": "التوثيق",
+ "webOptional": "اختياري",
+ "webShowPassword": "إظهار",
+ "webHidePassword": "إخفاء",
+ "webQrTitle": "تسجيل الدخول برمز QR",
+ "webQrWaiting": "في انتظار المسح…",
+ "webFieldRequired": "املأ هذا الحقل.",
+ "webPhoneInvalid": "أدخل رقم الهاتف مع رمز الدولة، مثل +39 123 456 7890.",
+ "tweb.Login.Title": "تسجيل الدخول إلى MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "رقم الهاتف غير صالح",
+ "tweb.Login.StartText": "يُرجى تأكيد رمز دولتك\nوإدخال رقم هاتفك.",
+ "tweb.Login.Code.SentSms": "لقد أرسلنا إليك رسالة SMS\nتحتوي على الرمز.",
+ "tweb.Login.Code.SentInApp": "لقد أرسلنا إليك رسالة في Telegram\nتحتوي على الرمز.",
+ "tweb.Login.Code.SentCall": "سنتصل بك ونملي عليك\nالرمز.",
+ "tweb.Login.Code.SentEmail": "يُرجى التحقق من بريدك الإلكتروني **%s** (لا تنسَ مجلد الرسائل غير المرغوب فيها) وإدخال الرمز الذي أرسلناه إليك للتو.",
+ "tweb.Login.Code.SentUnknown": "يُرجى البحث في كل مكان\nعن الرمز (النوع: %s)",
+ "tweb.Login.Code.SentMissedCall": "خلال الثواني القليلة القادمة ستتلقى\nمكالمة قصيرة من **%s**. لا تُجب عليها —\nفقط أدخل الأرقام الأخيرة من هذا الرقم.",
+ "tweb.Login.Code.SentSmsWord": "لقد أرسلنا رسالة SMS تحتوي على كلمة سرية\nإلى هاتفك **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "لقد أرسلنا رسالة SMS تحتوي على كلمة سرية تبدأ\nبـ \"**%2$s**\" إلى هاتفك **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "لقد أرسلنا رسالة SMS تحتوي على عبارة سرية\nإلى هاتفك **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "لقد أرسلنا رسالة SMS تحتوي على عبارة سرية تبدأ\nبـ \"**%2$s**\" إلى هاتفك **%1$s**.",
+ "tweb.Login.Code.SecretWord": "الكلمة السرية",
+ "tweb.Login.Code.SecretPhrase": "العبارة السرية",
+ "tweb.Login.Code.WordInvalid": "غير صحيح، يُرجى المحاولة مرة أخرى",
+ "tweb.Login.Code.WordBeginningInvalid": "كلمة غير صحيحة",
+ "tweb.Login.Password.Title": "أدخل كلمة المرور",
+ "tweb.Login.Password.Subtitle": "حسابك محمي\nبكلمة مرور إضافية",
+ "tweb.Login.Register.Subtitle": "أدخل اسمك\nلإنشاء حسابك",
+ "tweb.PleaseWait": "يُرجى الانتظار...",
+ "tweb.Code": "الرمز",
+ "tweb.LoginPassword": "كلمة المرور",
+ "tweb.YourName": "اسمك",
+ "tweb.FirstName": "الاسم الأول (مطلوب)",
+ "tweb.LastName": "اسم العائلة (اختياري)",
+ "tweb.StartMessaging": "ابدأ المراسلة",
+ "tweb.Country": "الدولة",
+ "tweb.Contacts.PhoneNumber.Placeholder": "رقم الهاتف",
+ "tweb.Login.Next": "التالي",
+ "tweb.Login.QR.Title": "تسجيل الدخول برمز QR",
+ "tweb.Login.QR.Help1": "افتح Telegram على هاتفك",
+ "tweb.Login.QR.Help2": "انتقل إلى **الإعدادات** > **الأجهزة** > **إضافة جهاز**",
+ "tweb.Login.QR.Help3": "وجّه هاتفك نحو هذه الشاشة لتأكيد تسجيل الدخول",
+ "tweb.Login.QR.Cancel": "تسجيل الدخول برقم الهاتف >",
+ "tweb.Login.QR.Login": "تسجيل الدخول برمز QR >",
+ "tweb.Login.QR.Subtitle": "امسح الرمز باستخدام تطبيق Telegram على هاتفك",
+ "tweb.PhoneNumber.Code.Fragment.Info": "احصل على الرمز من قسم الأرقام على [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "رمز غير صالح",
+ "tweb.PHONE_CODE_EXPIRED": "انتهت صلاحية الرمز",
+ "tweb.PASSWORD_HASH_INVALID": "كلمة المرور غير صحيحة",
+ "tweb.DarkMode": "الوضع الداكن",
+ "tweb.Error.AnError": "حدث خطأ. يُرجى المحاولة مرة أخرى لاحقًا.",
+ "tweb.AccDescr.LoginCode": "رمز تسجيل الدخول",
+ "tweb.Login.Bot": "تسجيل الدخول كبوت >",
+ "tweb.Login.Bot.Title": "تسجيل الدخول كبوت",
+ "tweb.Login.Bot.Subtitle": "أدخل التوكن الذي أعطاك إياه @BotFather\nعند إنشاء البوت.",
+ "tweb.Login.Bot.Token": "توكن البوت",
+ "tweb.Login.Bot.Cancel": "تسجيل الدخول كمستخدم >",
+ "tweb.Optional": "اختياري",
+ "tweb.PHONE_NUMBER_INVALID": "رقم الهاتف غير صالح",
+ "tweb.PHONE_NUMBER_BANNED": "رقم الهاتف هذا محظور",
+ "tweb.PHONE_NUMBER_FLOOD": "محاولات كثيرة جدًا، حاول مرة أخرى لاحقًا",
+ "tweb.PHONE_CODE_EMPTY": "رمز غير صالح",
+ "tweb.PHONE_PASSWORD_FLOOD": "محاولات كثيرة جدًا، حاول مرة أخرى لاحقًا",
+ "tweb.ACCESS_TOKEN_INVALID": "توكن البوت غير صالح",
+ "tweb.ACCESS_TOKEN_EXPIRED": "تم إبطال توكن البوت هذا",
+ "tweb.FIRSTNAME_INVALID": "الاسم الأول غير صالح",
+ "tweb.LASTNAME_INVALID": "اسم العائلة غير صالح",
+ "tweb.Close": "إغلاق"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ckb.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ckb.json
index ecfa036..a27ac6b 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ckb.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ckb.json
@@ -1,121 +1,274 @@
{
- "apiChooseManualAutoTip": "تێبینی بکە کە دەتوانیت API ID/hash ڕاستەوخۆ لە کۆدەکەدا دابین بکەیت بە بەکارهێنانی ڕێکخستنەکان: %s",
+ "baseDirLimitation": "سنووردارکردنێکی basedir ڕێکخراوە: ئەمە دەتوانێت کاریگەری لەسەر کارایی هەبێت و هەندێک کێشە دروست بکات، ئەگەر دەکرێت تکایە ناچالاکی بکە!",
+ "noReportPeers": "ئاگاداری: هیچ peer ێکی ڕاپۆرت دانەنراوە، تکایە ئەم شێوازەی خوارەوە بۆ event handler ەکەت زیاد بکە",
+ "manualAdminActionRequired": "!!!!!!!!! کرداری دەستیی بەڕێوەبەری سیستەم پێویستە !!!!!!!!!",
+ "mmapErrorPart1": "زۆرترین ژمارەی ناوچە نەخشەکێشراوەکانی بیرگە (mmap) تێپەڕێنرا (%s): بۆ چارەسەرکردن، تکایە ڕێکخستنی کێرنێڵی vm.max_map_count بۆ 262144 زیاد بکە.",
+ "mmapErrorPart2": "بۆ چارەسەرکردن، ئەم فەرمانەی خوارەوە وەک root جێبەجێ بکە: %s",
+ "mmapErrorPart3": "بۆ ئەوەی گۆڕانکارییەکە دوای دووبارە هەڵکردنەوەی سیستەم بمێنێتەوە: %s",
+ "mmapErrorPart4": "لە Windows و WSL دا، گەورەکردنی قەبارەی pagefile لەوانەیە یارمەتیدەر بێت؛ ئەگەر کێشەکە بەردەوام بوو، تکایە بگۆڕە بۆ Linux ی ڕاستەوخۆ (native).",
+ "botAlreadyRunning": "بۆتەکە پێشتر کاردەکات!",
+ "extensionRequired": "MadelineProto بۆ کارکردن پێویستی بە پاشکۆی %s هەیە. %s",
+ "extensionRequiredInstallWithApt": "هەوڵبدە sudo apt-get install %s جێبەجێ بکەیت.",
+ "extensionRequiredInstallWithCustomInstructions": "بۆ دامەزراندنی، ڕێنماییەکانی %s پەیڕەو بکە.",
+ "extensionRecommended": "ئاگاداری: پاشکۆی %s دانەمەزراوە، تکایە دایبمەزرێنە بۆ خێراکردنی MadelineProto!",
"go": "بڕۆ",
+ "apiChooseManualAutoTip": "تێبینی بکە کە دەتوانیت API ID/hash ڕاستەوخۆ لە کۆدەکەدا دابین بکەیت بە بەکارهێنانی ڕێکخستنەکان: %s",
"apiChooseManualAutoTipWeb": "تێبینی بکە کە دەتوانیت API ID/hash ڕاستەوخۆ لە کۆدەکەدا دابین بکەیت بە بەکارهێنانی ڕێکخستنەکان.",
- "constructor_not_found": "Constructor نەدۆزرایەوە بۆ جۆری: ",
- "botapi_conversion_error": "ناتوانرێت %s بگۆڕێت بۆ ئۆبجێکتی API بۆت",
- "file_type_invalid": "جۆری پەڕگەی نادروست دۆزراوەتەوە (%s)",
- "apiManualInstructions2": "کلیک لەسەر create application بکە",
- "signupLastNameWeb": "ناوی کۆتایی",
- "apiChoosePrompt": "هەڵبژاردەی تۆ: ",
+ "apiChoosePrompt": "هەڵبژاردەی تۆ (m/a): ",
"apiManualInstructions0": "چوونەژوورەوە بۆ https://my.telegram.org",
"apiManualInstructions1": "بڕۆ بۆ ئامرازەکانی پەرەپێدانی API",
+ "apiManualInstructions2": "کلیک لەسەر create application بکە",
"apiAppInstructionsManual0": "ناوی ئەپەکەت دەتوانێت هەر شتێک بێت",
+ "apiAppInstructionsManual1": "ناوی کورتی ئەپەکەت، ئەلفوبێی ژمارەیی، ٥-٣٢ پیت",
"apiAppInstructionsManual2": "URL ی ئەپ/ماڵپەڕەکەت، یان t.me/yourusername",
"apiAppInstructionsManual3": "هەر شتێک",
"apiAppInstructionsManual4": "لێرەدا باسی ئەپەکەت بکە",
"apiManualWeb": "API ID و API هاشەکەت دابنێ",
+ "apiManualPrompt0": "ناسنامەی API ی خۆت دابنێ: ",
"apiManualPrompt1": "هاشی API ەکەت بنووسە: ",
+ "apiAutoWeb": "ژمارەیەکی تەلەفۆن دابنێ کە پێشتر تۆمارکراوە لە تێلێگرام بۆ بەدەستهێنانی ناسنامەی API",
"apiAutoPrompt0": "ژمارەی تەلەفۆنێک داخڵ بکە کە پێشتر لە تێلێگرام تۆمار کراوە: ",
"apiAutoPrompt1": "ئەو کۆدەی پشتڕاستکردنەوە کە لە تێلێگرام وەرتگرتووە داخڵ بکە: ",
"apiAppWeb": "زانیارییەکانی API داخڵ بکە",
+ "apiAppInstructionsAuto0": "ناوی ئەپەکە بنووسە، دەتوانێت هەر شتێک بێت: ",
"apiAppInstructionsAuto1": "ناوی کورتی ئەپەکە بنووسە، ئەلفوبێی ژمارەیی، ٥-٣٢ پیت: ",
- "apiAppInstructionsAuto3": "چوونە ناو پلاتفۆرمی ئەپەکە: ",
+ "apiAppInstructionsAuto2": "URL ی ئەپ/ماڵپەڕەکە دابنێ، یان t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "پلاتفۆرمی ئەپەکە بنووسە: ",
"apiAppInstructionsAuto4": "باسی ئەپەکەت بکە: ",
"apiAppInstructionsAutoTypeOther": "شتی تر (لە وەسفدا دیاری بکە)",
+ "apiParamsError": "تۆ هەموو پارامێتەرەکانی پێویستت دابین نەکردووە!",
"apiError": "هەڵە: %s. دووبارە هەوڵبدەرەوە.",
"loginChoosePromptWeb": "دەتەوێت وەک بەکارهێنەر یان وەک بۆت بچیتە ژوورەوە؟",
+ "loginWebQr": "هەروەها دەتوانیت بە شێوەیەکی ئۆتۆماتیکی بچیتە ژوورەوە بە کردنەوەی تێلێگرام لە مۆبایلەکەتدا، چوون بۆ ڕێکخستنەکان > ئامێرەکان > بەستنەوەی ئامێری سەر مێز و سکانکردنی ئەم QR کۆدە:",
"loginWebQr1": "لە مۆبایلەکەتدا تێلێگرام بکەرەوە",
"loginWebQr2": "بڕۆ بۆ ڕێکخستنەکان > ئامێرەکان > بەستنەوەی ئامێری سەر مێز",
+ "loginWebQr3": "بۆ پشتڕاستکردنەوەی چوونەژوورەوە مۆبایلەکەت ئاراستەی ئەم شاشەیە بکە",
"loginOptionBot": "بۆت",
"loginOptionUser": "بەکارهێنەر",
"loginBot": "تۆکنی بۆتەکەت بنووسە: ",
- "loginUser": "ژمارەی مۆبایلت داخل بکە: ",
+ "loginUser": "ژمارەی مۆبایلت داخڵ بکە: ",
+ "loginQr": "لە مۆبایلەکەتدا تێلێگرام بکەرەوە، بڕۆ بۆ ڕێکخستنەکان > ئامێرەکان > بەستنەوەی ئامێری سەر مێز و کۆدی QR ی سەرەوە سکان بکە بۆ ئەوەی بە شێوەیەکی ئۆتۆماتیکی بچیتە ژوورەوە.",
"loginQrCodeSuccessful": "چوونەژوورەوەی کۆدی QR سەرکەوتوو بوو!",
"loginQrCodeExpired": "کۆدی QR بەسەرچوو، کۆدی نوێی دروستکرد...",
"loginManual": "یان دەتوانیت تۆکنێکی بۆت یان ژمارەی تەلەفۆنیش دابنێیت بۆ ئەوەی بە دەستی بچیتە ژوورەوە: ",
"loginUserCode": "کۆدەکە داخڵ بکە: ",
"loginUserPass": "وشەی نهێنی خۆت بنووسە (ئاماژە %s): ",
- "loginUserPassWeb": "ژمارەی نهێنییەکەت داخل بکە: ",
+ "loginUserPassWeb": "وشەی نهێنییەکەت داخڵ بکە: ",
"loginUserPassHint": "ئاماژە: %s",
"signupFirstName": "ناوی یەکەمی خۆت بنووسە: ",
"signupLastName": "ناوی کۆتایی خۆت بنووسە (دەتوانێت بەتاڵ بێت): ",
"signupWeb": "تکایە ناوت تۆمار بکە",
"signupFirstNameWeb": "ناوی یەکەم",
+ "signupLastNameWeb": "ناوی کۆتایی",
"loginNoCode": "تۆ کۆدی تەلەفۆنت بۆ دابین نەکرد!",
+ "loginNoPass": "تۆ پاسۆردەکەت دابین نەکرد!",
"loginNoName": "ناوی یەکەمتان دابین نەکردووە!",
"loginBotTokenWeb": "بۆت تۆکن",
"loginUserPhoneWeb": "ژمارەی تەلەفۆن",
"loginUserPhoneCodeWeb": "کۆد",
"done": "تەواو!",
+ "nearest_dc": "ئێمە لە %s داین، نزیکترین DC %d ە.",
"serialization_ofd": "زنجیرەییکردن بەسەرچووە، دووبارە بنیاتنانەوەی ئۆبجێکتی!",
- "session_corrupted": "دانیشتنەکە گەندەڵ بووە!",
+ "api_not_set": "پێویستە کلیلی api و api id دابین بکەیت، خۆت @ my.telegram.org بەدەست بهێنە",
+ "session_corrupted": "دانیشتنەکە تێکچووە!",
"value_bigger_than_2147483647": "بەهای دابینکراو %s گەورەترە لە 2147483647",
"value_smaller_than_2147483648": "بەهای دابینکراو %s بچووکترە لە -2147483648",
"value_bigger_than_9223372036854775807": "بەهای دابینکراو %s گەورەترە لە 9223372036854775807",
"value_smaller_than_9223372036854775808": "بەهای دابینکراو %s بچووکترە لە -9223372036854775808",
- "value_bigger_than_4294967296": "بەهای مەرجدار %s گەورەترە لە 4294967296",
- "value_smaller_than_0": "بەهای بە مەرجێک %s بچووکترە لە 0",
- "encode_double_error": "نەتوانرا بە باشی دووانە کۆد بکات",
+ "value_bigger_than_4294967296": "بەهای دابینکراو %s گەورەترە لە 4294967296",
+ "value_smaller_than_0": "بەهای دابینکراو %s بچووکترە لە 0",
+ "encode_double_error": "نەتوانرا double بە دروستی کۆد بکرێت",
"file_not_exist": "فایلهکه بوونی نییه",
+ "deserialization_error": "هەڵەیەک لە کاتی deserialization دا ڕوویدا",
+ "rpc_tg_error": "تێلێگرام هەڵەیەکی RPC ی گەڕاندەوە: %s (%s)، بەهۆی %s:%s%sشوێنپێی TL:",
"madelineproto_ready": "MadelineProto ئامادەیە!",
"logout_ok": "بە سەرکەوتوویی دەرچووە!",
"already_loggedIn": "ئەم نموونەیەی MadelineProto پێشتر چووەتە ژوورەوە!",
"login_ok": "بە سەرکەوتوویی چوونەژوورەوە!",
"login_user": "چوونە ژوورەوە وەک بەکارهێنەرێکی ئاسایی...",
"login_bot": "چوونە ژوورەوە وەک بۆتێک...",
- "login_code_uncalled": "چاوەڕێی کۆدەکە ناکەم! تکایە سەرەتا پەیوەندی بە شێوازی phoneLogin بکەن",
+ "login_code_sending": "ناردنی کۆد...",
+ "login_code_sent": "کۆد بە سەرکەوتوویی نێردراوە! کاتێک کۆدەکەت وەرگرت پێویستە فەنکشنی completePhoneLogin بەکاربهێنیت.",
+ "login_code_uncalled": "چاوەڕێی کۆدەکە ناکەم! تکایە سەرەتا بانگی شێوازی phoneLogin بکە",
"login_2fa_enabled": "2FA چالاک کراوە، دەبێت بانگی فەنکشنی complete2falogin بکەیت...",
+ "login_need_signup": "ئەکاونتێک بۆ ئەم ژمارەیە دروست نەکراوە، دەبێت بانگی فەنکشنی completeSignup بکەیت...",
"login_auth_key": "چوونە ژوورەوە بە بەکارهێنانی کلیلی auth...",
+ "not_loggedIn": "من نەچوومەتە ژوورەوە!",
+ "signup_uncalled": "چاوەڕێی ناو تۆمارکردن ناکەم! تکایە سەرەتا بانگی شێوازەکانی phoneLogin و completePhoneLogin بکە!",
"signing_up": "ناو تۆمارکردن وەک بەکارهێنەرێکی ئاسایی...",
"signup_ok": "بە سەرکەوتوویی ناوت تۆمار کرد!",
- "2fa_uncalled": "چاوەڕێی پاسۆردەکە ناکەم! تکایە سەرەتا پەیوەندی بە phoneLogin و شێوازەکانی completePhoneLogin بکەن!",
+ "2fa_uncalled": "چاوەڕێی پاسۆردەکە ناکەم! تکایە سەرەتا بانگی شێوازەکانی phoneLogin و completePhoneLogin بکە!",
+ "peer_not_in_db": "ئەم هاوتایە لە بنکەدراوەی ناوخۆیی هاوتادا ئامادە نییە",
"call_error_1": "نەتوانرا پەیوەندی %s بدۆزرێتەوە و وەریبگرێت",
"accepting_call": "وەرگرتنی پەیوەندی لە %s...",
"call_already_accepted": "پەیوەندی %s پێشتر وەرگیراوە",
+ "call_already_declined": "پەیوەندی %s پێشتر ڕەتکراوەتەوە",
+ "call_error_2": "نەتوانرا پەیوەندی %s بدۆزرێتەوە و پشتڕاستی بکاتەوە",
"call_confirming": "پشتڕاستکردنەوەی پەیوەندی لە %s...",
"call_error_3": "نەتوانرا پەیوەندی %s بدۆزرێتەوە و تەواو بکات",
+ "call_completing": "تەواوکردنی پەیوەندی لە %s...",
"fingerprint_invalid": "پەنجەمۆری کلیل نادروستە!",
"call_discarding": "فڕێدانی پەیوەندی %s...",
"file_parsing": "پارسکردنی %s...",
"src_file_invalid": "پەڕگەی سەرچاوەی نادروست دابین کرا: ",
+ "bool_error": "نەتوانرا boolean دەربهێنرێت",
"not_numeric": "بەهای پێدراو ژمارەیی نییە",
"long_not_16": "بەهای پێدراو درێژییەکەی ١٦ بایت نییە",
+ "long_not_32": "بەهای پێدراو درێژییەکەی ٣٢ بایت نییە",
"long_not_64": "بەهای پێدراو درێژییەکەی ٦٤ بایت نییە",
"array_invalid": "تۆ ڕیزبەندییەکی دروستت دابین نەکردووە",
+ "predicate_not_set": "Predicate (بەهای ژێر _) دانەنرابوو!",
+ "update_madelineproto": "تۆ وەشانێکی کۆنی MadelineProto بەکاردەهێنیت، نوێکردنەوە پێویستە: ئێستا وەشانی %s کاردەکات، بەڵام دوایین وەشان کە چەندین چاککردنەوەی هەڵە و تایبەتمەندی نوێی تێدایە %s ە!",
"type_extract_error": "نەتوانرا جۆری \"%s\" دەربهێنرێت، پێویستە MadelineProto نوێ بکەیتەوە!",
"method_not_found": "نەتوانرا شێواز بدۆزرێتەوە: ",
"params_missing": "پارامێتری پێویست نەماوە",
- "stream_handle_invalid": "دەستەیەکی نادروستی سترێم دابین کرابوو.",
- "apiAppInstructionsManual1": "ناوی کورتی ئەپەکەت، ئەلفوبێی ژمارەیی، ٥-٣٢ پیت",
- "apiManualPrompt0": "ناسنامەی API ی خۆت دابنێ: ",
- "apiAutoWeb": "ژمارەیەکی تەلەفۆن دابنێ کە پێشتر تۆمارکراوە لە تێلێگرام بۆ بەدەستهێنانی ناسنامەی API",
- "apiAppInstructionsAuto0": "ناوی ئەپەکە بنووسە، دەتوانێت هەر شتێک بێت: ",
- "apiAppInstructionsAuto2": "URL ی ئەپ/ماڵپەڕەکە دابنێ، یان t.me/yourusername: ",
- "apiParamsError": "تۆ هەموو پارامێتەرەکانی پێویستت دابین نەکردووە!",
- "loginWebQr": "هەروەها دەتوانیت بە شێوەیەکی ئۆتۆماتیکی بچیتە ژوورەوە بە سکانکردنی ئەم QR کۆدە:",
- "loginWebQr3": "بۆ پشتڕاستکردنەوەی چوونەژوورەوە مۆبایلەکەت ئاراستەی ئەم شاشەیە بکە",
- "loginQr": "کۆدی QR ی سەرەوە سکان بکە بۆ ئەوەی بە شێوەیەکی ئۆتۆماتیکی بچیتە ژوورەوە.",
- "loginNoPass": "تۆ پاسۆردەکەت دابین نەکرد!",
- "nearest_dc": "ئێمە لە %s داین، نزیکترین DC %d ە.",
- "api_not_set": "پێویستە کلیلی api و api id دابین بکەیت، خۆت @ my.telegram.org بەدەست بهێنە",
- "deserialization_error": "هەڵەیەک لە کاتی ڕیزبەندیکردندا ڕوویدا",
- "rpc_tg_error": "تێلێگرام هەڵەیەکی RPC ی گەڕاندەوە: %s (%s)، کە بەهۆی %s:%s%sTL شوێنپێهەڵگرتنەوە دروست بووە:",
- "login_code_sending": "ناردنی کۆد...",
- "login_code_sent": "کۆد بە سەرکەوتوویی نێردراوە! کاتێک کۆدەکەت وەرگرت پێویستە فەنکشنی completePhoneLogin بەکاربهێنیت.",
- "login_need_signup": "ئەکاونتێک بۆ ئەم ژمارەیە دروست نەکراوە، دەبێت پەیوەندی بە فەنکشنی completeSignup بکەیت...",
- "not_loggedIn": "من چوومەتە ژوورەوە!",
- "signup_uncalled": "چاوەڕێی ناو تۆمارکردن ناکەم! تکایە سەرەتا پەیوەندی بە phoneLogin و شێوازەکانی completePhoneLogin بکەن!",
- "peer_not_in_db": "ئەم هاوتایە لە بنکەدراوەی ناوخۆیی هاوتادا ئامادە نییە",
- "call_already_declined": "پەیوەندی %s پێشتر ڕەتکراوەتەوە",
- "call_error_2": "نەتوانرا پەیوەندی %s بدۆزرێتەوە و پشتڕاستی بکاتەوە",
- "call_completing": "تەواوکردنی پەیوەندی لە %s...",
- "bool_error": "نەتوانرا boolean دەربهێنرێت",
- "long_not_32": "بەهای پێدراو درێژییەکەی ٣٢ بایت نییە",
- "predicate_not_set": "پێشبینی (بەهای ژێر _) دانەنرابوو!",
"sec_peer_not_in_db": "ئەم هاوتا نهێنییە لە بنکەدراوەی ناوخۆیی هاوتادا ئامادە نییە",
+ "stream_handle_invalid": "دەستەیەکی نادروستی سترێم دابین کرابوو.",
"length_too_big": "درێژی زۆر گەورەیە",
+ "string_required": "چاوەڕێی string دەکرا!",
+ "waveform_must_have_100_values": "ڕیزبەندییەکی waveform دەبێت 100 بەهای هەبێت!",
+ "waveform_value": "بەهای waveform دەبێت لە نێوان 0 و 31 دا بێت!",
+ "could_not_convert_object": "نەتوانرا ئۆبجێکتی جۆری %s بگۆڕدرێت",
"type_extract_error_id": "نەتوانرا جۆری: %s بە id %s دەربهێنرێت، پێویستە MadelineProto نوێ بکەیتەوە!",
- "non_text_conversion": "هێشتا ناتوانرێت نامە نا کورتەکان بگۆڕدرێت!",
- "secret_chat_skipping": "من چاتی نهێنی %sم لە بنکەدراوەدا نییە، نامەکەم بەجێهێشتووە..."
+ "constructor_not_found": "Constructor نەدۆزرایەوە بۆ جۆری: ",
+ "botapi_conversion_error": "ناتوانرێت %s بگۆڕێت بۆ ئۆبجێکتی API بۆت",
+ "non_text_conversion": "هێشتا ناتوانرێت نامە نادەقییەکان بگۆڕدرێن!",
+ "file_type_invalid": "جۆری پەڕگەی نادروست دۆزراوەتەوە (%s)",
+ "static_analysis_minor": "لە کاتی شیکاری ستاتیکی %s دا کێشەیەکی بچووک دۆزرایەوە: %s",
+ "static_analysis_severe": "لە کاتی شیکاری ستاتیکی %s دا کێشەیەکی گەورە دۆزرایەوە: %s",
+ "secret_chat_skipping": "من چاتی نهێنی %sم لە بنکەدراوەدا نییە، نامەکەم بەجێهێشتووە...",
+ "must_have_declare_types": "بە هۆکاری کارایی، یەکەم ڕستەی پەڕگەی event handler دەبێت \"declare(strict_types=1);\" بێت",
+ "do_not_delete_MadelineProto.log": "پەڕگەی MadelineProto.log هەرگیز نابێت بسڕدرێتەوە، لە جیاتی ئەوە تکایە قەبارەیەکی زۆرینەی تایبەت لە ڕێکخستنەکاندا دابنێ!",
+ "do_not_remove_MadelineProto.log_phar": "تکایە madeline.phar یان madeline.php مەسڕەوە، ئەگەرنا MadelineProto تێکدەشکێت. ئەگەر هەر کێشەیەکت لەگەڵ MadelineProto هەبوو، ڕاپۆرتی بکە بۆ https://github.com/danog/MadelineProto یان https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "بە هۆکاری کارایی، event handler ەکان نابێت فەنکشنی بلۆککەری نا-async ی %s بەکاربهێنن، تکایە لە جیاتی ئەوە %s بەکاربهێنە",
+ "do_not_use_blocking_class": "بە هۆکاری کارایی، handler ەکان نابێت کلاسی بلۆککەری نا-async ی %s بەکاربهێنن، تکایە لە جیاتی ئەوە %s بەکاربهێنە",
+ "do_not_use_deprecated_function": "فەنکشنی %s کۆن بووە (deprecated)، تکایە لە جیاتی ئەوە %s بەکاربهێنە",
+ "do_not_use_non_root_require_in_event_handler": "بە هۆکاری کارایی، نابێت require یان include لەناو کلاسی event handler دا بەکاربهێنیت، تەنها require لە ئاستی سەرەکی (root) ی پەڕگەکەدا ڕێگەپێدراوە.",
+ "do_not_use_yield": "MadelineProto 8 پێویستی بە بەکارهێنانی yield لە فەنکشنە async ەکاندا نییە و پشتگیریشی ناکات، دەبێت هەموو ئەو yield انە لاببەیت کە پێشتر بۆ بانگکردنی فەنکشنە async ەکان بەکارتهێناون",
+ "recommend_not_use_filesystem_function": "بەکارهێنانی فەنکشنی %s پێشنیار ناکرێت، چونکە دەستگەیشتن بە سیستەمی پەڕگەکان لە کاتی مامەڵەکردن لەگەڵ update ەکاندا بۆتەکەت خاو دەکاتەوە، تکایە سەیری https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions بکە بۆ لیستێکی ڕێگە جێگرەوەکانی هەڵگرتنی داتا کە بۆتەکەت خاو ناکەنەوە!",
+ "plugins_do_not_use_require": "بە هۆکاری کارایی، پلەگینەکان تەنها دەتوانن پەڕگەکانی تری ناو فۆڵدەری پلەگینەکان بە شێوەی ئۆتۆماتیکی include یان require بکەن لە ڕێگەی autoloader ی PSR-4 ەوە (نەک بە require() کردنی دەستی).",
+ "plugins_must_have_exactly_one_class": "پلەگین دەبێت ڕێک یەک کلاس پێناسە بکات! بۆ پێناسەکردنی چەند کلاس، interface یان trait، پەڕگەی جیاواز دروست بکە، MadelineProto بە شێوەی ئۆتۆماتیکی autoload یان دەکات.",
+ "cli_need_dl.php_link": "تکایە کاتێک getDownloadLink لە ڕێگەی CLI بەکاردەهێنیت، URL ی سکریپتێکی داگرتن دیاری بکە!",
+ "invalid_dl.php_session": "%s سکریپتێکی داگرتنی دروست نییە چونکە ID ی دانیشتنەکەی جیاوازە (چاوەڕوانکراو %s، وەرگیراو %s)",
+ "need_dl.php": "نەتوانرا سکریپتی داگرتنی بنەڕەتی دروست بکرێت (%s)، تکایە پەڕگەیەکی dl.php بەم ناوەڕۆکەی خوارەوە دروست بکە: %s و URL ەکەی وەک پارامێتری دووەم بدە بە getDownloadLink",
+ "dl.php_powered_by_madelineproto": "سێرڤەری داگرتنی پەڕگەکانی تێلێگرام (تا 4GB)، بە هێزی MadelineProto!
کلیک لە ئێرە بکە بۆ زانیاری زیاتر لەسەر چۆنیەتی ڕێکخستنی سێرڤەری داگرتنی پەڕگەکانی تێلێگرامی تایبەت بە خۆت!",
+ "dl.php_check_logs_make_sure_session_running": "یان بۆتی EventHandler ی پەیوەندیداری MadelineProto یان سێرڤەری IPC ی MadelineProto ئۆفلاینە، تکایە لۆگەکان بپشکنە و دڵنیابە کە لانیکەم یەکێکیان کاردەکات!",
+ "account_banned": "!!!!!!! ئاگاداری !!!!!!!\nسیستەمی ڕێگریکردن لە flood ی تێلێگرام ئەم ئەکاونتەی ڕاگرتووە.\nبۆ بەردەوامبوون، پشتڕاستکردنەوەی دەستی پێویستە.\nئیمەیڵێک بنێرە بۆ recover@telegram.org و داوای لابردنی باندی ژمارەی تەلەفۆنی %s بکە، و بە کورتی باسی ئەوە بکە کە چی بەم ژمارە تەلەفۆنە دەکەیت.\nپاشان دووبارە بچۆ ژوورەوە.\nئەگەر بە ئەنقەست ئەم ئەکاونتەت سڕیوەتەوە، ئەم نامەیە پشتگوێ بخە.",
+ "plugin_path_does_not_exist": "ڕێڕەوی پلەگینی %s بوونی نییە!",
+ "could_not_connect_to_MadelineProto": "نەتوانرا پەیوەندی بە MadelineProto بکرێت، بۆ چارەسەرکردن تکایە proc_open چالاک بکە و سنوورەکانی open_basedir لاببە یان rewrite ی ڕێڕەوەکانی webserver ناچالاک بکە! ئەگەر پێشتر ئەمەت کردووە، دڵنیابە کە وەشانی CLI ی PHP ڕێک وەک وەشانی وێبە (هەمان وەشان، پاشکۆکان و هتد) و سەیری پەڕگەی MadelineProto.log بکە بۆ زانیاری زیاتر دەربارەی ئەو هەڵەیەی ڕێگری لە دەستپێکردنی سێرڤەری IPC کرد.",
+ "translate_madelineproto_web": "MadelineProto دەتوانرێت بۆ زمانەکەت وەربگێڕدرێت (ڕێژەی ئێستای وەرگێڕان: %d%%)، کلیک لێرە بکە بۆ بەشداریکردن لە وەرگێڕانەکە!",
+ "translate_madelineproto_cli": "MadelineProto دەتوانرێت بۆ زمانەکەت وەربگێڕدرێت (ڕێژەی ئێستای وەرگێڕان: %d%%)، بڕۆ بۆ https://github.com/danog/MadelineProto/tree/v8/langs بۆ بەشداریکردن لە وەرگێڕانەکە!",
+ "apiInvalidWeb": "API ID ژمارەیەکە و API hash درێژییەکەی 32 پیتە: دووبارە لە my.telegram.org کۆپییان بکە.",
+ "webDoneLead": "MadelineProto لەسەر سێرڤەرەکە بەردەوام کاردەکات: دەتوانیت ئەم پەڕەیە دابخەیت.",
+ "apiChooseManualAuto": "دەتەوێت API ID و hash بە شێوەی ئۆتۆماتیکی لە my.telegram.org وەربگریت (a)، یان بە دەستی داخڵیان بکەیت (m)؟",
+ "apiAutoFallbackManual": "لە جیاتی ئەوە، API ID و hash بە دەستی داخڵ بکە.",
+ "apiSetupTitleWeb": "API ID و hash ەکەت وەربگرە",
+ "apiSetupLeadWeb": "هەموو ئەپێکی Telegram پێویستی بە API ID و hash هەیە. MadelineProto دەتوانێت بە ژمارەی تەلەفۆنی ئەکاونتێکی Telegram ی هەبوو، لە my.telegram.org بۆت وەربگرێت.",
+ "apiAutoPhoneHintWeb": "my.telegram.org کۆدی چوونەژوورەوە بۆ ئەپی Telegram ەکەت دەنێرێت، نەک بە SMS.",
+ "apiSendCodeWeb": "ناردنی کۆد",
+ "apiChooseManualWeb": "پێشتر API ID م هەیە",
+ "apiChooseAutoWeb": "وەرگرتنی ئۆتۆماتیکی",
+ "apiStartOverWeb": "دەستپێکردنەوە لە سەرەتاوە",
+ "apiAutoCodeTitleWeb": "کۆدەکەی Telegram داخڵ بکە",
+ "apiAutoCodeLeadWeb": "my.telegram.org کۆدێکی چوونەژوورەوەی بۆ ئەپی Telegram ەکەت نارد، لە چاتەکەی Telegram دا (نەک بە SMS).",
+ "apiAutoCodeLabelWeb": "کۆدی چوونەژوورەوە",
+ "apiCreateTitleWeb": "ئەپەکەت دروست بکە",
+ "apiCreateLeadWeb": "ئەم ئەکاونتە هێشتا هیچ ئەپێکی لە my.telegram.org نییە. ئەم زانیاریانە تەنها بۆ تۆ پیشان دەدرێن، و دواتر دەتوانرێت بگۆڕدرێن.",
+ "apiAppTitleLabelWeb": "ناوی ئەپ",
+ "apiAppShortNameLabelWeb": "ناوی کورت",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "وەسف",
+ "apiCreateWeb": "دروستکردنی ئەپ",
+ "apiSaveWeb": "پاشەکەوتکردن و بەردەوامبوون",
+ "apiAutoErrorTitle": "my.telegram.org هەڵەیەکی گەڕاندەوە",
+ "apiCreateErrorTitle": "my.telegram.org ئەپەکەی دروست نەکرد",
+ "apiCreateVpsWarning": "Telegram ڕێگە نادات لە VPS و VPN و مەودای IP ی داتاسێنتەرەکانی ترەوە ئەپی نوێ لە my.telegram.org دروست بکرێت، و داواکارییەکە لە IP ی ئەو ئامێرەوە نێردرا کە MadelineProto ی لەسەر کاردەکات. ئەپەکە بە دەستی لە https://my.telegram.org لە ڕێگەی پەیوەندییەکی ماڵەوە (وەک مۆبایلەکەت بە داتای مۆبایل) دروست بکە، پاشان API ID و hash داخڵ بکە.",
+ "loginTitleWeb": "چوونەژوورەوە بۆ Telegram",
+ "loginLeadWeb": "ئەو ئەکاونت یان بۆتە هەڵبژێرە کە ئەم نموونەیەی MadelineProto وەک ئەو کاردەکات.",
+ "loginTypeWeb": "چوونەژوورەوە وەک",
+ "loginUserPhoneHintWeb": "لەگەڵ کۆدی وڵات، وەک +39 123 456 7890.",
+ "loginBotTokenHintWeb": "ئەو تۆکنەی @BotFather پێی دایت کاتێک بۆتەکەت دروست کرد.",
+ "loginCodeTitleWeb": "کۆدی چوونەژوورەوە داخڵ بکە",
+ "loginCodeLeadWeb": "Telegram کۆدێکی چوونەژوورەوەی بۆ ئەپی Telegram ەکەت نارد، یان بە SMS ئەگەر لە هیچ شوێنێکی تر نەچوویتە ژوورەوە.",
+ "loginPasswordTitleWeb": "پشتڕاستکردنەوەی دوو هەنگاوی",
+ "loginPasswordLeadWeb": "ئەم ئەکاونتە بە وشەی نهێنییەک پارێزراوە، کە لە ڕێکخستنەکان > تایبەتێتی و ئاسایش > پشتڕاستکردنەوەی دوو هەنگاوی دانراوە.",
+ "loginPasswordLabelWeb": "وشەی نهێنی",
+ "signupTitleWeb": "ئەکاونتەکەت دروست بکە",
+ "signupLeadWeb": "ئەم ژمارە تەلەفۆنە هێشتا لە Telegram دا نییە: ناوی ئەکاونتە نوێیەکە هەڵبژێرە.",
+ "webContinue": "بەردەوامبوون",
+ "webLogin": "چوونەژوورەوە",
+ "webError": "%s. بیپشکنە و دووبارە هەوڵبدەرەوە.",
+ "webStepApp": "API ID و hash",
+ "webStepAccount": "ئەکاونت",
+ "webStepVerify": "پشتڕاستکردنەوە",
+ "webStepDone": "کاردەکات",
+ "webProgress": "پێشکەوتنی ڕێکخستن",
+ "webDocs": "بەڵگەنامەکان",
+ "webOptional": "ئارەزوومەندانە",
+ "webShowPassword": "پیشاندان",
+ "webHidePassword": "شاردنەوە",
+ "webQrTitle": "چوونەژوورەوە بە کۆدی QR",
+ "webQrWaiting": "چاوەڕێی سکانکردن…",
+ "webFieldRequired": "ئەم خانەیە پڕ بکەرەوە.",
+ "webPhoneInvalid": "ژمارەی تەلەفۆن لەگەڵ کۆدی وڵاتەکەی داخڵ بکە، وەک +39 123 456 7890.",
+ "tweb.Login.Title": "چوونەژوورەوە بۆ MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "ژمارەی تەلەفۆن نادروستە",
+ "tweb.Login.StartText": "تکایە کۆدی وڵاتەکەت پشتڕاست بکەرەوە\nو ژمارەی تەلەفۆنەکەت داخڵ بکە.",
+ "tweb.Login.Code.SentSms": "SMS ێکمان بۆ ناردیت\nکە کۆدەکەی تێدایە.",
+ "tweb.Login.Code.SentInApp": "نامەیەکمان لە Telegram بۆ ناردیت\nکە کۆدەکەی تێدایە.",
+ "tweb.Login.Code.SentCall": "پەیوەندیت پێوە دەکەین و\nکۆدەکەت بۆ دەخوێنینەوە.",
+ "tweb.Login.Code.SentEmail": "تکایە ئیمەیڵەکەت **%s** بپشکنە (فۆڵدەری سپام لەبیر مەکە) و ئەو کۆدەی ئێستا بۆمان ناردیت داخڵ بکە.",
+ "tweb.Login.Code.SentUnknown": "تکایە هەموو شوێنێک بپشکنە\nبۆ دۆزینەوەی کۆدەکە (جۆر: %s)",
+ "tweb.Login.Code.SentMissedCall": "لە چەند چرکەی داهاتوودا\nپەیوەندییەکی کورت لە **%s** وەردەگریت. وەڵامی مەدەرەوە —\nتەنها دوایین ژمارەکانی ئەو ژمارەیە داخڵ بکە.",
+ "tweb.Login.Code.SentSmsWord": "SMS ێکمان کە وشەیەکی شاراوەی تێدایە\nبۆ تەلەفۆنەکەت **%s** نارد.",
+ "tweb.Login.Code.SentSmsWordBeginning": "SMS ێکمان کە وشەیەکی شاراوەی تێدایە و بە\n\"**%2$s**\" دەست پێدەکات، بۆ تەلەفۆنەکەت **%1$s** نارد.",
+ "tweb.Login.Code.SentSmsPhrase": "SMS ێکمان کە دەستەواژەیەکی شاراوەی تێدایە\nبۆ تەلەفۆنەکەت **%s** نارد.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "SMS ێکمان کە دەستەواژەیەکی شاراوەی تێدایە و بە\n\"**%2$s**\" دەست پێدەکات، بۆ تەلەفۆنەکەت **%1$s** نارد.",
+ "tweb.Login.Code.SecretWord": "وشەی شاراوە",
+ "tweb.Login.Code.SecretPhrase": "دەستەواژەی شاراوە",
+ "tweb.Login.Code.WordInvalid": "هەڵەیە، تکایە دووبارە هەوڵبدەرەوە",
+ "tweb.Login.Code.WordBeginningInvalid": "وشەی هەڵە",
+ "tweb.Login.Password.Title": "وشەی نهێنییەکەت داخڵ بکە",
+ "tweb.Login.Password.Subtitle": "ئەکاونتەکەت بە وشەیەکی نهێنی\nزیادە پارێزراوە",
+ "tweb.Login.Register.Subtitle": "ناوەکەت داخڵ بکە\nبۆ دروستکردنی ئەکاونتەکەت",
+ "tweb.PleaseWait": "تکایە چاوەڕێ بکە...",
+ "tweb.Code": "کۆد",
+ "tweb.LoginPassword": "وشەی نهێنی",
+ "tweb.YourName": "ناوەکەت",
+ "tweb.FirstName": "ناوی یەکەم (پێویستە)",
+ "tweb.LastName": "ناوی کۆتایی (ئارەزوومەندانە)",
+ "tweb.StartMessaging": "دەستپێکردنی نامەناردن",
+ "tweb.Country": "وڵات",
+ "tweb.Contacts.PhoneNumber.Placeholder": "ژمارەی تەلەفۆن",
+ "tweb.Login.Next": "دواتر",
+ "tweb.Login.QR.Title": "چوونەژوورەوە بە کۆدی QR",
+ "tweb.Login.QR.Help1": "لە مۆبایلەکەتدا Telegram بکەرەوە",
+ "tweb.Login.QR.Help2": "بڕۆ بۆ **ڕێکخستنەکان** > **ئامێرەکان** > **زیادکردنی ئامێر**",
+ "tweb.Login.QR.Help3": "بۆ پشتڕاستکردنەوەی چوونەژوورەوە مۆبایلەکەت ئاراستەی ئەم شاشەیە بکە",
+ "tweb.Login.QR.Cancel": "چوونەژوورەوە بە ژمارەی تەلەفۆن >",
+ "tweb.Login.QR.Login": "چوونەژوورەوە بە کۆدی QR >",
+ "tweb.Login.QR.Subtitle": "بە ئەپی Telegram ی مۆبایلەکەت سکانی بکە",
+ "tweb.PhoneNumber.Code.Fragment.Info": "کۆدەکە لە بەشی ژمارەکانی [Fragment]() وەربگرە",
+ "tweb.PHONE_CODE_INVALID": "کۆدەکە نادروستە",
+ "tweb.PHONE_CODE_EXPIRED": "کۆدەکە بەسەرچووە",
+ "tweb.PASSWORD_HASH_INVALID": "وشەی نهێنی هەڵەیە",
+ "tweb.DarkMode": "دۆخی تاریک",
+ "tweb.Error.AnError": "هەڵەیەک ڕوویدا. تکایە دواتر دووبارە هەوڵبدەرەوە.",
+ "tweb.AccDescr.LoginCode": "کۆدی چوونەژوورەوە",
+ "tweb.Login.Bot": "چوونەژوورەوە وەک بۆت >",
+ "tweb.Login.Bot.Title": "چوونەژوورەوە وەک بۆت",
+ "tweb.Login.Bot.Subtitle": "ئەو تۆکنە داخڵ بکە کە @BotFather پێی دایت\nکاتێک بۆتەکەت دروست کرد.",
+ "tweb.Login.Bot.Token": "تۆکنی بۆت",
+ "tweb.Login.Bot.Cancel": "چوونەژوورەوە وەک بەکارهێنەر >",
+ "tweb.Optional": "ئارەزوومەندانە",
+ "tweb.PHONE_NUMBER_INVALID": "ژمارەی تەلەفۆن نادروستە",
+ "tweb.PHONE_NUMBER_BANNED": "ئەم ژمارە تەلەفۆنە قەدەغە کراوە",
+ "tweb.PHONE_NUMBER_FLOOD": "هەوڵدانی زۆر، دواتر دووبارە هەوڵبدەرەوە",
+ "tweb.PHONE_CODE_EMPTY": "کۆدەکە نادروستە",
+ "tweb.PHONE_PASSWORD_FLOOD": "هەوڵدانی زۆر، دواتر دووبارە هەوڵبدەرەوە",
+ "tweb.ACCESS_TOKEN_INVALID": "تۆکنی بۆت نادروستە",
+ "tweb.ACCESS_TOKEN_EXPIRED": "ئەم تۆکنی بۆتە هەڵوەشێنراوەتەوە",
+ "tweb.FIRSTNAME_INVALID": "ناوی یەکەم نادروستە",
+ "tweb.LASTNAME_INVALID": "ناوی کۆتایی نادروستە",
+ "tweb.Close": "داخستن"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/de.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/de.json
index 0967ef4..dd206c9 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/de.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/de.json
@@ -1 +1,274 @@
-{}
+{
+ "baseDirLimitation": "Eine basedir-Beschränkung ist konfiguriert: Dies kann die Leistung beeinträchtigen und Probleme verursachen, bitte deaktivieren Sie sie nach Möglichkeit!",
+ "noReportPeers": "Warnung: Es sind keine Report-Peers festgelegt, bitte fügen Sie Ihrem Event-Handler die folgende Methode hinzu",
+ "manualAdminActionRequired": "!!!!!!!!! MANUELLER EINGRIFF DES SYSTEMADMINISTRATORS ERFORDERLICH !!!!!!!!!",
+ "mmapErrorPart1": "Die maximale Anzahl speicherabgebildeter Bereiche (mmap) wurde erreicht (%s): Erhöhen Sie zur Behebung den Kernel-Parameter vm.max_map_count auf 262144.",
+ "mmapErrorPart2": "Führen Sie zur Behebung den folgenden Befehl als root aus: %s",
+ "mmapErrorPart3": "Um die Änderung über Neustarts hinweg beizubehalten: %s",
+ "mmapErrorPart4": "Unter Windows und WSL kann eine Vergrößerung der Auslagerungsdatei helfen; bitte wechseln Sie zu nativem Linux, falls das Problem weiterhin besteht.",
+ "botAlreadyRunning": "Der Bot läuft bereits!",
+ "extensionRequired": "MadelineProto benötigt zur Ausführung die Erweiterung %s. %s",
+ "extensionRequiredInstallWithApt": "Versuchen Sie, sudo apt-get install %s auszuführen.",
+ "extensionRequiredInstallWithCustomInstructions": "Folgen Sie den Anweisungen unter %s, um sie zu installieren.",
+ "extensionRecommended": "Warnung: Die Erweiterung %s ist nicht installiert, bitte installieren Sie sie, um MadelineProto zu beschleunigen!",
+ "go": "Los",
+ "apiChooseManualAutoTip": "Beachten Sie, dass Sie API-ID/Hash auch direkt im Code über die Einstellungen angeben können: %s",
+ "apiChooseManualAutoTipWeb": "Beachten Sie, dass Sie API-ID/Hash auch direkt im Code über die Einstellungen angeben können.",
+ "apiChoosePrompt": "Ihre Wahl (m/a): ",
+ "apiManualInstructions0": "Melden Sie sich bei https://my.telegram.org an",
+ "apiManualInstructions1": "Gehen Sie zu „API development tools“",
+ "apiManualInstructions2": "Klicken Sie auf „Create application“",
+ "apiAppInstructionsManual0": "der Name Ihrer App, beliebig",
+ "apiAppInstructionsManual1": "der Kurzname Ihrer App, alphanumerisch, 5-32 Zeichen",
+ "apiAppInstructionsManual2": "die URL Ihrer App/Website oder t.me/yourusername",
+ "apiAppInstructionsManual3": "beliebig",
+ "apiAppInstructionsManual4": "Beschreiben Sie hier Ihre App",
+ "apiManualWeb": "Geben Sie Ihre API-ID und Ihren API-Hash ein",
+ "apiManualPrompt0": "Geben Sie Ihre API-ID ein: ",
+ "apiManualPrompt1": "Geben Sie Ihren API-Hash ein: ",
+ "apiAutoWeb": "Geben Sie eine Telefonnummer ein, die bereits bei Telegram registriert ist, um die API-ID zu erhalten",
+ "apiAutoPrompt0": "Geben Sie eine Telefonnummer ein, die bereits bei Telegram registriert ist: ",
+ "apiAutoPrompt1": "Geben Sie den Bestätigungscode ein, den Sie in Telegram erhalten haben: ",
+ "apiAppWeb": "API-Informationen eingeben",
+ "apiAppInstructionsAuto0": "Geben Sie den Namen der App ein, beliebig: ",
+ "apiAppInstructionsAuto1": "Geben Sie den Kurznamen der App ein, alphanumerisch, 5-32 Zeichen: ",
+ "apiAppInstructionsAuto2": "Geben Sie die URL der App/Website oder t.me/yourusername ein: ",
+ "apiAppInstructionsAuto3": "Geben Sie die Plattform der App ein: ",
+ "apiAppInstructionsAuto4": "Beschreiben Sie Ihre App: ",
+ "apiAppInstructionsAutoTypeOther": "Andere (in der Beschreibung angeben)",
+ "apiParamsError": "Sie haben nicht alle erforderlichen Parameter angegeben!",
+ "apiError": "FEHLER: %s. Versuchen Sie es erneut.",
+ "loginChoosePromptWeb": "Möchten Sie sich als Benutzer oder als Bot anmelden?",
+ "loginWebQr": "Sie können sich auch automatisch anmelden, indem Sie Telegram auf Ihrem Telefon öffnen, zu Einstellungen > Geräte > Desktop-Gerät verknüpfen gehen und den folgenden QR-Code scannen:",
+ "loginWebQr1": "Öffnen Sie Telegram auf Ihrem Telefon",
+ "loginWebQr2": "Gehen Sie zu Einstellungen > Geräte > Desktop-Gerät verknüpfen",
+ "loginWebQr3": "Richten Sie Ihr Telefon auf diesen Bildschirm, um die Anmeldung zu bestätigen",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Benutzer",
+ "loginBot": "Geben Sie Ihr Bot-Token ein: ",
+ "loginUser": "Geben Sie Ihre Telefonnummer ein: ",
+ "loginQr": "Öffnen Sie Telegram auf Ihrem Telefon, gehen Sie zu Einstellungen > Geräte > Desktop-Gerät verknüpfen und scannen Sie den obigen QR-Code, um sich automatisch anzumelden.",
+ "loginQrCodeSuccessful": "Anmeldung per QR-Code erfolgreich!",
+ "loginQrCodeExpired": "Der QR-Code ist abgelaufen, ein neuer wird generiert...",
+ "loginManual": "Alternativ können Sie auch ein Bot-Token oder eine Telefonnummer eingeben, um sich manuell anzumelden: ",
+ "loginUserCode": "Geben Sie den Code ein: ",
+ "loginUserPass": "Geben Sie Ihr Passwort ein (Hinweis: %s): ",
+ "loginUserPassWeb": "Geben Sie Ihr Passwort ein: ",
+ "loginUserPassHint": "Hinweis: %s",
+ "signupFirstName": "Geben Sie Ihren Vornamen ein: ",
+ "signupLastName": "Geben Sie Ihren Nachnamen ein (kann leer bleiben): ",
+ "signupWeb": "Bitte registrieren Sie sich",
+ "signupFirstNameWeb": "Vorname",
+ "signupLastNameWeb": "Nachname",
+ "loginNoCode": "Sie haben keinen Bestätigungscode angegeben!",
+ "loginNoPass": "Sie haben kein Passwort angegeben!",
+ "loginNoName": "Sie haben keinen Vornamen angegeben!",
+ "loginBotTokenWeb": "Bot-Token",
+ "loginUserPhoneWeb": "Telefonnummer",
+ "loginUserPhoneCodeWeb": "Code",
+ "done": "Fertig!",
+ "nearest_dc": "Wir sind in %s, das nächstgelegene DC ist %d.",
+ "serialization_ofd": "Die Serialisierung ist veraltet, das Objekt wird neu aufgebaut!",
+ "api_not_set": "Sie müssen einen API-Schlüssel und eine API-ID angeben, holen Sie sich Ihre eigenen unter my.telegram.org",
+ "session_corrupted": "Die Sitzung ist beschädigt!",
+ "value_bigger_than_2147483647": "Der angegebene Wert %s ist größer als 2147483647",
+ "value_smaller_than_2147483648": "Der angegebene Wert %s ist kleiner als -2147483648",
+ "value_bigger_than_9223372036854775807": "Der angegebene Wert %s ist größer als 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "Der angegebene Wert %s ist kleiner als -9223372036854775808",
+ "value_bigger_than_4294967296": "Der angegebene Wert %s ist größer als 4294967296",
+ "value_smaller_than_0": "Der angegebene Wert %s ist kleiner als 0",
+ "encode_double_error": "Double konnte nicht korrekt kodiert werden",
+ "file_not_exist": "Die Datei existiert nicht",
+ "deserialization_error": "Bei der Deserialisierung ist ein Fehler aufgetreten",
+ "rpc_tg_error": "Telegram hat einen RPC-Fehler zurückgegeben: %s (%s), verursacht durch %s:%s%sTL-Trace:",
+ "madelineproto_ready": "MadelineProto ist bereit!",
+ "logout_ok": "Erfolgreich abgemeldet!",
+ "already_loggedIn": "Diese MadelineProto-Instanz ist bereits angemeldet!",
+ "login_ok": "Erfolgreich angemeldet!",
+ "login_user": "Anmeldung als normaler Benutzer...",
+ "login_bot": "Anmeldung als Bot...",
+ "login_code_sending": "Code wird gesendet...",
+ "login_code_sent": "Code erfolgreich gesendet! Sobald Sie den Code erhalten haben, sollten Sie die Funktion completePhoneLogin verwenden.",
+ "login_code_uncalled": "Ich warte nicht auf den Code! Bitte rufen Sie zuerst die Methode phoneLogin auf",
+ "login_2fa_enabled": "2FA ist aktiviert, Sie müssen die Funktion complete2falogin aufrufen...",
+ "login_need_signup": "Für diese Nummer wurde noch kein Konto erstellt, Sie müssen die Funktion completeSignup aufrufen...",
+ "login_auth_key": "Anmeldung mit Auth-Key...",
+ "not_loggedIn": "Ich bin nicht angemeldet!",
+ "signup_uncalled": "Ich warte nicht auf eine Registrierung! Bitte rufen Sie zuerst die Methoden phoneLogin und completePhoneLogin auf!",
+ "signing_up": "Registrierung als normaler Benutzer...",
+ "signup_ok": "Erfolgreich registriert!",
+ "2fa_uncalled": "Ich warte nicht auf das Passwort! Bitte rufen Sie zuerst die Methoden phoneLogin und completePhoneLogin auf!",
+ "peer_not_in_db": "Dieser Peer ist nicht in der internen Peer-Datenbank vorhanden",
+ "call_error_1": "Anruf %s konnte nicht gefunden und angenommen werden",
+ "accepting_call": "Anruf von %s wird angenommen...",
+ "call_already_accepted": "Anruf %s wurde bereits angenommen",
+ "call_already_declined": "Anruf %s wurde bereits abgelehnt",
+ "call_error_2": "Anruf %s konnte nicht gefunden und bestätigt werden",
+ "call_confirming": "Anruf von %s wird bestätigt...",
+ "call_error_3": "Anruf %s konnte nicht gefunden und abgeschlossen werden",
+ "call_completing": "Anruf von %s wird abgeschlossen...",
+ "fingerprint_invalid": "Ungültiger Schlüssel-Fingerprint!",
+ "call_discarding": "Anruf %s wird beendet...",
+ "file_parsing": "%s wird geparst...",
+ "src_file_invalid": "Ungültige Quelldatei angegeben: ",
+ "bool_error": "Boolescher Wert konnte nicht extrahiert werden",
+ "not_numeric": "Der angegebene Wert ist nicht numerisch",
+ "long_not_16": "Der angegebene Wert ist nicht 16 Bytes lang",
+ "long_not_32": "Der angegebene Wert ist nicht 32 Bytes lang",
+ "long_not_64": "Der angegebene Wert ist nicht 64 Bytes lang",
+ "array_invalid": "Sie haben kein gültiges Array angegeben",
+ "predicate_not_set": "Prädikat (Wert unter _) wurde nicht gesetzt!",
+ "update_madelineproto": "Sie verwenden eine alte Version von MadelineProto, ein Update ist erforderlich: Aktuell läuft %s, aber die neueste Version mit zahlreichen Fehlerbehebungen und neuen Funktionen ist %s!",
+ "type_extract_error": "Typ \"%s\" konnte nicht extrahiert werden, Sie sollten MadelineProto aktualisieren!",
+ "method_not_found": "Methode nicht gefunden: ",
+ "params_missing": "Erforderlicher Parameter fehlt",
+ "sec_peer_not_in_db": "Dieser geheime Peer ist nicht in der internen Peer-Datenbank vorhanden",
+ "stream_handle_invalid": "Es wurde ein ungültiges Stream-Handle angegeben.",
+ "length_too_big": "Die Länge ist zu groß",
+ "string_required": "Ein String wurde erwartet!",
+ "waveform_must_have_100_values": "Ein Waveform-Array muss 100 Werte enthalten!",
+ "waveform_value": "Ein Waveform-Wert muss zwischen 0 und 31 liegen!",
+ "could_not_convert_object": "Objekt vom Typ %s konnte nicht konvertiert werden",
+ "type_extract_error_id": "Typ %s mit ID %s konnte nicht extrahiert werden, Sie sollten MadelineProto aktualisieren!",
+ "constructor_not_found": "Konstruktor nicht gefunden für Typ: ",
+ "botapi_conversion_error": "%s kann nicht in ein Bot-API-Objekt konvertiert werden",
+ "non_text_conversion": "Nicht-Text-Nachrichten können noch nicht konvertiert werden!",
+ "file_type_invalid": "Ungültiger Dateityp erkannt (%s)",
+ "static_analysis_minor": "Bei der statischen Analyse von %s wurde ein geringfügiges Problem festgestellt: %s",
+ "static_analysis_severe": "Bei der statischen Analyse von %s wurde ein schwerwiegendes Problem festgestellt: %s",
+ "secret_chat_skipping": "Der geheime Chat %s ist nicht in der Datenbank vorhanden, Nachricht wird übersprungen...",
+ "must_have_declare_types": "aus Performance-Gründen muss die erste Anweisung einer Event-Handler-Datei \"declare(strict_types=1);\" sein",
+ "do_not_delete_MadelineProto.log": "die Datei MadelineProto.log darf niemals gelöscht werden, bitte legen Sie stattdessen in den Einstellungen eine benutzerdefinierte Maximalgröße fest!",
+ "do_not_remove_MadelineProto.log_phar": "Bitte entfernen Sie madeline.phar oder madeline.php nicht, sonst stürzt MadelineProto ab. Wenn Sie ein Problem mit MadelineProto haben, melden Sie es unter https://github.com/danog/MadelineProto oder https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "aus Performance-Gründen dürfen Event-Handler die nicht asynchrone, blockierende Funktion %s nicht verwenden, bitte verwenden Sie stattdessen %s",
+ "do_not_use_blocking_class": "aus Performance-Gründen dürfen Handler die nicht asynchrone, blockierende Klasse %s nicht verwenden, bitte verwenden Sie stattdessen %s",
+ "do_not_use_deprecated_function": "die Funktion %s ist veraltet, bitte verwenden Sie stattdessen %s",
+ "do_not_use_non_root_require_in_event_handler": "aus Performance-Gründen dürfen Sie require oder include nicht innerhalb einer Event-Handler-Klasse verwenden, nur requires auf oberster Ebene sind erlaubt.",
+ "do_not_use_yield": "MadelineProto 8 benötigt und unterstützt kein yield in asynchronen Funktionen, Sie müssen alle yield-Schlüsselwörter entfernen, die zuvor für asynchrone Funktionsaufrufe verwendet wurden",
+ "recommend_not_use_filesystem_function": "die Verwendung der Funktion %s wird nicht empfohlen, da Dateisystemzugriffe während der Verarbeitung von Updates Ihren Bot verlangsamen. Unter https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions finden Sie alternative Möglichkeiten, Daten zu speichern, die Ihren Bot nicht verlangsamen!",
+ "plugins_do_not_use_require": "aus Performance-Gründen können Plugins andere Dateien im Plugin-Ordner nur automatisch über den PSR-4-Autoloader einbinden (nicht durch manuelles require()).",
+ "plugins_must_have_exactly_one_class": "ein Plugin muss genau eine Klasse definieren! Um mehrere Klassen, Interfaces oder Traits zu definieren, erstellen Sie separate Dateien, sie werden von MadelineProto automatisch geladen.",
+ "cli_need_dl.php_link": "Bitte geben Sie die URL eines Download-Skripts an, wenn Sie getDownloadLink über die CLI verwenden!",
+ "invalid_dl.php_session": "%s ist kein gültiges Download-Skript, da seine Sitzungs-ID abweicht (erwartet %s, erhalten %s)",
+ "need_dl.php": "Das Standard-Download-Skript konnte nicht generiert werden (%s), bitte erstellen Sie eine Datei dl.php mit folgendem Inhalt: %s und übergeben Sie ihre URL als zweiten Parameter an getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Telegram-Datei-Downloadserver (bis zu 4 GB), betrieben mit MadelineProto!
Klicken Sie hier, um zu erfahren, wie Sie Ihren eigenen Telegram-Datei-Downloadserver einrichten!",
+ "dl.php_check_logs_make_sure_session_running": "Entweder der zugehörige MadelineProto-EventHandler-Bot oder der MadelineProto-IPC-Server ist offline, bitte prüfen Sie die Logs und stellen Sie sicher, dass mindestens einer davon läuft!",
+ "account_banned": "!!!!!!! WARNUNG !!!!!!!\nDas Flood-Schutzsystem von Telegram hat dieses Konto gesperrt.\nUm fortzufahren, ist eine manuelle Verifizierung erforderlich.\nSenden Sie eine E-Mail an recover@telegram.org, in der Sie um die Entsperrung der Telefonnummer %s bitten, und beschreiben Sie kurz, was Sie mit dieser Telefonnummer tun werden.\nMelden Sie sich dann erneut an.\nWenn Sie dieses Konto absichtlich gelöscht haben, ignorieren Sie diese Nachricht.",
+ "plugin_path_does_not_exist": "Der Plugin-Pfad %s existiert nicht!",
+ "could_not_connect_to_MadelineProto": "Verbindung zu MadelineProto nicht möglich, bitte aktivieren Sie zur Behebung proc_open und entfernen Sie open_basedir-Beschränkungen oder deaktivieren Sie Pfad-Rewrites des Webservers! Falls Sie das bereits getan haben, stellen Sie sicher, dass die CLI-Version von PHP genau der Web-Version entspricht (gleiche Version, Erweiterungen usw.), und prüfen Sie die Datei MadelineProto.log auf weitere Informationen zu dem Fehler, der den Start des IPC-Servers verhindert hat.",
+ "translate_madelineproto_web": "MadelineProto kann in Ihre Sprache übersetzt werden (aktueller Übersetzungsfortschritt: %d%%), klicken Sie hier, um zur Übersetzung beizutragen!",
+ "translate_madelineproto_cli": "MadelineProto kann in Ihre Sprache übersetzt werden (aktueller Übersetzungsfortschritt: %d%%), besuchen Sie https://github.com/danog/MadelineProto/tree/v8/langs, um zur Übersetzung beizutragen!",
+ "apiInvalidWeb": "Die API-ID ist eine Zahl und der API-Hash ist 32 Zeichen lang: Kopieren Sie beide erneut von my.telegram.org.",
+ "webDoneLead": "MadelineProto läuft auf dem Server weiter: Sie können diese Seite schließen.",
+ "apiChooseManualAuto": "Möchten Sie API-ID und Hash automatisch von my.telegram.org abrufen (a) oder manuell eingeben (m)?",
+ "apiAutoFallbackManual": "Geben Sie API-ID und Hash stattdessen manuell ein.",
+ "apiSetupTitleWeb": "API-ID und Hash abrufen",
+ "apiSetupLeadWeb": "Jede Telegram-App benötigt eine API-ID und einen Hash. MadelineProto kann sie mit der Telefonnummer eines bestehenden Telegram-Kontos für Sie von my.telegram.org abrufen.",
+ "apiAutoPhoneHintWeb": "my.telegram.org sendet den Anmeldecode an Ihre Telegram-App, nicht per SMS.",
+ "apiSendCodeWeb": "Code senden",
+ "apiChooseManualWeb": "Ich habe bereits eine API-ID",
+ "apiChooseAutoWeb": "Automatisch abrufen",
+ "apiStartOverWeb": "Neu beginnen",
+ "apiAutoCodeTitleWeb": "Code aus Telegram eingeben",
+ "apiAutoCodeLeadWeb": "my.telegram.org hat einen Anmeldecode an Ihre Telegram-App gesendet, im Chat mit Telegram (nicht per SMS).",
+ "apiAutoCodeLabelWeb": "Anmeldecode",
+ "apiCreateTitleWeb": "App erstellen",
+ "apiCreateLeadWeb": "Dieses Konto hat noch keine App auf my.telegram.org. Diese Angaben sind nur für Sie sichtbar und können später geändert werden.",
+ "apiAppTitleLabelWeb": "App-Name",
+ "apiAppShortNameLabelWeb": "Kurzname",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Beschreibung",
+ "apiCreateWeb": "App erstellen",
+ "apiSaveWeb": "Speichern und fortfahren",
+ "apiAutoErrorTitle": "my.telegram.org hat einen Fehler zurückgegeben",
+ "apiCreateErrorTitle": "my.telegram.org hat die App nicht erstellt",
+ "apiCreateVpsWarning": "Telegram erlaubt es VPS-, VPN- und anderen Rechenzentrums-IP-Bereichen nicht, neue Apps auf my.telegram.org zu erstellen, und die Anfrage kam von der IP des Rechners, auf dem MadelineProto läuft. Erstellen Sie die App manuell unter https://my.telegram.org über einen privaten Internetanschluss (z. B. Ihr Telefon mit mobilen Daten) und geben Sie dann API-ID und Hash ein.",
+ "loginTitleWeb": "Bei Telegram anmelden",
+ "loginLeadWeb": "Wählen Sie das Konto oder den Bot, als der diese MadelineProto-Instanz laufen soll.",
+ "loginTypeWeb": "Anmelden als",
+ "loginUserPhoneHintWeb": "Mit Ländervorwahl, z. B. +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Das Token, das Ihnen @BotFather beim Erstellen des Bots gegeben hat.",
+ "loginCodeTitleWeb": "Anmeldecode eingeben",
+ "loginCodeLeadWeb": "Telegram hat einen Anmeldecode an Ihre Telegram-App gesendet, oder per SMS, falls Sie nirgendwo sonst angemeldet sind.",
+ "loginPasswordTitleWeb": "Zweistufige Bestätigung",
+ "loginPasswordLeadWeb": "Dieses Konto ist durch ein Passwort geschützt, das unter Einstellungen > Privatsphäre und Sicherheit > Zweistufige Bestätigung festgelegt wurde.",
+ "loginPasswordLabelWeb": "Passwort",
+ "signupTitleWeb": "Konto erstellen",
+ "signupLeadWeb": "Diese Telefonnummer ist noch nicht bei Telegram: Wählen Sie den Namen des neuen Kontos.",
+ "webContinue": "Weiter",
+ "webLogin": "Anmelden",
+ "webError": "%s. Bitte prüfen Sie die Eingabe und versuchen Sie es erneut.",
+ "webStepApp": "API-ID und Hash",
+ "webStepAccount": "Konto",
+ "webStepVerify": "Bestätigung",
+ "webStepDone": "Läuft",
+ "webProgress": "Einrichtungsfortschritt",
+ "webDocs": "Dokumentation",
+ "webOptional": "optional",
+ "webShowPassword": "Anzeigen",
+ "webHidePassword": "Verbergen",
+ "webQrTitle": "Mit QR-Code anmelden",
+ "webQrWaiting": "Warten auf den Scan…",
+ "webFieldRequired": "Bitte füllen Sie dieses Feld aus.",
+ "webPhoneInvalid": "Geben Sie die Telefonnummer mit Ländervorwahl ein, z. B. +39 123 456 7890.",
+ "tweb.Login.Title": "Bei MadelineProto anmelden",
+ "tweb.Login.PhoneLabelInvalid": "Ungültige Telefonnummer",
+ "tweb.Login.StartText": "Bitte bestätigen Sie Ihre Ländervorwahl\nund geben Sie Ihre Telefonnummer ein.",
+ "tweb.Login.Code.SentSms": "Wir haben Ihnen eine SMS\nmit dem Code gesendet.",
+ "tweb.Login.Code.SentInApp": "Wir haben Ihnen eine Nachricht in Telegram\nmit dem Code gesendet.",
+ "tweb.Login.Code.SentCall": "Wir rufen Sie an und diktieren\nIhnen den Code.",
+ "tweb.Login.Code.SentEmail": "Bitte prüfen Sie Ihre E-Mails unter **%s** (auch den Spam-Ordner) und geben Sie den Code ein, den wir Ihnen gerade gesendet haben.",
+ "tweb.Login.Code.SentUnknown": "Bitte suchen Sie überall\nnach einem Code (Typ: %s)",
+ "tweb.Login.Code.SentMissedCall": "In den nächsten Sekunden erhalten Sie\neinen kurzen Anruf von **%s**. Nehmen Sie nicht ab –\ngeben Sie einfach die letzten Ziffern dieser Nummer ein.",
+ "tweb.Login.Code.SentSmsWord": "Wir haben eine SMS mit einem geheimen Wort\nan Ihre Nummer **%s** gesendet.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Wir haben eine SMS mit einem geheimen Wort, das\nmit „**%2$s**“ beginnt, an Ihre Nummer **%1$s** gesendet.",
+ "tweb.Login.Code.SentSmsPhrase": "Wir haben eine SMS mit einem geheimen Satz\nan Ihre Nummer **%s** gesendet.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Wir haben eine SMS mit einem geheimen Satz, der\nmit „**%2$s**“ beginnt, an Ihre Nummer **%1$s** gesendet.",
+ "tweb.Login.Code.SecretWord": "Geheimes Wort",
+ "tweb.Login.Code.SecretPhrase": "Geheimer Satz",
+ "tweb.Login.Code.WordInvalid": "Falsch, bitte versuchen Sie es erneut",
+ "tweb.Login.Code.WordBeginningInvalid": "Falsches Wort",
+ "tweb.Login.Password.Title": "Passwort eingeben",
+ "tweb.Login.Password.Subtitle": "Ihr Konto ist durch ein\nzusätzliches Passwort geschützt",
+ "tweb.Login.Register.Subtitle": "Geben Sie Ihren Namen ein,\num Ihr Konto zu erstellen",
+ "tweb.PleaseWait": "Bitte warten...",
+ "tweb.Code": "Code",
+ "tweb.LoginPassword": "Passwort",
+ "tweb.YourName": "Ihr Name",
+ "tweb.FirstName": "Vorname (erforderlich)",
+ "tweb.LastName": "Nachname (optional)",
+ "tweb.StartMessaging": "Loslegen",
+ "tweb.Country": "Land",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Telefonnummer",
+ "tweb.Login.Next": "Weiter",
+ "tweb.Login.QR.Title": "Mit QR-Code anmelden",
+ "tweb.Login.QR.Help1": "Öffnen Sie Telegram auf Ihrem Telefon",
+ "tweb.Login.QR.Help2": "Gehen Sie zu **Einstellungen** > **Geräte** > **Gerät hinzufügen**",
+ "tweb.Login.QR.Help3": "Richten Sie Ihr Telefon auf diesen Bildschirm, um die Anmeldung zu bestätigen",
+ "tweb.Login.QR.Cancel": "Mit Telefonnummer anmelden >",
+ "tweb.Login.QR.Login": "Mit QR-Code anmelden >",
+ "tweb.Login.QR.Subtitle": "Mit der Telegram-App auf Ihrem Telefon scannen",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Den Code finden Sie im Bereich „Numbers“ auf [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Ungültiger Code",
+ "tweb.PHONE_CODE_EXPIRED": "Code abgelaufen",
+ "tweb.PASSWORD_HASH_INVALID": "Falsches Passwort",
+ "tweb.DarkMode": "Dunkler Modus",
+ "tweb.Error.AnError": "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.",
+ "tweb.AccDescr.LoginCode": "Anmeldecode",
+ "tweb.Login.Bot": "Als Bot anmelden >",
+ "tweb.Login.Bot.Title": "Als Bot anmelden",
+ "tweb.Login.Bot.Subtitle": "Geben Sie das Token ein, das Ihnen @BotFather\nbeim Erstellen des Bots gegeben hat.",
+ "tweb.Login.Bot.Token": "Bot-Token",
+ "tweb.Login.Bot.Cancel": "Als Benutzer anmelden >",
+ "tweb.Optional": "optional",
+ "tweb.PHONE_NUMBER_INVALID": "Ungültige Telefonnummer",
+ "tweb.PHONE_NUMBER_BANNED": "Diese Telefonnummer ist gesperrt",
+ "tweb.PHONE_NUMBER_FLOOD": "Zu viele Versuche, bitte später erneut versuchen",
+ "tweb.PHONE_CODE_EMPTY": "Ungültiger Code",
+ "tweb.PHONE_PASSWORD_FLOOD": "Zu viele Versuche, bitte später erneut versuchen",
+ "tweb.ACCESS_TOKEN_INVALID": "Ungültiges Bot-Token",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Dieses Bot-Token wurde widerrufen",
+ "tweb.FIRSTNAME_INVALID": "Ungültiger Vorname",
+ "tweb.LASTNAME_INVALID": "Ungültiger Nachname",
+ "tweb.Close": "Schließen"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/en.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/en.json
index 1a524af..9851265 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/en.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/en.json
@@ -155,8 +155,121 @@
"dl.php_check_logs_make_sure_session_running": "Either the associated MadelineProto EventHandler bot or the MadelineProto IPC server are offline, please check logs and make sure at least one of them is running!",
"account_banned": "!!!!!!! WARNING !!!!!!!\nTelegram's flood prevention system suspended this account.\nTo continue, manual verification is required.\nSend an email to recover@telegram.org, asking to unban the phone number %s, and shortly describe what will you do with this phone number.\nThen login again.\nIf you intentionally deleted this account, ignore this message.",
"plugin_path_does_not_exist": "Plugin path %s does not exist!",
- "windows_warning": "For Windows users: please switch to Linux if this fails. You can also try modifying the firewall settings to allow all PHP processes to create sockets (it's 100% easier to just switch to Linux, on Linux MadelineProto just works out of the box, no changes needed)",
"could_not_connect_to_MadelineProto": "Could not connect to MadelineProto, please enable proc_open and remove open_basedir restrictions or disable webserver path rewrites to fix! If you already did that, make sure the CLI version of PHP is exactly the same as the web version (same version, extensions, et cetera) and check out the MadelineProto.log file for more info about the error that prevented the IPC server from starting.",
- "translate_madelineproto_web": "MadelineProto can be translated in your language (current translation progress: %d%%), click here to contribute with the translation!",
- "translate_madelineproto_cli": "MadelineProto can be translated in your language (current translation progress: %d%%), go to https://weblate.madelineproto.xyz to contribute with the translation!"
+ "translate_madelineproto_web": "MadelineProto can be translated in your language (current translation progress: %d%%), click here to contribute with the translation!",
+ "translate_madelineproto_cli": "MadelineProto can be translated in your language (current translation progress: %d%%), go to https://github.com/danog/MadelineProto/tree/v8/langs to contribute with the translation!",
+ "apiInvalidWeb": "The API ID is a number, and the API hash is 32 characters long: copy them again from my.telegram.org.",
+ "webDoneLead": "MadelineProto keeps running on the server: you can close this page.",
+ "apiChooseManualAuto": "Do you want to get the API ID and hash automatically from my.telegram.org (a), or enter them manually (m)?",
+ "apiAutoFallbackManual": "Enter the API ID and hash manually instead.",
+ "apiSetupTitleWeb": "Get your API ID and hash",
+ "apiSetupLeadWeb": "Every Telegram app needs an API ID and hash. MadelineProto can get them for you from my.telegram.org, with the phone number of an existing Telegram account.",
+ "apiAutoPhoneHintWeb": "my.telegram.org sends the login code to your Telegram app, not by SMS.",
+ "apiSendCodeWeb": "Send code",
+ "apiChooseManualWeb": "I already have an API ID",
+ "apiChooseAutoWeb": "Get them automatically",
+ "apiStartOverWeb": "Start over",
+ "apiAutoCodeTitleWeb": "Enter the code from Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org sent a login code to your Telegram app, in the chat with Telegram (not by SMS).",
+ "apiAutoCodeLabelWeb": "Login code",
+ "apiCreateTitleWeb": "Create your app",
+ "apiCreateLeadWeb": "This account has no app on my.telegram.org yet. These details are only shown to you, and can be changed later.",
+ "apiAppTitleLabelWeb": "App title",
+ "apiAppShortNameLabelWeb": "Short name",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Description",
+ "apiCreateWeb": "Create app",
+ "apiSaveWeb": "Save and continue",
+ "apiAutoErrorTitle": "my.telegram.org returned an error",
+ "apiCreateErrorTitle": "my.telegram.org didn't create the app",
+ "apiCreateVpsWarning": "Telegram doesn't let VPS, VPN and other datacenter IP ranges create new apps on my.telegram.org, and the request was made from the IP of the machine running MadelineProto. Create the app manually at https://my.telegram.org from a residential connection (like your phone on mobile data), then enter the API ID and hash.",
+ "loginTitleWeb": "Log in to Telegram",
+ "loginLeadWeb": "Choose the account or the bot this MadelineProto instance will run as.",
+ "loginTypeWeb": "Log in as",
+ "loginUserPhoneHintWeb": "With the country code, like +39 123 456 7890.",
+ "loginBotTokenHintWeb": "The token @BotFather gave you when you created the bot.",
+ "loginCodeTitleWeb": "Enter the login code",
+ "loginCodeLeadWeb": "Telegram sent a login code to your Telegram app, or by SMS if you aren't logged in anywhere else.",
+ "loginPasswordTitleWeb": "Two-step verification",
+ "loginPasswordLeadWeb": "This account is protected by a password, set in Settings > Privacy and Security > Two-Step Verification.",
+ "loginPasswordLabelWeb": "Password",
+ "signupTitleWeb": "Create your account",
+ "signupLeadWeb": "This phone number isn't on Telegram yet: choose the name of the new account.",
+ "webContinue": "Continue",
+ "webLogin": "Log in",
+ "webError": "%s. Check it and try again.",
+ "webStepApp": "API ID and hash",
+ "webStepAccount": "Account",
+ "webStepVerify": "Verification",
+ "webStepDone": "Running",
+ "webProgress": "Setup progress",
+ "webDocs": "Documentation",
+ "webOptional": "optional",
+ "webShowPassword": "Show",
+ "webHidePassword": "Hide",
+ "webQrTitle": "Log in with a QR code",
+ "webQrWaiting": "Waiting for the scan…",
+ "webFieldRequired": "Fill in this field.",
+ "webPhoneInvalid": "Enter the phone number with its country code, like +39 123 456 7890.",
+ "tweb.Login.Title": "Sign in to MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Phone Number Invalid",
+ "tweb.Login.StartText": "Please confirm your country code\nand enter your phone number.",
+ "tweb.Login.Code.SentSms": "We have sent you an SMS\nwith the code.",
+ "tweb.Login.Code.SentInApp": "We have sent you a message in Telegram\nwith the code.",
+ "tweb.Login.Code.SentCall": "We will call you and dictate\nthe code.",
+ "tweb.Login.Code.SentEmail": "Please check your email **%s** (don't forget the spam folder) and enter the code we just sent you.",
+ "tweb.Login.Code.SentUnknown": "Please check everything\nfor a code (type: %s)",
+ "tweb.Login.Code.SentMissedCall": "Within the next few seconds you should receive\na short call from **%s**. Don't answer it —\njust enter the last digits of that number.",
+ "tweb.Login.Code.SentSmsWord": "We've sent an SMS with a secret word\nto your phone **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "We've sent an SMS with a secret word that starts\nwith \"**%2$s**\" to your phone **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "We've sent an SMS with a secret phrase\nto your phone **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "We've sent an SMS with a secret phrase that starts\nwith \"**%2$s**\" to your phone **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Secret word",
+ "tweb.Login.Code.SecretPhrase": "Secret phrase",
+ "tweb.Login.Code.WordInvalid": "Incorrect, please try again",
+ "tweb.Login.Code.WordBeginningInvalid": "Incorrect word",
+ "tweb.Login.Password.Title": "Enter Your Password",
+ "tweb.Login.Password.Subtitle": "Your account is protected with\nan additional password",
+ "tweb.Login.Register.Subtitle": "Enter your name\nto create your account",
+ "tweb.PleaseWait": "Please wait...",
+ "tweb.Code": "Code",
+ "tweb.LoginPassword": "Password",
+ "tweb.YourName": "Your Name",
+ "tweb.FirstName": "First name (required)",
+ "tweb.LastName": "Last name (optional)",
+ "tweb.StartMessaging": "Start Messaging",
+ "tweb.Country": "Country",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Phone Number",
+ "tweb.Login.Next": "Next",
+ "tweb.Login.QR.Title": "Log in by QR Code",
+ "tweb.Login.QR.Help1": "Open Telegram on your phone",
+ "tweb.Login.QR.Help2": "Go to **Settings** > **Devices** > **Add Device**",
+ "tweb.Login.QR.Help3": "Point your phone at this screen to confirm login",
+ "tweb.Login.QR.Cancel": "Log in by phone number >",
+ "tweb.Login.QR.Login": "Log in by QR Code >",
+ "tweb.Login.QR.Subtitle": "Scan with Telegram app on your phone",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Get the code in the Numbers section on [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Invalid code",
+ "tweb.PHONE_CODE_EXPIRED": "Code expired",
+ "tweb.PASSWORD_HASH_INVALID": "Incorrect password",
+ "tweb.DarkMode": "Dark Mode",
+ "tweb.Error.AnError": "An error occurred. Please try again later.",
+ "tweb.AccDescr.LoginCode": "Login code",
+ "tweb.Login.Bot": "Log in as a bot >",
+ "tweb.Login.Bot.Title": "Log in as a Bot",
+ "tweb.Login.Bot.Subtitle": "Enter the token @BotFather gave you\nwhen you created the bot.",
+ "tweb.Login.Bot.Token": "Bot Token",
+ "tweb.Login.Bot.Cancel": "Log in as a user >",
+ "tweb.Optional": "optional",
+ "tweb.PHONE_NUMBER_INVALID": "Phone Number Invalid",
+ "tweb.PHONE_NUMBER_BANNED": "This phone number is banned",
+ "tweb.PHONE_NUMBER_FLOOD": "Too many attempts, try again later",
+ "tweb.PHONE_CODE_EMPTY": "Invalid code",
+ "tweb.PHONE_PASSWORD_FLOOD": "Too many attempts, try again later",
+ "tweb.ACCESS_TOKEN_INVALID": "Invalid bot token",
+ "tweb.ACCESS_TOKEN_EXPIRED": "This bot token was revoked",
+ "tweb.FIRSTNAME_INVALID": "Invalid first name",
+ "tweb.LASTNAME_INVALID": "Invalid last name",
+ "tweb.Close": "Close",
+ "ipc_tcp_warning": "UNIX sockets are not available, so the IPC server of the session listens on TCP (127.0.0.1) instead: any program running on this machine can connect to it, and control the session. On Windows 10 1803+, enable the sockets extension (extension=sockets in php.ini) to use UNIX sockets."
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/es.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/es.json
new file mode 100644
index 0000000..6ca3ae4
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/es.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "Hay configurada una limitación de basedir: puede afectar al rendimiento y causar algunos problemas, desactívela si es posible.",
+ "noReportPeers": "Advertencia: no se ha configurado ningún peer para los informes de errores, añada el siguiente método a su gestor de eventos",
+ "manualAdminActionRequired": "!!!!!!!!! SE REQUIERE UNA ACCIÓN MANUAL DEL ADMINISTRADOR DEL SISTEMA !!!!!!!!!",
+ "mmapErrorPart1": "Se ha alcanzado el número máximo de regiones de memoria mapeada (mmap) (%s): para solucionarlo, aumente el parámetro del kernel vm.max_map_count a 262144.",
+ "mmapErrorPart2": "Para solucionarlo, ejecute el siguiente comando como root: %s",
+ "mmapErrorPart3": "Para que el cambio se mantenga tras los reinicios: %s",
+ "mmapErrorPart4": "En Windows y WSL, aumentar el tamaño del archivo de paginación puede ayudar; si el problema persiste, cambie a Linux nativo.",
+ "botAlreadyRunning": "¡El bot ya está en ejecución!",
+ "extensionRequired": "MadelineProto requiere la extensión %s para funcionar. %s",
+ "extensionRequiredInstallWithApt": "Intente ejecutar sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Siga las instrucciones de %s para instalarla.",
+ "extensionRecommended": "Advertencia: la extensión %s no está instalada, ¡instálela para acelerar MadelineProto!",
+ "go": "Ir",
+ "apiChooseManualAutoTip": "Tenga en cuenta que también puede proporcionar el API ID/hash directamente en el código mediante la configuración: %s",
+ "apiChooseManualAutoTipWeb": "Tenga en cuenta que también puede proporcionar el API ID/hash directamente en el código mediante la configuración.",
+ "apiChoosePrompt": "Su elección (m/a): ",
+ "apiManualInstructions0": "Inicie sesión en https://my.telegram.org",
+ "apiManualInstructions1": "Vaya a \"API development tools\"",
+ "apiManualInstructions2": "Haga clic en \"Create application\"",
+ "apiAppInstructionsManual0": "el nombre de su aplicación, puede ser cualquiera",
+ "apiAppInstructionsManual1": "el nombre corto de su aplicación, alfanumérico, de 5 a 32 caracteres",
+ "apiAppInstructionsManual2": "la URL de su aplicación/sitio web, o t.me/yourusername",
+ "apiAppInstructionsManual3": "cualquiera",
+ "apiAppInstructionsManual4": "Describa aquí su aplicación",
+ "apiManualWeb": "Introduzca su API ID y su API hash",
+ "apiManualPrompt0": "Introduzca su API ID: ",
+ "apiManualPrompt1": "Introduzca su API hash: ",
+ "apiAutoWeb": "Introduzca un número de teléfono ya registrado en Telegram para obtener el API ID",
+ "apiAutoPrompt0": "Introduzca un número de teléfono ya registrado en Telegram: ",
+ "apiAutoPrompt1": "Introduzca el código de verificación que ha recibido en Telegram: ",
+ "apiAppWeb": "Introduzca la información de la API",
+ "apiAppInstructionsAuto0": "Introduzca el nombre de la aplicación, puede ser cualquiera: ",
+ "apiAppInstructionsAuto1": "Introduzca el nombre corto de la aplicación, alfanumérico, de 5 a 32 caracteres: ",
+ "apiAppInstructionsAuto2": "Introduzca la URL de la aplicación/sitio web, o t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Introduzca la plataforma de la aplicación: ",
+ "apiAppInstructionsAuto4": "Describa su aplicación: ",
+ "apiAppInstructionsAutoTypeOther": "Otra (especifíquela en la descripción)",
+ "apiParamsError": "¡No ha proporcionado todos los parámetros obligatorios!",
+ "apiError": "ERROR: %s. Inténtelo de nuevo.",
+ "loginChoosePromptWeb": "¿Desea iniciar sesión como usuario o como bot?",
+ "loginWebQr": "También puede iniciar sesión automáticamente abriendo Telegram en su teléfono, yendo a Ajustes > Dispositivos > Vincular dispositivo de escritorio y escaneando el siguiente código QR:",
+ "loginWebQr1": "Abra Telegram en su teléfono",
+ "loginWebQr2": "Vaya a Ajustes > Dispositivos > Vincular dispositivo de escritorio",
+ "loginWebQr3": "Apunte su teléfono a esta pantalla para confirmar el inicio de sesión",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Usuario",
+ "loginBot": "Introduzca el token de su bot: ",
+ "loginUser": "Introduzca su número de teléfono: ",
+ "loginQr": "Abra Telegram en su teléfono, vaya a Ajustes > Dispositivos > Vincular dispositivo de escritorio y escanee el código QR anterior para iniciar sesión automáticamente.",
+ "loginQrCodeSuccessful": "¡Inicio de sesión con código QR completado!",
+ "loginQrCodeExpired": "El código QR ha caducado, generando uno nuevo...",
+ "loginManual": "También puede introducir un token de bot o un número de teléfono para iniciar sesión manualmente: ",
+ "loginUserCode": "Introduzca el código: ",
+ "loginUserPass": "Introduzca su contraseña (pista: %s): ",
+ "loginUserPassWeb": "Introduzca su contraseña: ",
+ "loginUserPassHint": "Pista: %s",
+ "signupFirstName": "Introduzca su nombre: ",
+ "signupLastName": "Introduzca sus apellidos (puede dejarse vacío): ",
+ "signupWeb": "Regístrese",
+ "signupFirstNameWeb": "Nombre",
+ "signupLastNameWeb": "Apellidos",
+ "loginNoCode": "¡No ha proporcionado el código de verificación!",
+ "loginNoPass": "¡No ha proporcionado la contraseña!",
+ "loginNoName": "¡No ha proporcionado el nombre!",
+ "loginBotTokenWeb": "Token del bot",
+ "loginUserPhoneWeb": "Número de teléfono",
+ "loginUserPhoneCodeWeb": "Código",
+ "done": "¡Listo!",
+ "nearest_dc": "Estamos en %s, el DC más cercano es %d.",
+ "serialization_ofd": "La serialización está desactualizada, ¡reconstruyendo el objeto!",
+ "api_not_set": "Debe proporcionar una clave de API y un ID de API, obtenga los suyos en my.telegram.org",
+ "session_corrupted": "¡La sesión está dañada!",
+ "value_bigger_than_2147483647": "El valor proporcionado %s es mayor que 2147483647",
+ "value_smaller_than_2147483648": "El valor proporcionado %s es menor que -2147483648",
+ "value_bigger_than_9223372036854775807": "El valor proporcionado %s es mayor que 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "El valor proporcionado %s es menor que -9223372036854775808",
+ "value_bigger_than_4294967296": "El valor proporcionado %s es mayor que 4294967296",
+ "value_smaller_than_0": "El valor proporcionado %s es menor que 0",
+ "encode_double_error": "No se pudo codificar correctamente el valor double",
+ "file_not_exist": "El archivo no existe",
+ "deserialization_error": "Se produjo un error durante la deserialización",
+ "rpc_tg_error": "Telegram devolvió un error RPC: %s (%s), causado por %s:%s%sTraza TL:",
+ "madelineproto_ready": "¡MadelineProto está listo!",
+ "logout_ok": "¡Sesión cerrada correctamente!",
+ "already_loggedIn": "¡Esta instancia de MadelineProto ya ha iniciado sesión!",
+ "login_ok": "¡Sesión iniciada correctamente!",
+ "login_user": "Iniciando sesión como usuario normal...",
+ "login_bot": "Iniciando sesión como bot...",
+ "login_code_sending": "Enviando el código...",
+ "login_code_sent": "¡Código enviado correctamente! Cuando reciba el código, utilice la función completePhoneLogin.",
+ "login_code_uncalled": "¡No se está esperando ningún código! Llame primero al método phoneLogin",
+ "login_2fa_enabled": "La 2FA está activada, deberá llamar a la función complete2falogin...",
+ "login_need_signup": "No se ha creado ninguna cuenta para este número, deberá llamar a la función completeSignup...",
+ "login_auth_key": "Iniciando sesión con la clave de autorización...",
+ "not_loggedIn": "¡No se ha iniciado sesión!",
+ "signup_uncalled": "¡No se está esperando ningún registro! Llame primero a los métodos phoneLogin y completePhoneLogin.",
+ "signing_up": "Registrándose como usuario normal...",
+ "signup_ok": "¡Registro completado correctamente!",
+ "2fa_uncalled": "¡No se está esperando la contraseña! Llame primero a los métodos phoneLogin y completePhoneLogin.",
+ "peer_not_in_db": "Este peer no está presente en la base de datos interna de peers",
+ "call_error_1": "No se pudo encontrar y aceptar la llamada %s",
+ "accepting_call": "Aceptando la llamada de %s...",
+ "call_already_accepted": "La llamada %s ya ha sido aceptada",
+ "call_already_declined": "La llamada %s ya ha sido rechazada",
+ "call_error_2": "No se pudo encontrar y confirmar la llamada %s",
+ "call_confirming": "Confirmando la llamada de %s...",
+ "call_error_3": "No se pudo encontrar y completar la llamada %s",
+ "call_completing": "Completando la llamada de %s...",
+ "fingerprint_invalid": "¡Huella digital de la clave no válida!",
+ "call_discarding": "Descartando la llamada %s...",
+ "file_parsing": "Analizando %s...",
+ "src_file_invalid": "Se proporcionó un archivo de origen no válido: ",
+ "bool_error": "No se pudo extraer el booleano",
+ "not_numeric": "El valor proporcionado no es numérico",
+ "long_not_16": "El valor proporcionado no tiene una longitud de 16 bytes",
+ "long_not_32": "El valor proporcionado no tiene una longitud de 32 bytes",
+ "long_not_64": "El valor proporcionado no tiene una longitud de 64 bytes",
+ "array_invalid": "No ha proporcionado un array válido",
+ "predicate_not_set": "¡No se ha establecido el predicado (el valor de _)!",
+ "update_madelineproto": "Está ejecutando una versión antigua de MadelineProto y es necesario actualizarla: la versión actual es %s, ¡pero la última versión, con numerosas correcciones de errores y nuevas funciones, es %s!",
+ "type_extract_error": "No se pudo extraer el tipo \"%s\", ¡actualice MadelineProto!",
+ "method_not_found": "No se encontró el método: ",
+ "params_missing": "Falta un parámetro obligatorio",
+ "sec_peer_not_in_db": "Este peer secreto no está presente en la base de datos interna de peers",
+ "stream_handle_invalid": "Se proporcionó un descriptor de flujo no válido.",
+ "length_too_big": "La longitud es demasiado grande",
+ "string_required": "¡Se esperaba una cadena!",
+ "waveform_must_have_100_values": "¡Un array de forma de onda debe tener 100 valores!",
+ "waveform_value": "¡Un valor de forma de onda debe estar entre 0 y 31!",
+ "could_not_convert_object": "No se pudo convertir el objeto de tipo %s",
+ "type_extract_error_id": "No se pudo extraer el tipo: %s con id %s, ¡actualice MadelineProto!",
+ "constructor_not_found": "No se encontró el constructor para el tipo: ",
+ "botapi_conversion_error": "No se puede convertir %s en un objeto de la bot API",
+ "non_text_conversion": "¡Todavía no se pueden convertir mensajes que no sean de texto!",
+ "file_type_invalid": "Se detectó un tipo de archivo no válido (%s)",
+ "static_analysis_minor": "Se encontró un problema menor durante el análisis estático de %s: %s",
+ "static_analysis_severe": "Se encontró un problema grave durante el análisis estático de %s: %s",
+ "secret_chat_skipping": "El chat secreto %s no está en la base de datos, se omite el mensaje...",
+ "must_have_declare_types": "por motivos de rendimiento, la primera instrucción de un archivo de gestor de eventos debe ser \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "el archivo MadelineProto.log nunca debe eliminarse, ¡en su lugar, establezca un tamaño máximo personalizado en la configuración!",
+ "do_not_remove_MadelineProto.log_phar": "No elimine madeline.phar ni madeline.php, o MadelineProto fallará. Si tiene algún problema con MadelineProto, notifíquelo en https://github.com/danog/MadelineProto o en https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "por motivos de rendimiento, los gestores de eventos no pueden usar la función bloqueante no asíncrona %s, utilice %s en su lugar",
+ "do_not_use_blocking_class": "por motivos de rendimiento, los gestores no pueden usar la clase bloqueante no asíncrona %s, utilice %s en su lugar",
+ "do_not_use_deprecated_function": "la función %s está obsoleta, utilice %s en su lugar",
+ "do_not_use_non_root_require_in_event_handler": "por motivos de rendimiento, no se debe usar require ni include dentro de una clase de gestor de eventos, solo se permiten los require de nivel raíz.",
+ "do_not_use_yield": "MadelineProto 8 no requiere ni admite el uso de yield en funciones asíncronas, debe eliminar todas las palabras clave yield usadas anteriormente en las llamadas a funciones asíncronas",
+ "recommend_not_use_filesystem_function": "no se recomienda usar la función %s, porque acceder al sistema de archivos durante la gestión de las actualizaciones ralentizará su bot; consulte https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions para ver una lista de formas alternativas de almacenar datos que no ralentizarán su bot.",
+ "plugins_do_not_use_require": "por motivos de rendimiento, los plugins solo pueden incluir o requerir automáticamente otros archivos presentes en la carpeta de plugins a través del autoloader PSR-4 (no mediante require() manuales).",
+ "plugins_must_have_exactly_one_class": "¡un plugin debe definir exactamente una clase! Para definir varias clases, interfaces o traits, cree archivos separados: MadelineProto los cargará automáticamente.",
+ "cli_need_dl.php_link": "¡Especifique la URL de un script de descarga al usar getDownloadLink desde la CLI!",
+ "invalid_dl.php_session": "%s no es un script de descarga válido porque su ID de sesión es diferente (se esperaba %s, se obtuvo %s)",
+ "need_dl.php": "No se pudo generar el script de descarga predeterminado (%s), cree un archivo dl.php con el siguiente contenido: %s y pase su URL como segundo parámetro de getDownloadLink",
+ "dl.php_powered_by_madelineproto": "¡Servidor de descarga de archivos de Telegram (hasta 4 GB) basado en MadelineProto!
Haga clic aquí para obtener más información sobre cómo configurar su propio servidor de descarga de archivos de Telegram.",
+ "dl.php_check_logs_make_sure_session_running": "El bot EventHandler de MadelineProto asociado o el servidor IPC de MadelineProto están desconectados, ¡revise los registros y asegúrese de que al menos uno de ellos esté en ejecución!",
+ "account_banned": "!!!!!!! ADVERTENCIA !!!!!!!\nEl sistema de prevención de flood de Telegram ha suspendido esta cuenta.\nPara continuar, se requiere una verificación manual.\nEnvíe un correo electrónico a recover@telegram.org solicitando el desbloqueo del número de teléfono %s y describa brevemente qué hará con este número de teléfono.\nA continuación, vuelva a iniciar sesión.\nSi eliminó esta cuenta intencionadamente, ignore este mensaje.",
+ "plugin_path_does_not_exist": "¡La ruta del plugin %s no existe!",
+ "could_not_connect_to_MadelineProto": "No se pudo conectar con MadelineProto: para solucionarlo, habilite proc_open y elimine las restricciones de open_basedir, o desactive las reescrituras de rutas del servidor web. Si ya lo ha hecho, asegúrese de que la versión CLI de PHP sea exactamente la misma que la versión web (misma versión, extensiones, etc.) y consulte el archivo MadelineProto.log para obtener más información sobre el error que impidió que se iniciara el servidor IPC.",
+ "translate_madelineproto_web": "MadelineProto puede traducirse a su idioma (progreso actual de la traducción: %d%%), haga clic aquí para contribuir a la traducción.",
+ "translate_madelineproto_cli": "MadelineProto puede traducirse a su idioma (progreso actual de la traducción: %d%%), visite https://github.com/danog/MadelineProto/tree/v8/langs para contribuir a la traducción.",
+ "apiInvalidWeb": "El API ID es un número y el API hash tiene 32 caracteres: cópielos de nuevo desde my.telegram.org.",
+ "webDoneLead": "MadelineProto sigue ejecutándose en el servidor: puede cerrar esta página.",
+ "apiChooseManualAuto": "¿Desea obtener el API ID y el hash automáticamente desde my.telegram.org (a) o introducirlos manualmente (m)?",
+ "apiAutoFallbackManual": "Introduzca el API ID y el hash manualmente.",
+ "apiSetupTitleWeb": "Obtenga su API ID y su hash",
+ "apiSetupLeadWeb": "Toda aplicación de Telegram necesita un API ID y un hash. MadelineProto puede obtenerlos por usted desde my.telegram.org, con el número de teléfono de una cuenta de Telegram existente.",
+ "apiAutoPhoneHintWeb": "my.telegram.org envía el código de inicio de sesión a su aplicación de Telegram, no por SMS.",
+ "apiSendCodeWeb": "Enviar código",
+ "apiChooseManualWeb": "Ya tengo un API ID",
+ "apiChooseAutoWeb": "Obtenerlos automáticamente",
+ "apiStartOverWeb": "Empezar de nuevo",
+ "apiAutoCodeTitleWeb": "Introduzca el código de Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org ha enviado un código de inicio de sesión a su aplicación de Telegram, en el chat con Telegram (no por SMS).",
+ "apiAutoCodeLabelWeb": "Código de inicio de sesión",
+ "apiCreateTitleWeb": "Cree su aplicación",
+ "apiCreateLeadWeb": "Esta cuenta aún no tiene ninguna aplicación en my.telegram.org. Estos datos solo los verá usted y podrá cambiarlos más adelante.",
+ "apiAppTitleLabelWeb": "Nombre de la aplicación",
+ "apiAppShortNameLabelWeb": "Nombre corto",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Descripción",
+ "apiCreateWeb": "Crear aplicación",
+ "apiSaveWeb": "Guardar y continuar",
+ "apiAutoErrorTitle": "my.telegram.org ha devuelto un error",
+ "apiCreateErrorTitle": "my.telegram.org no ha creado la aplicación",
+ "apiCreateVpsWarning": "Telegram no permite crear nuevas aplicaciones en my.telegram.org desde rangos de IP de VPS, VPN u otros centros de datos, y la solicitud se hizo desde la IP de la máquina que ejecuta MadelineProto. Cree la aplicación manualmente en https://my.telegram.org desde una conexión residencial (como su teléfono con datos móviles) y luego introduzca el API ID y el hash.",
+ "loginTitleWeb": "Iniciar sesión en Telegram",
+ "loginLeadWeb": "Elija la cuenta o el bot con el que se ejecutará esta instancia de MadelineProto.",
+ "loginTypeWeb": "Iniciar sesión como",
+ "loginUserPhoneHintWeb": "Con el prefijo del país, por ejemplo +39 123 456 7890.",
+ "loginBotTokenHintWeb": "El token que le dio @BotFather al crear el bot.",
+ "loginCodeTitleWeb": "Introduzca el código de inicio de sesión",
+ "loginCodeLeadWeb": "Telegram ha enviado un código de inicio de sesión a su aplicación de Telegram, o por SMS si no tiene la sesión iniciada en ningún otro sitio.",
+ "loginPasswordTitleWeb": "Verificación en dos pasos",
+ "loginPasswordLeadWeb": "Esta cuenta está protegida con una contraseña, configurada en Ajustes > Privacidad y seguridad > Verificación en dos pasos.",
+ "loginPasswordLabelWeb": "Contraseña",
+ "signupTitleWeb": "Cree su cuenta",
+ "signupLeadWeb": "Este número de teléfono aún no está en Telegram: elija el nombre de la nueva cuenta.",
+ "webContinue": "Continuar",
+ "webLogin": "Iniciar sesión",
+ "webError": "%s. Compruébelo e inténtelo de nuevo.",
+ "webStepApp": "API ID y hash",
+ "webStepAccount": "Cuenta",
+ "webStepVerify": "Verificación",
+ "webStepDone": "En ejecución",
+ "webProgress": "Progreso de la configuración",
+ "webDocs": "Documentación",
+ "webOptional": "opcional",
+ "webShowPassword": "Mostrar",
+ "webHidePassword": "Ocultar",
+ "webQrTitle": "Iniciar sesión con un código QR",
+ "webQrWaiting": "Esperando el escaneo…",
+ "webFieldRequired": "Rellene este campo.",
+ "webPhoneInvalid": "Introduzca el número de teléfono con el prefijo del país, por ejemplo +39 123 456 7890.",
+ "tweb.Login.Title": "Iniciar sesión en MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Número de teléfono no válido",
+ "tweb.Login.StartText": "Confirme el código de su país\ne introduzca su número de teléfono.",
+ "tweb.Login.Code.SentSms": "Le hemos enviado un SMS\ncon el código.",
+ "tweb.Login.Code.SentInApp": "Le hemos enviado un mensaje en Telegram\ncon el código.",
+ "tweb.Login.Code.SentCall": "Le llamaremos para dictarle\nel código.",
+ "tweb.Login.Code.SentEmail": "Revise su correo **%s** (no olvide la carpeta de spam) e introduzca el código que le acabamos de enviar.",
+ "tweb.Login.Code.SentUnknown": "Busque un código\nen todas partes (tipo: %s)",
+ "tweb.Login.Code.SentMissedCall": "En los próximos segundos recibirá\nuna breve llamada de **%s**. No la conteste:\nsolo introduzca los últimos dígitos de ese número.",
+ "tweb.Login.Code.SentSmsWord": "Hemos enviado un SMS con una palabra secreta\na su teléfono **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Hemos enviado un SMS con una palabra secreta que empieza\npor \"**%2$s**\" a su teléfono **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Hemos enviado un SMS con una frase secreta\na su teléfono **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Hemos enviado un SMS con una frase secreta que empieza\npor \"**%2$s**\" a su teléfono **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Palabra secreta",
+ "tweb.Login.Code.SecretPhrase": "Frase secreta",
+ "tweb.Login.Code.WordInvalid": "Incorrecto, inténtelo de nuevo",
+ "tweb.Login.Code.WordBeginningInvalid": "Palabra incorrecta",
+ "tweb.Login.Password.Title": "Introduzca su contraseña",
+ "tweb.Login.Password.Subtitle": "Su cuenta está protegida con\nuna contraseña adicional",
+ "tweb.Login.Register.Subtitle": "Introduzca su nombre\npara crear su cuenta",
+ "tweb.PleaseWait": "Espere, por favor...",
+ "tweb.Code": "Código",
+ "tweb.LoginPassword": "Contraseña",
+ "tweb.YourName": "Su nombre",
+ "tweb.FirstName": "Nombre (obligatorio)",
+ "tweb.LastName": "Apellidos (opcional)",
+ "tweb.StartMessaging": "Empezar a chatear",
+ "tweb.Country": "País",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Número de teléfono",
+ "tweb.Login.Next": "Siguiente",
+ "tweb.Login.QR.Title": "Iniciar sesión con código QR",
+ "tweb.Login.QR.Help1": "Abra Telegram en su teléfono",
+ "tweb.Login.QR.Help2": "Vaya a **Ajustes** > **Dispositivos** > **Vincular dispositivo**",
+ "tweb.Login.QR.Help3": "Apunte su teléfono a esta pantalla para confirmar el inicio de sesión",
+ "tweb.Login.QR.Cancel": "Iniciar sesión con número de teléfono >",
+ "tweb.Login.QR.Login": "Iniciar sesión con código QR >",
+ "tweb.Login.QR.Subtitle": "Escanee con la aplicación de Telegram de su teléfono",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Obtenga el código en la sección Numbers de [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Código no válido",
+ "tweb.PHONE_CODE_EXPIRED": "El código ha caducado",
+ "tweb.PASSWORD_HASH_INVALID": "Contraseña incorrecta",
+ "tweb.DarkMode": "Modo oscuro",
+ "tweb.Error.AnError": "Se ha producido un error. Inténtelo de nuevo más tarde.",
+ "tweb.AccDescr.LoginCode": "Código de inicio de sesión",
+ "tweb.Login.Bot": "Iniciar sesión como bot >",
+ "tweb.Login.Bot.Title": "Iniciar sesión como bot",
+ "tweb.Login.Bot.Subtitle": "Introduzca el token que le dio @BotFather\nal crear el bot.",
+ "tweb.Login.Bot.Token": "Token del bot",
+ "tweb.Login.Bot.Cancel": "Iniciar sesión como usuario >",
+ "tweb.Optional": "opcional",
+ "tweb.PHONE_NUMBER_INVALID": "Número de teléfono no válido",
+ "tweb.PHONE_NUMBER_BANNED": "Este número de teléfono está bloqueado",
+ "tweb.PHONE_NUMBER_FLOOD": "Demasiados intentos, inténtelo más tarde",
+ "tweb.PHONE_CODE_EMPTY": "Código no válido",
+ "tweb.PHONE_PASSWORD_FLOOD": "Demasiados intentos, inténtelo más tarde",
+ "tweb.ACCESS_TOKEN_INVALID": "Token del bot no válido",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Este token del bot ha sido revocado",
+ "tweb.FIRSTNAME_INVALID": "Nombre no válido",
+ "tweb.LASTNAME_INVALID": "Apellidos no válidos",
+ "tweb.Close": "Cerrar"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fa.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fa.json
index ae67208..5f2d0f1 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fa.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fa.json
@@ -1,31 +1,46 @@
{
+ "baseDirLimitation": "یک محدودیت basedir پیکربندی شده است: این میتواند روی پرفورمنس تاثیر بگذارد و باعث ایجاد مشکلات شود، لطفا در صورت امکان آن را غیرفعال کنید!",
+ "noReportPeers": "هشدار: هیچ peerی به عنوان peer گزارشات تنظیم نشده، لطفا متود زیر را به ایونت هندلر اضافه کنید",
+ "manualAdminActionRequired": "!!!!!!!!! فعالیت دستی ادمین سیستم نیاز است !!!!!!!!!",
+ "mmapErrorPart1": "بیشترین مقدار حافظه تخصیص داده شده (mmap ) پر شده است (%s ) : لطفا از داخل کانفیگ های مربوط به کرنل مقدار vm.max_map_count را به مقدار 262144 افزایش دهیدتا مشکل رفع گردد.",
+ "mmapErrorPart2": "برای حل کردن مشکل، کامند مقابل را با دسترسی root اجرا کنید: %s",
+ "mmapErrorPart3": "برای تداوم تغییر در طول راهاندازی دوباره: %s",
+ "mmapErrorPart4": "روی ویندوز و WSL، افزایش سایز pagefile ممکن است کمک کند؛ اگر مشکل پافشاری کرد لطفا سیستمعامل خود را به لینوکس تغییر دهید.",
+ "botAlreadyRunning": "ربات هم اکنون در حال اجرا است!",
+ "extensionRequired": "مدلین برای اجرا نیاز به افزونه %s دارد. %s",
+ "extensionRequiredInstallWithApt": "اجرای کامند sudo apt-get install %s را امتحان کنید.",
+ "extensionRequiredInstallWithCustomInstructions": "برای نصب آن، دستورالعمل ها را در %s دنبال کنید.",
+ "extensionRecommended": "هشدار: افزونه %s نصب نشده است. لطفا برای افزایش سرعت مدلینپروتو آن را نصب کنید!",
+ "go": "برو",
+ "apiChooseManualAutoTip": "در نظر داشته باشید که میتوانید API ID و API Hash را به طور مستقیم داخل کدتان با استفاده از تنظیمات وارد کنید. %s",
+ "apiChooseManualAutoTipWeb": "در نظر باشید که میتوانید API ID و API Hash را به صورت مستقیم داخل کدتان با استفاده از تنظیمات وارد کنید.",
"apiChoosePrompt": "انتخاب شما (m/a): ",
"apiManualInstructions0": "وارد حساب خود در https://my.telegram.org شوید",
+ "apiManualInstructions1": "به ابزارهای توسعه API بروید",
+ "apiManualInstructions2": "روی create application کلیک کنید",
"apiAppInstructionsManual0": "اسم اپلیکیشن شما، میتواند هرچیزی باشد",
"apiAppInstructionsManual1": "اسم کوتاه اپلیکیشن شما، 5 تا 32 کاراکتر، حروف و اعداد انگلیسی",
"apiAppInstructionsManual2": "لینک اپلیکیشن/وبسایت شما، یا t.me/yourusername",
"apiAppInstructionsManual3": "هرچیزی",
"apiAppInstructionsManual4": "اپلیکیشن خود را اینجا توصیف کنید",
+ "apiManualWeb": "API ID و API HASH خود را وارد کنید",
"apiManualPrompt0": "API ID خود را وارد کنید: ",
"apiManualPrompt1": "API Hash خود را وارد کنید: ",
+ "apiAutoWeb": "برای دریافت API ID شمارهای را وارد کنید که از قبل در تلگرام ثبتنام کرده باشد",
"apiAutoPrompt0": "شمارهای را وارد کنید که از قبل در تلگرام ثبتنام کرده باشد: ",
"apiAutoPrompt1": "کد تاییدی را که در تلگرام دریافت کردید، وارد کنید ",
"apiAppWeb": "اطلاعات API را وارد کنید",
+ "apiAppInstructionsAuto0": "نام برنامه خود را وارد کنید، میتواند هرچیزی باشد ",
"apiAppInstructionsAuto1": "نام مخفف برنامهتان را وارد کنید، 5 تا 32 کاراکتر الفبا اعداد: ",
"apiAppInstructionsAuto2": "لینک برنامه/وبسایت را وارد کنید، یا t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "سکوی (پلتفرم) برنامه را وارد کنید: ",
"apiAppInstructionsAuto4": "برنامهتان را توصیف کنید: ",
"apiAppInstructionsAutoTypeOther": "مابقی (در توضیحات مشخص کنید)",
- "apiChooseManualAutoTip": "در نظر داشته باشید که میتوانید API ID و API Hash را به طور مستقیم داخل کدتان با استفاده از تنظیمات وارد کنید. %s",
- "apiChooseManualAutoTipWeb": "در نظر باشید که میتوانید API ID و API Hash را به صورت مستقیم داخل کدتان با استفاده از تنظیمات وارد کنید.",
- "go": "برو",
- "apiManualWeb": "API ID و API HASH خود را وارد کنید",
- "apiAutoWeb": "برای دریافت API ID شمارهای را وارد کنید که از قبل در تلگرام ثبتنام کرده باشد",
- "apiAppInstructionsAuto0": "نام برنامه خود را وارد کنید، میتواند هرچیزی باشد ",
- "apiAppInstructionsAuto3": "سکوی (پلتفرم) برنامه را وارد کنید: ",
"apiParamsError": "شما تمام ورودیهای موردنیاز را وارد نکردید!",
"apiError": "ارور: %s. دوباره امتحان کنید.",
"loginChoosePromptWeb": "میخواهید به عنوان یک کاربر یا به عنوان یک ربات، وارد شوید؟",
"loginWebQr": "همچنین میتوانید به صورت خودکار با اسکن QR Code پایین وارد شوید:",
+ "loginWebQr1": "تلگرام را در موبایل خود باز کنید",
"loginWebQr2": "بروید به تنظیمات > دستگاهها > اتصال دستگاه دسکتاپ",
"loginWebQr3": "گوشی خود را به سمت این صفحه بگیرید تا ورود را تایید کنید",
"loginOptionBot": "ربات",
@@ -40,123 +55,220 @@
"loginUserPass": "رمز خود را وارد کنید (اشاره %s): ",
"loginUserPassWeb": "رمز خود را وارد کنید: ",
"loginUserPassHint": "اشاره: %s",
- "signupFirstNameWeb": "نام",
- "nearest_dc": "ما در %s هستیم، نزدیک ترین دیتاسنتر %d است.",
- "fingerprint_invalid": "اثرانگشت کلید نامعتبر است!",
- "value_bigger_than_2147483647": "مقدار داده شدهی %s بیشتر از 2147483647 است",
- "value_bigger_than_9223372036854775807": "مقدار داده شدهی %s بیشتر از 9223372036854775807 است",
- "already_loggedIn": "نمونهی MadelineProto از قبل وارد شده!",
- "login_code_sent": "کد با موفقیت ارسال شد! زمانی که کد را دریافت کردید باید از تابع completePhoneLogin استفاده کنید.",
- "apiManualInstructions2": "روی create application کلیک کنید",
"signupFirstName": "نام خود را وارد کنید: ",
"signupLastName": "نام خانوادگی خود را وارد کنید (میتواند خالی باشد): ",
+ "signupWeb": "لطفا ثبتنام کنید",
+ "signupFirstNameWeb": "نام",
+ "signupLastNameWeb": "نام خانوادگی",
+ "loginNoCode": "شما کد شماره را وارد نکردید!",
"loginNoPass": "شما کلمه عبور را وارد نکردید!",
"loginNoName": "شما نام را وارد نکردید!",
"loginBotTokenWeb": "توکن ربات",
"loginUserPhoneWeb": "شماره تلفن",
"loginUserPhoneCodeWeb": "کد",
"done": "انجام شد!",
+ "nearest_dc": "ما در %s هستیم، نزدیک ترین دیتاسنتر %d است.",
"serialization_ofd": "مرتب سازی (سریالایز) منقضی شده، درحال بازسازی شی!",
+ "api_not_set": "شما باید یک api key و یک api id وارد کنید، @ خوتان را از my.telegram.org بگیرید",
"session_corrupted": "سشن شما خراب است!",
- "value_smaller_than_9223372036854775808": "مقدار داده شدهی %s کمتر از -9223372036854775808 است",
+ "value_bigger_than_2147483647": "مقدار داده شدهی %s بیشتر از 2147483647 است",
"value_smaller_than_2147483648": "مقدار داده شدهی %s کمتر از -2147483648 است",
+ "value_bigger_than_9223372036854775807": "مقدار داده شدهی %s بیشتر از 9223372036854775807 است",
+ "value_smaller_than_9223372036854775808": "مقدار داده شدهی %s کمتر از -9223372036854775808 است",
"value_bigger_than_4294967296": "مقدار داده شدهی %s بیشتر از 4294967296 است",
"value_smaller_than_0": "مقدار داده شدهی %s کمتر از 0 است",
+ "encode_double_error": "نمیتوان به درستی double را رمزنگاری (انکد) کرد",
"file_not_exist": "فایل وجود ندارد",
+ "deserialization_error": "مشکلی در سریالزدایی پیش آمد",
+ "rpc_tg_error": "تلگرام یک خطای RPC برگرداند: %s (%s), ناشی از %s:%s%sTL رد:",
"madelineproto_ready": "MadelineProto آماده است!",
"logout_ok": "با موفقیت خارج شد!",
+ "already_loggedIn": "نمونهی MadelineProto از قبل وارد شده!",
"login_ok": "با موفقیت وارد شد!",
"login_user": "در حال ورود به عنوان یک کاربر عادی...",
"login_bot": "در حال ورود به عنوان یک ربات...",
"login_code_sending": "در حال ارسال کد...",
+ "login_code_sent": "کد با موفقیت ارسال شد! زمانی که کد را دریافت کردید باید از تابع completePhoneLogin استفاده کنید.",
"login_code_uncalled": "من منتظر کد نیستم! لطفا اول تابع phoneLogin را صدا بزنید",
+ "login_2fa_enabled": "احراز هویت دوعاملی فعال است، شما باید تابع complete2falogin را صدا بزنید...",
"login_need_signup": "حسابی برای این شماره ساخته نشدهاست، شما باید تابع completeSignup را صدا بزنید...",
"login_auth_key": "درحال ورود با استفاده از کلید هویتی...",
"not_loggedIn": "من وارد نشدم!",
+ "signup_uncalled": "من منتظر ساخت حساب نیستم! لطفا اول توابع phoneLogin و completePhoneLogin را صدا بزنید!",
"signing_up": "در حال ثبتنام به عنوان یک کاربر عادی...",
"signup_ok": "با موفقیت ثبتنام شد!",
"2fa_uncalled": "من منتظر کلمه عبور نیستم! لطفا اول توابع phoneLogin و completePhoneLogin را صدا بزنید!",
+ "peer_not_in_db": "این peer در پایگاه داده (دیتابیس) peer وجود ندارد",
+ "call_error_1": "نمیتوان تماس %s را پیدا کرد و پذیرفت",
"accepting_call": "در حال پذیرش تماس از طرف %s...",
"call_already_accepted": "تماس %s از قبل پذیرفته شده",
"call_already_declined": "تماس %s از قبل رد شده",
- "login_2fa_enabled": "احراز هویت دوعاملی فعال است، شما باید تابع complete2falogin را صدا بزنید...",
+ "call_error_2": "نمیتوان تماس %s را پیدا و تایید کرد",
+ "call_confirming": "در حال تایید تماس از طرف %s...",
"call_error_3": "نمیتوان تماس %s را یافت و کامل کرد",
"call_completing": "در حال کامل کردن تماس از طرف %s...",
+ "fingerprint_invalid": "اثرانگشت کلید نامعتبر است!",
"call_discarding": "درحال صرف نظر کردن از تماس %s...",
"file_parsing": "درحال تجزیه %s...",
+ "src_file_invalid": "منبع فایل نامعتبری لحاظ گردیده: ",
+ "bool_error": "نمیتوان boolean را استخراج کرد",
"not_numeric": "مقدار ورودی عددی نیست",
- "signup_uncalled": "من منتظر ساخت حساب نیستم! لطفا اول توابع phoneLogin و completePhoneLogin را صدا بزنید!",
- "call_error_1": "نمیتوان تماس %s را پیدا کرد و پذیرفت",
- "call_error_2": "نمیتوان تماس %s را پیدا و تایید کرد",
- "signupLastNameWeb": "نام خانوادگی",
- "call_confirming": "در حال تایید تماس از طرف %s...",
"long_not_16": "مقدار ورودی به طول 16 بایت نیست",
"long_not_32": "مقدار ورودی به طول 32 بایت نیست",
"long_not_64": "مقدار ورودی به طول 64 بایت نیست",
"array_invalid": "شما یک آرایه معتبر وارد نکردید",
"predicate_not_set": "مستند (مقدار تحت _) تنظیم نشده!",
+ "update_madelineproto": "شما نسخه قدیمی MadelineProto را اجرا میکنید، سورس شما نیاز به بروزرسانی دارد: در حال حاضر %s در حال اجرا است، اما آخرین نسخه با چندین رفع اشکال و ویژگیهای جدید %s است!",
"type_extract_error": "نمیتوان نوع (تایپ) \"%s\" را استخراج کرد، شما باید MadelineProto را به روز رسانی کنید!",
- "apiManualInstructions1": "به ابزارهای توسعه API بروید",
- "loginWebQr1": "تلگرام را در موبایل خود باز کنید",
- "signupWeb": "لطفا ثبتنام کنید",
- "loginNoCode": "شما کد شماره را وارد نکردید!",
- "api_not_set": "شما باید یک api key و یک api id وارد کنید، @ خوتان را از my.telegram.org بگیرید",
- "deserialization_error": "مشکلی در سریالزدایی پیش آمد",
- "rpc_tg_error": "تلگرام یک خطای RPC برگرداند: %s (%s), ناشی از %s:%s%sTL رد:",
- "peer_not_in_db": "این peer در پایگاه داده (دیتابیس) peer وجود ندارد",
- "encode_double_error": "نمیتوان به درستی double را رمزنگاری (انکد) کرد",
"method_not_found": "تابع پیدا نشد: ",
"params_missing": "ورودی موردنیاز یافت نشد",
+ "sec_peer_not_in_db": "این peer مخفی در پایگاه داده (دیتابیس) داخلی peer وجود ندارد",
+ "stream_handle_invalid": "یک کنترلکننده جریان (استریم هندل) نامعتبر لحاظ گردیده.",
"length_too_big": "طول بسیار بزرگ است",
+ "string_required": "مقدار مورد انتظار رشته است!",
+ "waveform_must_have_100_values": "آرایه waveformباید 100 مقدار داشته باشد(سایز مورد انتظار 100 است ) !",
+ "waveform_value": "مقدار عددیwaveform باید بین 0 تا 31 باشد!",
+ "could_not_convert_object": "نمیتوان مقدار آبجکت تایپ %s را تبدیل کرد",
"type_extract_error_id": "نمیتوان نوع: %s را با ایدی %s استخراج کرد، شما باید MadelineProto را به روز رسانی کنید!",
"constructor_not_found": "سازنده برای این نوع پیدا نشد: ",
"botapi_conversion_error": "نمیتوان %s را به شی ربات API تبدیل کرد",
"non_text_conversion": "فعلا نمیتوان پیامهای غیرمتنی را تبدیل کرد!",
"file_type_invalid": "نوع فایل نامعتبر شناسایی شد (%s)",
+ "static_analysis_minor": "یک مشکل جزئی در طول بررسی استاتیک %s رخ داد: %s",
+ "static_analysis_severe": "یک مشکل سمت سرور در طول بررسی استاتیک %s رخ داد: %s",
"secret_chat_skipping": "من چت مخفی (سکرت) %s را در پایگاه داده (دیتابیس) ندارم، درحال رد شدن از پیام...",
- "src_file_invalid": "منبع فایل نامعتبری لحاظ گردیده: ",
- "bool_error": "نمیتوان boolean را استخراج کرد",
- "sec_peer_not_in_db": "این peer مخفی در پایگاه داده (دیتابیس) داخلی peer وجود ندارد",
- "stream_handle_invalid": "یک کنترلکننده جریان (استریم هندل) نامعتبر لحاظ گردیده.",
- "noReportPeers": "هشدار: هیچ peerی به عنوان peer گزارشات تنظیم نشده، لطفا متود زیر را به ایونت هندلر اضافه کنید",
- "mmapErrorPart2": "برای حل کردن مشکل، کامند مقابل را با دسترسی root اجرا کنید: %s",
- "mmapErrorPart4": "روی ویندوز و WSL، افزایش سایز pagefile ممکن است کمک کند؛ اگر مشکل پافشاری کرد لطفا سیستمعامل خود را به لینوکس تغییر دهید.",
- "extensionRecommended": "هشدار: افزونه %s نصب نشده است. لطفا برای افزایش سرعت مدلینپروتو آن را نصب کنید!",
- "botAlreadyRunning": "ربات هم اکنون در حال اجرا است!",
- "extensionRequiredInstallWithApt": "اجرای کامند sudo apt-get install %s را امتحان کنید.",
- "extensionRequiredInstallWithCustomInstructions": "برای نصب آن، دستورالعمل ها را در %s دنبال کنید.",
- "extensionRequired": "مدلین برای اجرا نیاز به افزونه %s دارد. %s",
- "manualAdminActionRequired": "!!!!!!!!! فعالیت دستی ادمین سیستم نیاز است !!!!!!!!!",
"must_have_declare_types": "به دلایل عملکردی و اجرایی، اولین دستور فایل ایونتهندلر باید دستور مقابل باشد: \"declare(strict_types=1);\"",
"do_not_delete_MadelineProto.log": "فایل MadelineProto.log هیچوقت نباید حذف شود، لطفا به جای حذف، بیشترین اندازه دلخواه را در تنظیمات مشخص کنید!",
"do_not_remove_MadelineProto.log_phar": "لطفا madeline.phar یا madeline.php را حذف نکنید، در غیراینصورت مدلینپروتو crash خواهد کرد. در صورت داشتن هرگونه مشکل با مدلینپروتو، آن را به https://github.com/danog/MadelineProto یا https://t.me/pwrtelegramgroup گزارش کنید",
- "do_not_use_deprecated_function": "تابع %s منسوخ شده، لطفا به جای آن از %s استفاده کنید",
- "mmapErrorPart3": "برای تداوم تغییر در طول راهاندازی دوباره: %s",
- "recommend_not_use_filesystem_function": "استفاده از تابع %s پیشنهاد نمیشود، چراکه دسترسی و کار با فایل های سیستمی موقع پردازش آپدیت باعث کم شدن سرعت ربات شما میشود، لطفا صفحه https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions را ببینید تا با راههای جایگزین برای ذخیره اطلاعات که باعث کاهش سرعت ربات شما نمیشوند آشنا شوید!",
"do_not_use_blocking_function": "به دلایل عملکردی و اجرایی، ایونتهندلرها نباید از فانکشن %s که async نیست استفاده کنند، لطفا به جای آن از %s استفاده کنید",
"do_not_use_blocking_class": "به دلایل عملکردی و اجرایی، هندلرها نباید از کلس %s که async نیست استفاده کنند، به جای آن از %s استفاده کنید",
+ "do_not_use_deprecated_function": "تابع %s منسوخ شده، لطفا به جای آن از %s استفاده کنید",
"do_not_use_non_root_require_in_event_handler": "به دلایل عملکردی و اجرایی، شما نباید از require یا include داخل کلس ایونتهندلر استفاده کنید، فقط require های سطح root مجاز هستند.",
- "plugins_must_have_exactly_one_class": "یک پلاگین باید دقیقا یک کلس را تعریف کند! برای تعریف چند کلس، اینترفیس یا تریت، فایلهای جداگانه بسازید، آنها توسط مدلینپروتو به صورت خودکار بارگذاری خواهند شد.",
+ "do_not_use_yield": "مدلینپروتو نسخه 8 نیازی به yield در توابع async ندارد و حتی آن را پشتیبانی هم نمیکند، شما باید تمام کلمات کلیدی yield را که قبلا در اجرای توابع async به کار میرفتند حذف کنید",
+ "recommend_not_use_filesystem_function": "استفاده از تابع %s پیشنهاد نمیشود، چراکه دسترسی و کار با فایل های سیستمی موقع پردازش آپدیت باعث کم شدن سرعت ربات شما میشود، لطفا صفحه https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions را ببینید تا با راههای جایگزین برای ذخیره اطلاعات که باعث کاهش سرعت ربات شما نمیشوند آشنا شوید!",
"plugins_do_not_use_require": "به دلایل عملکردی و اجرایی، پلاگینها فقط میتوانند فایل های دیگر را که در پوشه پلاگین هاست با استفاده از راهاندازی بارگذار خودکار PSR-4، به صورت خودکار include یا require کنند (بدون require کردن دستی آنها).",
- "static_analysis_minor": "یک مشکل جزئی در طول بررسی استاتیک %s رخ داد: %s",
- "static_analysis_severe": "یک مشکل سمت سرور در طول بررسی استاتیک %s رخ داد: %s",
+ "plugins_must_have_exactly_one_class": "یک پلاگین باید دقیقا یک کلس را تعریف کند! برای تعریف چند کلس، اینترفیس یا تریت، فایلهای جداگانه بسازید، آنها توسط مدلینپروتو به صورت خودکار بارگذاری خواهند شد.",
"cli_need_dl.php_link": "لطفا هنگام استفاده از getDownloadLink روی CLI (محیط ترمینال)، لینک اسکریپت دانلود را مشخص کنید!",
+ "invalid_dl.php_session": "%s یک اسکریپت دانلود درست و معتبر نیست چرا که سشنآیدی متفاوت است (انتظار این سشنآیدی وجود داشت: %s، اما این دریافت شد: %s)",
"need_dl.php": "اسکریپت دانلود پیشفرض تولید نشد (%s)، لطفا یک فایل dl.php بسیازید و این محتوا را در آن قرار دهید: %s سپس لینک آن فایل را به ورودی دوم getDownloadLink بدهید",
"dl.php_powered_by_madelineproto": "سرور دانلود فایل تلگرام (تا حداکثر 4 گیگابایت)، قدرت گرفته از مدلینپروتو!
برای اطلاعات بیشتر در مورد طریقه اجرای سرور دانلود تلگرام شخصی خود اینجا کلیک کنید!",
- "update_madelineproto": "شما نسخه قدیمی MadelineProto را اجرا میکنید، سورس شما نیاز به بروزرسانی دارد: در حال حاضر %s در حال اجرا است، اما آخرین نسخه با چندین رفع اشکال و ویژگیهای جدید %s است!",
"dl.php_check_logs_make_sure_session_running": "هم ربات ایونتهندلر مدلینپروتو مرتبط و هم سرور IPC مدلینپروتو آفلاین هستند، لطفا لاگها را بررسی کنید و مطمئن شوید حداقل یکی از آنها در حال اجراست!",
- "invalid_dl.php_session": "%s یک اسکریپت دانلود درست و معتبر نیست چرا که سشنآیدی متفاوت است (انتظار این سشنآیدی وجود داشت: %s، اما این دریافت شد: %s)",
"account_banned": "!!!!!!! اخطار !!!!!!!\nسیستم جلوگیری از فلود تلگرام، این حساب را معلق کرده.\nبرای ادامه، تایید دستی نیاز است.\nیک ایمیل به recover@telegram.org بفرستید، و از آنها آزادسازی شماره %s را جویا باشید، و کوتاه توضیح دهید که چه کاری با این شماره انجام خواهید داد.\nسپس دوباره وارد شوید.\nاگر از قصد این حساب را حذف کردهاید، این پیام را نادیده بگیرید.",
"plugin_path_does_not_exist": "مسیر پلاگین %s وجود ندارد!",
- "string_required": "مقدار مورد انتظار رشته است!",
- "waveform_must_have_100_values": "آرایه waveformباید 100 مقدار داشته باشد(سایز مورد انتظار 100 است ) !",
- "waveform_value": "مقدار عددیwaveform باید بین 0 تا 31 باشد!",
- "could_not_convert_object": "نمیتوان مقدار آبجکت تایپ %s را تبدیل کرد",
- "mmapErrorPart1": "بیشترین مقدار حافظه تخصیص داده شده (mmap ) پر شده است (%s ) : لطفا از داخل کانفیگ های مربوط به کرنل مقدار vm.max_map_count را به مقدار 262144 افزایش دهیدتا مشکل رفع گردد.",
"could_not_connect_to_MadelineProto": "نمی توان به مدلینپروتو متصل شد، لطفاً proc_open را فعال کنید و محدودیت open_basedir را بردارید، یا بازنویسی مسیر وب سرور را غیرفعال کنید تا مشکل رفع شود! اگر این کار را کردید، مطمئن شوید که نسخه PHP در کامندلاین و وبسرور دقیقا یکی است (ورژن یکسان، افزونههای یکسان و...) و برای کسب اطلاعات بیشتر راجب اروری که مانع شروع IPC server میشود، فایل MadelineProto.log را بررسی کنید.",
- "do_not_use_yield": "مدلینپروتو نسخه 8 نیازی به yield در توابع async ندارد و حتی آن را پشتیبانی هم نمیکند، شما باید تمام کلمات کلیدی yield را که قبلا در اجرای توابع async به کار میرفتند حذف کنید",
- "windows_warning": "برای کاربران ویندوزی: لطفا اگر این ناموفق بود به لینوکس کوچ کنید. همچنین میتوانید تلاش کنید تا تنظیمات فایروال خود را تغییر دهید تا به تمام پروسههای PHP اجازه ساخت سوکت را بدهید (100 درصد تغییر سیستم به لینوکس آسانتر است، مدلینپروتو در لینوکس خارج از باکس کار میکند، نیازی به تغییر ندارد)",
- "translate_madelineproto_web": "مدلینپروتو را میتوان به زبان شما ترجمه کرد (پیشرفت ترجمه فعلی: %d%%)، برای مشارکت در ترجمه اینجا را کلیک کنید!",
- "translate_madelineproto_cli": "مدلینپروتو را میتوان به زبان شما ترجمه کرد (پیشرفت ترجمه فعلی: %d%%)، برای مشارکت در ترجمه به https://weblate.madelineproto.xyz بروید!",
- "baseDirLimitation": "یک محدودیت basedir پیکربندی شده است: این میتواند روی پرفورمنس تاثیر بگذارد و باعث ایجاد مشکلات شود، لطفا در صورت امکان آن را غیرفعال کنید!"
+ "translate_madelineproto_web": "مدلینپروتو را میتوان به زبان شما ترجمه کرد (پیشرفت ترجمه فعلی: %d%%)، برای مشارکت در ترجمه اینجا را کلیک کنید!",
+ "translate_madelineproto_cli": "مدلینپروتو را میتوان به زبان شما ترجمه کرد (پیشرفت ترجمه فعلی: %d%%)، برای مشارکت در ترجمه به https://github.com/danog/MadelineProto/tree/v8/langs بروید!",
+ "apiInvalidWeb": "API ID یک عدد است و API Hash ۳۲ کاراکتر دارد: آنها را دوباره از my.telegram.org کپی کنید.",
+ "webDoneLead": "MadelineProto روی سرور به اجرا ادامه میدهد: میتوانید این صفحه را ببندید.",
+ "apiChooseManualAuto": "میخواهید API ID و API Hash را بهصورت خودکار از my.telegram.org دریافت کنید (a)، یا آنها را دستی وارد کنید (m)؟",
+ "apiAutoFallbackManual": "بهجای آن، API ID و API Hash را دستی وارد کنید.",
+ "apiSetupTitleWeb": "API ID و API Hash خود را دریافت کنید",
+ "apiSetupLeadWeb": "هر برنامه Telegram به یک API ID و API Hash نیاز دارد. MadelineProto میتواند آنها را با شماره تلفن یک حساب Telegram موجود، از my.telegram.org برایتان دریافت کند.",
+ "apiAutoPhoneHintWeb": "my.telegram.org کد ورود را به برنامه Telegram شما میفرستد، نه با پیامک.",
+ "apiSendCodeWeb": "ارسال کد",
+ "apiChooseManualWeb": "از قبل API ID دارم",
+ "apiChooseAutoWeb": "دریافت خودکار",
+ "apiStartOverWeb": "شروع دوباره",
+ "apiAutoCodeTitleWeb": "کد دریافتی از Telegram را وارد کنید",
+ "apiAutoCodeLeadWeb": "my.telegram.org یک کد ورود به برنامه Telegram شما، در گفتگو با Telegram فرستاد (نه با پیامک).",
+ "apiAutoCodeLabelWeb": "کد ورود",
+ "apiCreateTitleWeb": "برنامه خود را بسازید",
+ "apiCreateLeadWeb": "این حساب هنوز هیچ برنامهای در my.telegram.org ندارد. این اطلاعات فقط به شما نمایش داده میشود و بعداً قابل تغییر است.",
+ "apiAppTitleLabelWeb": "نام برنامه",
+ "apiAppShortNameLabelWeb": "نام کوتاه",
+ "apiAppUrlLabelWeb": "لینک",
+ "apiAppDescLabelWeb": "توضیحات",
+ "apiCreateWeb": "ساخت برنامه",
+ "apiSaveWeb": "ذخیره و ادامه",
+ "apiAutoErrorTitle": "my.telegram.org خطا برگرداند",
+ "apiCreateErrorTitle": "my.telegram.org برنامه را نساخت",
+ "apiCreateVpsWarning": "Telegram اجازه نمیدهد از IPهای VPS، VPN و دیگر محدودههای IP دیتاسنترها برنامه جدید در my.telegram.org ساخته شود، و این درخواست از IP دستگاهی ارسال شد که MadelineProto را اجرا میکند. برنامه را بهصورت دستی در https://my.telegram.org با یک اتصال خانگی (مثلاً گوشی خود با اینترنت همراه) بسازید، سپس API ID و API Hash را وارد کنید.",
+ "loginTitleWeb": "ورود به Telegram",
+ "loginLeadWeb": "حساب یا رباتی را انتخاب کنید که این نمونه MadelineProto با آن اجرا خواهد شد.",
+ "loginTypeWeb": "ورود به عنوان",
+ "loginUserPhoneHintWeb": "همراه با کد کشور، مانند +39 123 456 7890.",
+ "loginBotTokenHintWeb": "توکنی که @BotFather هنگام ساخت ربات به شما داد.",
+ "loginCodeTitleWeb": "کد ورود را وارد کنید",
+ "loginCodeLeadWeb": "Telegram یک کد ورود به برنامه Telegram شما فرستاد، یا اگر جای دیگری وارد نشده باشید، با پیامک.",
+ "loginPasswordTitleWeb": "تأیید دو مرحلهای",
+ "loginPasswordLeadWeb": "این حساب با رمز عبوری محافظت میشود که در تنظیمات > حریم خصوصی و امنیت > تأیید دو مرحلهای تعیین شده است.",
+ "loginPasswordLabelWeb": "رمز عبور",
+ "signupTitleWeb": "حساب خود را بسازید",
+ "signupLeadWeb": "این شماره تلفن هنوز در Telegram ثبت نشده است: نام حساب جدید را انتخاب کنید.",
+ "webContinue": "ادامه",
+ "webLogin": "ورود",
+ "webError": "%s. آن را بررسی کنید و دوباره امتحان کنید.",
+ "webStepApp": "API ID و API Hash",
+ "webStepAccount": "حساب",
+ "webStepVerify": "تأیید",
+ "webStepDone": "در حال اجرا",
+ "webProgress": "پیشرفت راهاندازی",
+ "webDocs": "مستندات",
+ "webOptional": "اختیاری",
+ "webShowPassword": "نمایش",
+ "webHidePassword": "پنهان کردن",
+ "webQrTitle": "ورود با QR Code",
+ "webQrWaiting": "در انتظار اسکن…",
+ "webFieldRequired": "این فیلد را پر کنید.",
+ "webPhoneInvalid": "شماره تلفن را همراه با کد کشور وارد کنید، مانند +39 123 456 7890.",
+ "tweb.Login.Title": "ورود به MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "شماره تلفن نامعتبر است",
+ "tweb.Login.StartText": "لطفاً کد کشور خود را تأیید کنید\nو شماره تلفن خود را وارد کنید.",
+ "tweb.Login.Code.SentSms": "کد را با پیامک\nبرایتان فرستادیم.",
+ "tweb.Login.Code.SentInApp": "کد را در پیامی در Telegram\nبرایتان فرستادیم.",
+ "tweb.Login.Code.SentCall": "با شما تماس میگیریم و\nکد را برایتان میخوانیم.",
+ "tweb.Login.Code.SentEmail": "لطفاً ایمیل خود **%s** را بررسی کنید (پوشه اسپم را فراموش نکنید) و کدی را که همین حالا فرستادیم وارد کنید.",
+ "tweb.Login.Code.SentUnknown": "لطفاً همهجا را برای یافتن\nکد بررسی کنید (نوع: %s)",
+ "tweb.Login.Code.SentMissedCall": "تا چند ثانیه دیگر یک تماس کوتاه\nاز **%s** دریافت میکنید. به آن پاسخ ندهید —\nفقط ارقام آخر آن شماره را وارد کنید.",
+ "tweb.Login.Code.SentSmsWord": "یک پیامک حاوی کلمه مخفی\nبه شماره **%s** فرستادیم.",
+ "tweb.Login.Code.SentSmsWordBeginning": "یک پیامک حاوی کلمه مخفی که با\n\"**%2$s**\" شروع میشود به شماره **%1$s** فرستادیم.",
+ "tweb.Login.Code.SentSmsPhrase": "یک پیامک حاوی عبارت مخفی\nبه شماره **%s** فرستادیم.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "یک پیامک حاوی عبارت مخفی که با\n\"**%2$s**\" شروع میشود به شماره **%1$s** فرستادیم.",
+ "tweb.Login.Code.SecretWord": "کلمه مخفی",
+ "tweb.Login.Code.SecretPhrase": "عبارت مخفی",
+ "tweb.Login.Code.WordInvalid": "نادرست است، لطفاً دوباره امتحان کنید",
+ "tweb.Login.Code.WordBeginningInvalid": "کلمه نادرست",
+ "tweb.Login.Password.Title": "رمز عبور خود را وارد کنید",
+ "tweb.Login.Password.Subtitle": "حساب شما با یک رمز عبور\nاضافی محافظت میشود",
+ "tweb.Login.Register.Subtitle": "برای ساخت حساب\nنام خود را وارد کنید",
+ "tweb.PleaseWait": "لطفاً صبر کنید...",
+ "tweb.Code": "کد",
+ "tweb.LoginPassword": "رمز عبور",
+ "tweb.YourName": "نام شما",
+ "tweb.FirstName": "نام (الزامی)",
+ "tweb.LastName": "نام خانوادگی (اختیاری)",
+ "tweb.StartMessaging": "شروع پیامرسانی",
+ "tweb.Country": "کشور",
+ "tweb.Contacts.PhoneNumber.Placeholder": "شماره تلفن",
+ "tweb.Login.Next": "بعدی",
+ "tweb.Login.QR.Title": "ورود با QR Code",
+ "tweb.Login.QR.Help1": "Telegram را در گوشی خود باز کنید",
+ "tweb.Login.QR.Help2": "به **تنظیمات** > **دستگاهها** > **افزودن دستگاه** بروید",
+ "tweb.Login.QR.Help3": "گوشی خود را به سمت این صفحه بگیرید تا ورود را تأیید کنید",
+ "tweb.Login.QR.Cancel": "ورود با شماره تلفن >",
+ "tweb.Login.QR.Login": "ورود با QR Code >",
+ "tweb.Login.QR.Subtitle": "با برنامه Telegram روی گوشی خود اسکن کنید",
+ "tweb.PhoneNumber.Code.Fragment.Info": "کد را از بخش شمارهها در [Fragment]() دریافت کنید",
+ "tweb.PHONE_CODE_INVALID": "کد نامعتبر است",
+ "tweb.PHONE_CODE_EXPIRED": "کد منقضی شده است",
+ "tweb.PASSWORD_HASH_INVALID": "رمز عبور نادرست است",
+ "tweb.DarkMode": "حالت تاریک",
+ "tweb.Error.AnError": "خطایی رخ داد. لطفاً بعداً دوباره امتحان کنید.",
+ "tweb.AccDescr.LoginCode": "کد ورود",
+ "tweb.Login.Bot": "ورود به عنوان ربات >",
+ "tweb.Login.Bot.Title": "ورود به عنوان ربات",
+ "tweb.Login.Bot.Subtitle": "توکنی را که @BotFather هنگام ساخت ربات\nبه شما داد وارد کنید.",
+ "tweb.Login.Bot.Token": "توکن ربات",
+ "tweb.Login.Bot.Cancel": "ورود به عنوان کاربر >",
+ "tweb.Optional": "اختیاری",
+ "tweb.PHONE_NUMBER_INVALID": "شماره تلفن نامعتبر است",
+ "tweb.PHONE_NUMBER_BANNED": "این شماره تلفن مسدود شده است",
+ "tweb.PHONE_NUMBER_FLOOD": "تلاشهای بیش از حد، بعداً دوباره امتحان کنید",
+ "tweb.PHONE_CODE_EMPTY": "کد نامعتبر است",
+ "tweb.PHONE_PASSWORD_FLOOD": "تلاشهای بیش از حد، بعداً دوباره امتحان کنید",
+ "tweb.ACCESS_TOKEN_INVALID": "توکن ربات نامعتبر است",
+ "tweb.ACCESS_TOKEN_EXPIRED": "این توکن ربات باطل شده است",
+ "tweb.FIRSTNAME_INVALID": "نام نامعتبر است",
+ "tweb.LASTNAME_INVALID": "نام خانوادگی نامعتبر است",
+ "tweb.Close": "بستن"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fr.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fr.json
index c49e3c2..9f64034 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fr.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/fr.json
@@ -1,61 +1,274 @@
{
+ "baseDirLimitation": "Une restriction basedir est configurée: cela peut affecter les performances et causer des problèmes, veuillez la désactiver si possible!",
+ "noReportPeers": "Avertissement: aucun destinataire des rapports (report peers) n'est défini, veuillez ajouter la méthode suivante à votre gestionnaire d'événements",
+ "manualAdminActionRequired": "!!!!!!!!! INTERVENTION MANUELLE DE L'ADMINISTRATEUR SYSTÈME REQUISE !!!!!!!!!",
+ "mmapErrorPart1": "Le nombre maximal de régions mappées en mémoire (mmap) a été atteint (%s): pour corriger le problème, veuillez augmenter le paramètre du noyau vm.max_map_count à 262144.",
+ "mmapErrorPart2": "Pour corriger le problème, exécutez la commande suivante en tant que root: %s",
+ "mmapErrorPart3": "Pour conserver la modification après un redémarrage: %s",
+ "mmapErrorPart4": "Sous Windows et WSL, augmenter la taille du fichier d'échange peut aider; veuillez passer à un Linux natif si le problème persiste.",
+ "botAlreadyRunning": "Le bot est déjà en cours d'exécution!",
+ "extensionRequired": "MadelineProto nécessite l'extension %s pour fonctionner. %s",
+ "extensionRequiredInstallWithApt": "Essayez d'exécuter sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Suivez les instructions sur %s pour l'installer.",
+ "extensionRecommended": "Avertissement: l'extension %s n'est pas installée, veuillez l'installer pour accélérer MadelineProto!",
+ "go": "Valider",
+ "apiChooseManualAutoTip": "Notez que vous pouvez également fournir l'API ID/hash directement dans le code via les paramètres: %s",
+ "apiChooseManualAutoTipWeb": "Notez que vous pouvez également fournir l'API ID/hash directement dans le code via les paramètres.",
+ "apiChoosePrompt": "Votre choix (m/a): ",
+ "apiManualInstructions0": "Connectez-vous à https://my.telegram.org",
+ "apiManualInstructions1": "Allez dans « API development tools »",
+ "apiManualInstructions2": "Cliquez sur « Create application »",
+ "apiAppInstructionsManual0": "le nom de votre application, peut être n'importe quoi",
+ "apiAppInstructionsManual1": "le nom court de votre application, alphanumérique, 5-32 caractères",
+ "apiAppInstructionsManual2": "l'URL de votre application/site web, ou t.me/yourusername",
+ "apiAppInstructionsManual3": "n'importe quoi",
+ "apiAppInstructionsManual4": "Décrivez votre application ici",
+ "apiManualWeb": "Entrez votre API ID et votre API hash",
+ "apiManualPrompt0": "Entrez votre API ID: ",
+ "apiManualPrompt1": "Entrez votre API hash: ",
+ "apiAutoWeb": "Entrez un numéro de téléphone déjà enregistré sur Telegram pour obtenir l'API ID",
+ "apiAutoPrompt0": "Entrez un numéro de téléphone déjà enregistré sur Telegram: ",
+ "apiAutoPrompt1": "Saisissez le code de vérification que vous avez reçu dans Telegram : ",
+ "apiAppWeb": "Entrez les informations de l'API",
+ "apiAppInstructionsAuto0": "Entrez le nom de l'application, peut être n'importe quoi: ",
+ "apiAppInstructionsAuto1": "Entrez le nom court de l'application, alphanumérique, 5-32 caractères: ",
+ "apiAppInstructionsAuto2": "Entrez l'URL de l'application/du site web, ou t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Entrez la plateforme de l'application: ",
+ "apiAppInstructionsAuto4": "Décrivez votre application: ",
+ "apiAppInstructionsAutoTypeOther": "Autre (à préciser dans la description)",
+ "apiParamsError": "Vous n'avez pas fourni tous les paramètres requis!",
+ "apiError": "ERREUR: %s. Essayez de nouveau.",
+ "loginChoosePromptWeb": "Voulez-vous vous connecter en tant qu'utilisateur ou en tant que bot?",
+ "loginWebQr": "Vous pouvez également vous connecter automatiquement en ouvrant Telegram sur votre téléphone, en allant dans Paramètres > Appareils > Lier un appareil de bureau et en scannant le code QR suivant:",
+ "loginWebQr1": "Ouvrez Telegram sur votre téléphone",
+ "loginWebQr2": "Allez dans Paramètres > Appareils > Lier un appareil de bureau",
+ "loginWebQr3": "Pointez votre téléphone vers cet écran pour confirmer la connexion",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Utilisateur",
+ "loginBot": "Entrez le token de votre bot: ",
+ "loginUser": "Entrez votre numéro de téléphone: ",
+ "loginQr": "Ouvrez Telegram sur votre téléphone, allez dans Paramètres > Appareils > Lier un appareil de bureau et scannez le code QR ci-dessus pour vous connecter automatiquement.",
+ "loginQrCodeSuccessful": "Connexion par code QR réussie!",
+ "loginQrCodeExpired": "Le code QR a expiré, génération d'un nouveau code...",
+ "loginManual": "Vous pouvez aussi entrer un token de bot ou un numéro de téléphone pour vous connecter manuellement: ",
"loginUserCode": "Entrez le code: ",
"loginUserPass": "Entrez votre mot de passe (Indice %s): ",
"loginUserPassWeb": "Entrez votre mot de passe: ",
"loginUserPassHint": "Indice: %s",
"signupFirstName": "Entrez votre prénom: ",
"signupLastName": "Entrez votre nom de famille (peut être vide): ",
- "loginOptionUser": "Utilisateur",
- "loginUser": "Entrez votre numéro de téléphone: ",
- "file_not_exist": "Le fichier n'existe pas",
- "deserialization_error": "Une erreur s'est produite lors de la désérialisation",
- "loginUserPhoneCodeWeb": "Code",
+ "signupWeb": "Inscrivez-vous s'il vous plaît",
+ "signupFirstNameWeb": "Prénom",
+ "signupLastNameWeb": "Nom de famille",
+ "loginNoCode": "Vous n'avez pas fourni de code de vérification!",
+ "loginNoPass": "Vous n'avez pas fourni le mot de passe!",
"loginNoName": "Vous n'avez pas fourni le prénom!",
+ "loginBotTokenWeb": "Token du bot",
"loginUserPhoneWeb": "Numéro de téléphone",
- "login_user": "Connexion en tant qu'utilisateur normal...",
+ "loginUserPhoneCodeWeb": "Code",
+ "done": "Terminé!",
+ "nearest_dc": "Nous sommes en %s, le DC le plus proche est %d.",
+ "serialization_ofd": "La sérialisation est obsolète, reconstruction de l'objet!",
+ "api_not_set": "Vous devez fournir une clé API et un ID API, obtenez les vôtres sur my.telegram.org",
+ "session_corrupted": "La session est corrompue!",
+ "value_bigger_than_2147483647": "La valeur fournie %s est supérieure à 2147483647",
+ "value_smaller_than_2147483648": "La valeur fournie %s est inférieure à -2147483648",
+ "value_bigger_than_9223372036854775807": "La valeur fournie %s est supérieure à 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "La valeur fournie %s est inférieure à -9223372036854775808",
+ "value_bigger_than_4294967296": "La valeur fournie %s est supérieure à 4294967296",
+ "value_smaller_than_0": "La valeur fournie %s est inférieure à 0",
+ "encode_double_error": "Impossible d'encoder correctement le double",
+ "file_not_exist": "Le fichier n'existe pas",
+ "deserialization_error": "Une erreur s'est produite lors de la désérialisation",
+ "rpc_tg_error": "Telegram a renvoyé une erreur RPC: %s (%s), causée par %s:%s%sTrace TL:",
"madelineproto_ready": "MadelineProto est prêt!",
"logout_ok": "Déconnecté avec succès!",
"already_loggedIn": "Cette instance de MadelineProto est déjà connectée!",
"login_ok": "Connecté avec succès!",
- "apiManualInstructions0": "Connectez-vous à https://my.telegram.org",
- "apiAutoPrompt1": "Saisissez le code de vérification que vous avez reçu dans Telegram : ",
- "params_missing": "Paramètre requis manquant",
- "array_invalid": "Vous n'avez pas fourni de tableau valide",
- "not_numeric": "La valeur donnée n'est pas numérique",
- "non_text_conversion": "Impossible de convertir des messages non textuels pour le moment!",
- "signup_ok": "Inscription réussie!",
+ "login_user": "Connexion en tant qu'utilisateur normal...",
+ "login_bot": "Connexion en tant que bot...",
"login_code_sending": "Envoi du code...",
"login_code_sent": "Code envoyé avec succès! Une fois que vous avez reçu le code, vous devez utiliser la fonction completePhoneLogin.",
- "loginQr": "Scannez le code QR ci-dessus pour vous connecter automatiquement.",
- "loginQrCodeSuccessful": "Connexion par code QR réussie!",
- "loginWebQr": "Vous pouvez également vous connecter automatiquement en scannant le code QR suivant:",
- "loginWebQr1": "Ouvrez Telegram sur votre téléphone",
- "loginNoPass": "Vous n'avez pas fourni le mot de passe!",
- "signupFirstNameWeb": "Prénom",
- "signupLastNameWeb": "Nom de famille",
- "serialization_ofd": "La sérialisation est obsolète, reconstruction de l'objet!",
- "session_corrupted": "La session est corrompue!",
- "apiParamsError": "Vous n'avez pas fourni tous les paramètres requis!",
- "apiError": "ERREUR: %s. Essayez de nouveau.",
- "signupWeb": "Inscrivez-vous s'il vous plaît",
- "loginWebQr3": "Pointez votre téléphone vers cet écran pour confirmer la connexion",
+ "login_code_uncalled": "Je n'attends pas de code! Veuillez d'abord appeler la méthode phoneLogin",
"login_2fa_enabled": "2FA activé, vous devrez appeler la fonction complete2falogin...",
+ "login_need_signup": "Aucun compte n'a été créé pour ce numéro, vous devrez appeler la fonction completeSignup...",
+ "login_auth_key": "Connexion avec la clé d'autorisation...",
+ "not_loggedIn": "Je ne suis pas connecté!",
+ "signup_uncalled": "Je n'attends pas d'inscription! Veuillez d'abord appeler les méthodes phoneLogin et completePhoneLogin!",
"signing_up": "Inscription en tant qu'utilisateur normal...",
- "value_bigger_than_9223372036854775807": "La valeur fournie %s est supérieure à 9223372036854775807",
- "value_smaller_than_9223372036854775808": "La valeur fournie %s est inférieure à -9223372036854775808",
- "value_bigger_than_4294967296": "La valeur fournie %s est supérieure à 4294967296",
- "value_smaller_than_0": "La valeur fournie %s est inférieure à 0",
- "value_bigger_than_2147483647": "La valeur fournie %s est supérieure à 2147483647",
- "value_smaller_than_2147483648": "La valeur fournie %s est inférieure à -2147483648",
+ "signup_ok": "Inscription réussie!",
+ "2fa_uncalled": "Je n'attends pas le mot de passe! Veuillez d'abord appeler les méthodes phoneLogin et completePhoneLogin!",
+ "peer_not_in_db": "Ce peer n'est pas présent dans la base de données interne des peers",
"call_error_1": "Impossible de trouver et d'accepter l'appel %s",
"accepting_call": "Acceptation de l'appel de %s...",
+ "call_already_accepted": "Appel %s déjà accepté",
+ "call_already_declined": "Appel %s déjà refusé",
"call_error_2": "Impossible de trouver et de confirmer l'appel %s",
+ "call_confirming": "Confirmation de l'appel de %s...",
+ "call_error_3": "Impossible de trouver et de finaliser l'appel %s",
+ "call_completing": "Finalisation de l'appel de %s...",
+ "fingerprint_invalid": "Empreinte de clé invalide!",
+ "call_discarding": "Abandon de l'appel %s...",
+ "file_parsing": "Analyse de %s...",
+ "src_file_invalid": "Un fichier source invalide a été fourni: ",
+ "bool_error": "Impossible d'extraire le booléen",
+ "not_numeric": "La valeur donnée n'est pas numérique",
"long_not_16": "La valeur donnée ne fait pas 16 octets",
"long_not_32": "La valeur donnée ne fait pas 32 octets",
"long_not_64": "La valeur donnée ne fait pas 64 octets",
- "call_error_3": "Impossible de trouver et de terminer l'appel %s",
- "call_completing": "Fin de l'appel de %s...",
- "call_confirming": "Confirmation de l'appel de %s...",
- "call_discarding": "Abandon de l'appel %s...",
- "file_parsing": "Analyse de %s..."
+ "array_invalid": "Vous n'avez pas fourni de tableau valide",
+ "predicate_not_set": "Le prédicat (valeur sous _) n'a pas été défini!",
+ "update_madelineproto": "Vous utilisez une ancienne version de MadelineProto, une mise à jour est requise: vous utilisez actuellement la version %s, mais la dernière version, avec de nombreuses corrections de bugs et nouvelles fonctionnalités, est la %s!",
+ "type_extract_error": "Impossible d'extraire le type \"%s\", vous devriez mettre à jour MadelineProto!",
+ "method_not_found": "Méthode introuvable: ",
+ "params_missing": "Paramètre requis manquant",
+ "sec_peer_not_in_db": "Ce peer secret n'est pas présent dans la base de données interne des peers",
+ "stream_handle_invalid": "Un handle de flux invalide a été fourni.",
+ "length_too_big": "La longueur est trop grande",
+ "string_required": "Une chaîne était attendue!",
+ "waveform_must_have_100_values": "Un tableau de forme d'onde doit contenir 100 valeurs!",
+ "waveform_value": "Une valeur de forme d'onde doit être comprise entre 0 et 31!",
+ "could_not_convert_object": "Impossible de convertir l'objet de type %s",
+ "type_extract_error_id": "Impossible d'extraire le type %s avec l'id %s, vous devriez mettre à jour MadelineProto!",
+ "constructor_not_found": "Constructeur introuvable pour le type: ",
+ "botapi_conversion_error": "Impossible de convertir %s en objet de la bot API",
+ "non_text_conversion": "Impossible de convertir des messages non textuels pour le moment!",
+ "file_type_invalid": "Type de fichier invalide détecté (%s)",
+ "static_analysis_minor": "Un problème mineur a été détecté lors de l'analyse statique de %s: %s",
+ "static_analysis_severe": "Un problème grave a été détecté lors de l'analyse statique de %s: %s",
+ "secret_chat_skipping": "Je n'ai pas le chat secret %s dans la base de données, message ignoré...",
+ "must_have_declare_types": "pour des raisons de performance, la première instruction d'un fichier de gestionnaire d'événements doit être \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "le fichier MadelineProto.log ne doit jamais être supprimé, veuillez plutôt définir une taille maximale personnalisée dans les paramètres!",
+ "do_not_remove_MadelineProto.log_phar": "Veuillez ne pas supprimer madeline.phar ou madeline.php, sinon MadelineProto plantera. Si vous rencontrez un problème avec MadelineProto, signalez-le sur https://github.com/danog/MadelineProto ou https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "pour des raisons de performance, les gestionnaires d'événements ne peuvent pas utiliser la fonction bloquante non asynchrone %s, veuillez plutôt utiliser %s",
+ "do_not_use_blocking_class": "pour des raisons de performance, les gestionnaires ne peuvent pas utiliser la classe bloquante non asynchrone %s, veuillez plutôt utiliser %s",
+ "do_not_use_deprecated_function": "la fonction %s est obsolète, veuillez plutôt utiliser %s",
+ "do_not_use_non_root_require_in_event_handler": "pour des raisons de performance, vous ne devez pas utiliser require ou include à l'intérieur d'une classe de gestionnaire d'événements, seuls les require au niveau racine sont autorisés.",
+ "do_not_use_yield": "MadelineProto 8 ne nécessite pas et ne prend pas en charge l'utilisation de yield dans les fonctions asynchrones, vous devez supprimer tous les mots-clés yield utilisés auparavant pour les appels de fonctions asynchrones",
+ "recommend_not_use_filesystem_function": "l'utilisation de la fonction %s n'est pas recommandée, car accéder au système de fichiers pendant le traitement des mises à jour ralentira votre bot, consultez https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions pour une liste de méthodes alternatives de stockage des données qui ne ralentiront pas votre bot!",
+ "plugins_do_not_use_require": "pour des raisons de performance, les plugins ne peuvent inclure ou requérir automatiquement d'autres fichiers présents dans le dossier des plugins qu'en déclenchant l'autoloader PSR-4 (et non en les incluant manuellement avec require()).",
+ "plugins_must_have_exactly_one_class": "un plugin doit définir exactement une classe! Pour définir plusieurs classes, interfaces ou traits, créez des fichiers séparés, ils seront chargés automatiquement par MadelineProto.",
+ "cli_need_dl.php_link": "Veuillez spécifier l'URL d'un script de téléchargement lorsque vous utilisez getDownloadLink en CLI!",
+ "invalid_dl.php_session": "%s n'est pas un script de téléchargement valide car son ID de session est différent (attendu %s, obtenu %s)",
+ "need_dl.php": "Impossible de générer le script de téléchargement par défaut (%s), veuillez créer un fichier dl.php avec le contenu suivant: %s et passer son URL comme deuxième paramètre de getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Serveur de téléchargement de fichiers Telegram (jusqu'à 4 Go), propulsé par MadelineProto!
Cliquez ici pour savoir comment configurer votre propre serveur de téléchargement de fichiers Telegram!",
+ "dl.php_check_logs_make_sure_session_running": "Le bot EventHandler MadelineProto associé ou le serveur IPC MadelineProto est hors ligne, veuillez vérifier les logs et vous assurer qu'au moins l'un d'eux est en cours d'exécution!",
+ "account_banned": "!!!!!!! AVERTISSEMENT !!!!!!!\nLe système anti-flood de Telegram a suspendu ce compte.\nPour continuer, une vérification manuelle est requise.\nEnvoyez un e-mail à recover@telegram.org pour demander le débannissement du numéro de téléphone %s, en décrivant brièvement ce que vous ferez avec ce numéro.\nPuis connectez-vous à nouveau.\nSi vous avez supprimé ce compte intentionnellement, ignorez ce message.",
+ "plugin_path_does_not_exist": "Le chemin du plugin %s n'existe pas!",
+ "could_not_connect_to_MadelineProto": "Impossible de se connecter à MadelineProto, veuillez activer proc_open et supprimer les restrictions open_basedir ou désactiver la réécriture des chemins du serveur web pour corriger le problème! Si c'est déjà fait, assurez-vous que la version CLI de PHP est exactement la même que la version web (même version, mêmes extensions, etc.) et consultez le fichier MadelineProto.log pour plus d'informations sur l'erreur qui a empêché le démarrage du serveur IPC.",
+ "translate_madelineproto_web": "MadelineProto peut être traduit dans votre langue (progression actuelle de la traduction: %d%%), cliquez ici pour contribuer à la traduction!",
+ "translate_madelineproto_cli": "MadelineProto peut être traduit dans votre langue (progression actuelle de la traduction: %d%%), rendez-vous sur https://github.com/danog/MadelineProto/tree/v8/langs pour contribuer à la traduction!",
+ "apiInvalidWeb": "L'API ID est un nombre et l'API hash fait 32 caractères : copiez-les à nouveau depuis my.telegram.org.",
+ "webDoneLead": "MadelineProto continue de tourner sur le serveur : vous pouvez fermer cette page.",
+ "apiChooseManualAuto": "Voulez-vous obtenir l'API ID et le hash automatiquement depuis my.telegram.org (a), ou les saisir manuellement (m) ?",
+ "apiAutoFallbackManual": "Saisissez plutôt l'API ID et le hash manuellement.",
+ "apiSetupTitleWeb": "Obtenez votre API ID et votre hash",
+ "apiSetupLeadWeb": "Chaque application Telegram a besoin d'un API ID et d'un hash. MadelineProto peut les obtenir pour vous depuis my.telegram.org, avec le numéro de téléphone d'un compte Telegram existant.",
+ "apiAutoPhoneHintWeb": "my.telegram.org envoie le code de connexion à votre application Telegram, pas par SMS.",
+ "apiSendCodeWeb": "Envoyer le code",
+ "apiChooseManualWeb": "J'ai déjà un API ID",
+ "apiChooseAutoWeb": "Les obtenir automatiquement",
+ "apiStartOverWeb": "Recommencer",
+ "apiAutoCodeTitleWeb": "Entrez le code reçu dans Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org a envoyé un code de connexion à votre application Telegram, dans la discussion avec Telegram (pas par SMS).",
+ "apiAutoCodeLabelWeb": "Code de connexion",
+ "apiCreateTitleWeb": "Créez votre application",
+ "apiCreateLeadWeb": "Ce compte n'a pas encore d'application sur my.telegram.org. Ces informations ne sont visibles que par vous et pourront être modifiées plus tard.",
+ "apiAppTitleLabelWeb": "Nom de l'application",
+ "apiAppShortNameLabelWeb": "Nom court",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Description",
+ "apiCreateWeb": "Créer l'application",
+ "apiSaveWeb": "Enregistrer et continuer",
+ "apiAutoErrorTitle": "my.telegram.org a renvoyé une erreur",
+ "apiCreateErrorTitle": "my.telegram.org n'a pas créé l'application",
+ "apiCreateVpsWarning": "Telegram ne permet pas aux plages d'IP de VPS, de VPN et autres centres de données de créer de nouvelles applications sur my.telegram.org, et la requête a été faite depuis l'IP de la machine qui exécute MadelineProto. Créez l'application manuellement sur https://my.telegram.org depuis une connexion résidentielle (comme votre téléphone en données mobiles), puis saisissez l'API ID et le hash.",
+ "loginTitleWeb": "Connexion à Telegram",
+ "loginLeadWeb": "Choisissez le compte ou le bot sous lequel cette instance de MadelineProto fonctionnera.",
+ "loginTypeWeb": "Se connecter en tant que",
+ "loginUserPhoneHintWeb": "Avec l'indicatif du pays, par exemple +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Le token que @BotFather vous a donné lors de la création du bot.",
+ "loginCodeTitleWeb": "Entrez le code de connexion",
+ "loginCodeLeadWeb": "Telegram a envoyé un code de connexion à votre application Telegram, ou par SMS si vous n'êtes connecté nulle part ailleurs.",
+ "loginPasswordTitleWeb": "Validation en deux étapes",
+ "loginPasswordLeadWeb": "Ce compte est protégé par un mot de passe, défini dans Paramètres > Confidentialité et sécurité > Validation en deux étapes.",
+ "loginPasswordLabelWeb": "Mot de passe",
+ "signupTitleWeb": "Créez votre compte",
+ "signupLeadWeb": "Ce numéro de téléphone n'est pas encore sur Telegram : choisissez le nom du nouveau compte.",
+ "webContinue": "Continuer",
+ "webLogin": "Se connecter",
+ "webError": "%s. Vérifiez et réessayez.",
+ "webStepApp": "API ID et hash",
+ "webStepAccount": "Compte",
+ "webStepVerify": "Vérification",
+ "webStepDone": "En cours d'exécution",
+ "webProgress": "Progression de la configuration",
+ "webDocs": "Documentation",
+ "webOptional": "facultatif",
+ "webShowPassword": "Afficher",
+ "webHidePassword": "Masquer",
+ "webQrTitle": "Se connecter avec un code QR",
+ "webQrWaiting": "En attente du scan…",
+ "webFieldRequired": "Veuillez remplir ce champ.",
+ "webPhoneInvalid": "Entrez le numéro de téléphone avec l'indicatif du pays, par exemple +39 123 456 7890.",
+ "tweb.Login.Title": "Connexion à MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Numéro de téléphone invalide",
+ "tweb.Login.StartText": "Veuillez confirmer l'indicatif de votre pays\net entrer votre numéro de téléphone.",
+ "tweb.Login.Code.SentSms": "Nous vous avons envoyé un SMS\navec le code.",
+ "tweb.Login.Code.SentInApp": "Nous vous avons envoyé un message dans Telegram\navec le code.",
+ "tweb.Login.Code.SentCall": "Nous allons vous appeler pour vous dicter\nle code.",
+ "tweb.Login.Code.SentEmail": "Veuillez consulter votre e-mail **%s** (sans oublier le dossier des spams) et entrer le code que nous venons de vous envoyer.",
+ "tweb.Login.Code.SentUnknown": "Veuillez chercher un code\npartout (type : %s)",
+ "tweb.Login.Code.SentMissedCall": "Dans les prochaines secondes, vous allez recevoir\nun bref appel de **%s**. Ne répondez pas :\nentrez simplement les derniers chiffres de ce numéro.",
+ "tweb.Login.Code.SentSmsWord": "Nous avons envoyé un SMS avec un mot secret\nà votre numéro **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Nous avons envoyé un SMS avec un mot secret commençant\npar « **%2$s** » à votre numéro **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Nous avons envoyé un SMS avec une phrase secrète\nà votre numéro **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Nous avons envoyé un SMS avec une phrase secrète commençant\npar « **%2$s** » à votre numéro **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Mot secret",
+ "tweb.Login.Code.SecretPhrase": "Phrase secrète",
+ "tweb.Login.Code.WordInvalid": "Incorrect, veuillez réessayer",
+ "tweb.Login.Code.WordBeginningInvalid": "Mot incorrect",
+ "tweb.Login.Password.Title": "Entrez votre mot de passe",
+ "tweb.Login.Password.Subtitle": "Votre compte est protégé par\nun mot de passe supplémentaire",
+ "tweb.Login.Register.Subtitle": "Entrez votre nom\npour créer votre compte",
+ "tweb.PleaseWait": "Veuillez patienter...",
+ "tweb.Code": "Code",
+ "tweb.LoginPassword": "Mot de passe",
+ "tweb.YourName": "Votre nom",
+ "tweb.FirstName": "Prénom (obligatoire)",
+ "tweb.LastName": "Nom (facultatif)",
+ "tweb.StartMessaging": "Commencer",
+ "tweb.Country": "Pays",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Numéro de téléphone",
+ "tweb.Login.Next": "Suivant",
+ "tweb.Login.QR.Title": "Connexion par code QR",
+ "tweb.Login.QR.Help1": "Ouvrez Telegram sur votre téléphone",
+ "tweb.Login.QR.Help2": "Allez dans **Paramètres** > **Appareils** > **Ajouter un appareil**",
+ "tweb.Login.QR.Help3": "Pointez votre téléphone vers cet écran pour confirmer la connexion",
+ "tweb.Login.QR.Cancel": "Connexion par numéro de téléphone >",
+ "tweb.Login.QR.Login": "Connexion par code QR >",
+ "tweb.Login.QR.Subtitle": "Scannez avec l'application Telegram sur votre téléphone",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Obtenez le code dans la section Numbers sur [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Code invalide",
+ "tweb.PHONE_CODE_EXPIRED": "Code expiré",
+ "tweb.PASSWORD_HASH_INVALID": "Mot de passe incorrect",
+ "tweb.DarkMode": "Mode sombre",
+ "tweb.Error.AnError": "Une erreur s'est produite. Veuillez réessayer plus tard.",
+ "tweb.AccDescr.LoginCode": "Code de connexion",
+ "tweb.Login.Bot": "Se connecter en tant que bot >",
+ "tweb.Login.Bot.Title": "Connexion en tant que bot",
+ "tweb.Login.Bot.Subtitle": "Entrez le token que @BotFather vous a donné\nlors de la création du bot.",
+ "tweb.Login.Bot.Token": "Token du bot",
+ "tweb.Login.Bot.Cancel": "Se connecter en tant qu'utilisateur >",
+ "tweb.Optional": "facultatif",
+ "tweb.PHONE_NUMBER_INVALID": "Numéro de téléphone invalide",
+ "tweb.PHONE_NUMBER_BANNED": "Ce numéro de téléphone est banni",
+ "tweb.PHONE_NUMBER_FLOOD": "Trop de tentatives, réessayez plus tard",
+ "tweb.PHONE_CODE_EMPTY": "Code invalide",
+ "tweb.PHONE_PASSWORD_FLOOD": "Trop de tentatives, réessayez plus tard",
+ "tweb.ACCESS_TOKEN_INVALID": "Token de bot invalide",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Ce token de bot a été révoqué",
+ "tweb.FIRSTNAME_INVALID": "Prénom invalide",
+ "tweb.LASTNAME_INVALID": "Nom invalide",
+ "tweb.Close": "Fermer"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/he.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/he.json
index f10635a..574fee8 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/he.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/he.json
@@ -1,4 +1,16 @@
{
+ "baseDirLimitation": "מגבלת תיקיית בסיס מוגדרת: זה יכול להשפיע על הביצועים ולגרום לבעיות מסוימות, אנא השבת אותה אם אפשר!",
+ "noReportPeers": "אזהרה: לא מוגדרים עמיתים לדיווח, אנא הוסף את השיטה הבאה למטפל באירועים שלך",
+ "manualAdminActionRequired": "!!!!!!!!! נדרשת פעולה ידנית של מנהל מערכת !!!!!!!!!",
+ "mmapErrorPart1": "המספר המרבי של אזורים ממופי זיכרון (mmap) הושג (%s): הגדל את תצורת ליבת vm.max_map_count ל-262144 כדי לתקן.",
+ "mmapErrorPart2": "כדי לתקן, הפעל את הפקודה הבאה: %s (בתור root)",
+ "mmapErrorPart3": "כדי להחיל את השינוי לאחר אתחול מחדש: %s",
+ "mmapErrorPart4": "ב-Windows וב-WSL, הגדלת גודל קובץ הדף עשויה לעזור; אנא עבור ללינוקס מקורית אם הבעיה נמשכת.",
+ "botAlreadyRunning": "הבוט כבר פועל!",
+ "extensionRequired": "MadelineProto דורשת את התוסף %s כדי לפעול. %s",
+ "extensionRequiredInstallWithApt": "נסה להפעיל את sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "עקוב אחר ההוראות ב-%s כדי להתקין אותו.",
+ "extensionRecommended": "אזהרה: התוסף %s אינו מותקן, אנא התקן אותו כדי להאיץ את MadelineProto!",
"go": "קדימה",
"apiChooseManualAutoTip": "שים לב שאתה יכול גם לספק את מזהה ה-API/hash ישירות בקוד באמצעות ההגדרות: %s",
"apiChooseManualAutoTipWeb": "שים לב שאתה יכול גם לספק את מזהה ה-API/hash ישירות בקוד באמצעות ה- הגדרות.",
@@ -106,57 +118,157 @@
"long_not_64": "הערך הנתון אינו באורך 64 בתים",
"array_invalid": "לא סיפקת מערך חוקי",
"predicate_not_set": "פרדיקט (ערך תחת _) לא הוגדר!",
+ "update_madelineproto": "אתה מפעיל גרסה ישנה של MadelineProto, נדרש עדכון: פועל כעת %s, אך הגרסה האחרונה עם מספר תיקוני באגים ותכונות חדשות היא %s!",
"type_extract_error": "לא ניתן היה לחלץ את הסוג \"%s\", נדרש לעדכן את MadelineProto!",
"method_not_found": "הפונקציה לא נמצא: ",
"params_missing": "חסר פרמטר נדרש",
"sec_peer_not_in_db": "עמית סודי זה אינו קיים במסד הנתונים הפנימי של עמיתים",
"stream_handle_invalid": "סופק stream handle לא חוקי.",
"length_too_big": "האורך גדול מדי",
+ "string_required": "המחרוזת הייתה צפויה!",
+ "waveform_must_have_100_values": "מערך צורות גל(waveform ) חייב להיות 100 ערכים!",
+ "waveform_value": "ערך waveform חייב להיות בין 0 ל-31!",
+ "could_not_convert_object": "לא ניתן להמיר אובייקט מסוג %s",
"type_extract_error_id": "לא ניתן היה לחלץ את הסוג: %s עם מזהה id %s, נדרש לעדכן את MadelineProto!",
"constructor_not_found": "הבנאי לא נמצא לסוג: ",
"botapi_conversion_error": "לא ניתן להמיר את %s לאובייקט bot API",
"non_text_conversion": "עדיין לא ניתן להמיר הודעות שאינן טקסט!",
"file_type_invalid": "זוהה סוג קובץ לא חוקי (%s)",
+ "static_analysis_minor": "נתקלה בבעיה קלה במהלך ניתוח סטטי של %s: %s",
+ "static_analysis_severe": "נתקלה בבעיה חמורה במהלך ניתוח סטטי של %s: %s",
"secret_chat_skipping": "אין לי את הצ'אט הסודי %s במסד הנתונים, דילוג על הודעה...",
- "waveform_value": "ערך waveform חייב להיות בין 0 ל-31!",
- "string_required": "המחרוזת הייתה צפויה!",
- "waveform_must_have_100_values": "מערך צורות גל(waveform ) חייב להיות 100 ערכים!",
- "could_not_convert_object": "לא ניתן להמיר אובייקט מסוג %s",
+ "must_have_declare_types": "מסיבות ביצועים, ההצהרה הראשונה של קובץ מטפל באירוע חייבת להיות \"declare(strict_types=1);\"",
"do_not_delete_MadelineProto.log": "אסור למחוק את הקובץ MadelineProto.log, אנא הגדר גודל מקסימלי מותאם אישית בהגדרות, במקום זאת!",
"do_not_remove_MadelineProto.log_phar": "נא לא להסיר madeline.phar או madeline.php, אחרת MadelineProto תקרוס. אם יש לך בעיה כלשהי עם MadelineProto, דווח על זה אל https://github.com/danog/MadelineProto או https://t.me/pwrtelegramgroup",
- "plugins_must_have_exactly_one_class": "תוסף חייב להגדיר בדיוק מחלקה אחת! כדי להגדיר מספר מחלקות, ממשקים או תכונות, צור קבצים נפרדים, הם ייטענו אוטומטית על ידי MadelineProto באופן אוטומטי.",
+ "do_not_use_blocking_function": "מטעמי ביצועים, ייתכן שמטפלי אירועים לא ישתמשו בפונקציית החסימה הלא-אסינכרונית %s, אנא השתמש ב-%s, במקום זאת",
"do_not_use_blocking_class": "מטעמי ביצועים, מטפלים אינם רשאים להשתמש במחלקה החוסמת ללא אסינכרון %s, אנא השתמש ב-%s, במקום זאת",
- "need_dl.php": "לא ניתן ליצור סקריפט הורדה כברירת מחדל (%s), אנא צור קובץ dl.php עם התוכן הבא: %s והעביר את כתובת האתר שלו לפרמטר השני של getDownloadLink",
- "mmapErrorPart2": "כדי לתקן, הפעל את הפקודה הבאה: %s (בתור root)",
- "mmapErrorPart3": "כדי להחיל את השינוי לאחר אתחול מחדש: %s",
- "static_analysis_minor": "נתקלה בבעיה קלה במהלך ניתוח סטטי של %s: %s",
- "static_analysis_severe": "נתקלה בבעיה חמורה במהלך ניתוח סטטי של %s: %s",
- "cli_need_dl.php_link": "אנא ציין כתובת אתר של סקריפט הורדה בעת שימוש ב-getDownloadLink דרך CLI!",
- "manualAdminActionRequired": "!!!!!!!!! נדרשת פעולה ידנית של מנהל מערכת !!!!!!!!!",
- "extensionRequired": "MadelineProto דורשת את התוסף %s כדי לפעול. %s",
- "extensionRequiredInstallWithCustomInstructions": "עקוב אחר ההוראות ב-%s כדי להתקין אותו.",
- "plugin_path_does_not_exist": "נתיב התוסף %s אינו קיים!",
- "update_madelineproto": "אתה מפעיל גרסה ישנה של MadelineProto, נדרש עדכון: פועל כעת %s, אך הגרסה האחרונה עם מספר תיקוני באגים ותכונות חדשות היא %s!",
"do_not_use_deprecated_function": "הפונקציה %s הוצאה משימוש, אנא השתמש ב-%s במקום זאת",
- "baseDirLimitation": "מגבלת תיקיית בסיס מוגדרת: זה יכול להשפיע על הביצועים ולגרום לבעיות מסוימות, אנא השבת אותה אם אפשר!",
- "noReportPeers": "אזהרה: לא מוגדרים עמיתים לדיווח, אנא הוסף את השיטה הבאה למטפל באירועים שלך",
- "mmapErrorPart1": "המספר המרבי של אזורים ממופי זיכרון (mmap) הושג (%s): הגדל את תצורת ליבת vm.max_map_count ל-262144 כדי לתקן.",
- "mmapErrorPart4": "ב-Windows וב-WSL, הגדלת גודל קובץ הדף עשויה לעזור; אנא עבור ללינוקס מקורית אם הבעיה נמשכת.",
- "botAlreadyRunning": "הבוט כבר פועל!",
- "extensionRequiredInstallWithApt": "נסה להפעיל את sudo apt-get install %s.",
- "extensionRecommended": "אזהרה: התוסף %s אינו מותקן, אנא התקן אותו כדי להאיץ את MadelineProto!",
- "must_have_declare_types": "מסיבות ביצועים, ההצהרה הראשונה של קובץ מטפל באירוע חייבת להיות \"declare(strict_types=1);\"",
- "do_not_use_blocking_function": "מטעמי ביצועים, ייתכן שמטפלי אירועים לא ישתמשו בפונקציית החסימה הלא-אסינכרונית %s, אנא השתמש ב-%s, במקום זאת",
- "could_not_connect_to_MadelineProto": "לא ניתן להתחבר ל-MadelineProto, אנא הפעל את proc_open והסר הגבלות open_basedir או השבת שכתוב של נתיב שרת אינטרנט כדי לתקן! אם כבר עשית זאת, ודא שגרסת ה-CLI של PHP זהה בדיוק לגרסת האינטרנט (אותה גרסה, הרחבות וכו') ועיין בקובץ MadelineProto.log לקבלת מידע נוסף על השגיאה שמנעה משרת ה-IPC להתחיל.",
"do_not_use_non_root_require_in_event_handler": "מסיבות ביצועים, אסור להשתמש ב-require או לכלול בתוך מחלקה של מטפל באירועים, רק דרישות ברמת השורש מותרות.",
"do_not_use_yield": "MadelineProto 8 אינו דורש או תומך בשימוש בתשואה בפונקציות אסינכרון, עליך להסיר את כל מילות המפתח של תשואה ששימשו בעבר עבור קריאות פונקציות אסינכרון",
- "account_banned": "!!!!!!! אזהרה!!!!!!!\nמערכת מניעת הצפות של טלגרם השעתה את החשבון הזה.\nכדי להמשיך, נדרש אימות ידני.\nשלח אימייל לכתובת recover@telegram.org, בבקשה לבטל את החסימה של מספר הטלפון %s, ותאר בקצרה מה תעשה עם מספר הטלפון הזה.\nלאחר מכן התחבר שוב.\nאם מחקת את החשבון הזה בכוונה, התעלם מהודעה זו.",
- "windows_warning": "למשתמשי Windows: נא לעבור ללינוקס אם זה נכשל. אתה יכול גם לנסות לשנות את הגדרות חומת האש כדי לאפשר לכל תהליכי PHP ליצור שקעים (קל ב-100% פשוט לעבור ללינוקס, ב-Linux MadelineProto פשוט עובד מחוץ לקופסה, אין צורך בשינויים)",
- "translate_madelineproto_cli": "ניתן לתרגם את MadelineProto בשפה שלך (התקדמות התרגום הנוכחית: %d%%), עבור אל https://weblate.madelineproto.xyz כדי לתרום עם התרגום!",
"recommend_not_use_filesystem_function": "השימוש בפונקציה %s אינו מומלץ, מכיוון שגישה למערכת הקבצים במהלך טיפול בעדכונים תאט את הבוט שלך, אנא ראה https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions עבור רשימה של דרכים חלופיות לאחסון נתונים שלא יאט את הבוט שלך!",
"plugins_do_not_use_require": "מטעמי ביצועים, תוספים יכולים לכלול או לדרוש אוטומטית קבצים אחרים הנמצאים בתיקיית התוספים על ידי הפעלת הטעינה האוטומטית של PSR-4 (לא על ידי הפעלתם ידנית של require()'ing them).",
- "dl.php_check_logs_make_sure_session_running": "הבוט של MadelineProto EventHandler או שרת ה-IPC של MadelineProto אינם מקוונים, אנא בדוק יומנים וודא שלפחות אחד מהם פועל!",
+ "plugins_must_have_exactly_one_class": "תוסף חייב להגדיר בדיוק מחלקה אחת! כדי להגדיר מספר מחלקות, ממשקים או תכונות, צור קבצים נפרדים, הם ייטענו אוטומטית על ידי MadelineProto באופן אוטומטי.",
+ "cli_need_dl.php_link": "אנא ציין כתובת אתר של סקריפט הורדה בעת שימוש ב-getDownloadLink דרך CLI!",
"invalid_dl.php_session": "%s אינו סקריפט הורדה חוקי מכיוון שמזהה ההפעלה שלו שונה (צפי %s, קיבל %s)",
+ "need_dl.php": "לא ניתן ליצור סקריפט הורדה כברירת מחדל (%s), אנא צור קובץ dl.php עם התוכן הבא: %s והעביר את כתובת האתר שלו לפרמטר השני של getDownloadLink",
"dl.php_powered_by_madelineproto": "שרת הורדת קבצי Telegram (עד 4GB), מופעל על ידי MadelineProto!
Click here למידע נוסף על איך להגדיר שרת הורדת קבצים משלך בטלגרם!",
- "translate_madelineproto_web": "ניתן לתרגם את MadelineProto בשפה שלך (התקדמות התרגום הנוכחית: %d%%), לחץ כאן כדי לתרום עם התרגום!"
+ "dl.php_check_logs_make_sure_session_running": "הבוט של MadelineProto EventHandler או שרת ה-IPC של MadelineProto אינם מקוונים, אנא בדוק יומנים וודא שלפחות אחד מהם פועל!",
+ "account_banned": "!!!!!!! אזהרה!!!!!!!\nמערכת מניעת הצפות של טלגרם השעתה את החשבון הזה.\nכדי להמשיך, נדרש אימות ידני.\nשלח אימייל לכתובת recover@telegram.org, בבקשה לבטל את החסימה של מספר הטלפון %s, ותאר בקצרה מה תעשה עם מספר הטלפון הזה.\nלאחר מכן התחבר שוב.\nאם מחקת את החשבון הזה בכוונה, התעלם מהודעה זו.",
+ "plugin_path_does_not_exist": "נתיב התוסף %s אינו קיים!",
+ "could_not_connect_to_MadelineProto": "לא ניתן להתחבר ל-MadelineProto, אנא הפעל את proc_open והסר הגבלות open_basedir או השבת שכתוב של נתיב שרת אינטרנט כדי לתקן! אם כבר עשית זאת, ודא שגרסת ה-CLI של PHP זהה בדיוק לגרסת האינטרנט (אותה גרסה, הרחבות וכו') ועיין בקובץ MadelineProto.log לקבלת מידע נוסף על השגיאה שמנעה משרת ה-IPC להתחיל.",
+ "translate_madelineproto_web": "ניתן לתרגם את MadelineProto בשפה שלך (התקדמות התרגום הנוכחית: %d%%), לחץ כאן כדי לתרום עם התרגום!",
+ "translate_madelineproto_cli": "ניתן לתרגם את MadelineProto בשפה שלך (התקדמות התרגום הנוכחית: %d%%), עבור אל https://github.com/danog/MadelineProto/tree/v8/langs כדי לתרום עם התרגום!",
+ "apiInvalidWeb": "ה-API ID הוא מספר, וה-API hash באורך 32 תווים: העתק אותם שוב מ-my.telegram.org.",
+ "webDoneLead": "MadelineProto ממשיך לפעול בשרת: אפשר לסגור את הדף הזה.",
+ "apiChooseManualAuto": "האם לקבל את ה-API ID וה-hash אוטומטית מ-my.telegram.org (a), או להזין אותם ידנית (m)?",
+ "apiAutoFallbackManual": "במקום זאת, הזן את ה-API ID וה-hash ידנית.",
+ "apiSetupTitleWeb": "קבלת API ID ו-hash",
+ "apiSetupLeadWeb": "כל אפליקציית Telegram צריכה API ID ו-hash. MadelineProto יכול לקבל אותם עבורך מ-my.telegram.org, בעזרת מספר הטלפון של חשבון Telegram קיים.",
+ "apiAutoPhoneHintWeb": "my.telegram.org שולח את קוד הכניסה לאפליקציית Telegram שלך, לא ב-SMS.",
+ "apiSendCodeWeb": "שליחת קוד",
+ "apiChooseManualWeb": "כבר יש לי API ID",
+ "apiChooseAutoWeb": "קבלה אוטומטית",
+ "apiStartOverWeb": "התחלה מחדש",
+ "apiAutoCodeTitleWeb": "הזן את הקוד מ-Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org שלח קוד כניסה לאפליקציית Telegram שלך, בצ'אט עם Telegram (לא ב-SMS).",
+ "apiAutoCodeLabelWeb": "קוד כניסה",
+ "apiCreateTitleWeb": "יצירת האפליקציה שלך",
+ "apiCreateLeadWeb": "לחשבון הזה עדיין אין אפליקציה ב-my.telegram.org. הפרטים האלה מוצגים רק לך, ואפשר לשנות אותם בהמשך.",
+ "apiAppTitleLabelWeb": "שם האפליקציה",
+ "apiAppShortNameLabelWeb": "שם קצר",
+ "apiAppUrlLabelWeb": "כתובת URL",
+ "apiAppDescLabelWeb": "תיאור",
+ "apiCreateWeb": "יצירת אפליקציה",
+ "apiSaveWeb": "שמירה והמשך",
+ "apiAutoErrorTitle": "my.telegram.org החזיר שגיאה",
+ "apiCreateErrorTitle": "my.telegram.org לא יצר את האפליקציה",
+ "apiCreateVpsWarning": "Telegram לא מאפשר ליצור אפליקציות חדשות ב-my.telegram.org מטווחי IP של VPS, VPN ומרכזי נתונים אחרים, והבקשה נשלחה מה-IP של המחשב שמריץ את MadelineProto. צור את האפליקציה ידנית ב-https://my.telegram.org מחיבור ביתי (למשל מהטלפון שלך עם גלישה סלולרית), ואז הזן את ה-API ID וה-hash.",
+ "loginTitleWeb": "כניסה ל-Telegram",
+ "loginLeadWeb": "בחר את החשבון או הבוט שבשמו יפעל מופע MadelineProto הזה.",
+ "loginTypeWeb": "כניסה בתור",
+ "loginUserPhoneHintWeb": "עם קידומת המדינה, למשל +39 123 456 7890.",
+ "loginBotTokenHintWeb": "הטוקן ש-@BotFather נתן לך כשיצרת את הבוט.",
+ "loginCodeTitleWeb": "הזן את קוד הכניסה",
+ "loginCodeLeadWeb": "Telegram שלח קוד כניסה לאפליקציית Telegram שלך, או ב-SMS אם אינך מחובר בשום מקום אחר.",
+ "loginPasswordTitleWeb": "אימות דו-שלבי",
+ "loginPasswordLeadWeb": "החשבון הזה מוגן בסיסמה, שהוגדרה בהגדרות > פרטיות ואבטחה > אימות דו-שלבי.",
+ "loginPasswordLabelWeb": "סיסמה",
+ "signupTitleWeb": "יצירת החשבון שלך",
+ "signupLeadWeb": "מספר הטלפון הזה עדיין לא רשום ב-Telegram: בחר את השם של החשבון החדש.",
+ "webContinue": "המשך",
+ "webLogin": "כניסה",
+ "webError": "%s. בדוק ונסה שוב.",
+ "webStepApp": "API ID ו-hash",
+ "webStepAccount": "חשבון",
+ "webStepVerify": "אימות",
+ "webStepDone": "פועל",
+ "webProgress": "התקדמות ההגדרה",
+ "webDocs": "תיעוד",
+ "webOptional": "אופציונלי",
+ "webShowPassword": "הצג",
+ "webHidePassword": "הסתר",
+ "webQrTitle": "כניסה באמצעות קוד QR",
+ "webQrWaiting": "ממתין לסריקה…",
+ "webFieldRequired": "יש למלא את השדה הזה.",
+ "webPhoneInvalid": "הזן את מספר הטלפון עם קידומת המדינה, למשל +39 123 456 7890.",
+ "tweb.Login.Title": "כניסה ל-MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "מספר טלפון לא תקין",
+ "tweb.Login.StartText": "נא לאשר את קידומת המדינה\nולהזין את מספר הטלפון שלך.",
+ "tweb.Login.Code.SentSms": "שלחנו לך SMS\nעם הקוד.",
+ "tweb.Login.Code.SentInApp": "שלחנו לך הודעה ב-Telegram\nעם הקוד.",
+ "tweb.Login.Code.SentCall": "נתקשר אליך ונקריא לך\nאת הקוד.",
+ "tweb.Login.Code.SentEmail": "נא לבדוק את האימייל שלך **%s** (אל תשכח את תיקיית הספאם) ולהזין את הקוד ששלחנו לך זה עתה.",
+ "tweb.Login.Code.SentUnknown": "נא לחפש בכל מקום\nאת הקוד (סוג: %s)",
+ "tweb.Login.Code.SentMissedCall": "בשניות הקרובות תקבל\nשיחה קצרה מ-**%s**. אל תענה לה —\nפשוט הזן את הספרות האחרונות של המספר הזה.",
+ "tweb.Login.Code.SentSmsWord": "שלחנו SMS עם מילה סודית\nלטלפון שלך **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "שלחנו SMS עם מילה סודית שמתחילה\nב-\"**%2$s**\" לטלפון שלך **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "שלחנו SMS עם ביטוי סודי\nלטלפון שלך **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "שלחנו SMS עם ביטוי סודי שמתחיל\nב-\"**%2$s**\" לטלפון שלך **%1$s**.",
+ "tweb.Login.Code.SecretWord": "מילה סודית",
+ "tweb.Login.Code.SecretPhrase": "ביטוי סודי",
+ "tweb.Login.Code.WordInvalid": "שגוי, נא לנסות שוב",
+ "tweb.Login.Code.WordBeginningInvalid": "מילה שגויה",
+ "tweb.Login.Password.Title": "הזן את הסיסמה שלך",
+ "tweb.Login.Password.Subtitle": "החשבון שלך מוגן\nבסיסמה נוספת",
+ "tweb.Login.Register.Subtitle": "הזן את שמך\nכדי ליצור את החשבון שלך",
+ "tweb.PleaseWait": "נא להמתין...",
+ "tweb.Code": "קוד",
+ "tweb.LoginPassword": "סיסמה",
+ "tweb.YourName": "השם שלך",
+ "tweb.FirstName": "שם פרטי (חובה)",
+ "tweb.LastName": "שם משפחה (אופציונלי)",
+ "tweb.StartMessaging": "התחל לשלוח הודעות",
+ "tweb.Country": "מדינה",
+ "tweb.Contacts.PhoneNumber.Placeholder": "מספר טלפון",
+ "tweb.Login.Next": "הבא",
+ "tweb.Login.QR.Title": "כניסה באמצעות קוד QR",
+ "tweb.Login.QR.Help1": "פתח את Telegram בטלפון שלך",
+ "tweb.Login.QR.Help2": "עבור אל **הגדרות** > **מכשירים** > **הוספת מכשיר**",
+ "tweb.Login.QR.Help3": "כוון את הטלפון שלך למסך זה כדי לאשר את הכניסה",
+ "tweb.Login.QR.Cancel": "כניסה באמצעות מספר טלפון >",
+ "tweb.Login.QR.Login": "כניסה באמצעות קוד QR >",
+ "tweb.Login.QR.Subtitle": "סרוק באמצעות אפליקציית Telegram בטלפון שלך",
+ "tweb.PhoneNumber.Code.Fragment.Info": "קבל את הקוד באזור המספרים ב-[Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "קוד שגוי",
+ "tweb.PHONE_CODE_EXPIRED": "פג תוקף הקוד",
+ "tweb.PASSWORD_HASH_INVALID": "סיסמה שגויה",
+ "tweb.DarkMode": "מצב כהה",
+ "tweb.Error.AnError": "אירעה שגיאה. נא לנסות שוב מאוחר יותר.",
+ "tweb.AccDescr.LoginCode": "קוד כניסה",
+ "tweb.Login.Bot": "כניסה בתור בוט >",
+ "tweb.Login.Bot.Title": "כניסה בתור בוט",
+ "tweb.Login.Bot.Subtitle": "הזן את הטוקן ש-@BotFather נתן לך\nכשיצרת את הבוט.",
+ "tweb.Login.Bot.Token": "טוקן הבוט",
+ "tweb.Login.Bot.Cancel": "כניסה בתור משתמש >",
+ "tweb.Optional": "אופציונלי",
+ "tweb.PHONE_NUMBER_INVALID": "מספר טלפון לא תקין",
+ "tweb.PHONE_NUMBER_BANNED": "מספר הטלפון הזה חסום",
+ "tweb.PHONE_NUMBER_FLOOD": "יותר מדי ניסיונות, נסה שוב מאוחר יותר",
+ "tweb.PHONE_CODE_EMPTY": "קוד שגוי",
+ "tweb.PHONE_PASSWORD_FLOOD": "יותר מדי ניסיונות, נסה שוב מאוחר יותר",
+ "tweb.ACCESS_TOKEN_INVALID": "טוקן בוט לא תקין",
+ "tweb.ACCESS_TOKEN_EXPIRED": "טוקן הבוט הזה בוטל",
+ "tweb.FIRSTNAME_INVALID": "שם פרטי לא תקין",
+ "tweb.LASTNAME_INVALID": "שם משפחה לא תקין",
+ "tweb.Close": "סגירה"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/hi.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/hi.json
new file mode 100644
index 0000000..28520ac
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/hi.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "basedir प्रतिबंध कॉन्फ़िगर किया गया है: इससे परफ़ॉर्मेंस प्रभावित हो सकती है और कुछ समस्याएँ हो सकती हैं, कृपया संभव हो तो इसे अक्षम करें!",
+ "noReportPeers": "चेतावनी: कोई रिपोर्ट पीयर सेट नहीं है, कृपया अपने इवेंट हैंडलर में निम्नलिखित मेथड जोड़ें",
+ "manualAdminActionRequired": "!!!!!!!!! सिस्टम एडमिन द्वारा मैन्युअल कार्रवाई आवश्यक है !!!!!!!!!",
+ "mmapErrorPart1": "मेमोरी मैप्ड (mmap) क्षेत्रों की अधिकतम संख्या पूरी हो गई है (%s): इसे ठीक करने के लिए कृपया कर्नेल कॉन्फ़िग vm.max_map_count को बढ़ाकर 262144 करें।",
+ "mmapErrorPart2": "ठीक करने के लिए, निम्नलिखित कमांड को root के रूप में चलाएँ: %s",
+ "mmapErrorPart3": "रीबूट के बाद भी बदलाव बनाए रखने के लिए: %s",
+ "mmapErrorPart4": "Windows और WSL पर, pagefile का आकार बढ़ाने से मदद मिल सकती है; यदि समस्या बनी रहती है तो कृपया नेटिव Linux पर स्विच करें।",
+ "botAlreadyRunning": "बॉट पहले से चल रहा है!",
+ "extensionRequired": "MadelineProto को चलने के लिए %s एक्सटेंशन की आवश्यकता है। %s",
+ "extensionRequiredInstallWithApt": "sudo apt-get install %s चलाकर देखें।",
+ "extensionRequiredInstallWithCustomInstructions": "इसे इंस्टॉल करने के लिए %s पर दिए गए निर्देशों का पालन करें।",
+ "extensionRecommended": "चेतावनी: %s एक्सटेंशन इंस्टॉल नहीं है, कृपया MadelineProto की गति बढ़ाने के लिए इसे इंस्टॉल करें!",
+ "go": "आगे बढ़ें",
+ "apiChooseManualAutoTip": "ध्यान दें कि आप सेटिंग्स का उपयोग करके API ID/hash सीधे कोड में भी दे सकते हैं: %s",
+ "apiChooseManualAutoTipWeb": "ध्यान दें कि आप सेटिंग्स का उपयोग करके API ID/hash सीधे कोड में भी दे सकते हैं।",
+ "apiChoosePrompt": "आपका विकल्प (m/a): ",
+ "apiManualInstructions0": "https://my.telegram.org पर लॉगिन करें",
+ "apiManualInstructions1": "API development tools पर जाएँ",
+ "apiManualInstructions2": "create application पर क्लिक करें",
+ "apiAppInstructionsManual0": "आपके ऐप का नाम, कुछ भी हो सकता है",
+ "apiAppInstructionsManual1": "आपके ऐप का छोटा नाम, केवल अक्षर और अंक, 5-32 वर्ण",
+ "apiAppInstructionsManual2": "आपके ऐप/वेबसाइट का URL, या t.me/yourusername",
+ "apiAppInstructionsManual3": "कुछ भी",
+ "apiAppInstructionsManual4": "यहाँ अपने ऐप का विवरण दें",
+ "apiManualWeb": "अपना API ID और API hash दर्ज करें",
+ "apiManualPrompt0": "अपना API ID दर्ज करें: ",
+ "apiManualPrompt1": "अपना API hash दर्ज करें: ",
+ "apiAutoWeb": "API ID प्राप्त करने के लिए वह फ़ोन नंबर दर्ज करें जो Telegram पर पहले से रजिस्टर्ड है",
+ "apiAutoPrompt0": "वह फ़ोन नंबर दर्ज करें जो Telegram पर पहले से रजिस्टर्ड है: ",
+ "apiAutoPrompt1": "Telegram में प्राप्त वेरिफ़िकेशन कोड दर्ज करें: ",
+ "apiAppWeb": "API जानकारी दर्ज करें",
+ "apiAppInstructionsAuto0": "ऐप का नाम दर्ज करें, कुछ भी हो सकता है: ",
+ "apiAppInstructionsAuto1": "ऐप का छोटा नाम दर्ज करें, केवल अक्षर और अंक, 5-32 वर्ण: ",
+ "apiAppInstructionsAuto2": "ऐप/वेबसाइट का URL दर्ज करें, या t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "ऐप का प्लेटफ़ॉर्म दर्ज करें: ",
+ "apiAppInstructionsAuto4": "अपने ऐप का विवरण दें: ",
+ "apiAppInstructionsAutoTypeOther": "अन्य (विवरण में बताएँ)",
+ "apiParamsError": "आपने सभी आवश्यक पैरामीटर नहीं दिए!",
+ "apiError": "त्रुटि: %s। फिर से प्रयास करें।",
+ "loginChoosePromptWeb": "क्या आप यूज़र के रूप में लॉगिन करना चाहते हैं या बॉट के रूप में?",
+ "loginWebQr": "आप अपने फ़ोन पर Telegram खोलकर, Settings > Devices > Link Desktop Device पर जाकर और निम्नलिखित QR कोड स्कैन करके अपने-आप भी लॉगिन कर सकते हैं:",
+ "loginWebQr1": "अपने फ़ोन पर Telegram खोलें",
+ "loginWebQr2": "Settings > Devices > Link Desktop Device पर जाएँ",
+ "loginWebQr3": "लॉगिन की पुष्टि करने के लिए अपने फ़ोन को इस स्क्रीन की ओर करें",
+ "loginOptionBot": "बॉट",
+ "loginOptionUser": "यूज़र",
+ "loginBot": "अपना बॉट टोकन दर्ज करें: ",
+ "loginUser": "अपना फ़ोन नंबर दर्ज करें: ",
+ "loginQr": "अपने फ़ोन पर Telegram खोलें, Settings > Devices > Link Desktop Device पर जाएँ और अपने-आप लॉगिन करने के लिए ऊपर दिया गया QR कोड स्कैन करें।",
+ "loginQrCodeSuccessful": "QR कोड से लॉगिन सफल रहा!",
+ "loginQrCodeExpired": "QR कोड की समय-सीमा समाप्त हो गई, नया कोड बनाया जा रहा है...",
+ "loginManual": "वैकल्पिक रूप से, आप मैन्युअल रूप से लॉगिन करने के लिए बॉट टोकन या फ़ोन नंबर भी दर्ज कर सकते हैं: ",
+ "loginUserCode": "कोड दर्ज करें: ",
+ "loginUserPass": "अपना पासवर्ड दर्ज करें (संकेत %s): ",
+ "loginUserPassWeb": "अपना पासवर्ड दर्ज करें: ",
+ "loginUserPassHint": "संकेत: %s",
+ "signupFirstName": "अपना पहला नाम दर्ज करें: ",
+ "signupLastName": "अपना उपनाम दर्ज करें (खाली छोड़ सकते हैं): ",
+ "signupWeb": "कृपया साइन अप करें",
+ "signupFirstNameWeb": "पहला नाम",
+ "signupLastNameWeb": "उपनाम",
+ "loginNoCode": "आपने फ़ोन कोड नहीं दिया!",
+ "loginNoPass": "आपने पासवर्ड नहीं दिया!",
+ "loginNoName": "आपने पहला नाम नहीं दिया!",
+ "loginBotTokenWeb": "बॉट टोकन",
+ "loginUserPhoneWeb": "फ़ोन नंबर",
+ "loginUserPhoneCodeWeb": "कोड",
+ "done": "हो गया!",
+ "nearest_dc": "हम %s में हैं, निकटतम DC %d है।",
+ "serialization_ofd": "सीरियलाइज़ेशन पुराना हो गया है, ऑब्जेक्ट को फिर से बनाया जा रहा है!",
+ "api_not_set": "आपको api key और api id देनी होगी, अपनी खुद की my.telegram.org पर प्राप्त करें",
+ "session_corrupted": "सेशन दूषित हो गया है!",
+ "value_bigger_than_2147483647": "दिया गया मान %s, 2147483647 से बड़ा है",
+ "value_smaller_than_2147483648": "दिया गया मान %s, -2147483648 से छोटा है",
+ "value_bigger_than_9223372036854775807": "दिया गया मान %s, 9223372036854775807 से बड़ा है",
+ "value_smaller_than_9223372036854775808": "दिया गया मान %s, -9223372036854775808 से छोटा है",
+ "value_bigger_than_4294967296": "दिया गया मान %s, 4294967296 से बड़ा है",
+ "value_smaller_than_0": "दिया गया मान %s, 0 से छोटा है",
+ "encode_double_error": "double को ठीक से एनकोड नहीं किया जा सका",
+ "file_not_exist": "फ़ाइल मौजूद नहीं है",
+ "deserialization_error": "डीसीरियलाइज़ेशन के दौरान एक त्रुटि हुई",
+ "rpc_tg_error": "Telegram ने एक RPC त्रुटि लौटाई: %s (%s), जो %s:%s के कारण हुई%sTL ट्रेस:",
+ "madelineproto_ready": "MadelineProto तैयार है!",
+ "logout_ok": "सफलतापूर्वक लॉग आउट हो गया!",
+ "already_loggedIn": "MadelineProto का यह इंस्टेंस पहले से लॉग इन है!",
+ "login_ok": "सफलतापूर्वक लॉग इन हो गया!",
+ "login_user": "सामान्य यूज़र के रूप में लॉग इन किया जा रहा है...",
+ "login_bot": "बॉट के रूप में लॉग इन किया जा रहा है...",
+ "login_code_sending": "कोड भेजा जा रहा है...",
+ "login_code_sent": "कोड सफलतापूर्वक भेज दिया गया! कोड प्राप्त होने के बाद आपको completePhoneLogin फ़ंक्शन का उपयोग करना चाहिए।",
+ "login_code_uncalled": "मैं कोड की प्रतीक्षा नहीं कर रहा हूँ! कृपया पहले phoneLogin मेथड कॉल करें",
+ "login_2fa_enabled": "2FA सक्षम है, आपको complete2falogin फ़ंक्शन कॉल करना होगा...",
+ "login_need_signup": "इस नंबर के लिए कोई अकाउंट नहीं बनाया गया है, आपको completeSignup फ़ंक्शन कॉल करना होगा...",
+ "login_auth_key": "auth key का उपयोग करके लॉग इन किया जा रहा है...",
+ "not_loggedIn": "मैं लॉग इन नहीं हूँ!",
+ "signup_uncalled": "मैं साइन अप की प्रतीक्षा नहीं कर रहा हूँ! कृपया पहले phoneLogin और completePhoneLogin मेथड कॉल करें!",
+ "signing_up": "सामान्य यूज़र के रूप में साइन अप किया जा रहा है...",
+ "signup_ok": "सफलतापूर्वक साइन अप हो गया!",
+ "2fa_uncalled": "मैं पासवर्ड की प्रतीक्षा नहीं कर रहा हूँ! कृपया पहले phoneLogin और completePhoneLogin मेथड कॉल करें!",
+ "peer_not_in_db": "यह पीयर आंतरिक पीयर डेटाबेस में मौजूद नहीं है",
+ "call_error_1": "कॉल %s को ढूँढकर स्वीकार नहीं किया जा सका",
+ "accepting_call": "%s की कॉल स्वीकार की जा रही है...",
+ "call_already_accepted": "कॉल %s पहले ही स्वीकार की जा चुकी है",
+ "call_already_declined": "कॉल %s पहले ही अस्वीकार की जा चुकी है",
+ "call_error_2": "कॉल %s को ढूँढकर उसकी पुष्टि नहीं की जा सकी",
+ "call_confirming": "%s की कॉल की पुष्टि की जा रही है...",
+ "call_error_3": "कॉल %s को ढूँढकर पूरा नहीं किया जा सका",
+ "call_completing": "%s की कॉल पूरी की जा रही है...",
+ "fingerprint_invalid": "अमान्य कुंजी फ़िंगरप्रिंट!",
+ "call_discarding": "कॉल %s समाप्त की जा रही है...",
+ "file_parsing": "%s पार्स किया जा रहा है...",
+ "src_file_invalid": "अमान्य सोर्स फ़ाइल दी गई: ",
+ "bool_error": "boolean नहीं निकाला जा सका",
+ "not_numeric": "दिया गया मान संख्यात्मक नहीं है",
+ "long_not_16": "दिया गया मान 16 बाइट लंबा नहीं है",
+ "long_not_32": "दिया गया मान 32 बाइट लंबा नहीं है",
+ "long_not_64": "दिया गया मान 64 बाइट लंबा नहीं है",
+ "array_invalid": "आपने एक मान्य array नहीं दिया",
+ "predicate_not_set": "Predicate (_ के अंतर्गत मान) सेट नहीं किया गया!",
+ "update_madelineproto": "आप MadelineProto का पुराना संस्करण चला रहे हैं, अपडेट आवश्यक है: अभी %s चल रहा है, लेकिन कई बग फ़िक्स और नई सुविधाओं वाला नवीनतम संस्करण %s है!",
+ "type_extract_error": "टाइप \"%s\" नहीं निकाला जा सका, आपको MadelineProto अपडेट करना चाहिए!",
+ "method_not_found": "मेथड नहीं मिला: ",
+ "params_missing": "आवश्यक पैरामीटर मौजूद नहीं है",
+ "sec_peer_not_in_db": "यह सीक्रेट पीयर आंतरिक पीयर डेटाबेस में मौजूद नहीं है",
+ "stream_handle_invalid": "एक अमान्य स्ट्रीम हैंडल दिया गया।",
+ "length_too_big": "लंबाई बहुत अधिक है",
+ "string_required": "एक string अपेक्षित थी!",
+ "waveform_must_have_100_values": "waveform array में 100 मान होने चाहिए!",
+ "waveform_value": "waveform का मान 0 और 31 के बीच होना चाहिए!",
+ "could_not_convert_object": "%s टाइप के ऑब्जेक्ट को कन्वर्ट नहीं किया जा सका",
+ "type_extract_error_id": "टाइप नहीं निकाला जा सका: %s (id %s), आपको MadelineProto अपडेट करना चाहिए!",
+ "constructor_not_found": "इस टाइप के लिए constructor नहीं मिला: ",
+ "botapi_conversion_error": "%s को bot API ऑब्जेक्ट में कन्वर्ट नहीं किया जा सकता",
+ "non_text_conversion": "गैर-टेक्स्ट संदेशों को अभी कन्वर्ट नहीं किया जा सकता!",
+ "file_type_invalid": "अमान्य फ़ाइल टाइप का पता चला (%s)",
+ "static_analysis_minor": "%s के स्टैटिक एनालिसिस के दौरान एक छोटी समस्या मिली: %s",
+ "static_analysis_severe": "%s के स्टैटिक एनालिसिस के दौरान एक गंभीर समस्या मिली: %s",
+ "secret_chat_skipping": "डेटाबेस में सीक्रेट चैट %s मौजूद नहीं है, संदेश छोड़ा जा रहा है...",
+ "must_have_declare_types": "परफ़ॉर्मेंस कारणों से, इवेंट हैंडलर फ़ाइल का पहला स्टेटमेंट \"declare(strict_types=1);\" होना चाहिए",
+ "do_not_delete_MadelineProto.log": "MadelineProto.log फ़ाइल को कभी भी डिलीट नहीं किया जाना चाहिए, इसके बजाय कृपया सेटिंग्स में एक कस्टम अधिकतम आकार सेट करें!",
+ "do_not_remove_MadelineProto.log_phar": "कृपया madeline.phar या madeline.php को न हटाएँ, अन्यथा MadelineProto क्रैश हो जाएगा। यदि आपको MadelineProto के साथ कोई समस्या है, तो उसे https://github.com/danog/MadelineProto या https://t.me/pwrtelegramgroup पर रिपोर्ट करें",
+ "do_not_use_blocking_function": "परफ़ॉर्मेंस कारणों से, इवेंट हैंडलर नॉन-async ब्लॉकिंग फ़ंक्शन %s का उपयोग नहीं कर सकते, कृपया इसके बजाय %s का उपयोग करें",
+ "do_not_use_blocking_class": "परफ़ॉर्मेंस कारणों से, हैंडलर नॉन-async ब्लॉकिंग क्लास %s का उपयोग नहीं कर सकते, कृपया इसके बजाय %s का उपयोग करें",
+ "do_not_use_deprecated_function": "%s फ़ंक्शन अप्रचलित (deprecated) है, कृपया इसके बजाय %s का उपयोग करें",
+ "do_not_use_non_root_require_in_event_handler": "परफ़ॉर्मेंस कारणों से, आपको इवेंट हैंडलर क्लास के अंदर require या include का उपयोग नहीं करना चाहिए, केवल रूट-लेवल require की अनुमति है।",
+ "do_not_use_yield": "MadelineProto 8 को async फ़ंक्शनों में yield के उपयोग की न तो आवश्यकता है और न ही यह इसका समर्थन करता है, आपको async फ़ंक्शन कॉल के लिए पहले उपयोग किए गए सभी yield कीवर्ड हटाने होंगे",
+ "recommend_not_use_filesystem_function": "%s फ़ंक्शन का उपयोग अनुशंसित नहीं है, क्योंकि अपडेट हैंडल करते समय फ़ाइलसिस्टम एक्सेस करने से आपका बॉट धीमा हो जाएगा, डेटा स्टोर करने के ऐसे वैकल्पिक तरीकों की सूची के लिए जो आपके बॉट को धीमा नहीं करेंगे, कृपया https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions देखें!",
+ "plugins_do_not_use_require": "परफ़ॉर्मेंस कारणों से, प्लगइन plugins फ़ोल्डर में मौजूद अन्य फ़ाइलों को केवल PSR-4 autoloader को ट्रिगर करके ही अपने-आप include या require कर सकते हैं (उन्हें मैन्युअल रूप से require() करके नहीं)।",
+ "plugins_must_have_exactly_one_class": "एक प्लगइन को ठीक एक क्लास परिभाषित करनी चाहिए! कई क्लास, interface या trait परिभाषित करने के लिए अलग-अलग फ़ाइलें बनाएँ, MadelineProto उन्हें अपने-आप autoload कर लेगा।",
+ "cli_need_dl.php_link": "CLI के माध्यम से getDownloadLink का उपयोग करते समय कृपया डाउनलोड स्क्रिप्ट का URL निर्दिष्ट करें!",
+ "invalid_dl.php_session": "%s एक मान्य डाउनलोड स्क्रिप्ट नहीं है क्योंकि इसका सेशन ID अलग है (अपेक्षित %s, प्राप्त %s)",
+ "need_dl.php": "डिफ़ॉल्ट डाउनलोड स्क्रिप्ट नहीं बनाई जा सकी (%s), कृपया निम्नलिखित सामग्री के साथ एक dl.php फ़ाइल बनाएँ: %s और उसका URL getDownloadLink के दूसरे पैरामीटर में पास करें",
+ "dl.php_powered_by_madelineproto": "Telegram फ़ाइल डाउनलोड सर्वर (4GB तक), MadelineProto द्वारा संचालित!
अपना खुद का Telegram फ़ाइल डाउनलोड सर्वर सेट अप करने के बारे में अधिक जानकारी के लिए यहाँ क्लिक करें!",
+ "dl.php_check_logs_make_sure_session_running": "या तो संबंधित MadelineProto EventHandler बॉट या MadelineProto IPC सर्वर ऑफ़लाइन है, कृपया लॉग जाँचें और सुनिश्चित करें कि उनमें से कम से कम एक चल रहा हो!",
+ "account_banned": "!!!!!!! चेतावनी !!!!!!!\nTelegram की फ़्लड रोकथाम प्रणाली ने इस अकाउंट को निलंबित कर दिया है।\nजारी रखने के लिए मैन्युअल वेरिफ़िकेशन आवश्यक है।\nrecover@telegram.org पर एक ईमेल भेजें, जिसमें फ़ोन नंबर %s को अनबैन करने का अनुरोध करें, और संक्षेप में बताएँ कि आप इस फ़ोन नंबर के साथ क्या करेंगे।\nफिर दोबारा लॉगिन करें।\nयदि आपने जानबूझकर यह अकाउंट डिलीट किया है, तो इस संदेश को अनदेखा करें।",
+ "plugin_path_does_not_exist": "प्लगइन पाथ %s मौजूद नहीं है!",
+ "could_not_connect_to_MadelineProto": "MadelineProto से कनेक्ट नहीं किया जा सका, इसे ठीक करने के लिए कृपया proc_open सक्षम करें और open_basedir प्रतिबंध हटाएँ या वेबसर्वर पाथ रीराइट अक्षम करें! यदि आप यह पहले ही कर चुके हैं, तो सुनिश्चित करें कि PHP का CLI संस्करण वेब संस्करण के बिल्कुल समान है (समान संस्करण, एक्सटेंशन आदि) और उस त्रुटि के बारे में अधिक जानकारी के लिए MadelineProto.log फ़ाइल देखें जिसने IPC सर्वर को शुरू होने से रोका।",
+ "translate_madelineproto_web": "MadelineProto का आपकी भाषा में अनुवाद किया जा सकता है (वर्तमान अनुवाद प्रगति: %d%%), अनुवाद में योगदान देने के लिए यहाँ क्लिक करें!",
+ "translate_madelineproto_cli": "MadelineProto का आपकी भाषा में अनुवाद किया जा सकता है (वर्तमान अनुवाद प्रगति: %d%%), अनुवाद में योगदान देने के लिए https://github.com/danog/MadelineProto/tree/v8/langs पर जाएँ!",
+ "apiInvalidWeb": "API ID एक संख्या होती है और API hash 32 वर्णों का होता है: इन्हें my.telegram.org से फिर से कॉपी करें।",
+ "webDoneLead": "MadelineProto सर्वर पर चलता रहेगा: आप यह पेज बंद कर सकते हैं।",
+ "apiChooseManualAuto": "क्या आप API ID और hash को my.telegram.org से अपने-आप प्राप्त करना चाहते हैं (a), या उन्हें मैन्युअल रूप से दर्ज करना चाहते हैं (m)?",
+ "apiAutoFallbackManual": "इसके बजाय API ID और hash मैन्युअल रूप से दर्ज करें।",
+ "apiSetupTitleWeb": "अपना API ID और hash प्राप्त करें",
+ "apiSetupLeadWeb": "हर Telegram ऐप को एक API ID और hash की ज़रूरत होती है। MadelineProto किसी मौजूदा Telegram अकाउंट के फ़ोन नंबर से इन्हें आपके लिए my.telegram.org से प्राप्त कर सकता है।",
+ "apiAutoPhoneHintWeb": "my.telegram.org लॉगिन कोड SMS से नहीं, बल्कि आपके Telegram ऐप पर भेजता है।",
+ "apiSendCodeWeb": "कोड भेजें",
+ "apiChooseManualWeb": "मेरे पास पहले से API ID है",
+ "apiChooseAutoWeb": "अपने-आप प्राप्त करें",
+ "apiStartOverWeb": "फिर से शुरू करें",
+ "apiAutoCodeTitleWeb": "Telegram से मिला कोड दर्ज करें",
+ "apiAutoCodeLeadWeb": "my.telegram.org ने आपके Telegram ऐप में, Telegram वाली चैट में एक लॉगिन कोड भेजा है (SMS से नहीं)।",
+ "apiAutoCodeLabelWeb": "लॉगिन कोड",
+ "apiCreateTitleWeb": "अपना ऐप बनाएँ",
+ "apiCreateLeadWeb": "इस अकाउंट का my.telegram.org पर अभी कोई ऐप नहीं है। ये जानकारी केवल आपको दिखाई देती है और बाद में बदली जा सकती है।",
+ "apiAppTitleLabelWeb": "ऐप का नाम",
+ "apiAppShortNameLabelWeb": "छोटा नाम",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "विवरण",
+ "apiCreateWeb": "ऐप बनाएँ",
+ "apiSaveWeb": "सहेजें और जारी रखें",
+ "apiAutoErrorTitle": "my.telegram.org ने एक त्रुटि लौटाई",
+ "apiCreateErrorTitle": "my.telegram.org ने ऐप नहीं बनाया",
+ "apiCreateVpsWarning": "Telegram, VPS, VPN और अन्य डेटा सेंटर IP रेंज से my.telegram.org पर नए ऐप बनाने की अनुमति नहीं देता, और यह अनुरोध MadelineProto चला रही मशीन के IP से भेजा गया था। किसी घरेलू कनेक्शन (जैसे मोबाइल डेटा पर आपका फ़ोन) से https://my.telegram.org पर मैन्युअल रूप से ऐप बनाएँ, फिर API ID और hash दर्ज करें।",
+ "loginTitleWeb": "Telegram में लॉगिन करें",
+ "loginLeadWeb": "वह अकाउंट या बॉट चुनें जिसके रूप में यह MadelineProto इंस्टेंस चलेगा।",
+ "loginTypeWeb": "इस रूप में लॉगिन करें",
+ "loginUserPhoneHintWeb": "देश कोड के साथ, जैसे +39 123 456 7890।",
+ "loginBotTokenHintWeb": "बॉट बनाते समय @BotFather द्वारा दिया गया टोकन।",
+ "loginCodeTitleWeb": "लॉगिन कोड दर्ज करें",
+ "loginCodeLeadWeb": "Telegram ने आपके Telegram ऐप पर एक लॉगिन कोड भेजा है, या यदि आप कहीं और लॉग इन नहीं हैं तो SMS से।",
+ "loginPasswordTitleWeb": "टू-स्टेप वेरिफ़िकेशन",
+ "loginPasswordLeadWeb": "यह अकाउंट एक पासवर्ड से सुरक्षित है, जो Settings > Privacy and Security > Two-Step Verification में सेट किया गया है।",
+ "loginPasswordLabelWeb": "पासवर्ड",
+ "signupTitleWeb": "अपना अकाउंट बनाएँ",
+ "signupLeadWeb": "यह फ़ोन नंबर अभी Telegram पर नहीं है: नए अकाउंट का नाम चुनें।",
+ "webContinue": "जारी रखें",
+ "webLogin": "लॉगिन करें",
+ "webError": "%s। इसे जाँचें और फिर से प्रयास करें।",
+ "webStepApp": "API ID और hash",
+ "webStepAccount": "अकाउंट",
+ "webStepVerify": "वेरिफ़िकेशन",
+ "webStepDone": "चल रहा है",
+ "webProgress": "सेटअप की प्रगति",
+ "webDocs": "डॉक्यूमेंटेशन",
+ "webOptional": "वैकल्पिक",
+ "webShowPassword": "दिखाएँ",
+ "webHidePassword": "छिपाएँ",
+ "webQrTitle": "QR कोड से लॉगिन करें",
+ "webQrWaiting": "स्कैन की प्रतीक्षा की जा रही है…",
+ "webFieldRequired": "यह फ़ील्ड भरें।",
+ "webPhoneInvalid": "देश कोड के साथ फ़ोन नंबर दर्ज करें, जैसे +39 123 456 7890।",
+ "tweb.Login.Title": "MadelineProto में साइन इन करें",
+ "tweb.Login.PhoneLabelInvalid": "अमान्य फ़ोन नंबर",
+ "tweb.Login.StartText": "कृपया अपने देश कोड की पुष्टि करें\nऔर अपना फ़ोन नंबर दर्ज करें।",
+ "tweb.Login.Code.SentSms": "हमने आपको कोड के साथ\nएक SMS भेजा है।",
+ "tweb.Login.Code.SentInApp": "हमने आपको Telegram में कोड के साथ\nएक संदेश भेजा है।",
+ "tweb.Login.Code.SentCall": "हम आपको कॉल करके\nकोड बताएँगे।",
+ "tweb.Login.Code.SentEmail": "कृपया अपना ईमेल **%s** जाँचें (स्पैम फ़ोल्डर देखना न भूलें) और हमारे द्वारा अभी भेजा गया कोड दर्ज करें।",
+ "tweb.Login.Code.SentUnknown": "कृपया हर जगह कोड\nदेखें (प्रकार: %s)",
+ "tweb.Login.Code.SentMissedCall": "अगले कुछ सेकंड में आपको **%s** से\nएक छोटी कॉल आएगी। इसका जवाब न दें —\nबस उस नंबर के आख़िरी अंक दर्ज करें।",
+ "tweb.Login.Code.SentSmsWord": "हमने आपके फ़ोन **%s** पर\nएक गुप्त शब्द के साथ SMS भेजा है।",
+ "tweb.Login.Code.SentSmsWordBeginning": "हमने आपके फ़ोन **%1$s** पर एक गुप्त शब्द के साथ SMS भेजा है,\nजो \"**%2$s**\" से शुरू होता है।",
+ "tweb.Login.Code.SentSmsPhrase": "हमने आपके फ़ोन **%s** पर\nएक गुप्त वाक्यांश के साथ SMS भेजा है।",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "हमने आपके फ़ोन **%1$s** पर एक गुप्त वाक्यांश के साथ SMS भेजा है,\nजो \"**%2$s**\" से शुरू होता है।",
+ "tweb.Login.Code.SecretWord": "गुप्त शब्द",
+ "tweb.Login.Code.SecretPhrase": "गुप्त वाक्यांश",
+ "tweb.Login.Code.WordInvalid": "गलत है, कृपया फिर से प्रयास करें",
+ "tweb.Login.Code.WordBeginningInvalid": "गलत शब्द",
+ "tweb.Login.Password.Title": "अपना पासवर्ड दर्ज करें",
+ "tweb.Login.Password.Subtitle": "आपका अकाउंट एक अतिरिक्त पासवर्ड\nसे सुरक्षित है",
+ "tweb.Login.Register.Subtitle": "अपना अकाउंट बनाने के लिए\nअपना नाम दर्ज करें",
+ "tweb.PleaseWait": "कृपया प्रतीक्षा करें...",
+ "tweb.Code": "कोड",
+ "tweb.LoginPassword": "पासवर्ड",
+ "tweb.YourName": "आपका नाम",
+ "tweb.FirstName": "पहला नाम (आवश्यक)",
+ "tweb.LastName": "उपनाम (वैकल्पिक)",
+ "tweb.StartMessaging": "मैसेजिंग शुरू करें",
+ "tweb.Country": "देश",
+ "tweb.Contacts.PhoneNumber.Placeholder": "फ़ोन नंबर",
+ "tweb.Login.Next": "आगे",
+ "tweb.Login.QR.Title": "QR कोड से लॉगिन करें",
+ "tweb.Login.QR.Help1": "अपने फ़ोन पर Telegram खोलें",
+ "tweb.Login.QR.Help2": "**Settings** > **Devices** > **Add Device** पर जाएँ",
+ "tweb.Login.QR.Help3": "लॉगिन की पुष्टि करने के लिए अपने फ़ोन को इस स्क्रीन की ओर करें",
+ "tweb.Login.QR.Cancel": "फ़ोन नंबर से लॉगिन करें >",
+ "tweb.Login.QR.Login": "QR कोड से लॉगिन करें >",
+ "tweb.Login.QR.Subtitle": "अपने फ़ोन पर Telegram ऐप से स्कैन करें",
+ "tweb.PhoneNumber.Code.Fragment.Info": "[Fragment]() पर Numbers सेक्शन में कोड प्राप्त करें",
+ "tweb.PHONE_CODE_INVALID": "अमान्य कोड",
+ "tweb.PHONE_CODE_EXPIRED": "कोड की समय-सीमा समाप्त हो गई",
+ "tweb.PASSWORD_HASH_INVALID": "गलत पासवर्ड",
+ "tweb.DarkMode": "डार्क मोड",
+ "tweb.Error.AnError": "एक त्रुटि हुई। कृपया बाद में फिर से प्रयास करें।",
+ "tweb.AccDescr.LoginCode": "लॉगिन कोड",
+ "tweb.Login.Bot": "बॉट के रूप में लॉगिन करें >",
+ "tweb.Login.Bot.Title": "बॉट के रूप में लॉगिन करें",
+ "tweb.Login.Bot.Subtitle": "बॉट बनाते समय @BotFather द्वारा\nदिया गया टोकन दर्ज करें।",
+ "tweb.Login.Bot.Token": "बॉट टोकन",
+ "tweb.Login.Bot.Cancel": "यूज़र के रूप में लॉगिन करें >",
+ "tweb.Optional": "वैकल्पिक",
+ "tweb.PHONE_NUMBER_INVALID": "अमान्य फ़ोन नंबर",
+ "tweb.PHONE_NUMBER_BANNED": "यह फ़ोन नंबर प्रतिबंधित है",
+ "tweb.PHONE_NUMBER_FLOOD": "बहुत अधिक प्रयास, बाद में फिर से प्रयास करें",
+ "tweb.PHONE_CODE_EMPTY": "अमान्य कोड",
+ "tweb.PHONE_PASSWORD_FLOOD": "बहुत अधिक प्रयास, बाद में फिर से प्रयास करें",
+ "tweb.ACCESS_TOKEN_INVALID": "अमान्य बॉट टोकन",
+ "tweb.ACCESS_TOKEN_EXPIRED": "यह बॉट टोकन रद्द कर दिया गया है",
+ "tweb.FIRSTNAME_INVALID": "अमान्य पहला नाम",
+ "tweb.LASTNAME_INVALID": "अमान्य उपनाम",
+ "tweb.Close": "बंद करें"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/id.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/id.json
new file mode 100644
index 0000000..9a32ca1
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/id.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "Pembatasan basedir sedang dikonfigurasi: hal ini dapat memengaruhi kinerja dan menyebabkan beberapa masalah, harap nonaktifkan jika memungkinkan!",
+ "noReportPeers": "Peringatan: tidak ada peer pelaporan yang diatur, harap tambahkan metode berikut ke event handler Anda",
+ "manualAdminActionRequired": "!!!!!!!!! DIPERLUKAN TINDAKAN MANUAL DARI ADMIN SISTEM !!!!!!!!!",
+ "mmapErrorPart1": "Jumlah maksimum region memori yang dipetakan (mmap) telah tercapai (%s): harap naikkan konfigurasi kernel vm.max_map_count menjadi 262144 untuk memperbaikinya.",
+ "mmapErrorPart2": "Untuk memperbaikinya, jalankan perintah berikut sebagai root: %s",
+ "mmapErrorPart3": "Agar perubahan tetap berlaku setelah reboot: %s",
+ "mmapErrorPart4": "Di Windows dan WSL, memperbesar ukuran pagefile mungkin dapat membantu; harap beralih ke Linux native jika masalah berlanjut.",
+ "botAlreadyRunning": "Bot sudah berjalan!",
+ "extensionRequired": "MadelineProto memerlukan ekstensi %s untuk berjalan. %s",
+ "extensionRequiredInstallWithApt": "Coba jalankan sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Ikuti petunjuk di %s untuk memasangnya.",
+ "extensionRecommended": "Peringatan: ekstensi %s tidak terpasang, harap pasang untuk mempercepat MadelineProto!",
+ "go": "Lanjut",
+ "apiChooseManualAutoTip": "Perhatikan bahwa Anda juga dapat memberikan API ID/hash langsung di kode menggunakan pengaturan: %s",
+ "apiChooseManualAutoTipWeb": "Perhatikan bahwa Anda juga dapat memberikan API ID/hash langsung di kode menggunakan pengaturan.",
+ "apiChoosePrompt": "Pilihan Anda (m/a): ",
+ "apiManualInstructions0": "Login ke https://my.telegram.org",
+ "apiManualInstructions1": "Buka API development tools",
+ "apiManualInstructions2": "Klik create application",
+ "apiAppInstructionsManual0": "nama aplikasi Anda, bebas",
+ "apiAppInstructionsManual1": "nama pendek aplikasi Anda, alfanumerik, 5-32 karakter",
+ "apiAppInstructionsManual2": "URL aplikasi/situs web Anda, atau t.me/yourusername",
+ "apiAppInstructionsManual3": "bebas",
+ "apiAppInstructionsManual4": "Jelaskan aplikasi Anda di sini",
+ "apiManualWeb": "Masukkan API ID dan API hash Anda",
+ "apiManualPrompt0": "Masukkan API ID Anda: ",
+ "apiManualPrompt1": "Masukkan API hash Anda: ",
+ "apiAutoWeb": "Masukkan nomor telepon yang sudah terdaftar di Telegram untuk mendapatkan API ID",
+ "apiAutoPrompt0": "Masukkan nomor telepon yang sudah terdaftar di Telegram: ",
+ "apiAutoPrompt1": "Masukkan kode verifikasi yang Anda terima di Telegram: ",
+ "apiAppWeb": "Masukkan informasi API",
+ "apiAppInstructionsAuto0": "Masukkan nama aplikasi, bebas: ",
+ "apiAppInstructionsAuto1": "Masukkan nama pendek aplikasi, alfanumerik, 5-32 karakter: ",
+ "apiAppInstructionsAuto2": "Masukkan URL aplikasi/situs web, atau t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Masukkan platform aplikasi: ",
+ "apiAppInstructionsAuto4": "Jelaskan aplikasi Anda: ",
+ "apiAppInstructionsAutoTypeOther": "Lainnya (jelaskan di deskripsi)",
+ "apiParamsError": "Anda tidak memberikan semua parameter yang diperlukan!",
+ "apiError": "KESALAHAN: %s. Silakan coba lagi.",
+ "loginChoosePromptWeb": "Apakah Anda ingin login sebagai pengguna atau sebagai bot?",
+ "loginWebQr": "Anda juga dapat login secara otomatis dengan membuka Telegram di ponsel Anda, masuk ke Pengaturan > Perangkat > Tautkan Perangkat Desktop, lalu memindai kode QR berikut:",
+ "loginWebQr1": "Buka Telegram di ponsel Anda",
+ "loginWebQr2": "Masuk ke Pengaturan > Perangkat > Tautkan Perangkat Desktop",
+ "loginWebQr3": "Arahkan ponsel Anda ke layar ini untuk mengonfirmasi login",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Pengguna",
+ "loginBot": "Masukkan token bot Anda: ",
+ "loginUser": "Masukkan nomor telepon Anda: ",
+ "loginQr": "Buka Telegram di ponsel Anda, masuk ke Pengaturan > Perangkat > Tautkan Perangkat Desktop, lalu pindai kode QR di atas untuk login secara otomatis.",
+ "loginQrCodeSuccessful": "Login dengan kode QR berhasil!",
+ "loginQrCodeExpired": "Kode QR kedaluwarsa, membuat kode baru...",
+ "loginManual": "Atau, Anda juga dapat memasukkan token bot atau nomor telepon untuk login secara manual: ",
+ "loginUserCode": "Masukkan kode: ",
+ "loginUserPass": "Masukkan kata sandi Anda (petunjuk %s): ",
+ "loginUserPassWeb": "Masukkan kata sandi Anda: ",
+ "loginUserPassHint": "Petunjuk: %s",
+ "signupFirstName": "Masukkan nama depan Anda: ",
+ "signupLastName": "Masukkan nama belakang Anda (boleh kosong): ",
+ "signupWeb": "Silakan mendaftar",
+ "signupFirstNameWeb": "Nama depan",
+ "signupLastNameWeb": "Nama belakang",
+ "loginNoCode": "Anda tidak memberikan kode telepon!",
+ "loginNoPass": "Anda tidak memberikan kata sandi!",
+ "loginNoName": "Anda tidak memberikan nama depan!",
+ "loginBotTokenWeb": "Token bot",
+ "loginUserPhoneWeb": "Nomor telepon",
+ "loginUserPhoneCodeWeb": "Kode",
+ "done": "Selesai!",
+ "nearest_dc": "Kami berada di %s, DC terdekat adalah %d.",
+ "serialization_ofd": "Serialisasi sudah usang, merekonstruksi objek!",
+ "api_not_set": "Anda harus memberikan api key dan api id, dapatkan milik Anda sendiri di my.telegram.org",
+ "session_corrupted": "Sesi rusak!",
+ "value_bigger_than_2147483647": "Nilai yang diberikan %s lebih besar dari 2147483647",
+ "value_smaller_than_2147483648": "Nilai yang diberikan %s lebih kecil dari -2147483648",
+ "value_bigger_than_9223372036854775807": "Nilai yang diberikan %s lebih besar dari 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "Nilai yang diberikan %s lebih kecil dari -9223372036854775808",
+ "value_bigger_than_4294967296": "Nilai yang diberikan %s lebih besar dari 4294967296",
+ "value_smaller_than_0": "Nilai yang diberikan %s lebih kecil dari 0",
+ "encode_double_error": "Tidak dapat mengenkode double dengan benar",
+ "file_not_exist": "File tidak ada",
+ "deserialization_error": "Terjadi kesalahan saat deserialisasi",
+ "rpc_tg_error": "Telegram mengembalikan galat RPC: %s (%s), disebabkan oleh %s:%s%sJejak TL:",
+ "madelineproto_ready": "MadelineProto siap!",
+ "logout_ok": "Berhasil logout!",
+ "already_loggedIn": "Instance MadelineProto ini sudah login!",
+ "login_ok": "Berhasil login!",
+ "login_user": "Login sebagai pengguna biasa...",
+ "login_bot": "Login sebagai bot...",
+ "login_code_sending": "Mengirim kode...",
+ "login_code_sent": "Kode berhasil dikirim! Setelah menerima kode, Anda harus menggunakan fungsi completePhoneLogin.",
+ "login_code_uncalled": "Saya tidak sedang menunggu kode! Harap panggil metode phoneLogin terlebih dahulu",
+ "login_2fa_enabled": "2FA aktif, Anda harus memanggil fungsi complete2falogin...",
+ "login_need_signup": "Belum ada akun yang dibuat untuk nomor ini, Anda harus memanggil fungsi completeSignup...",
+ "login_auth_key": "Login menggunakan auth key...",
+ "not_loggedIn": "Saya belum login!",
+ "signup_uncalled": "Saya tidak sedang menunggu pendaftaran! Harap panggil metode phoneLogin dan completePhoneLogin terlebih dahulu!",
+ "signing_up": "Mendaftar sebagai pengguna biasa...",
+ "signup_ok": "Berhasil mendaftar!",
+ "2fa_uncalled": "Saya tidak sedang menunggu kata sandi! Harap panggil metode phoneLogin dan completePhoneLogin terlebih dahulu!",
+ "peer_not_in_db": "Peer ini tidak ada di database peer internal",
+ "call_error_1": "Tidak dapat menemukan dan menerima panggilan %s",
+ "accepting_call": "Menerima panggilan dari %s...",
+ "call_already_accepted": "Panggilan %s sudah diterima",
+ "call_already_declined": "Panggilan %s sudah ditolak",
+ "call_error_2": "Tidak dapat menemukan dan mengonfirmasi panggilan %s",
+ "call_confirming": "Mengonfirmasi panggilan dari %s...",
+ "call_error_3": "Tidak dapat menemukan dan menyelesaikan panggilan %s",
+ "call_completing": "Menyelesaikan panggilan dari %s...",
+ "fingerprint_invalid": "Fingerprint kunci tidak valid!",
+ "call_discarding": "Mengakhiri panggilan %s...",
+ "file_parsing": "Mem-parsing %s...",
+ "src_file_invalid": "File sumber yang diberikan tidak valid: ",
+ "bool_error": "Tidak dapat mengekstrak boolean",
+ "not_numeric": "Nilai yang diberikan bukan numerik",
+ "long_not_16": "Panjang nilai yang diberikan bukan 16 byte",
+ "long_not_32": "Panjang nilai yang diberikan bukan 32 byte",
+ "long_not_64": "Panjang nilai yang diberikan bukan 64 byte",
+ "array_invalid": "Anda tidak memberikan array yang valid",
+ "predicate_not_set": "Predicate (nilai di bawah _) tidak diatur!",
+ "update_madelineproto": "Anda menjalankan versi lama MadelineProto, pembaruan diperlukan: versi saat ini %s, sedangkan versi terbaru dengan banyak perbaikan bug dan fitur baru adalah %s!",
+ "type_extract_error": "Tidak dapat mengekstrak tipe \"%s\", Anda harus memperbarui MadelineProto!",
+ "method_not_found": "Tidak dapat menemukan metode: ",
+ "params_missing": "Parameter wajib tidak ada",
+ "sec_peer_not_in_db": "Peer rahasia ini tidak ada di database peer internal",
+ "stream_handle_invalid": "Stream handle yang diberikan tidak valid.",
+ "length_too_big": "Panjang terlalu besar",
+ "string_required": "Diharapkan sebuah string!",
+ "waveform_must_have_100_values": "Array waveform harus memiliki 100 nilai!",
+ "waveform_value": "Nilai waveform harus antara 0 dan 31!",
+ "could_not_convert_object": "Tidak dapat mengonversi objek bertipe %s",
+ "type_extract_error_id": "Tidak dapat mengekstrak tipe: %s dengan id %s, Anda harus memperbarui MadelineProto!",
+ "constructor_not_found": "Constructor tidak ditemukan untuk tipe: ",
+ "botapi_conversion_error": "Tidak dapat mengonversi %s menjadi objek bot API",
+ "non_text_conversion": "Belum dapat mengonversi pesan non-teks!",
+ "file_type_invalid": "Terdeteksi tipe file tidak valid (%s)",
+ "static_analysis_minor": "Ditemukan masalah kecil saat analisis statis %s: %s",
+ "static_analysis_severe": "Ditemukan masalah serius saat analisis statis %s: %s",
+ "secret_chat_skipping": "Saya tidak memiliki obrolan rahasia %s di database, melewati pesan...",
+ "must_have_declare_types": "demi alasan kinerja, pernyataan pertama dari file event handler harus \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "file MadelineProto.log tidak boleh dihapus, sebagai gantinya atur ukuran maksimum kustom di pengaturan!",
+ "do_not_remove_MadelineProto.log_phar": "Jangan hapus madeline.phar atau madeline.php, karena MadelineProto akan crash. Jika Anda mengalami masalah dengan MadelineProto, laporkan ke https://github.com/danog/MadelineProto atau https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "demi alasan kinerja, event handler tidak boleh menggunakan fungsi blocking non-async %s, sebagai gantinya gunakan %s",
+ "do_not_use_blocking_class": "demi alasan kinerja, handler tidak boleh menggunakan kelas blocking non-async %s, sebagai gantinya gunakan %s",
+ "do_not_use_deprecated_function": "fungsi %s sudah usang (deprecated), sebagai gantinya gunakan %s",
+ "do_not_use_non_root_require_in_event_handler": "demi alasan kinerja, Anda tidak boleh menggunakan require atau include di dalam kelas event handler, hanya require di level root yang diizinkan.",
+ "do_not_use_yield": "MadelineProto 8 tidak memerlukan maupun mendukung penggunaan yield dalam fungsi async, Anda harus menghapus semua kata kunci yield yang sebelumnya digunakan untuk pemanggilan fungsi async",
+ "recommend_not_use_filesystem_function": "penggunaan fungsi %s tidak disarankan, karena mengakses filesystem saat menangani update akan memperlambat bot Anda, silakan lihat https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions untuk daftar cara alternatif menyimpan data yang tidak akan memperlambat bot Anda!",
+ "plugins_do_not_use_require": "demi alasan kinerja, plugin hanya dapat meng-include atau me-require file lain yang ada di folder plugins secara otomatis dengan memicu autoloader PSR-4 (bukan dengan require() secara manual).",
+ "plugins_must_have_exactly_one_class": "sebuah plugin harus mendefinisikan tepat satu kelas! Untuk mendefinisikan beberapa kelas, interface, atau trait, buat file terpisah, file-file tersebut akan dimuat otomatis oleh MadelineProto.",
+ "cli_need_dl.php_link": "Harap tentukan URL skrip unduhan saat menggunakan getDownloadLink melalui CLI!",
+ "invalid_dl.php_session": "%s bukan skrip unduhan yang valid karena ID sesinya berbeda (diharapkan %s, didapat %s)",
+ "need_dl.php": "Tidak dapat membuat skrip unduhan default (%s), harap buat file dl.php dengan konten berikut: %s dan berikan URL-nya ke parameter kedua getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Server unduhan file Telegram (hingga 4GB), diberdayakan oleh MadelineProto!
Klik di sini untuk info lebih lanjut tentang cara menyiapkan server unduhan file Telegram Anda sendiri!",
+ "dl.php_check_logs_make_sure_session_running": "Bot EventHandler MadelineProto terkait atau server IPC MadelineProto sedang offline, harap periksa log dan pastikan setidaknya salah satunya berjalan!",
+ "account_banned": "!!!!!!! PERINGATAN !!!!!!!\nSistem pencegahan flood Telegram telah menangguhkan akun ini.\nUntuk melanjutkan, diperlukan verifikasi manual.\nKirim email ke recover@telegram.org, minta agar blokir nomor telepon %s dibuka, dan jelaskan secara singkat apa yang akan Anda lakukan dengan nomor telepon ini.\nKemudian login kembali.\nJika Anda sengaja menghapus akun ini, abaikan pesan ini.",
+ "plugin_path_does_not_exist": "Path plugin %s tidak ada!",
+ "could_not_connect_to_MadelineProto": "Tidak dapat terhubung ke MadelineProto, harap aktifkan proc_open dan hapus pembatasan open_basedir atau nonaktifkan path rewrite webserver untuk memperbaikinya! Jika Anda sudah melakukannya, pastikan versi CLI PHP sama persis dengan versi web (versi, ekstensi, dan lain-lain yang sama) dan periksa file MadelineProto.log untuk info lebih lanjut tentang kesalahan yang mencegah server IPC berjalan.",
+ "translate_madelineproto_web": "MadelineProto dapat diterjemahkan ke bahasa Anda (progres terjemahan saat ini: %d%%), klik di sini untuk berkontribusi pada terjemahan!",
+ "translate_madelineproto_cli": "MadelineProto dapat diterjemahkan ke bahasa Anda (progres terjemahan saat ini: %d%%), kunjungi https://github.com/danog/MadelineProto/tree/v8/langs untuk berkontribusi pada terjemahan!",
+ "apiInvalidWeb": "API ID berupa angka, dan API hash terdiri dari 32 karakter: salin kembali keduanya dari my.telegram.org.",
+ "webDoneLead": "MadelineProto tetap berjalan di server: Anda dapat menutup halaman ini.",
+ "apiChooseManualAuto": "Apakah Anda ingin mendapatkan API ID dan hash secara otomatis dari my.telegram.org (a), atau memasukkannya secara manual (m)?",
+ "apiAutoFallbackManual": "Sebagai gantinya, masukkan API ID dan hash secara manual.",
+ "apiSetupTitleWeb": "Dapatkan API ID dan hash Anda",
+ "apiSetupLeadWeb": "Setiap aplikasi Telegram memerlukan API ID dan hash. MadelineProto dapat mengambilnya untuk Anda dari my.telegram.org, menggunakan nomor telepon akun Telegram yang sudah ada.",
+ "apiAutoPhoneHintWeb": "my.telegram.org mengirimkan kode login ke aplikasi Telegram Anda, bukan melalui SMS.",
+ "apiSendCodeWeb": "Kirim kode",
+ "apiChooseManualWeb": "Saya sudah punya API ID",
+ "apiChooseAutoWeb": "Dapatkan secara otomatis",
+ "apiStartOverWeb": "Mulai dari awal",
+ "apiAutoCodeTitleWeb": "Masukkan kode dari Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org telah mengirimkan kode login ke aplikasi Telegram Anda, di obrolan dengan Telegram (bukan melalui SMS).",
+ "apiAutoCodeLabelWeb": "Kode login",
+ "apiCreateTitleWeb": "Buat aplikasi Anda",
+ "apiCreateLeadWeb": "Akun ini belum memiliki aplikasi di my.telegram.org. Detail ini hanya ditampilkan kepada Anda, dan dapat diubah nanti.",
+ "apiAppTitleLabelWeb": "Nama aplikasi",
+ "apiAppShortNameLabelWeb": "Nama pendek",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Deskripsi",
+ "apiCreateWeb": "Buat aplikasi",
+ "apiSaveWeb": "Simpan dan lanjutkan",
+ "apiAutoErrorTitle": "my.telegram.org mengembalikan kesalahan",
+ "apiCreateErrorTitle": "my.telegram.org tidak membuat aplikasi",
+ "apiCreateVpsWarning": "Telegram tidak mengizinkan rentang IP VPS, VPN, dan pusat data lainnya membuat aplikasi baru di my.telegram.org, dan permintaan ini dibuat dari IP mesin yang menjalankan MadelineProto. Buat aplikasi secara manual di https://my.telegram.org dari koneksi rumahan (misalnya ponsel Anda dengan data seluler), lalu masukkan API ID dan hash.",
+ "loginTitleWeb": "Login ke Telegram",
+ "loginLeadWeb": "Pilih akun atau bot yang akan digunakan untuk menjalankan instance MadelineProto ini.",
+ "loginTypeWeb": "Login sebagai",
+ "loginUserPhoneHintWeb": "Dengan kode negara, misalnya +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Token yang diberikan @BotFather saat Anda membuat bot.",
+ "loginCodeTitleWeb": "Masukkan kode login",
+ "loginCodeLeadWeb": "Telegram telah mengirimkan kode login ke aplikasi Telegram Anda, atau melalui SMS jika Anda tidak login di tempat lain.",
+ "loginPasswordTitleWeb": "Verifikasi dua langkah",
+ "loginPasswordLeadWeb": "Akun ini dilindungi kata sandi, yang diatur di Pengaturan > Privasi dan Keamanan > Verifikasi Dua Langkah.",
+ "loginPasswordLabelWeb": "Kata sandi",
+ "signupTitleWeb": "Buat akun Anda",
+ "signupLeadWeb": "Nomor telepon ini belum terdaftar di Telegram: pilih nama untuk akun baru.",
+ "webContinue": "Lanjutkan",
+ "webLogin": "Login",
+ "webError": "%s. Periksa dan coba lagi.",
+ "webStepApp": "API ID dan hash",
+ "webStepAccount": "Akun",
+ "webStepVerify": "Verifikasi",
+ "webStepDone": "Berjalan",
+ "webProgress": "Progres penyiapan",
+ "webDocs": "Dokumentasi",
+ "webOptional": "opsional",
+ "webShowPassword": "Tampilkan",
+ "webHidePassword": "Sembunyikan",
+ "webQrTitle": "Login dengan kode QR",
+ "webQrWaiting": "Menunggu pemindaian…",
+ "webFieldRequired": "Isi kolom ini.",
+ "webPhoneInvalid": "Masukkan nomor telepon beserta kode negaranya, misalnya +39 123 456 7890.",
+ "tweb.Login.Title": "Login ke MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Nomor telepon tidak valid",
+ "tweb.Login.StartText": "Silakan konfirmasi kode negara Anda\ndan masukkan nomor telepon Anda.",
+ "tweb.Login.Code.SentSms": "Kami telah mengirimkan SMS\nberisi kode kepada Anda.",
+ "tweb.Login.Code.SentInApp": "Kami telah mengirimkan pesan di Telegram\nberisi kode kepada Anda.",
+ "tweb.Login.Code.SentCall": "Kami akan menelepon Anda dan\nmenyebutkan kodenya.",
+ "tweb.Login.Code.SentEmail": "Silakan periksa email Anda **%s** (jangan lupa folder spam) dan masukkan kode yang baru saja kami kirimkan.",
+ "tweb.Login.Code.SentUnknown": "Silakan periksa semuanya\nuntuk menemukan kode (tipe: %s)",
+ "tweb.Login.Code.SentMissedCall": "Dalam beberapa detik, Anda akan menerima\npanggilan singkat dari **%s**. Jangan dijawab —\ncukup masukkan digit terakhir dari nomor tersebut.",
+ "tweb.Login.Code.SentSmsWord": "Kami telah mengirimkan SMS berisi kata rahasia\nke ponsel Anda **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Kami telah mengirimkan SMS berisi kata rahasia yang diawali\ndengan \"**%2$s**\" ke ponsel Anda **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Kami telah mengirimkan SMS berisi frasa rahasia\nke ponsel Anda **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Kami telah mengirimkan SMS berisi frasa rahasia yang diawali\ndengan \"**%2$s**\" ke ponsel Anda **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Kata rahasia",
+ "tweb.Login.Code.SecretPhrase": "Frasa rahasia",
+ "tweb.Login.Code.WordInvalid": "Salah, silakan coba lagi",
+ "tweb.Login.Code.WordBeginningInvalid": "Kata salah",
+ "tweb.Login.Password.Title": "Masukkan kata sandi Anda",
+ "tweb.Login.Password.Subtitle": "Akun Anda dilindungi dengan\nkata sandi tambahan",
+ "tweb.Login.Register.Subtitle": "Masukkan nama Anda\nuntuk membuat akun",
+ "tweb.PleaseWait": "Mohon tunggu...",
+ "tweb.Code": "Kode",
+ "tweb.LoginPassword": "Kata sandi",
+ "tweb.YourName": "Nama Anda",
+ "tweb.FirstName": "Nama depan (wajib)",
+ "tweb.LastName": "Nama belakang (opsional)",
+ "tweb.StartMessaging": "Mulai Berkirim Pesan",
+ "tweb.Country": "Negara",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Nomor telepon",
+ "tweb.Login.Next": "Berikutnya",
+ "tweb.Login.QR.Title": "Login dengan kode QR",
+ "tweb.Login.QR.Help1": "Buka Telegram di ponsel Anda",
+ "tweb.Login.QR.Help2": "Masuk ke **Pengaturan** > **Perangkat** > **Tambah Perangkat**",
+ "tweb.Login.QR.Help3": "Arahkan ponsel Anda ke layar ini untuk mengonfirmasi login",
+ "tweb.Login.QR.Cancel": "Login dengan nomor telepon >",
+ "tweb.Login.QR.Login": "Login dengan kode QR >",
+ "tweb.Login.QR.Subtitle": "Pindai dengan aplikasi Telegram di ponsel Anda",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Dapatkan kode di bagian Numbers di [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Kode tidak valid",
+ "tweb.PHONE_CODE_EXPIRED": "Kode kedaluwarsa",
+ "tweb.PASSWORD_HASH_INVALID": "Kata sandi salah",
+ "tweb.DarkMode": "Mode Gelap",
+ "tweb.Error.AnError": "Terjadi kesalahan. Silakan coba lagi nanti.",
+ "tweb.AccDescr.LoginCode": "Kode login",
+ "tweb.Login.Bot": "Login sebagai bot >",
+ "tweb.Login.Bot.Title": "Login sebagai bot",
+ "tweb.Login.Bot.Subtitle": "Masukkan token yang diberikan @BotFather\nsaat Anda membuat bot.",
+ "tweb.Login.Bot.Token": "Token bot",
+ "tweb.Login.Bot.Cancel": "Login sebagai pengguna >",
+ "tweb.Optional": "opsional",
+ "tweb.PHONE_NUMBER_INVALID": "Nomor telepon tidak valid",
+ "tweb.PHONE_NUMBER_BANNED": "Nomor telepon ini diblokir",
+ "tweb.PHONE_NUMBER_FLOOD": "Terlalu banyak percobaan, coba lagi nanti",
+ "tweb.PHONE_CODE_EMPTY": "Kode tidak valid",
+ "tweb.PHONE_PASSWORD_FLOOD": "Terlalu banyak percobaan, coba lagi nanti",
+ "tweb.ACCESS_TOKEN_INVALID": "Token bot tidak valid",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Token bot ini telah dicabut",
+ "tweb.FIRSTNAME_INVALID": "Nama depan tidak valid",
+ "tweb.LASTNAME_INVALID": "Nama belakang tidak valid",
+ "tweb.Close": "Tutup"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/it.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/it.json
index 8da2889..1baffe2 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/it.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/it.json
@@ -1,4 +1,72 @@
{
+ "baseDirLimitation": "È presente una limitazione basedir: questo può impattare negativamente sulle performance e causare vari problemi, si prega di disabilitare le limitazioni basedir se possibile!",
+ "noReportPeers": "Attenzione: non è stato impostato alcun peer per la segnalazione errori, per favore aggiungi il seguente metodo all'event handler",
+ "manualAdminActionRequired": "!!!!!!!!! È NECESSARIO L'INTERVENTO DELL'AMMINISTRATORE DI SISTEMA !!!!!!!!!",
+ "mmapErrorPart1": "È stato raggiunto il limite massimo di regioni di memoria mappate (mmap, %s): è necessario incrementare il parametro di configurazione del kernel vm.max_map_count a 262144 per correggere l'errore.",
+ "mmapErrorPart2": "Per correggere l'errore, avviare il seguente comando come root: %s",
+ "mmapErrorPart3": "Per correggere l'errore in modo permanente, anche dopo un riavvio: %s",
+ "mmapErrorPart4": "Su Windows e WSL, potrebbe aiutare l'incremento della dimensione del file di paginazione; passare a Linux nativo se il problema persiste.",
+ "botAlreadyRunning": "Il bot è già in esecuzione!",
+ "extensionRequired": "MadelineProto richiede l'estensione %s. %s",
+ "extensionRequiredInstallWithApt": "Provate ad avviare sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Seguire le istruzioni su %s per installarla.",
+ "extensionRecommended": "Attenzione: l'estensione %s non è installata, si prega di installarla per velocizzare MadelineProto!",
+ "go": "Vai",
+ "apiChooseManualAutoTip": "Nota che puoi anche fornire i parametri API direttamente nelle impostazioni: %s",
+ "apiChooseManualAutoTipWeb": "Nota che puoi anche fornire i parametri API direttamente nelle impostazioni.",
+ "apiChoosePrompt": "La tua scelta (m/a): ",
+ "apiManualInstructions0": "Effettua il login su https://my.telegram.org",
+ "apiManualInstructions1": "Vai su API development tools",
+ "apiManualInstructions2": "Clicca su create application",
+ "apiAppInstructionsManual0": "titolo dell'app, può essere qualsiasi cosa",
+ "apiAppInstructionsManual1": "il nome ridotto dell'app, caratteri alfanumerici",
+ "apiAppInstructionsManual2": "L'indirizzo del tuo sito, oppure t.me/username",
+ "apiAppInstructionsManual3": "Qualsiasi",
+ "apiAppInstructionsManual4": "Descrivi la tua app",
+ "apiManualWeb": "Inserisci il tuo API ID e API hash",
+ "apiManualPrompt0": "Inserisci il tuo API ID: ",
+ "apiManualPrompt1": "Inserisci il tuo API hash: ",
+ "apiAutoWeb": "Inserisci un numero di telefono già registrato su Telegram per ottenere l'API ID",
+ "apiAutoPrompt0": "Inserisci un numero di telefono che è già registrato su Telegram: ",
+ "apiAutoPrompt1": "Inserisci il codice di verifica che hai ricevuto su Telegram: ",
+ "apiAppWeb": "Inserire informazioni API",
+ "apiAppInstructionsAuto0": "Inserisci il nome dell'app, può essere qualsiasi cosa: ",
+ "apiAppInstructionsAuto1": "Inserisci il nome ridotto dell'app, caratteri alfanumerici: ",
+ "apiAppInstructionsAuto2": "Inserisci il sito internet dell'app, oppure t.me/username: ",
+ "apiAppInstructionsAuto3": "Inserisci la piattaforma dell'app: ",
+ "apiAppInstructionsAuto4": "Descrivi la tua app: ",
+ "apiAppInstructionsAutoTypeOther": "Altro (specificare nella descrizione)",
+ "apiParamsError": "Non hai fornito tutti i parametri richiesti!",
+ "apiError": "ERRORE: %s. Prova ancora.",
+ "loginChoosePromptWeb": "Vuoi effettuare il login come utente o come bot?",
+ "loginWebQr": "Puoi anche effettuare il login automaticamente aprendo Telegram sul telefono, andando in Impostazioni > Dispositivi > Collega dispositivo desktop e scansionando il seguente codice QR:",
+ "loginWebQr1": "Apri Telegram sul tuo telefono",
+ "loginWebQr2": "Vai su Impostazioni > Dispositivi > Collega dispositivo desktop",
+ "loginWebQr3": "Inquadra il codice sullo schermo per completare il login",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Utente",
+ "loginBot": "Inserisci il tuo bot token: ",
+ "loginUser": "Inserisci il tuo numero di telefono: ",
+ "loginQr": "Apri Telegram sul tuo telefono, vai in Impostazioni > Dispositivi > Collega dispositivo desktop e scansiona il codice QR per fare il login automaticamente.",
+ "loginQrCodeSuccessful": "Il login con codice QR è stato effettuato correttamente!",
+ "loginQrCodeExpired": "Il codice QR è scaduto, generazione di un nuovo codice QR in corso...",
+ "loginManual": "In alternativa, puoi inserire un bot token o un numero di telefono per effettuare il login manualmente: ",
+ "loginUserCode": "Inserisci il codice di verifica: ",
+ "loginUserPass": "Inserisci la tua password (suggerimento %s): ",
+ "loginUserPassWeb": "Inserisci la tua password: ",
+ "loginUserPassHint": "Suggerimento: %s",
+ "signupFirstName": "Inserisci il tuo nome: ",
+ "signupLastName": "Inserisci il tuo cognome: ",
+ "signupWeb": "Registrazione",
+ "signupFirstNameWeb": "Nome",
+ "signupLastNameWeb": "Cognome",
+ "loginNoCode": "Non hai fornito un codice di verifica!",
+ "loginNoPass": "Non hai fornito la password!",
+ "loginNoName": "Non hai fornito un nome!",
+ "loginBotTokenWeb": "Token del bot",
+ "loginUserPhoneWeb": "Numero di telefono",
+ "loginUserPhoneCodeWeb": "Codice di verifica",
+ "done": "Fatto!",
"nearest_dc": "Siamo in %s, il DC più vicino è %d.",
"serialization_ofd": "La serializzazione non è aggiornata, reistanziamento dell'oggetto in corso!",
"api_not_set": "Devi specificare una chiave ed un ID API, ottienili su https://my.telegram.org",
@@ -50,113 +118,157 @@
"long_not_64": "Il valore fornito non è lungo 64 byte",
"array_invalid": "Il valore fornito non è un array",
"predicate_not_set": "Il predicato (valore sotto chiave _, esempio ['_' => 'inputPeer']) non è impostato!",
+ "update_madelineproto": "Stai usando una vecchia versione di MadelineProto, è necessario un aggiornamento: la versione che stai usando adesso è %s, ma l'ultima versione con tutti gli ultimi bugfix e tante nuove funzionalità è %s!",
"type_extract_error": "Impossibile estrarre il tipo \"%s\", dovresti aggiornare MadelineProto!",
"method_not_found": "Impossibile trovare il seguente metodo: ",
"params_missing": "Non hai fornito un parametro obbligatorio, rileggi la documentazione API",
"sec_peer_not_in_db": "La chat segreta non è presente nel database interno MadelineProto",
"stream_handle_invalid": "Il valore fornito non è uno stream.",
"length_too_big": "Il valore fornito è troppo lungo",
+ "string_required": "È richiesta una stringa!",
+ "waveform_must_have_100_values": "Una forma d'onda deve essere un array contenente 100 valori!",
+ "waveform_value": "Un singolo valore di una forma d'onda deve essere compreso tra 0 e 31!",
+ "could_not_convert_object": "Non è stato possibile convertire l'oggetto di tipo %s",
"type_extract_error_id": "Non sono riuscito ad estrarre il tipo %s con ID %s, dovresti aggiornare MadelineProto!",
"constructor_not_found": "Costruttore non trovato per tipo: ",
"botapi_conversion_error": "Non sono risucito a convertire %s in un oggetto bot API",
"non_text_conversion": "Non posso ancora convertire messaggi media!",
- "file_type_invalid": "È stato fornito un tipo file errato",
+ "file_type_invalid": "È stato rilevato un tipo di file non valido (%s)",
+ "static_analysis_minor": "È stato riscontrato un problema minore durante l'analisi statica di %s: %s",
+ "static_analysis_severe": "È stato riscontrato un problema grave durante l'analisi statica di %s: %s",
"secret_chat_skipping": "Non ho la chat segreta %s nel database, ignorando messaggio...",
- "done": "Fatto!",
- "apiAppInstructionsAuto0": "Inserisci il nome dell'app, può essere qualsiasi cosa: ",
- "apiAppInstructionsAuto1": "Inserisci il nome ridotto dell'app, caratteri alfanumerici: ",
- "apiAppInstructionsAuto2": "Inserisci il sito internet dell'app, oppure t.me/username: ",
- "apiAppInstructionsAuto3": "Inserisci la piattaforma dell'app: ",
- "apiAppInstructionsAuto4": "Descrivi la tua app: ",
- "apiAppInstructionsManual0": "titolo dell'app, può essere qualsiasi cosa",
- "apiAppInstructionsManual1": "il nome ridotto dell'app, caratteri alfanumerici",
- "apiAppInstructionsManual2": "L'indirizzo del tuo sito, oppure t.me/username",
- "apiAppInstructionsManual3": "Qualsiasi",
- "apiAppInstructionsManual4": "Descrivi la tua app",
- "apiAutoPrompt0": "Inserisci un numero di telefono che è già registrato su Telegram: ",
- "apiAutoPrompt1": "Inserisci il codice di verifica che hai ricevuto su Telegram: ",
- "apiChooseManualAutoTip": "Nota che puoi anche fornire i parametri API direttamente nelle impostazioni: %s",
- "apiChoosePrompt": "La tua scelta (m/a): ",
- "apiError": "ERRORE: %s. Prova ancora.",
- "apiManualInstructions0": "Effettua il login su https://my.telegram.org",
- "apiManualInstructions1": "Vai su API development tools",
- "apiManualInstructions2": "Clicca su create application",
- "apiManualPrompt0": "Inserisci il tuo API ID: ",
- "apiManualPrompt1": "Inserisci il tuo API hash: ",
- "apiParamsError": "Non hai fornito tutti i parametri richiesti!",
- "loginBot": "Inserisci il tuo bot token: ",
- "loginQr": "Apri Telegram sul tuo telefono, vai in Impostazioni > Dispositivi > Collega dispositivo desktop e scansiona il codice QR per fare il login automaticamente.",
- "loginManual": "In alternativa, puoi inserire un bot token o un numero di telefono per effettuare il login manualmente: ",
- "loginNoCode": "Non hai fornito un codice di verifica!",
- "loginNoName": "Non hai fornito un nome!",
- "loginNoPass": "Non hai fornito la password!",
- "loginUser": "Inserisci il tuo numero di telefono: ",
- "loginUserPass": "Inserisci la tua password (suggerimento %s): ",
- "loginUserPassHint": "Suggerimento: %s",
- "loginUserPassWeb": "Inserisci la tua password: ",
- "loginUserCode": "Inserisci il codice di verifica: ",
- "signupFirstName": "Inserisci il tuo nome: ",
- "signupFirstNameWeb": "Nome",
- "signupLastName": "Inserisci il tuo cognome: ",
- "signupLastNameWeb": "Cognome",
- "signupWeb": "Registrazione",
- "go": "Vai",
- "loginChoosePromptWeb": "Vuoi effettuare il login come utente o come bot?",
- "loginWebQr": "Puoi anche effettuare il login automaticamente aprendo Telegram sul telefono, andando in Impostazioni > Dispositivi > Collega dispositivo desktop e scansionando il seguente codice QR:",
- "loginWebQr1": "Apri Telegram sul tuo telefono",
- "loginWebQr2": "Vai su Impostazioni > Dispositivi > Collega dispositivo desktop",
- "loginWebQr3": "Inquadra il codice sullo schermo per completare il login",
- "loginOptionBot": "Bot",
- "loginOptionUser": "Utente",
- "loginBotTokenWeb": "Token del bot",
- "loginUserPhoneCodeWeb": "Codice di verifica",
- "loginUserPhoneWeb": "Numero di telefono",
- "apiAutoWeb": "Inserisci un numero di telefono già registrato su Telegram per ottenere l'API ID",
- "apiManualWeb": "Inserisci il tuo API ID e API hash",
- "apiAppInstructionsAutoTypeOther": "Altro (specificare nella descrizione)",
- "apiAppWeb": "Inserire informazioni API",
- "apiChooseManualAutoTipWeb": "Nota che puoi anche fornire i parametri API direttamente nelle impostazioni.",
- "loginQrCodeSuccessful": "Il login con codice QR è stato effettuato correttamente!",
- "loginQrCodeExpired": "Il codice QR è scaduto, generazione di un nuovo codice QR in corso...",
- "noReportPeers": "Attenzione: non è stato impostato alcun peer per la segnalazione errori, per favore aggiungi il seguente metodo all'event handler",
- "manualAdminActionRequired": "!!!!!!!!! È NECESSARIO L'INTERVENTO DELL'AMMINISTRATORE DI SISTEMA !!!!!!!!!",
- "mmapErrorPart2": "Per correggere l'errore, avviare il seguente comando come root: %s",
- "mmapErrorPart3": "Per correggere l'errore in modo permanente, anche dopo un riavvio: %s",
- "mmapErrorPart4": "Su Windows e WSL, potrebbe aiutare l'incremento della dimensione del file di paginazione; passare a Linux nativo se il problema persiste.",
- "extensionRequired": "MadelineProto richiede l'estensione %s. %s",
- "extensionRequiredInstallWithApt": "Provate ad avviare sudo apt-get install %s.",
- "extensionRequiredInstallWithCustomInstructions": "Seguire le istruzioni su %s per installarla.",
- "extensionRecommended": "Attenzione: l'estensione %s non è installata, si prega di installarla per velocizzare MadelineProto!",
- "mmapErrorPart1": "È stato raggiunto il limite massimo di regioni di memoria mappate (mmap, %s): è necessario incrementare il parametro di configurazione del kernel vm.max_map_count a 262144 per correggere l'errore.",
- "botAlreadyRunning": "Il bot è già in esecuzione!",
+ "must_have_declare_types": "per motivi di performance, la prima riga del file contenente l'event handler deve essere uguale a \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "il file MadelineProto.log non deve essere mai eliminato, per favore imposta una dimensione massima nelle impostazioni invece di eliminarlo!",
"do_not_remove_MadelineProto.log_phar": "Per favore non rimuovere madeline.phar o madeline.php, o MadelineProto crasherà. Se hai problemi con MadelineProto, segnalali su https://github.com/danog/MadelineProto o https://t.me/pwrtelegramgroup",
"do_not_use_blocking_function": "per motivi di performance, gli event handler non possono usare la funzione bloccante non asincrona %s, per favore usa %s",
- "do_not_use_deprecated_function": "la funzione %s è deprecata, per favore usa %s",
- "recommend_not_use_filesystem_function": "l'uso della funzione %s non è racommandato, perché l'accesso al filesystem durante la gestione degli update rallenterà il bot, si prega di leggere https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions per una lista di modi alternativi per memorizzare informazioni in modi che non rallenteranno il tuo bot!",
"do_not_use_blocking_class": "per motivi di performance, gli event handler non possono usare la classe bloccante non-asincrona %s, per favore usa %s",
- "must_have_declare_types": "per motivi di performance, la prima riga del file contenente l'event handler deve essere uguale a \"declare(strict_types=1);\"",
- "do_not_delete_MadelineProto.log": "il file MadelineProto.log non deve essere mai eliminato, per favore imposta una dimensione massima nelle impostazioni invece di eliminarlo!",
+ "do_not_use_deprecated_function": "la funzione %s è deprecata, per favore usa %s",
"do_not_use_non_root_require_in_event_handler": "per motivi di performance, non è possibile usare require o include dentro l'event handler, è possibile includere file solo all'esterno della classe.",
- "static_analysis_minor": "È stato riscontrato un problema minore durante l'analisi statica di %s: %s",
- "static_analysis_severe": "È stato riscontrato un problema grave durante l'analisi statica di %s: %s",
- "plugins_must_have_exactly_one_class": "un plugin deve definire esattamente una classe! Per definire più classi, interfacce o trait, si prega di creare file separati, che verranno caricati da MadelineProto automaticamente.",
+ "do_not_use_yield": "MadelineProto 8 non richede e non supporta l'uso della parola chiave yield in funzioni asincrono, è necessario rimuovere tutte gli yield usati in precedenza per chiamate a funzioni asincrone",
+ "recommend_not_use_filesystem_function": "l'uso della funzione %s non è racommandato, perché l'accesso al filesystem durante la gestione degli update rallenterà il bot, si prega di leggere https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions per una lista di modi alternativi per memorizzare informazioni in modi che non rallenteranno il tuo bot!",
"plugins_do_not_use_require": "per motivi di performance, i plugin possono solo includere altri file presenti nella cartella plugins usando il meccanismo di autocaricamento PSR-4 (non usando require o include).",
+ "plugins_must_have_exactly_one_class": "un plugin deve definire esattamente una classe! Per definire più classi, interfacce o trait, si prega di creare file separati, che verranno caricati da MadelineProto automaticamente.",
"cli_need_dl.php_link": "È necessario specificare l'URL dello script di scaricamente per usare getDownloadLink via CLI!",
+ "invalid_dl.php_session": "%s non è uno script di scaricamento valido perché l'ID della sessione non è corretto (mi aspettavo %s, ho ricevuto %s)",
"need_dl.php": "Impossibile generare lo script di scaricamento di default (%s), è necessario creare un file dl.php con il seguente contenuto: %s e passare il suo URL al secondo parametro di getDownloadLink",
"dl.php_powered_by_madelineproto": "Server di scaricamento file Telegram (fino a 4GB), creato usando MadelineProto!
Clicca qui per configurare il tuo personale server di scaricamento file Telegram!",
- "invalid_dl.php_session": "%s non è uno script di scaricamento valido perché l'ID della sessione non è corretto (mi aspettavo %s, ho ricevuto %s)",
+ "dl.php_check_logs_make_sure_session_running": "Sia l'event handler associato al bot che il server IPC della sessione sono offline, controllare i log e assicurarsi che almeno uno dei due sia online!",
"account_banned": "!!!!!!! ATTENZIONE !!!!!!!\nIl sistema antispam di telegram ha sospeso questo account.\nPer continuare, è richiesta una verifica manuale.\nMandare un'email in inglese a recover@telegram.org, chiedendo di sbannare il numero di telefono %s, spiegando brevemente cosa si ha intenzione di fare con l'account.\nPoi rieseguite nuovamente il login.\nIgnorare questo messaggio se la sessione è stata resettata intenzionalmente.",
"plugin_path_does_not_exist": "La cartella dei plugin %s non esiste!",
- "string_required": "È richiesta una stringa!",
- "waveform_must_have_100_values": "Una forma d'onda deve essere un array contenente 100 valori!",
- "waveform_value": "Un singolo valore di una forma d'onda deve essere compreso tra 0 e 31!",
- "could_not_convert_object": "Non è stato possibile convertire l'oggetto di tipo %s",
- "dl.php_check_logs_make_sure_session_running": "Sia l'event handler associato al bot che il server IPC della sessione sono offline, controllare i log e assicurarsi che almeno uno dei due sia online!",
- "update_madelineproto": "Stai usando una vecchia versione di MadelineProto, è necessario un aggiornamento: la versione che stai usando adesso è %s, ma l'ultima versione con tutti gli ultimi bugfix e tante nuove funzionalità è %s!",
- "do_not_use_yield": "MadelineProto 8 non richede e non supporta l'uso della parola chiave yield in funzioni asincrono, è necessario rimuovere tutte gli yield usati in precedenza per chiamate a funzioni asincrone",
- "translate_madelineproto_web": "MadelineProto può essere tradotto nella tua lingua (stato attuale della traduzione: %d%%), cliccate qui per contribuire alla traduzione!",
- "translate_madelineproto_cli": "MadelineProto può essere tradotto nella tua lingua (stato attuale della traduzione: %d%%), vai su https://weblate.madelineproto.xyz per contribuire alla traduzione!",
- "windows_warning": "Per utenti Windows: per favore passate a Linux se questo passaggio fallisce. Per continuare ad usare Windows, potrebbe essere necessario modificare le impostazioni del firewall per permettere a tutti i processi PHP di creare socket (100% è più facile passare a Linux, su Linux MadelineProto funziona direttamente senza alcuna modifica richiesta)",
"could_not_connect_to_MadelineProto": "Non è stato possibile collegarsi a MadelineProto, per favore abilitare la funzione proc_open e rimuovere ogni limitazione open_basedir o disabilitare le rewrite lato server per fixare! Se l'avete già fatto, assicuratevi che la versione PHP CLI è la stessa versione di PHP web (apache/php-fpm) (stessa versione, estensioni, eccetera) e controllate il file MadelineProto.log per più informazioni sull'errore che ha impedito l'avvio del server IPC.",
- "baseDirLimitation": "È presente una limitazione basedir: questo può impattare negativamente sulle performance e causare vari problemi, si prega di disabilitare le limitazioni basedir se possibile!"
+ "translate_madelineproto_web": "MadelineProto può essere tradotto nella tua lingua (stato attuale della traduzione: %d%%), cliccate qui per contribuire alla traduzione!",
+ "translate_madelineproto_cli": "MadelineProto può essere tradotto nella tua lingua (stato attuale della traduzione: %d%%), vai su https://github.com/danog/MadelineProto/tree/v8/langs per contribuire alla traduzione!",
+ "apiInvalidWeb": "L'API ID è un numero e l'API hash è lungo 32 caratteri: copiali di nuovo da my.telegram.org.",
+ "webDoneLead": "MadelineProto continua a funzionare sul server: puoi chiudere questa pagina.",
+ "apiChooseManualAuto": "Vuoi ottenere API ID e hash automaticamente da my.telegram.org (a) o inserirli manualmente (m)?",
+ "apiAutoFallbackManual": "Inserisci invece API ID e hash manualmente.",
+ "apiSetupTitleWeb": "Ottieni API ID e hash",
+ "apiSetupLeadWeb": "Ogni app Telegram ha bisogno di un API ID e di un hash. MadelineProto può ottenerli per te da my.telegram.org, usando il numero di telefono di un account Telegram già esistente.",
+ "apiAutoPhoneHintWeb": "my.telegram.org invia il codice di accesso alla tua app Telegram, non via SMS.",
+ "apiSendCodeWeb": "Invia codice",
+ "apiChooseManualWeb": "Ho già un API ID",
+ "apiChooseAutoWeb": "Ottienili automaticamente",
+ "apiStartOverWeb": "Ricomincia",
+ "apiAutoCodeTitleWeb": "Inserisci il codice ricevuto su Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org ha inviato un codice di accesso alla tua app Telegram, nella chat con Telegram (non via SMS).",
+ "apiAutoCodeLabelWeb": "Codice di accesso",
+ "apiCreateTitleWeb": "Crea la tua app",
+ "apiCreateLeadWeb": "Questo account non ha ancora un'app su my.telegram.org. Questi dati sono visibili solo a te e potrai modificarli in seguito.",
+ "apiAppTitleLabelWeb": "Titolo dell'app",
+ "apiAppShortNameLabelWeb": "Nome breve",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Descrizione",
+ "apiCreateWeb": "Crea app",
+ "apiSaveWeb": "Salva e continua",
+ "apiAutoErrorTitle": "my.telegram.org ha restituito un errore",
+ "apiCreateErrorTitle": "my.telegram.org non ha creato l'app",
+ "apiCreateVpsWarning": "Telegram non permette di creare nuove app su my.telegram.org da indirizzi IP di VPS, VPN e altri datacenter, e la richiesta è partita dall'IP della macchina su cui gira MadelineProto. Crea l'app manualmente su https://my.telegram.org da una connessione domestica (ad esempio dal telefono con i dati mobili), poi inserisci API ID e hash.",
+ "loginTitleWeb": "Accedi a Telegram",
+ "loginLeadWeb": "Scegli l'account o il bot con cui funzionerà questa istanza di MadelineProto.",
+ "loginTypeWeb": "Accedi come",
+ "loginUserPhoneHintWeb": "Con il prefisso internazionale, ad esempio +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Il token che ti ha dato @BotFather quando hai creato il bot.",
+ "loginCodeTitleWeb": "Inserisci il codice di accesso",
+ "loginCodeLeadWeb": "Telegram ha inviato un codice di accesso alla tua app Telegram, oppure via SMS se non hai effettuato l'accesso da nessun'altra parte.",
+ "loginPasswordTitleWeb": "Verifica in due passaggi",
+ "loginPasswordLeadWeb": "Questo account è protetto da una password, impostata in Impostazioni > Privacy e sicurezza > Verifica in due passaggi.",
+ "loginPasswordLabelWeb": "Password",
+ "signupTitleWeb": "Crea il tuo account",
+ "signupLeadWeb": "Questo numero di telefono non è ancora su Telegram: scegli il nome del nuovo account.",
+ "webContinue": "Continua",
+ "webLogin": "Accedi",
+ "webError": "%s. Controlla e riprova.",
+ "webStepApp": "API ID e hash",
+ "webStepAccount": "Account",
+ "webStepVerify": "Verifica",
+ "webStepDone": "In esecuzione",
+ "webProgress": "Avanzamento della configurazione",
+ "webDocs": "Documentazione",
+ "webOptional": "facoltativo",
+ "webShowPassword": "Mostra",
+ "webHidePassword": "Nascondi",
+ "webQrTitle": "Accedi con un codice QR",
+ "webQrWaiting": "In attesa della scansione…",
+ "webFieldRequired": "Compila questo campo.",
+ "webPhoneInvalid": "Inserisci il numero di telefono con il prefisso internazionale, ad esempio +39 123 456 7890.",
+ "tweb.Login.Title": "Accedi a MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Numero di telefono non valido",
+ "tweb.Login.StartText": "Conferma il prefisso del tuo paese\ne inserisci il tuo numero di telefono.",
+ "tweb.Login.Code.SentSms": "Ti abbiamo inviato un SMS\ncon il codice.",
+ "tweb.Login.Code.SentInApp": "Ti abbiamo inviato un messaggio su Telegram\ncon il codice.",
+ "tweb.Login.Code.SentCall": "Ti chiameremo per dettarti\nil codice.",
+ "tweb.Login.Code.SentEmail": "Controlla la tua email **%s** (non dimenticare la cartella spam) e inserisci il codice che ti abbiamo appena inviato.",
+ "tweb.Login.Code.SentUnknown": "Cerca un codice\novunque (tipo: %s)",
+ "tweb.Login.Code.SentMissedCall": "Entro pochi secondi riceverai\nuna breve chiamata da **%s**. Non rispondere:\ninserisci solo le ultime cifre di quel numero.",
+ "tweb.Login.Code.SentSmsWord": "Abbiamo inviato un SMS con una parola segreta\nal tuo numero **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Abbiamo inviato un SMS con una parola segreta che inizia\ncon \"**%2$s**\" al tuo numero **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Abbiamo inviato un SMS con una frase segreta\nal tuo numero **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Abbiamo inviato un SMS con una frase segreta che inizia\ncon \"**%2$s**\" al tuo numero **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Parola segreta",
+ "tweb.Login.Code.SecretPhrase": "Frase segreta",
+ "tweb.Login.Code.WordInvalid": "Non corretta, riprova",
+ "tweb.Login.Code.WordBeginningInvalid": "Parola non corretta",
+ "tweb.Login.Password.Title": "Inserisci la tua password",
+ "tweb.Login.Password.Subtitle": "Il tuo account è protetto\nda una password aggiuntiva",
+ "tweb.Login.Register.Subtitle": "Inserisci il tuo nome\nper creare il tuo account",
+ "tweb.PleaseWait": "Attendi...",
+ "tweb.Code": "Codice",
+ "tweb.LoginPassword": "Password",
+ "tweb.YourName": "Il tuo nome",
+ "tweb.FirstName": "Nome (obbligatorio)",
+ "tweb.LastName": "Cognome (facoltativo)",
+ "tweb.StartMessaging": "Inizia a messaggiare",
+ "tweb.Country": "Paese",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Numero di telefono",
+ "tweb.Login.Next": "Avanti",
+ "tweb.Login.QR.Title": "Accedi con codice QR",
+ "tweb.Login.QR.Help1": "Apri Telegram sul tuo telefono",
+ "tweb.Login.QR.Help2": "Vai su **Impostazioni** > **Dispositivi** > **Aggiungi dispositivo**",
+ "tweb.Login.QR.Help3": "Inquadra questo schermo con il telefono per confermare l'accesso",
+ "tweb.Login.QR.Cancel": "Accedi con il numero di telefono >",
+ "tweb.Login.QR.Login": "Accedi con codice QR >",
+ "tweb.Login.QR.Subtitle": "Scansiona con l'app Telegram sul tuo telefono",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Ottieni il codice nella sezione Numbers su [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Codice non valido",
+ "tweb.PHONE_CODE_EXPIRED": "Codice scaduto",
+ "tweb.PASSWORD_HASH_INVALID": "Password errata",
+ "tweb.DarkMode": "Modalità scura",
+ "tweb.Error.AnError": "Si è verificato un errore. Riprova più tardi.",
+ "tweb.AccDescr.LoginCode": "Codice di accesso",
+ "tweb.Login.Bot": "Accedi come bot >",
+ "tweb.Login.Bot.Title": "Accedi come bot",
+ "tweb.Login.Bot.Subtitle": "Inserisci il token che ti ha dato @BotFather\nquando hai creato il bot.",
+ "tweb.Login.Bot.Token": "Token del bot",
+ "tweb.Login.Bot.Cancel": "Accedi come utente >",
+ "tweb.Optional": "facoltativo",
+ "tweb.PHONE_NUMBER_INVALID": "Numero di telefono non valido",
+ "tweb.PHONE_NUMBER_BANNED": "Questo numero di telefono è stato bannato",
+ "tweb.PHONE_NUMBER_FLOOD": "Troppi tentativi, riprova più tardi",
+ "tweb.PHONE_CODE_EMPTY": "Codice non valido",
+ "tweb.PHONE_PASSWORD_FLOOD": "Troppi tentativi, riprova più tardi",
+ "tweb.ACCESS_TOKEN_INVALID": "Token del bot non valido",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Questo token del bot è stato revocato",
+ "tweb.FIRSTNAME_INVALID": "Nome non valido",
+ "tweb.LASTNAME_INVALID": "Cognome non valido",
+ "tweb.Close": "Chiudi"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ja.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ja.json
new file mode 100644
index 0000000..317d457
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ja.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "basedir 制限が設定されています。パフォーマンスに影響し、問題の原因になる可能性があるため、可能であれば無効にしてください。",
+ "noReportPeers": "警告: レポート先のピアが設定されていません。イベントハンドラーに次のメソッドを追加してください",
+ "manualAdminActionRequired": "!!!!!!!!! システム管理者による手動対応が必要です !!!!!!!!!",
+ "mmapErrorPart1": "メモリマップ (mmap) 領域の最大数に達しました (%s)。修正するには、カーネル設定 vm.max_map_count を 262144 に増やしてください。",
+ "mmapErrorPart2": "修正するには、root として次のコマンドを実行してください: %s",
+ "mmapErrorPart3": "再起動後も変更を維持するには: %s",
+ "mmapErrorPart4": "Windows および WSL では、ページファイルのサイズを増やすと改善する場合があります。問題が解決しない場合は、ネイティブの Linux に切り替えてください。",
+ "botAlreadyRunning": "ボットはすでに実行中です!",
+ "extensionRequired": "MadelineProto の実行には %s 拡張機能が必要です。%s",
+ "extensionRequiredInstallWithApt": "sudo apt-get install %s を実行してみてください。",
+ "extensionRequiredInstallWithCustomInstructions": "%s の手順に従ってインストールしてください。",
+ "extensionRecommended": "警告: %s 拡張機能がインストールされていません。MadelineProto を高速化するためにインストールしてください!",
+ "go": "実行",
+ "apiChooseManualAutoTip": "API ID/hash は、設定を使ってコード内で直接指定することもできます: %s",
+ "apiChooseManualAutoTipWeb": "API ID/hash は、設定を使ってコード内で直接指定することもできます。",
+ "apiChoosePrompt": "選択してください (m/a): ",
+ "apiManualInstructions0": "https://my.telegram.org にログインします",
+ "apiManualInstructions1": "API development tools に移動します",
+ "apiManualInstructions2": "create application をクリックします",
+ "apiAppInstructionsManual0": "アプリの名前 (任意)",
+ "apiAppInstructionsManual1": "アプリの短い名前 (英数字、5〜32 文字)",
+ "apiAppInstructionsManual2": "アプリ/ウェブサイトの URL、または t.me/yourusername",
+ "apiAppInstructionsManual3": "任意",
+ "apiAppInstructionsManual4": "ここにアプリの説明を入力します",
+ "apiManualWeb": "API ID と API hash を入力してください",
+ "apiManualPrompt0": "API ID を入力してください: ",
+ "apiManualPrompt1": "API hash を入力してください: ",
+ "apiAutoWeb": "API ID を取得するには、Telegram に登録済みの電話番号を入力してください",
+ "apiAutoPrompt0": "Telegram に登録済みの電話番号を入力してください: ",
+ "apiAutoPrompt1": "Telegram で受け取った認証コードを入力してください: ",
+ "apiAppWeb": "API 情報を入力してください",
+ "apiAppInstructionsAuto0": "アプリの名前を入力してください (任意): ",
+ "apiAppInstructionsAuto1": "アプリの短い名前を入力してください (英数字、5〜32 文字): ",
+ "apiAppInstructionsAuto2": "アプリ/ウェブサイトの URL、または t.me/yourusername を入力してください: ",
+ "apiAppInstructionsAuto3": "アプリのプラットフォームを入力してください: ",
+ "apiAppInstructionsAuto4": "アプリの説明を入力してください: ",
+ "apiAppInstructionsAutoTypeOther": "その他 (説明欄に記入)",
+ "apiParamsError": "必須パラメーターがすべて指定されていません!",
+ "apiError": "エラー: %s。もう一度お試しください。",
+ "loginChoosePromptWeb": "ユーザーとボットのどちらでログインしますか?",
+ "loginWebQr": "スマートフォンで Telegram を開き、[設定] > [デバイス] > [デスクトップ端末をリンク] に進んで次の QR コードをスキャンすると、自動でログインすることもできます:",
+ "loginWebQr1": "スマートフォンで Telegram を開きます",
+ "loginWebQr2": "[設定] > [デバイス] > [デスクトップ端末をリンク] に進みます",
+ "loginWebQr3": "スマートフォンをこの画面に向けてログインを確認します",
+ "loginOptionBot": "ボット",
+ "loginOptionUser": "ユーザー",
+ "loginBot": "ボットトークンを入力してください: ",
+ "loginUser": "電話番号を入力してください: ",
+ "loginQr": "スマートフォンで Telegram を開き、[設定] > [デバイス] > [デスクトップ端末をリンク] に進んで上の QR コードをスキャンすると、自動でログインできます。",
+ "loginQrCodeSuccessful": "QR コードでのログインに成功しました!",
+ "loginQrCodeExpired": "QR コードの有効期限が切れました。新しいコードを生成しています...",
+ "loginManual": "または、ボットトークンか電話番号を入力して手動でログインすることもできます: ",
+ "loginUserCode": "コードを入力してください: ",
+ "loginUserPass": "パスワードを入力してください (ヒント: %s): ",
+ "loginUserPassWeb": "パスワードを入力してください: ",
+ "loginUserPassHint": "ヒント: %s",
+ "signupFirstName": "名を入力してください: ",
+ "signupLastName": "姓を入力してください (空欄可): ",
+ "signupWeb": "アカウントを登録してください",
+ "signupFirstNameWeb": "名",
+ "signupLastNameWeb": "姓",
+ "loginNoCode": "電話認証コードが入力されていません!",
+ "loginNoPass": "パスワードが入力されていません!",
+ "loginNoName": "名が入力されていません!",
+ "loginBotTokenWeb": "ボットトークン",
+ "loginUserPhoneWeb": "電話番号",
+ "loginUserPhoneCodeWeb": "コード",
+ "done": "完了しました!",
+ "nearest_dc": "現在地は %s、最寄りの DC は %d です。",
+ "serialization_ofd": "シリアライズ形式が古いため、オブジェクトを再構築しています!",
+ "api_not_set": "API キーと API ID を指定する必要があります。my.telegram.org で取得してください",
+ "session_corrupted": "セッションが破損しています!",
+ "value_bigger_than_2147483647": "指定された値 %s が 2147483647 より大きいです",
+ "value_smaller_than_2147483648": "指定された値 %s が -2147483648 より小さいです",
+ "value_bigger_than_9223372036854775807": "指定された値 %s が 9223372036854775807 より大きいです",
+ "value_smaller_than_9223372036854775808": "指定された値 %s が -9223372036854775808 より小さいです",
+ "value_bigger_than_4294967296": "指定された値 %s が 4294967296 より大きいです",
+ "value_smaller_than_0": "指定された値 %s が 0 より小さいです",
+ "encode_double_error": "double を正しくエンコードできませんでした",
+ "file_not_exist": "ファイルが存在しません",
+ "deserialization_error": "デシリアライズ中にエラーが発生しました",
+ "rpc_tg_error": "Telegram が RPC エラーを返しました: %s (%s)、発生箇所 %s:%s%sTL トレース:",
+ "madelineproto_ready": "MadelineProto の準備ができました!",
+ "logout_ok": "ログアウトしました!",
+ "already_loggedIn": "この MadelineProto インスタンスはすでにログインしています!",
+ "login_ok": "ログインしました!",
+ "login_user": "通常のユーザーとしてログインしています...",
+ "login_bot": "ボットとしてログインしています...",
+ "login_code_sending": "コードを送信しています...",
+ "login_code_sent": "コードを送信しました!コードを受け取ったら completePhoneLogin 関数を使用してください。",
+ "login_code_uncalled": "コードを待機していません!先に phoneLogin メソッドを呼び出してください",
+ "login_2fa_enabled": "2 段階認証が有効になっています。complete2falogin 関数を呼び出す必要があります...",
+ "login_need_signup": "この番号のアカウントはまだ作成されていません。completeSignup 関数を呼び出す必要があります...",
+ "login_auth_key": "認証キーを使用してログインしています...",
+ "not_loggedIn": "ログインしていません!",
+ "signup_uncalled": "登録を待機していません!先に phoneLogin と completePhoneLogin メソッドを呼び出してください!",
+ "signing_up": "通常のユーザーとして登録しています...",
+ "signup_ok": "登録しました!",
+ "2fa_uncalled": "パスワードを待機していません!先に phoneLogin と completePhoneLogin メソッドを呼び出してください!",
+ "peer_not_in_db": "このピアは内部のピアデータベースに存在しません",
+ "call_error_1": "通話 %s が見つからず、応答できませんでした",
+ "accepting_call": "%s からの通話に応答しています...",
+ "call_already_accepted": "通話 %s はすでに応答済みです",
+ "call_already_declined": "通話 %s はすでに拒否されています",
+ "call_error_2": "通話 %s が見つからず、確認できませんでした",
+ "call_confirming": "%s からの通話を確認しています...",
+ "call_error_3": "通話 %s が見つからず、完了できませんでした",
+ "call_completing": "%s からの通話を完了しています...",
+ "fingerprint_invalid": "キーのフィンガープリントが無効です!",
+ "call_discarding": "通話 %s を破棄しています...",
+ "file_parsing": "%s を解析しています...",
+ "src_file_invalid": "無効なソースファイルが指定されました: ",
+ "bool_error": "ブール値を抽出できませんでした",
+ "not_numeric": "指定された値は数値ではありません",
+ "long_not_16": "指定された値の長さが 16 バイトではありません",
+ "long_not_32": "指定された値の長さが 32 バイトではありません",
+ "long_not_64": "指定された値の長さが 64 バイトではありません",
+ "array_invalid": "有効な配列が指定されていません",
+ "predicate_not_set": "述語 (_ の値) が設定されていません!",
+ "update_madelineproto": "古いバージョンの MadelineProto を実行しているため、アップデートが必要です。現在のバージョンは %s ですが、多数のバグ修正と新機能を含む最新バージョンは %s です!",
+ "type_extract_error": "型 \"%s\" を抽出できませんでした。MadelineProto をアップデートしてください!",
+ "method_not_found": "メソッドが見つかりませんでした: ",
+ "params_missing": "必須パラメーターがありません",
+ "sec_peer_not_in_db": "このシークレットピアは内部のピアデータベースに存在しません",
+ "stream_handle_invalid": "無効なストリームハンドルが指定されました。",
+ "length_too_big": "長さが大きすぎます",
+ "string_required": "文字列が必要です!",
+ "waveform_must_have_100_values": "波形の配列には 100 個の値が必要です!",
+ "waveform_value": "波形の値は 0 から 31 の範囲でなければなりません!",
+ "could_not_convert_object": "型 %s のオブジェクトを変換できませんでした",
+ "type_extract_error_id": "型 %s (ID %s) を抽出できませんでした。MadelineProto をアップデートしてください!",
+ "constructor_not_found": "次の型のコンストラクターが見つかりません: ",
+ "botapi_conversion_error": "%s を Bot API オブジェクトに変換できません",
+ "non_text_conversion": "テキスト以外のメッセージはまだ変換できません!",
+ "file_type_invalid": "無効なファイル形式が検出されました (%s)",
+ "static_analysis_minor": "%s の静的解析中に軽微な問題が見つかりました: %s",
+ "static_analysis_severe": "%s の静的解析中に重大な問題が見つかりました: %s",
+ "secret_chat_skipping": "シークレットチャット %s がデータベースにないため、メッセージをスキップします...",
+ "must_have_declare_types": "パフォーマンス上の理由から、イベントハンドラーファイルの最初の文は \"declare(strict_types=1);\" でなければなりません",
+ "do_not_delete_MadelineProto.log": "MadelineProto.log ファイルは絶対に削除しないでください。代わりに、設定でカスタムの最大サイズを指定してください!",
+ "do_not_remove_MadelineProto.log_phar": "madeline.phar や madeline.php を削除しないでください。削除すると MadelineProto がクラッシュします。MadelineProto で問題が発生した場合は、https://github.com/danog/MadelineProto または https://t.me/pwrtelegramgroup に報告してください",
+ "do_not_use_blocking_function": "パフォーマンス上の理由から、イベントハンドラーでは非同期でないブロッキング関数 %s を使用できません。代わりに %s を使用してください",
+ "do_not_use_blocking_class": "パフォーマンス上の理由から、ハンドラーでは非同期でないブロッキングクラス %s を使用できません。代わりに %s を使用してください",
+ "do_not_use_deprecated_function": "%s 関数は非推奨です。代わりに %s を使用してください",
+ "do_not_use_non_root_require_in_event_handler": "パフォーマンス上の理由から、イベントハンドラークラスの内部で require や include を使用してはいけません。ルートレベルの require のみ使用できます。",
+ "do_not_use_yield": "MadelineProto 8 では非同期関数での yield の使用は不要で、サポートもされていません。非同期関数の呼び出しに使用していた yield キーワードをすべて削除してください",
+ "recommend_not_use_filesystem_function": "%s 関数の使用は推奨されません。アップデートの処理中にファイルシステムにアクセスするとボットが遅くなるためです。ボットを遅くしないデータの保存方法については https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions を参照してください!",
+ "plugins_do_not_use_require": "パフォーマンス上の理由から、プラグインが plugins フォルダー内の他のファイルを読み込めるのは、PSR-4 オートローダーによる自動的な include/require のみです (手動で require() することはできません)。",
+ "plugins_must_have_exactly_one_class": "プラグインはクラスを 1 つだけ定義する必要があります!複数のクラス、インターフェイス、トレイトを定義するには別々のファイルを作成してください。MadelineProto が自動的にオートロードします。",
+ "cli_need_dl.php_link": "CLI から getDownloadLink を使用する場合は、ダウンロードスクリプトの URL を指定してください!",
+ "invalid_dl.php_session": "%s はセッション ID が異なるため、有効なダウンロードスクリプトではありません (想定: %s、実際: %s)",
+ "need_dl.php": "デフォルトのダウンロードスクリプトを生成できませんでした (%s)。次の内容で dl.php ファイルを作成し: %s その URL を getDownloadLink の第 2 引数に渡してください",
+ "dl.php_powered_by_madelineproto": "Telegram ファイルダウンロードサーバー (最大 4GB)、powered by MadelineProto!
独自の Telegram ファイルダウンロードサーバーを構築する方法の詳細はこちらをクリックしてください!",
+ "dl.php_check_logs_make_sure_session_running": "関連付けられた MadelineProto EventHandler ボットか MadelineProto IPC サーバーのいずれかがオフラインです。ログを確認し、少なくとも一方が実行中であることを確認してください!",
+ "account_banned": "!!!!!!! 警告 !!!!!!!\nTelegram のフラッド防止システムによって、このアカウントは停止されました。\n続行するには手動での認証が必要です。\nrecover@telegram.org にメールを送り、電話番号 %s の停止解除を依頼するとともに、この電話番号で何をするのかを簡単に説明してください。\nその後、もう一度ログインしてください。\nこのアカウントを意図的に削除した場合は、このメッセージを無視してください。",
+ "plugin_path_does_not_exist": "プラグインのパス %s が存在しません!",
+ "could_not_connect_to_MadelineProto": "MadelineProto に接続できませんでした。修正するには、proc_open を有効にして open_basedir の制限を解除するか、Web サーバーのパス書き換えを無効にしてください!すでに対応済みの場合は、CLI 版の PHP が Web 版とまったく同じ (バージョン、拡張機能など) であることを確認し、IPC サーバーの起動を妨げたエラーの詳細について MadelineProto.log ファイルを確認してください。",
+ "translate_madelineproto_web": "MadelineProto はあなたの言語に翻訳できます (現在の翻訳進捗: %d%%)。こちらをクリックして翻訳に協力してください!",
+ "translate_madelineproto_cli": "MadelineProto はあなたの言語に翻訳できます (現在の翻訳進捗: %d%%)。翻訳に協力するには https://github.com/danog/MadelineProto/tree/v8/langs にアクセスしてください!",
+ "apiInvalidWeb": "API ID は数字で、API hash は 32 文字です。my.telegram.org からもう一度コピーしてください。",
+ "webDoneLead": "MadelineProto はサーバー上で実行を続けています。このページは閉じてもかまいません。",
+ "apiChooseManualAuto": "API ID と hash を my.telegram.org から自動で取得しますか (a)、それとも手動で入力しますか (m)?",
+ "apiAutoFallbackManual": "代わりに API ID と hash を手動で入力してください。",
+ "apiSetupTitleWeb": "API ID と hash を取得",
+ "apiSetupLeadWeb": "すべての Telegram アプリには API ID と hash が必要です。既存の Telegram アカウントの電話番号を使って、MadelineProto が my.telegram.org から取得できます。",
+ "apiAutoPhoneHintWeb": "my.telegram.org はログインコードを SMS ではなく Telegram アプリに送信します。",
+ "apiSendCodeWeb": "コードを送信",
+ "apiChooseManualWeb": "API ID を持っています",
+ "apiChooseAutoWeb": "自動で取得する",
+ "apiStartOverWeb": "最初からやり直す",
+ "apiAutoCodeTitleWeb": "Telegram で受け取ったコードを入力",
+ "apiAutoCodeLeadWeb": "my.telegram.org が Telegram アプリの「Telegram」とのチャットにログインコードを送信しました (SMS ではありません)。",
+ "apiAutoCodeLabelWeb": "ログインコード",
+ "apiCreateTitleWeb": "アプリを作成",
+ "apiCreateLeadWeb": "このアカウントには my.telegram.org のアプリがまだありません。以下の情報はあなたにのみ表示され、後から変更できます。",
+ "apiAppTitleLabelWeb": "アプリ名",
+ "apiAppShortNameLabelWeb": "短い名前",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "説明",
+ "apiCreateWeb": "アプリを作成",
+ "apiSaveWeb": "保存して続行",
+ "apiAutoErrorTitle": "my.telegram.org がエラーを返しました",
+ "apiCreateErrorTitle": "my.telegram.org でアプリを作成できませんでした",
+ "apiCreateVpsWarning": "Telegram では、VPS、VPN などのデータセンターの IP 範囲から my.telegram.org で新しいアプリを作成することはできません。このリクエストは MadelineProto を実行しているマシンの IP から送信されました。家庭用回線 (モバイルデータ通信中のスマートフォンなど) から https://my.telegram.org で手動でアプリを作成し、API ID と hash を入力してください。",
+ "loginTitleWeb": "Telegram にログイン",
+ "loginLeadWeb": "この MadelineProto インスタンスで使用するアカウントまたはボットを選択してください。",
+ "loginTypeWeb": "ログインの種類",
+ "loginUserPhoneHintWeb": "国番号を含めて入力してください (例: +39 123 456 7890)。",
+ "loginBotTokenHintWeb": "ボットの作成時に @BotFather から受け取ったトークンです。",
+ "loginCodeTitleWeb": "ログインコードを入力",
+ "loginCodeLeadWeb": "Telegram がログインコードを Telegram アプリに送信しました。他の端末でログインしていない場合は SMS で送信されます。",
+ "loginPasswordTitleWeb": "2 段階認証",
+ "loginPasswordLeadWeb": "このアカウントは、[設定] > [プライバシーとセキュリティ] > [2 段階認証] で設定されたパスワードで保護されています。",
+ "loginPasswordLabelWeb": "パスワード",
+ "signupTitleWeb": "アカウントを作成",
+ "signupLeadWeb": "この電話番号はまだ Telegram に登録されていません。新しいアカウントの名前を入力してください。",
+ "webContinue": "続行",
+ "webLogin": "ログイン",
+ "webError": "%s。確認してもう一度お試しください。",
+ "webStepApp": "API ID と hash",
+ "webStepAccount": "アカウント",
+ "webStepVerify": "認証",
+ "webStepDone": "実行中",
+ "webProgress": "セットアップの進捗",
+ "webDocs": "ドキュメント",
+ "webOptional": "任意",
+ "webShowPassword": "表示",
+ "webHidePassword": "非表示",
+ "webQrTitle": "QR コードでログイン",
+ "webQrWaiting": "スキャンを待っています…",
+ "webFieldRequired": "この項目を入力してください。",
+ "webPhoneInvalid": "国番号を含めて電話番号を入力してください (例: +39 123 456 7890)。",
+ "tweb.Login.Title": "MadelineProto にログイン",
+ "tweb.Login.PhoneLabelInvalid": "無効な電話番号",
+ "tweb.Login.StartText": "国番号を確認して\n電話番号を入力してください。",
+ "tweb.Login.Code.SentSms": "コードを記載した SMS を\n送信しました。",
+ "tweb.Login.Code.SentInApp": "コードを記載したメッセージを\nTelegram で送信しました。",
+ "tweb.Login.Code.SentCall": "お電話でコードを\nお伝えします。",
+ "tweb.Login.Code.SentEmail": "メールアドレス **%s** を確認し (迷惑メールフォルダーもご確認ください)、送信したコードを入力してください。",
+ "tweb.Login.Code.SentUnknown": "あらゆる場所でコードを\nご確認ください (種類: %s)",
+ "tweb.Login.Code.SentMissedCall": "数秒以内に **%s** から\n短い着信があります。応答せずに、\nその番号の末尾の数字を入力してください。",
+ "tweb.Login.Code.SentSmsWord": "電話番号 **%s** に\n秘密の単語を記載した SMS を送信しました。",
+ "tweb.Login.Code.SentSmsWordBeginning": "電話番号 **%1$s** に、「**%2$s**」で始まる\n秘密の単語を記載した SMS を送信しました。",
+ "tweb.Login.Code.SentSmsPhrase": "電話番号 **%s** に\n秘密のフレーズを記載した SMS を送信しました。",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "電話番号 **%1$s** に、「**%2$s**」で始まる\n秘密のフレーズを記載した SMS を送信しました。",
+ "tweb.Login.Code.SecretWord": "秘密の単語",
+ "tweb.Login.Code.SecretPhrase": "秘密のフレーズ",
+ "tweb.Login.Code.WordInvalid": "正しくありません。もう一度お試しください",
+ "tweb.Login.Code.WordBeginningInvalid": "単語が正しくありません",
+ "tweb.Login.Password.Title": "パスワードを入力",
+ "tweb.Login.Password.Subtitle": "このアカウントは追加のパスワードで\n保護されています",
+ "tweb.Login.Register.Subtitle": "アカウントを作成するには\n名前を入力してください",
+ "tweb.PleaseWait": "お待ちください...",
+ "tweb.Code": "コード",
+ "tweb.LoginPassword": "パスワード",
+ "tweb.YourName": "名前",
+ "tweb.FirstName": "名 (必須)",
+ "tweb.LastName": "姓 (任意)",
+ "tweb.StartMessaging": "メッセージを始める",
+ "tweb.Country": "国",
+ "tweb.Contacts.PhoneNumber.Placeholder": "電話番号",
+ "tweb.Login.Next": "次へ",
+ "tweb.Login.QR.Title": "QR コードでログイン",
+ "tweb.Login.QR.Help1": "スマートフォンで Telegram を開きます",
+ "tweb.Login.QR.Help2": "**[設定]** > **[デバイス]** > **[デバイスを追加]** に進みます",
+ "tweb.Login.QR.Help3": "スマートフォンをこの画面に向けてログインを確認します",
+ "tweb.Login.QR.Cancel": "電話番号でログイン >",
+ "tweb.Login.QR.Login": "QR コードでログイン >",
+ "tweb.Login.QR.Subtitle": "スマートフォンの Telegram アプリでスキャンしてください",
+ "tweb.PhoneNumber.Code.Fragment.Info": "[Fragment]() の Numbers セクションでコードを確認してください",
+ "tweb.PHONE_CODE_INVALID": "無効なコードです",
+ "tweb.PHONE_CODE_EXPIRED": "コードの有効期限が切れました",
+ "tweb.PASSWORD_HASH_INVALID": "パスワードが正しくありません",
+ "tweb.DarkMode": "ダークモード",
+ "tweb.Error.AnError": "エラーが発生しました。しばらくしてからもう一度お試しください。",
+ "tweb.AccDescr.LoginCode": "ログインコード",
+ "tweb.Login.Bot": "ボットとしてログイン >",
+ "tweb.Login.Bot.Title": "ボットとしてログイン",
+ "tweb.Login.Bot.Subtitle": "ボットの作成時に @BotFather から\n受け取ったトークンを入力してください。",
+ "tweb.Login.Bot.Token": "ボットトークン",
+ "tweb.Login.Bot.Cancel": "ユーザーとしてログイン >",
+ "tweb.Optional": "任意",
+ "tweb.PHONE_NUMBER_INVALID": "無効な電話番号です",
+ "tweb.PHONE_NUMBER_BANNED": "この電話番号は利用停止されています",
+ "tweb.PHONE_NUMBER_FLOOD": "試行回数が多すぎます。しばらくしてからもう一度お試しください",
+ "tweb.PHONE_CODE_EMPTY": "無効なコードです",
+ "tweb.PHONE_PASSWORD_FLOOD": "試行回数が多すぎます。しばらくしてからもう一度お試しください",
+ "tweb.ACCESS_TOKEN_INVALID": "無効なボットトークンです",
+ "tweb.ACCESS_TOKEN_EXPIRED": "このボットトークンは無効化されています",
+ "tweb.FIRSTNAME_INVALID": "無効な名です",
+ "tweb.LASTNAME_INVALID": "無効な姓です",
+ "tweb.Close": "閉じる"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ko.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ko.json
new file mode 100644
index 0000000..1c9e265
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ko.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "basedir 제한이 설정되어 있습니다. 성능에 영향을 주고 문제를 일으킬 수 있으므로 가능하면 비활성화하십시오!",
+ "noReportPeers": "경고: 보고 대상 피어가 설정되지 않았습니다. 이벤트 핸들러에 다음 메서드를 추가하십시오",
+ "manualAdminActionRequired": "!!!!!!!!! 시스템 관리자의 수동 조치가 필요합니다 !!!!!!!!!",
+ "mmapErrorPart1": "메모리 매핑(mmap) 영역의 최대 개수에 도달했습니다(%s). 해결하려면 커널 설정 vm.max_map_count를 262144로 늘리십시오.",
+ "mmapErrorPart2": "해결하려면 root 권한으로 다음 명령을 실행하십시오: %s",
+ "mmapErrorPart3": "재부팅 후에도 변경 사항을 유지하려면: %s",
+ "mmapErrorPart4": "Windows 및 WSL에서는 페이지 파일 크기를 늘리면 도움이 될 수 있습니다. 문제가 계속되면 네이티브 Linux로 전환하십시오.",
+ "botAlreadyRunning": "봇이 이미 실행 중입니다!",
+ "extensionRequired": "MadelineProto를 실행하려면 %s 확장이 필요합니다. %s",
+ "extensionRequiredInstallWithApt": "sudo apt-get install %s 명령을 실행해 보십시오.",
+ "extensionRequiredInstallWithCustomInstructions": "%s의 안내에 따라 설치하십시오.",
+ "extensionRecommended": "경고: %s 확장이 설치되어 있지 않습니다. MadelineProto의 속도를 높이려면 설치하십시오!",
+ "go": "실행",
+ "apiChooseManualAutoTip": "설정을 사용하여 코드에서 API ID/hash를 직접 지정할 수도 있습니다: %s",
+ "apiChooseManualAutoTipWeb": "설정을 사용하여 코드에서 API ID/hash를 직접 지정할 수도 있습니다.",
+ "apiChoosePrompt": "선택하십시오 (m/a): ",
+ "apiManualInstructions0": "https://my.telegram.org에 로그인합니다",
+ "apiManualInstructions1": "API development tools로 이동합니다",
+ "apiManualInstructions2": "create application을 클릭합니다",
+ "apiAppInstructionsManual0": "앱 이름, 아무 이름이나 가능",
+ "apiAppInstructionsManual1": "앱의 짧은 이름, 영문자와 숫자, 5~32자",
+ "apiAppInstructionsManual2": "앱/웹사이트 URL 또는 t.me/yourusername",
+ "apiAppInstructionsManual3": "아무 값이나 가능",
+ "apiAppInstructionsManual4": "여기에 앱 설명을 입력합니다",
+ "apiManualWeb": "API ID와 API hash를 입력하십시오",
+ "apiManualPrompt0": "API ID를 입력하십시오: ",
+ "apiManualPrompt1": "API hash를 입력하십시오: ",
+ "apiAutoWeb": "API ID를 받으려면 Telegram에 이미 등록된 전화번호를 입력하십시오",
+ "apiAutoPrompt0": "Telegram에 이미 등록된 전화번호를 입력하십시오: ",
+ "apiAutoPrompt1": "Telegram에서 받은 인증 코드를 입력하십시오: ",
+ "apiAppWeb": "API 정보를 입력하십시오",
+ "apiAppInstructionsAuto0": "앱 이름을 입력하십시오(아무 이름이나 가능): ",
+ "apiAppInstructionsAuto1": "앱의 짧은 이름을 입력하십시오(영문자와 숫자, 5~32자): ",
+ "apiAppInstructionsAuto2": "앱/웹사이트 URL 또는 t.me/yourusername을 입력하십시오: ",
+ "apiAppInstructionsAuto3": "앱 플랫폼을 입력하십시오: ",
+ "apiAppInstructionsAuto4": "앱 설명을 입력하십시오: ",
+ "apiAppInstructionsAutoTypeOther": "기타(설명에 명시)",
+ "apiParamsError": "필수 매개변수를 모두 입력하지 않았습니다!",
+ "apiError": "오류: %s. 다시 시도하십시오.",
+ "loginChoosePromptWeb": "사용자와 봇 중 어느 것으로 로그인하시겠습니까?",
+ "loginWebQr": "휴대폰에서 Telegram을 열고 설정 > 기기 > 데스크톱 기기 연결로 이동하여 다음 QR 코드를 스캔하면 자동으로 로그인할 수도 있습니다:",
+ "loginWebQr1": "휴대폰에서 Telegram을 엽니다",
+ "loginWebQr2": "설정 > 기기 > 데스크톱 기기 연결로 이동합니다",
+ "loginWebQr3": "휴대폰을 이 화면에 비추어 로그인을 확인합니다",
+ "loginOptionBot": "봇",
+ "loginOptionUser": "사용자",
+ "loginBot": "봇 토큰을 입력하십시오: ",
+ "loginUser": "전화번호를 입력하십시오: ",
+ "loginQr": "휴대폰에서 Telegram을 열고 설정 > 기기 > 데스크톱 기기 연결로 이동하여 위의 QR 코드를 스캔하면 자동으로 로그인됩니다.",
+ "loginQrCodeSuccessful": "QR 코드 로그인에 성공했습니다!",
+ "loginQrCodeExpired": "QR 코드가 만료되었습니다. 새 코드를 생성하는 중...",
+ "loginManual": "또는 봇 토큰이나 전화번호를 입력하여 수동으로 로그인할 수도 있습니다: ",
+ "loginUserCode": "코드를 입력하십시오: ",
+ "loginUserPass": "비밀번호를 입력하십시오(힌트: %s): ",
+ "loginUserPassWeb": "비밀번호를 입력하십시오: ",
+ "loginUserPassHint": "힌트: %s",
+ "signupFirstName": "이름을 입력하십시오: ",
+ "signupLastName": "성을 입력하십시오(비워 둘 수 있음): ",
+ "signupWeb": "가입하십시오",
+ "signupFirstNameWeb": "이름",
+ "signupLastNameWeb": "성",
+ "loginNoCode": "전화 인증 코드를 입력하지 않았습니다!",
+ "loginNoPass": "비밀번호를 입력하지 않았습니다!",
+ "loginNoName": "이름을 입력하지 않았습니다!",
+ "loginBotTokenWeb": "봇 토큰",
+ "loginUserPhoneWeb": "전화번호",
+ "loginUserPhoneCodeWeb": "코드",
+ "done": "완료되었습니다!",
+ "nearest_dc": "현재 위치는 %s이며, 가장 가까운 DC는 %d입니다.",
+ "serialization_ofd": "직렬화 형식이 오래되어 객체를 재구성하는 중입니다!",
+ "api_not_set": "API 키와 API ID를 입력해야 합니다. my.telegram.org에서 발급받으십시오",
+ "session_corrupted": "세션이 손상되었습니다!",
+ "value_bigger_than_2147483647": "입력한 값 %s이(가) 2147483647보다 큽니다",
+ "value_smaller_than_2147483648": "입력한 값 %s이(가) -2147483648보다 작습니다",
+ "value_bigger_than_9223372036854775807": "입력한 값 %s이(가) 9223372036854775807보다 큽니다",
+ "value_smaller_than_9223372036854775808": "입력한 값 %s이(가) -9223372036854775808보다 작습니다",
+ "value_bigger_than_4294967296": "입력한 값 %s이(가) 4294967296보다 큽니다",
+ "value_smaller_than_0": "입력한 값 %s이(가) 0보다 작습니다",
+ "encode_double_error": "double을 올바르게 인코딩할 수 없습니다",
+ "file_not_exist": "파일이 존재하지 않습니다",
+ "deserialization_error": "역직렬화 중 오류가 발생했습니다",
+ "rpc_tg_error": "Telegram이 RPC 오류를 반환했습니다: %s (%s), 발생 위치 %s:%s%sTL 추적:",
+ "madelineproto_ready": "MadelineProto가 준비되었습니다!",
+ "logout_ok": "로그아웃되었습니다!",
+ "already_loggedIn": "이 MadelineProto 인스턴스는 이미 로그인되어 있습니다!",
+ "login_ok": "로그인되었습니다!",
+ "login_user": "일반 사용자로 로그인하는 중...",
+ "login_bot": "봇으로 로그인하는 중...",
+ "login_code_sending": "코드를 보내는 중...",
+ "login_code_sent": "코드를 보냈습니다! 코드를 받으면 completePhoneLogin 함수를 사용하십시오.",
+ "login_code_uncalled": "코드를 기다리고 있지 않습니다! 먼저 phoneLogin 메서드를 호출하십시오",
+ "login_2fa_enabled": "2단계 인증이 활성화되어 있습니다. complete2falogin 함수를 호출해야 합니다...",
+ "login_need_signup": "이 번호로 생성된 계정이 없습니다. completeSignup 함수를 호출해야 합니다...",
+ "login_auth_key": "인증 키로 로그인하는 중...",
+ "not_loggedIn": "로그인되어 있지 않습니다!",
+ "signup_uncalled": "가입을 기다리고 있지 않습니다! 먼저 phoneLogin 및 completePhoneLogin 메서드를 호출하십시오!",
+ "signing_up": "일반 사용자로 가입하는 중...",
+ "signup_ok": "가입되었습니다!",
+ "2fa_uncalled": "비밀번호를 기다리고 있지 않습니다! 먼저 phoneLogin 및 completePhoneLogin 메서드를 호출하십시오!",
+ "peer_not_in_db": "이 피어는 내부 피어 데이터베이스에 없습니다",
+ "call_error_1": "통화 %s을(를) 찾아 수락할 수 없습니다",
+ "accepting_call": "%s의 통화를 수락하는 중...",
+ "call_already_accepted": "통화 %s은(는) 이미 수락되었습니다",
+ "call_already_declined": "통화 %s은(는) 이미 거절되었습니다",
+ "call_error_2": "통화 %s을(를) 찾아 확인할 수 없습니다",
+ "call_confirming": "%s의 통화를 확인하는 중...",
+ "call_error_3": "통화 %s을(를) 찾아 완료할 수 없습니다",
+ "call_completing": "%s의 통화를 완료하는 중...",
+ "fingerprint_invalid": "키 지문이 유효하지 않습니다!",
+ "call_discarding": "통화 %s을(를) 종료하는 중...",
+ "file_parsing": "%s을(를) 파싱하는 중...",
+ "src_file_invalid": "유효하지 않은 소스 파일이 입력되었습니다: ",
+ "bool_error": "불리언 값을 추출할 수 없습니다",
+ "not_numeric": "입력한 값이 숫자가 아닙니다",
+ "long_not_16": "입력한 값의 길이가 16바이트가 아닙니다",
+ "long_not_32": "입력한 값의 길이가 32바이트가 아닙니다",
+ "long_not_64": "입력한 값의 길이가 64바이트가 아닙니다",
+ "array_invalid": "유효한 배열을 입력하지 않았습니다",
+ "predicate_not_set": "술어(_ 아래의 값)가 설정되지 않았습니다!",
+ "update_madelineproto": "오래된 버전의 MadelineProto를 실행 중이므로 업데이트가 필요합니다. 현재 실행 중인 버전은 %s이지만, 여러 버그 수정과 새 기능이 포함된 최신 버전은 %s입니다!",
+ "type_extract_error": "타입 \"%s\"을(를) 추출할 수 없습니다. MadelineProto를 업데이트하십시오!",
+ "method_not_found": "메서드를 찾을 수 없습니다: ",
+ "params_missing": "필수 매개변수가 없습니다",
+ "sec_peer_not_in_db": "이 비밀 피어는 내부 피어 데이터베이스에 없습니다",
+ "stream_handle_invalid": "유효하지 않은 스트림 핸들이 입력되었습니다.",
+ "length_too_big": "길이가 너무 깁니다",
+ "string_required": "문자열이 필요합니다!",
+ "waveform_must_have_100_values": "파형 배열에는 100개의 값이 있어야 합니다!",
+ "waveform_value": "파형 값은 0에서 31 사이여야 합니다!",
+ "could_not_convert_object": "%s 타입의 객체를 변환할 수 없습니다",
+ "type_extract_error_id": "타입 %s(ID %s)을(를) 추출할 수 없습니다. MadelineProto를 업데이트하십시오!",
+ "constructor_not_found": "다음 타입의 생성자를 찾을 수 없습니다: ",
+ "botapi_conversion_error": "%s을(를) Bot API 객체로 변환할 수 없습니다",
+ "non_text_conversion": "텍스트가 아닌 메시지는 아직 변환할 수 없습니다!",
+ "file_type_invalid": "유효하지 않은 파일 형식이 감지되었습니다(%s)",
+ "static_analysis_minor": "%s의 정적 분석 중 경미한 문제가 발견되었습니다: %s",
+ "static_analysis_severe": "%s의 정적 분석 중 심각한 문제가 발견되었습니다: %s",
+ "secret_chat_skipping": "데이터베이스에 비밀 채팅 %s이(가) 없으므로 메시지를 건너뜁니다...",
+ "must_have_declare_types": "성능상의 이유로 이벤트 핸들러 파일의 첫 번째 문은 \"declare(strict_types=1);\"이어야 합니다",
+ "do_not_delete_MadelineProto.log": "MadelineProto.log 파일은 절대 삭제하면 안 됩니다. 대신 설정에서 사용자 지정 최대 크기를 설정하십시오!",
+ "do_not_remove_MadelineProto.log_phar": "madeline.phar 또는 madeline.php를 삭제하지 마십시오. 삭제하면 MadelineProto가 비정상 종료됩니다. MadelineProto에 문제가 있으면 https://github.com/danog/MadelineProto 또는 https://t.me/pwrtelegramgroup에 보고하십시오",
+ "do_not_use_blocking_function": "성능상의 이유로 이벤트 핸들러에서는 비동기가 아닌 블로킹 함수 %s을(를) 사용할 수 없습니다. 대신 %s을(를) 사용하십시오",
+ "do_not_use_blocking_class": "성능상의 이유로 핸들러에서는 비동기가 아닌 블로킹 클래스 %s을(를) 사용할 수 없습니다. 대신 %s을(를) 사용하십시오",
+ "do_not_use_deprecated_function": "%s 함수는 더 이상 사용되지 않습니다. 대신 %s을(를) 사용하십시오",
+ "do_not_use_non_root_require_in_event_handler": "성능상의 이유로 이벤트 핸들러 클래스 내부에서 require 또는 include를 사용하면 안 됩니다. 루트 수준의 require만 허용됩니다.",
+ "do_not_use_yield": "MadelineProto 8에서는 비동기 함수에서 yield를 사용할 필요가 없으며 지원하지도 않습니다. 이전에 비동기 함수 호출에 사용한 yield 키워드를 모두 제거하십시오",
+ "recommend_not_use_filesystem_function": "%s 함수는 사용하지 않는 것이 좋습니다. 업데이트를 처리하는 동안 파일 시스템에 접근하면 봇이 느려지기 때문입니다. 봇을 느리게 하지 않는 데이터 저장 방법은 https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions 을 참조하십시오!",
+ "plugins_do_not_use_require": "성능상의 이유로 플러그인은 PSR-4 오토로더를 통해서만 plugins 폴더의 다른 파일을 자동으로 include 또는 require할 수 있습니다(직접 require()할 수 없습니다).",
+ "plugins_must_have_exactly_one_class": "플러그인은 정확히 하나의 클래스만 정의해야 합니다! 여러 클래스, 인터페이스 또는 트레이트를 정의하려면 별도의 파일을 만드십시오. MadelineProto가 자동으로 오토로드합니다.",
+ "cli_need_dl.php_link": "CLI에서 getDownloadLink를 사용할 때는 다운로드 스크립트 URL을 지정하십시오!",
+ "invalid_dl.php_session": "%s은(는) 세션 ID가 달라 유효한 다운로드 스크립트가 아닙니다(예상: %s, 실제: %s)",
+ "need_dl.php": "기본 다운로드 스크립트를 생성할 수 없습니다(%s). 다음 내용으로 dl.php 파일을 만들고: %s 해당 URL을 getDownloadLink의 두 번째 매개변수로 전달하십시오",
+ "dl.php_powered_by_madelineproto": "Telegram 파일 다운로드 서버(최대 4GB), powered by MadelineProto!
나만의 Telegram 파일 다운로드 서버를 설정하는 방법에 대한 자세한 내용은 여기를 클릭하십시오!",
+ "dl.php_check_logs_make_sure_session_running": "연결된 MadelineProto EventHandler 봇 또는 MadelineProto IPC 서버가 오프라인입니다. 로그를 확인하고 둘 중 하나 이상이 실행 중인지 확인하십시오!",
+ "account_banned": "!!!!!!! 경고 !!!!!!!\nTelegram의 플러드 방지 시스템이 이 계정을 정지했습니다.\n계속하려면 수동 인증이 필요합니다.\nrecover@telegram.org로 이메일을 보내 전화번호 %s의 정지 해제를 요청하고, 이 전화번호로 무엇을 할 것인지 간단히 설명하십시오.\n그런 다음 다시 로그인하십시오.\n이 계정을 의도적으로 삭제한 경우 이 메시지를 무시하십시오.",
+ "plugin_path_does_not_exist": "플러그인 경로 %s이(가) 존재하지 않습니다!",
+ "could_not_connect_to_MadelineProto": "MadelineProto에 연결할 수 없습니다. 해결하려면 proc_open을 활성화하고 open_basedir 제한을 제거하거나 웹 서버의 경로 재작성을 비활성화하십시오! 이미 그렇게 했다면 CLI 버전의 PHP가 웹 버전과 정확히 같은지(버전, 확장 등) 확인하고, IPC 서버의 시작을 막은 오류에 대한 자세한 내용은 MadelineProto.log 파일을 확인하십시오.",
+ "translate_madelineproto_web": "MadelineProto를 여러분의 언어로 번역할 수 있습니다(현재 번역 진행률: %d%%). 여기를 클릭하여 번역에 참여하십시오!",
+ "translate_madelineproto_cli": "MadelineProto를 여러분의 언어로 번역할 수 있습니다(현재 번역 진행률: %d%%). 번역에 참여하려면 https://github.com/danog/MadelineProto/tree/v8/langs 에 방문하십시오!",
+ "apiInvalidWeb": "API ID는 숫자이고 API hash는 32자입니다. my.telegram.org에서 다시 복사하십시오.",
+ "webDoneLead": "MadelineProto가 서버에서 계속 실행 중입니다. 이 페이지를 닫아도 됩니다.",
+ "apiChooseManualAuto": "my.telegram.org에서 API ID와 hash를 자동으로 받으시겠습니까(a), 아니면 직접 입력하시겠습니까(m)?",
+ "apiAutoFallbackManual": "대신 API ID와 hash를 직접 입력하십시오.",
+ "apiSetupTitleWeb": "API ID와 hash 받기",
+ "apiSetupLeadWeb": "모든 Telegram 앱에는 API ID와 hash가 필요합니다. 기존 Telegram 계정의 전화번호로 MadelineProto가 my.telegram.org에서 대신 받아올 수 있습니다.",
+ "apiAutoPhoneHintWeb": "my.telegram.org는 로그인 코드를 SMS가 아닌 Telegram 앱으로 보냅니다.",
+ "apiSendCodeWeb": "코드 보내기",
+ "apiChooseManualWeb": "이미 API ID가 있습니다",
+ "apiChooseAutoWeb": "자동으로 받기",
+ "apiStartOverWeb": "처음부터 다시",
+ "apiAutoCodeTitleWeb": "Telegram에서 받은 코드 입력",
+ "apiAutoCodeLeadWeb": "my.telegram.org가 Telegram 앱의 Telegram 채팅으로 로그인 코드를 보냈습니다(SMS 아님).",
+ "apiAutoCodeLabelWeb": "로그인 코드",
+ "apiCreateTitleWeb": "앱 만들기",
+ "apiCreateLeadWeb": "이 계정에는 아직 my.telegram.org 앱이 없습니다. 아래 정보는 본인에게만 표시되며 나중에 변경할 수 있습니다.",
+ "apiAppTitleLabelWeb": "앱 이름",
+ "apiAppShortNameLabelWeb": "짧은 이름",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "설명",
+ "apiCreateWeb": "앱 만들기",
+ "apiSaveWeb": "저장하고 계속",
+ "apiAutoErrorTitle": "my.telegram.org가 오류를 반환했습니다",
+ "apiCreateErrorTitle": "my.telegram.org에서 앱을 만들지 못했습니다",
+ "apiCreateVpsWarning": "Telegram은 VPS, VPN 및 기타 데이터 센터 IP 대역에서 my.telegram.org의 새 앱을 만드는 것을 허용하지 않으며, 이 요청은 MadelineProto를 실행하는 머신의 IP에서 전송되었습니다. 가정용 회선(예: 모바일 데이터를 사용하는 휴대폰)에서 https://my.telegram.org에 접속해 직접 앱을 만든 다음 API ID와 hash를 입력하십시오.",
+ "loginTitleWeb": "Telegram에 로그인",
+ "loginLeadWeb": "이 MadelineProto 인스턴스가 사용할 계정 또는 봇을 선택하십시오.",
+ "loginTypeWeb": "로그인 유형",
+ "loginUserPhoneHintWeb": "국가 코드를 포함하여 입력하십시오(예: +39 123 456 7890).",
+ "loginBotTokenHintWeb": "봇을 만들 때 @BotFather가 알려 준 토큰입니다.",
+ "loginCodeTitleWeb": "로그인 코드 입력",
+ "loginCodeLeadWeb": "Telegram이 Telegram 앱으로 로그인 코드를 보냈습니다. 다른 곳에 로그인되어 있지 않다면 SMS로 보냅니다.",
+ "loginPasswordTitleWeb": "2단계 인증",
+ "loginPasswordLeadWeb": "이 계정은 설정 > 개인정보 및 보안 > 2단계 인증에서 설정한 비밀번호로 보호되어 있습니다.",
+ "loginPasswordLabelWeb": "비밀번호",
+ "signupTitleWeb": "계정 만들기",
+ "signupLeadWeb": "이 전화번호는 아직 Telegram에 가입되어 있지 않습니다. 새 계정의 이름을 입력하십시오.",
+ "webContinue": "계속",
+ "webLogin": "로그인",
+ "webError": "%s. 확인 후 다시 시도하십시오.",
+ "webStepApp": "API ID 및 hash",
+ "webStepAccount": "계정",
+ "webStepVerify": "인증",
+ "webStepDone": "실행 중",
+ "webProgress": "설정 진행 상황",
+ "webDocs": "문서",
+ "webOptional": "선택 사항",
+ "webShowPassword": "표시",
+ "webHidePassword": "숨기기",
+ "webQrTitle": "QR 코드로 로그인",
+ "webQrWaiting": "스캔을 기다리는 중…",
+ "webFieldRequired": "이 항목을 입력하십시오.",
+ "webPhoneInvalid": "국가 코드를 포함한 전화번호를 입력하십시오(예: +39 123 456 7890).",
+ "tweb.Login.Title": "MadelineProto에 로그인",
+ "tweb.Login.PhoneLabelInvalid": "잘못된 전화번호",
+ "tweb.Login.StartText": "국가 코드를 확인하고\n전화번호를 입력하십시오.",
+ "tweb.Login.Code.SentSms": "코드가 담긴 SMS를\n보냈습니다.",
+ "tweb.Login.Code.SentInApp": "코드가 담긴 메시지를\nTelegram으로 보냈습니다.",
+ "tweb.Login.Code.SentCall": "전화로 코드를\n불러 드립니다.",
+ "tweb.Login.Code.SentEmail": "이메일 **%s**을(를) 확인하고(스팸함도 확인하십시오) 방금 보낸 코드를 입력하십시오.",
+ "tweb.Login.Code.SentUnknown": "모든 곳에서 코드를\n확인하십시오(유형: %s)",
+ "tweb.Login.Code.SentMissedCall": "몇 초 안에 **%s**에서\n짧은 전화가 걸려 옵니다. 받지 말고\n그 번호의 마지막 숫자를 입력하십시오.",
+ "tweb.Login.Code.SentSmsWord": "전화번호 **%s**(으)로\n비밀 단어가 담긴 SMS를 보냈습니다.",
+ "tweb.Login.Code.SentSmsWordBeginning": "전화번호 **%1$s**(으)로 \"**%2$s**\"(으)로 시작하는\n비밀 단어가 담긴 SMS를 보냈습니다.",
+ "tweb.Login.Code.SentSmsPhrase": "전화번호 **%s**(으)로\n비밀 문구가 담긴 SMS를 보냈습니다.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "전화번호 **%1$s**(으)로 \"**%2$s**\"(으)로 시작하는\n비밀 문구가 담긴 SMS를 보냈습니다.",
+ "tweb.Login.Code.SecretWord": "비밀 단어",
+ "tweb.Login.Code.SecretPhrase": "비밀 문구",
+ "tweb.Login.Code.WordInvalid": "올바르지 않습니다. 다시 시도하십시오",
+ "tweb.Login.Code.WordBeginningInvalid": "잘못된 단어",
+ "tweb.Login.Password.Title": "비밀번호 입력",
+ "tweb.Login.Password.Subtitle": "이 계정은 추가 비밀번호로\n보호되어 있습니다",
+ "tweb.Login.Register.Subtitle": "계정을 만들려면\n이름을 입력하십시오",
+ "tweb.PleaseWait": "잠시 기다려 주십시오...",
+ "tweb.Code": "코드",
+ "tweb.LoginPassword": "비밀번호",
+ "tweb.YourName": "이름",
+ "tweb.FirstName": "이름(필수)",
+ "tweb.LastName": "성(선택 사항)",
+ "tweb.StartMessaging": "메시지 시작하기",
+ "tweb.Country": "국가",
+ "tweb.Contacts.PhoneNumber.Placeholder": "전화번호",
+ "tweb.Login.Next": "다음",
+ "tweb.Login.QR.Title": "QR 코드로 로그인",
+ "tweb.Login.QR.Help1": "휴대폰에서 Telegram을 엽니다",
+ "tweb.Login.QR.Help2": "**설정** > **기기** > **기기 추가**로 이동합니다",
+ "tweb.Login.QR.Help3": "휴대폰을 이 화면에 비추어 로그인을 확인합니다",
+ "tweb.Login.QR.Cancel": "전화번호로 로그인 >",
+ "tweb.Login.QR.Login": "QR 코드로 로그인 >",
+ "tweb.Login.QR.Subtitle": "휴대폰의 Telegram 앱으로 스캔하십시오",
+ "tweb.PhoneNumber.Code.Fragment.Info": "[Fragment]()의 Numbers 섹션에서 코드를 받으십시오",
+ "tweb.PHONE_CODE_INVALID": "잘못된 코드",
+ "tweb.PHONE_CODE_EXPIRED": "코드가 만료되었습니다",
+ "tweb.PASSWORD_HASH_INVALID": "비밀번호가 올바르지 않습니다",
+ "tweb.DarkMode": "다크 모드",
+ "tweb.Error.AnError": "오류가 발생했습니다. 나중에 다시 시도하십시오.",
+ "tweb.AccDescr.LoginCode": "로그인 코드",
+ "tweb.Login.Bot": "봇으로 로그인 >",
+ "tweb.Login.Bot.Title": "봇으로 로그인",
+ "tweb.Login.Bot.Subtitle": "봇을 만들 때 @BotFather가 알려 준\n토큰을 입력하십시오.",
+ "tweb.Login.Bot.Token": "봇 토큰",
+ "tweb.Login.Bot.Cancel": "사용자로 로그인 >",
+ "tweb.Optional": "선택 사항",
+ "tweb.PHONE_NUMBER_INVALID": "잘못된 전화번호",
+ "tweb.PHONE_NUMBER_BANNED": "이 전화번호는 차단되었습니다",
+ "tweb.PHONE_NUMBER_FLOOD": "시도 횟수가 너무 많습니다. 나중에 다시 시도하십시오",
+ "tweb.PHONE_CODE_EMPTY": "잘못된 코드",
+ "tweb.PHONE_PASSWORD_FLOOD": "시도 횟수가 너무 많습니다. 나중에 다시 시도하십시오",
+ "tweb.ACCESS_TOKEN_INVALID": "잘못된 봇 토큰",
+ "tweb.ACCESS_TOKEN_EXPIRED": "이 봇 토큰은 폐기되었습니다",
+ "tweb.FIRSTNAME_INVALID": "잘못된 이름",
+ "tweb.LASTNAME_INVALID": "잘못된 성",
+ "tweb.Close": "닫기"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pl.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pl.json
index aafea4b..9f9f37e 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pl.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pl.json
@@ -1,4 +1,274 @@
{
- "noReportPeers": "Ostrzeżenie: nie ustawiono żadnych elementów równorzędnych raportu, dodaj następującą metodę do programu obsługi zdarzeń",
- "baseDirLimitation": "Skonfigurowane jest ograniczenie katalogu bazowego: może to wpłynąć na wydajność i spowodować pewne problemy, wyłącz je, jeśli to możliwe!"
+ "baseDirLimitation": "Skonfigurowane jest ograniczenie katalogu bazowego: może to wpłynąć na wydajność i spowodować pewne problemy, wyłącz je, jeśli to możliwe!",
+ "noReportPeers": "Ostrzeżenie: nie ustawiono odbiorców raportów (report peers), dodaj następującą metodę do swojego event handlera",
+ "manualAdminActionRequired": "!!!!!!!!! WYMAGANA RĘCZNA INTERWENCJA ADMINISTRATORA SYSTEMU !!!!!!!!!",
+ "mmapErrorPart1": "Osiągnięto maksymalną liczbę regionów pamięci mapowanej (mmap) (%s): aby to naprawić, zwiększ parametr jądra vm.max_map_count do 262144.",
+ "mmapErrorPart2": "Aby to naprawić, uruchom jako root następujące polecenie: %s",
+ "mmapErrorPart3": "Aby zmiana została zachowana po ponownym uruchomieniu: %s",
+ "mmapErrorPart4": "W systemie Windows i WSL może pomóc zwiększenie rozmiaru pliku stronicowania; jeśli problem nie ustąpi, przejdź na natywny system Linux.",
+ "botAlreadyRunning": "Bot jest już uruchomiony!",
+ "extensionRequired": "MadelineProto wymaga do działania rozszerzenia %s. %s",
+ "extensionRequiredInstallWithApt": "Spróbuj uruchomić sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Aby je zainstalować, postępuj zgodnie z instrukcjami na %s.",
+ "extensionRecommended": "Ostrzeżenie: rozszerzenie %s nie jest zainstalowane, zainstaluj je, aby przyspieszyć MadelineProto!",
+ "go": "Dalej",
+ "apiChooseManualAutoTip": "Pamiętaj, że API ID/hash możesz też podać bezpośrednio w kodzie za pomocą ustawień: %s",
+ "apiChooseManualAutoTipWeb": "Pamiętaj, że API ID/hash możesz też podać bezpośrednio w kodzie za pomocą ustawień.",
+ "apiChoosePrompt": "Twój wybór (m/a): ",
+ "apiManualInstructions0": "Zaloguj się na https://my.telegram.org",
+ "apiManualInstructions1": "Przejdź do „API development tools”",
+ "apiManualInstructions2": "Kliknij „Create application”",
+ "apiAppInstructionsManual0": "nazwa aplikacji, dowolna",
+ "apiAppInstructionsManual1": "krótka nazwa aplikacji, alfanumeryczna, 5-32 znaki",
+ "apiAppInstructionsManual2": "adres URL aplikacji/strony internetowej lub t.me/yourusername",
+ "apiAppInstructionsManual3": "cokolwiek",
+ "apiAppInstructionsManual4": "Opisz tutaj swoją aplikację",
+ "apiManualWeb": "Wprowadź swoje API ID i API hash",
+ "apiManualPrompt0": "Wprowadź swoje API ID: ",
+ "apiManualPrompt1": "Wprowadź swój API hash: ",
+ "apiAutoWeb": "Wprowadź numer telefonu, który jest już zarejestrowany w Telegramie, aby uzyskać API ID",
+ "apiAutoPrompt0": "Wprowadź numer telefonu, który jest już zarejestrowany w Telegramie: ",
+ "apiAutoPrompt1": "Wprowadź kod weryfikacyjny otrzymany w Telegramie: ",
+ "apiAppWeb": "Wprowadź informacje o API",
+ "apiAppInstructionsAuto0": "Wprowadź nazwę aplikacji (dowolną): ",
+ "apiAppInstructionsAuto1": "Wprowadź krótką nazwę aplikacji (alfanumeryczną, 5-32 znaki): ",
+ "apiAppInstructionsAuto2": "Wprowadź adres URL aplikacji/strony internetowej lub t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Wprowadź platformę aplikacji: ",
+ "apiAppInstructionsAuto4": "Opisz swoją aplikację: ",
+ "apiAppInstructionsAutoTypeOther": "Inna (określ w opisie)",
+ "apiParamsError": "Nie podano wszystkich wymaganych parametrów!",
+ "apiError": "BŁĄD: %s. Spróbuj ponownie.",
+ "loginChoosePromptWeb": "Czy chcesz zalogować się jako użytkownik, czy jako bot?",
+ "loginWebQr": "Możesz też zalogować się automatycznie: otwórz Telegram na telefonie, przejdź do Ustawienia > Urządzenia > Połącz urządzenie desktopowe i zeskanuj poniższy kod QR:",
+ "loginWebQr1": "Otwórz Telegram na telefonie",
+ "loginWebQr2": "Przejdź do Ustawienia > Urządzenia > Połącz urządzenie desktopowe",
+ "loginWebQr3": "Skieruj telefon na ten ekran, aby potwierdzić logowanie",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Użytkownik",
+ "loginBot": "Wprowadź token bota: ",
+ "loginUser": "Wprowadź swój numer telefonu: ",
+ "loginQr": "Otwórz Telegram na telefonie, przejdź do Ustawienia > Urządzenia > Połącz urządzenie desktopowe i zeskanuj powyższy kod QR, aby zalogować się automatycznie.",
+ "loginQrCodeSuccessful": "Logowanie kodem QR powiodło się!",
+ "loginQrCodeExpired": "Kod QR wygasł, generowanie nowego...",
+ "loginManual": "Możesz też wprowadzić token bota lub numer telefonu, aby zalogować się ręcznie: ",
+ "loginUserCode": "Wprowadź kod: ",
+ "loginUserPass": "Wprowadź hasło (podpowiedź: %s): ",
+ "loginUserPassWeb": "Wprowadź hasło: ",
+ "loginUserPassHint": "Podpowiedź: %s",
+ "signupFirstName": "Wprowadź imię: ",
+ "signupLastName": "Wprowadź nazwisko (może być puste): ",
+ "signupWeb": "Zarejestruj się",
+ "signupFirstNameWeb": "Imię",
+ "signupLastNameWeb": "Nazwisko",
+ "loginNoCode": "Nie podano kodu weryfikacyjnego!",
+ "loginNoPass": "Nie podano hasła!",
+ "loginNoName": "Nie podano imienia!",
+ "loginBotTokenWeb": "Token bota",
+ "loginUserPhoneWeb": "Numer telefonu",
+ "loginUserPhoneCodeWeb": "Kod",
+ "done": "Gotowe!",
+ "nearest_dc": "Jesteśmy w %s, najbliższe DC to %d.",
+ "serialization_ofd": "Serializacja jest nieaktualna, odtwarzanie obiektu!",
+ "api_not_set": "Musisz podać klucz API i API ID, uzyskaj własne na my.telegram.org",
+ "session_corrupted": "Sesja jest uszkodzona!",
+ "value_bigger_than_2147483647": "Podana wartość %s jest większa niż 2147483647",
+ "value_smaller_than_2147483648": "Podana wartość %s jest mniejsza niż -2147483648",
+ "value_bigger_than_9223372036854775807": "Podana wartość %s jest większa niż 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "Podana wartość %s jest mniejsza niż -9223372036854775808",
+ "value_bigger_than_4294967296": "Podana wartość %s jest większa niż 4294967296",
+ "value_smaller_than_0": "Podana wartość %s jest mniejsza niż 0",
+ "encode_double_error": "Nie udało się poprawnie zakodować wartości double",
+ "file_not_exist": "Plik nie istnieje",
+ "deserialization_error": "Wystąpił błąd podczas deserializacji",
+ "rpc_tg_error": "Telegram zwrócił błąd RPC: %s (%s), spowodowany przez %s:%s%sŚlad TL:",
+ "madelineproto_ready": "MadelineProto jest gotowe!",
+ "logout_ok": "Wylogowano pomyślnie!",
+ "already_loggedIn": "Ta instancja MadelineProto jest już zalogowana!",
+ "login_ok": "Zalogowano pomyślnie!",
+ "login_user": "Logowanie jako zwykły użytkownik...",
+ "login_bot": "Logowanie jako bot...",
+ "login_code_sending": "Wysyłanie kodu...",
+ "login_code_sent": "Kod został wysłany! Po otrzymaniu kodu użyj funkcji completePhoneLogin.",
+ "login_code_uncalled": "Nie oczekuję na kod! Najpierw wywołaj metodę phoneLogin",
+ "login_2fa_enabled": "Włączono 2FA, musisz wywołać funkcję complete2falogin...",
+ "login_need_signup": "Dla tego numeru nie utworzono konta, musisz wywołać funkcję completeSignup...",
+ "login_auth_key": "Logowanie za pomocą klucza autoryzacji...",
+ "not_loggedIn": "Nie jestem zalogowany!",
+ "signup_uncalled": "Nie oczekuję na rejestrację! Najpierw wywołaj metody phoneLogin i completePhoneLogin!",
+ "signing_up": "Rejestracja jako zwykły użytkownik...",
+ "signup_ok": "Zarejestrowano pomyślnie!",
+ "2fa_uncalled": "Nie oczekuję na hasło! Najpierw wywołaj metody phoneLogin i completePhoneLogin!",
+ "peer_not_in_db": "Tego peera nie ma w wewnętrznej bazie danych peerów",
+ "call_error_1": "Nie udało się znaleźć i odebrać połączenia %s",
+ "accepting_call": "Odbieranie połączenia od %s...",
+ "call_already_accepted": "Połączenie %s zostało już odebrane",
+ "call_already_declined": "Połączenie %s zostało już odrzucone",
+ "call_error_2": "Nie udało się znaleźć i potwierdzić połączenia %s",
+ "call_confirming": "Potwierdzanie połączenia od %s...",
+ "call_error_3": "Nie udało się znaleźć i sfinalizować połączenia %s",
+ "call_completing": "Finalizowanie połączenia od %s...",
+ "fingerprint_invalid": "Nieprawidłowy odcisk klucza!",
+ "call_discarding": "Kończenie połączenia %s...",
+ "file_parsing": "Parsowanie %s...",
+ "src_file_invalid": "Podano nieprawidłowy plik źródłowy: ",
+ "bool_error": "Nie udało się wyodrębnić wartości logicznej",
+ "not_numeric": "Podana wartość nie jest liczbą",
+ "long_not_16": "Podana wartość nie ma długości 16 bajtów",
+ "long_not_32": "Podana wartość nie ma długości 32 bajtów",
+ "long_not_64": "Podana wartość nie ma długości 64 bajtów",
+ "array_invalid": "Nie podano prawidłowej tablicy",
+ "predicate_not_set": "Predykat (wartość pod _) nie został ustawiony!",
+ "update_madelineproto": "Używasz starej wersji MadelineProto, wymagana jest aktualizacja: obecnie uruchomiona jest wersja %s, a najnowsza wersja z wieloma poprawkami błędów i nowymi funkcjami to %s!",
+ "type_extract_error": "Nie udało się wyodrębnić typu \"%s\", zaktualizuj MadelineProto!",
+ "method_not_found": "Nie znaleziono metody: ",
+ "params_missing": "Brak wymaganego parametru",
+ "sec_peer_not_in_db": "Tego tajnego peera nie ma w wewnętrznej bazie danych peerów",
+ "stream_handle_invalid": "Podano nieprawidłowy uchwyt strumienia.",
+ "length_too_big": "Długość jest zbyt duża",
+ "string_required": "Oczekiwano ciągu znaków!",
+ "waveform_must_have_100_values": "Tablica kształtu fali (waveform) musi zawierać 100 wartości!",
+ "waveform_value": "Wartość kształtu fali (waveform) musi mieścić się w zakresie od 0 do 31!",
+ "could_not_convert_object": "Nie udało się przekonwertować obiektu typu %s",
+ "type_extract_error_id": "Nie udało się wyodrębnić typu %s o id %s, zaktualizuj MadelineProto!",
+ "constructor_not_found": "Nie znaleziono konstruktora dla typu: ",
+ "botapi_conversion_error": "Nie można przekonwertować %s na obiekt Bot API",
+ "non_text_conversion": "Konwersja wiadomości innych niż tekstowe nie jest jeszcze obsługiwana!",
+ "file_type_invalid": "Wykryto nieprawidłowy typ pliku (%s)",
+ "static_analysis_minor": "Podczas analizy statycznej %s napotkano drobny problem: %s",
+ "static_analysis_severe": "Podczas analizy statycznej %s napotkano poważny problem: %s",
+ "secret_chat_skipping": "Nie mam tajnego czatu %s w bazie danych, pomijanie wiadomości...",
+ "must_have_declare_types": "ze względu na wydajność pierwszą instrukcją pliku event handlera musi być \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "pliku MadelineProto.log nigdy nie wolno usuwać, zamiast tego ustaw w ustawieniach niestandardowy rozmiar maksymalny!",
+ "do_not_remove_MadelineProto.log_phar": "Nie usuwaj madeline.phar ani madeline.php, w przeciwnym razie MadelineProto ulegnie awarii. Jeśli masz jakikolwiek problem z MadelineProto, zgłoś go na https://github.com/danog/MadelineProto lub https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "ze względu na wydajność event handlery nie mogą używać nieasynchronicznej, blokującej funkcji %s, zamiast niej użyj %s",
+ "do_not_use_blocking_class": "ze względu na wydajność handlery nie mogą używać nieasynchronicznej, blokującej klasy %s, zamiast niej użyj %s",
+ "do_not_use_deprecated_function": "funkcja %s jest przestarzała, zamiast niej użyj %s",
+ "do_not_use_non_root_require_in_event_handler": "ze względu na wydajność nie wolno używać require ani include wewnątrz klasy event handlera, dozwolone są tylko require na najwyższym poziomie.",
+ "do_not_use_yield": "MadelineProto 8 nie wymaga ani nie obsługuje używania yield w funkcjach asynchronicznych, musisz usunąć wszystkie słowa kluczowe yield używane wcześniej przy wywołaniach funkcji asynchronicznych",
+ "recommend_not_use_filesystem_function": "używanie funkcji %s nie jest zalecane, ponieważ dostęp do systemu plików podczas obsługi aktualizacji spowolni bota; na stronie https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions znajdziesz listę alternatywnych sposobów przechowywania danych, które nie spowalniają bota!",
+ "plugins_do_not_use_require": "ze względu na wydajność pluginy mogą automatycznie dołączać inne pliki z folderu pluginów wyłącznie za pośrednictwem autoloadera PSR-4 (a nie przez ręczne require()).",
+ "plugins_must_have_exactly_one_class": "plugin musi definiować dokładnie jedną klasę! Aby zdefiniować wiele klas, interfejsów lub traitów, utwórz osobne pliki, MadelineProto załaduje je automatycznie.",
+ "cli_need_dl.php_link": "Podaj adres URL skryptu pobierania, gdy używasz getDownloadLink z poziomu CLI!",
+ "invalid_dl.php_session": "%s nie jest prawidłowym skryptem pobierania, ponieważ jego ID sesji jest inne (oczekiwano %s, otrzymano %s)",
+ "need_dl.php": "Nie udało się wygenerować domyślnego skryptu pobierania (%s), utwórz plik dl.php o następującej zawartości: %s i przekaż jego adres URL jako drugi parametr getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Serwer pobierania plików z Telegrama (do 4 GB), oparty na MadelineProto!
Kliknij tutaj, aby dowiedzieć się, jak skonfigurować własny serwer pobierania plików z Telegrama!",
+ "dl.php_check_logs_make_sure_session_running": "Powiązany bot EventHandler MadelineProto lub serwer IPC MadelineProto jest offline, sprawdź logi i upewnij się, że co najmniej jeden z nich działa!",
+ "account_banned": "!!!!!!! OSTRZEŻENIE !!!!!!!\nSystem ochrony przed floodem Telegrama zawiesił to konto.\nAby kontynuować, wymagana jest ręczna weryfikacja.\nWyślij e-mail na adres recover@telegram.org z prośbą o odblokowanie numeru telefonu %s i krótko opisz, do czego będzie używany ten numer.\nNastępnie zaloguj się ponownie.\nJeśli konto zostało celowo usunięte, zignoruj tę wiadomość.",
+ "plugin_path_does_not_exist": "Ścieżka pluginu %s nie istnieje!",
+ "could_not_connect_to_MadelineProto": "Nie udało się połączyć z MadelineProto, aby to naprawić, włącz proc_open i usuń ograniczenia open_basedir lub wyłącz przepisywanie ścieżek na serwerze WWW! Jeśli zostało to już zrobione, upewnij się, że wersja CLI PHP jest dokładnie taka sama jak wersja webowa (ta sama wersja, rozszerzenia itd.), i sprawdź plik MadelineProto.log, aby uzyskać więcej informacji o błędzie, który uniemożliwił uruchomienie serwera IPC.",
+ "translate_madelineproto_web": "MadelineProto można przetłumaczyć na Twój język (obecny postęp tłumaczenia: %d%%), kliknij tutaj, aby pomóc w tłumaczeniu!",
+ "translate_madelineproto_cli": "MadelineProto można przetłumaczyć na Twój język (obecny postęp tłumaczenia: %d%%), przejdź na https://github.com/danog/MadelineProto/tree/v8/langs, aby pomóc w tłumaczeniu!",
+ "apiInvalidWeb": "API ID to liczba, a API hash ma 32 znaki: skopiuj je ponownie z my.telegram.org.",
+ "webDoneLead": "MadelineProto nadal działa na serwerze: możesz zamknąć tę stronę.",
+ "apiChooseManualAuto": "Czy chcesz pobrać API ID i API hash automatycznie z my.telegram.org (a), czy wprowadzić je ręcznie (m)?",
+ "apiAutoFallbackManual": "Zamiast tego wprowadź API ID i API hash ręcznie.",
+ "apiSetupTitleWeb": "Uzyskaj API ID i API hash",
+ "apiSetupLeadWeb": "Każda aplikacja Telegrama potrzebuje API ID i API hash. MadelineProto może pobrać je za Ciebie z my.telegram.org, używając numeru telefonu istniejącego konta Telegram.",
+ "apiAutoPhoneHintWeb": "my.telegram.org wysyła kod logowania do aplikacji Telegram, a nie SMS-em.",
+ "apiSendCodeWeb": "Wyślij kod",
+ "apiChooseManualWeb": "Mam już API ID",
+ "apiChooseAutoWeb": "Pobierz automatycznie",
+ "apiStartOverWeb": "Zacznij od nowa",
+ "apiAutoCodeTitleWeb": "Wprowadź kod z Telegrama",
+ "apiAutoCodeLeadWeb": "my.telegram.org wysłał kod logowania do Twojej aplikacji Telegram, na czacie z Telegramem (nie SMS-em).",
+ "apiAutoCodeLabelWeb": "Kod logowania",
+ "apiCreateTitleWeb": "Utwórz aplikację",
+ "apiCreateLeadWeb": "To konto nie ma jeszcze aplikacji na my.telegram.org. Te dane widzisz tylko Ty i możesz je później zmienić.",
+ "apiAppTitleLabelWeb": "Nazwa aplikacji",
+ "apiAppShortNameLabelWeb": "Krótka nazwa",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Opis",
+ "apiCreateWeb": "Utwórz aplikację",
+ "apiSaveWeb": "Zapisz i kontynuuj",
+ "apiAutoErrorTitle": "my.telegram.org zwrócił błąd",
+ "apiCreateErrorTitle": "my.telegram.org nie utworzył aplikacji",
+ "apiCreateVpsWarning": "Telegram nie pozwala na tworzenie nowych aplikacji na my.telegram.org z adresów IP serwerów VPS, sieci VPN i innych centrów danych, a żądanie zostało wysłane z adresu IP maszyny, na której działa MadelineProto. Utwórz aplikację ręcznie na https://my.telegram.org z połączenia domowego (np. z telefonu przez dane komórkowe), a następnie wprowadź API ID i API hash.",
+ "loginTitleWeb": "Zaloguj się do Telegrama",
+ "loginLeadWeb": "Wybierz konto lub bota, jako który będzie działać ta instancja MadelineProto.",
+ "loginTypeWeb": "Zaloguj jako",
+ "loginUserPhoneHintWeb": "Z numerem kierunkowym kraju, np. +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Token, który otrzymałeś od @BotFather podczas tworzenia bota.",
+ "loginCodeTitleWeb": "Wprowadź kod logowania",
+ "loginCodeLeadWeb": "Telegram wysłał kod logowania do Twojej aplikacji Telegram lub SMS-em, jeśli nie jesteś zalogowany nigdzie indziej.",
+ "loginPasswordTitleWeb": "Weryfikacja dwuetapowa",
+ "loginPasswordLeadWeb": "To konto jest chronione hasłem ustawionym w Ustawienia > Prywatność i bezpieczeństwo > Weryfikacja dwuetapowa.",
+ "loginPasswordLabelWeb": "Hasło",
+ "signupTitleWeb": "Utwórz konto",
+ "signupLeadWeb": "Tego numeru telefonu nie ma jeszcze w Telegramie: wybierz nazwę nowego konta.",
+ "webContinue": "Kontynuuj",
+ "webLogin": "Zaloguj się",
+ "webError": "%s. Sprawdź i spróbuj ponownie.",
+ "webStepApp": "API ID i API hash",
+ "webStepAccount": "Konto",
+ "webStepVerify": "Weryfikacja",
+ "webStepDone": "Działa",
+ "webProgress": "Postęp konfiguracji",
+ "webDocs": "Dokumentacja",
+ "webOptional": "opcjonalnie",
+ "webShowPassword": "Pokaż",
+ "webHidePassword": "Ukryj",
+ "webQrTitle": "Zaloguj się kodem QR",
+ "webQrWaiting": "Oczekiwanie na zeskanowanie…",
+ "webFieldRequired": "Wypełnij to pole.",
+ "webPhoneInvalid": "Wprowadź numer telefonu z numerem kierunkowym kraju, np. +39 123 456 7890.",
+ "tweb.Login.Title": "Zaloguj się do MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Nieprawidłowy numer telefonu",
+ "tweb.Login.StartText": "Potwierdź kod kraju\ni wprowadź swój numer telefonu.",
+ "tweb.Login.Code.SentSms": "Wysłaliśmy Ci SMS\nz kodem.",
+ "tweb.Login.Code.SentInApp": "Wysłaliśmy Ci wiadomość w Telegramie\nz kodem.",
+ "tweb.Login.Code.SentCall": "Zadzwonimy do Ciebie i podyktujemy\nkod.",
+ "tweb.Login.Code.SentEmail": "Sprawdź swoją skrzynkę **%s** (nie zapomnij o folderze spam) i wprowadź kod, który właśnie wysłaliśmy.",
+ "tweb.Login.Code.SentUnknown": "Poszukaj kodu\nwszędzie (typ: %s)",
+ "tweb.Login.Code.SentMissedCall": "W ciągu kilku sekund powinieneś otrzymać\nkrótkie połączenie z numeru **%s**. Nie odbieraj —\npo prostu wpisz ostatnie cyfry tego numeru.",
+ "tweb.Login.Code.SentSmsWord": "Wysłaliśmy SMS z tajnym słowem\nna Twój telefon **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Wysłaliśmy SMS z tajnym słowem zaczynającym się\nod „**%2$s**” na Twój telefon **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Wysłaliśmy SMS z tajną frazą\nna Twój telefon **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Wysłaliśmy SMS z tajną frazą zaczynającą się\nod „**%2$s**” na Twój telefon **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Tajne słowo",
+ "tweb.Login.Code.SecretPhrase": "Tajna fraza",
+ "tweb.Login.Code.WordInvalid": "Niepoprawnie, spróbuj ponownie",
+ "tweb.Login.Code.WordBeginningInvalid": "Niepoprawne słowo",
+ "tweb.Login.Password.Title": "Wprowadź hasło",
+ "tweb.Login.Password.Subtitle": "Twoje konto jest chronione\ndodatkowym hasłem",
+ "tweb.Login.Register.Subtitle": "Wprowadź swoje imię,\naby utworzyć konto",
+ "tweb.PleaseWait": "Proszę czekać...",
+ "tweb.Code": "Kod",
+ "tweb.LoginPassword": "Hasło",
+ "tweb.YourName": "Twoje imię",
+ "tweb.FirstName": "Imię (wymagane)",
+ "tweb.LastName": "Nazwisko (opcjonalnie)",
+ "tweb.StartMessaging": "Zacznij pisać",
+ "tweb.Country": "Kraj",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Numer telefonu",
+ "tweb.Login.Next": "Dalej",
+ "tweb.Login.QR.Title": "Zaloguj się kodem QR",
+ "tweb.Login.QR.Help1": "Otwórz Telegram na telefonie",
+ "tweb.Login.QR.Help2": "Przejdź do **Ustawienia** > **Urządzenia** > **Połącz urządzenie desktopowe**",
+ "tweb.Login.QR.Help3": "Skieruj telefon na ten ekran, aby potwierdzić logowanie",
+ "tweb.Login.QR.Cancel": "Zaloguj się numerem telefonu >",
+ "tweb.Login.QR.Login": "Zaloguj się kodem QR >",
+ "tweb.Login.QR.Subtitle": "Zeskanuj aplikacją Telegram na telefonie",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Odbierz kod w sekcji Numbers na [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Nieprawidłowy kod",
+ "tweb.PHONE_CODE_EXPIRED": "Kod wygasł",
+ "tweb.PASSWORD_HASH_INVALID": "Nieprawidłowe hasło",
+ "tweb.DarkMode": "Tryb ciemny",
+ "tweb.Error.AnError": "Wystąpił błąd. Spróbuj ponownie później.",
+ "tweb.AccDescr.LoginCode": "Kod logowania",
+ "tweb.Login.Bot": "Zaloguj się jako bot >",
+ "tweb.Login.Bot.Title": "Zaloguj się jako bot",
+ "tweb.Login.Bot.Subtitle": "Wprowadź token, który otrzymałeś od @BotFather\npodczas tworzenia bota.",
+ "tweb.Login.Bot.Token": "Token bota",
+ "tweb.Login.Bot.Cancel": "Zaloguj się jako użytkownik >",
+ "tweb.Optional": "opcjonalnie",
+ "tweb.PHONE_NUMBER_INVALID": "Nieprawidłowy numer telefonu",
+ "tweb.PHONE_NUMBER_BANNED": "Ten numer telefonu jest zablokowany",
+ "tweb.PHONE_NUMBER_FLOOD": "Zbyt wiele prób, spróbuj ponownie później",
+ "tweb.PHONE_CODE_EMPTY": "Nieprawidłowy kod",
+ "tweb.PHONE_PASSWORD_FLOOD": "Zbyt wiele prób, spróbuj ponownie później",
+ "tweb.ACCESS_TOKEN_INVALID": "Nieprawidłowy token bota",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Ten token bota został unieważniony",
+ "tweb.FIRSTNAME_INVALID": "Nieprawidłowe imię",
+ "tweb.LASTNAME_INVALID": "Nieprawidłowe nazwisko",
+ "tweb.Close": "Zamknij"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pt.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pt.json
index 58b8bff..839241b 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pt.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/pt.json
@@ -1,13 +1,19 @@
{
- "go": "Pronto",
- "loginChoosePromptWeb": "Deseja fazer login como Usuário ou como Bot?",
- "noReportPeers": "Aviso: nenhum peers de relatório está definido, adicione o seguinte método ao seu event handler",
+ "baseDirLimitation": "Uma limitação de basedir está configurada: isso pode afetar o desempenho e causar alguns problemas, desative-a se possível!",
+ "noReportPeers": "Aviso: nenhum peer de relatório está definido, adicione o seguinte método ao seu event handler",
"manualAdminActionRequired": "!!!!!!!!! AÇÃO MANUAL DO ADMINISTRADOR DO SISTEMA NECESSÁRIA !!!!!!!!",
+ "mmapErrorPart1": "O número máximo de regiões mapeadas de memória (mmap) foi atingido (%s): aumente a configuração do kernel vm.max_map_count para 262144 para corrigir.",
"mmapErrorPart2": "Para corrigir, execute o seguinte comando como root: %s",
+ "mmapErrorPart3": "Para manter a alteração após reinicializações: %s",
+ "mmapErrorPart4": "No Windows e no WSL, aumentar o tamanho do arquivo de paginação pode ajudar; mude para o Linux nativo se o problema persistir.",
"botAlreadyRunning": "O bot já está em execução!",
"extensionRequired": "MadelineProto requer a extensão %s para ser executada. %s",
"extensionRequiredInstallWithApt": "Tente executar sudo apt-get install %s.",
"extensionRequiredInstallWithCustomInstructions": "Siga as instruções em %s para instalá-lo.",
+ "extensionRecommended": "Aviso: a extensão %s não está instalada, instale-a para acelerar o MadelineProto!",
+ "go": "Pronto",
+ "apiChooseManualAutoTip": "Observe que você também pode fornecer o ID/hash da API diretamente no código usando as configurações: %s",
+ "apiChooseManualAutoTipWeb": "Observe que você também pode fornecer o ID/hash da API diretamente no código usando as configurações.",
"apiChoosePrompt": "Sua escolha (m/a): ",
"apiManualInstructions0": "Faça login em https://my.telegram.org",
"apiManualInstructions1": "Ir para API development tools",
@@ -15,28 +21,16 @@
"apiAppInstructionsManual0": "nome do seu aplicativo, pode ser qualquer coisa",
"apiAppInstructionsManual1": "o nome abreviado do seu aplicativo, alfanumérico, de 5 a 32 caracteres",
"apiAppInstructionsManual2": "URL do seu aplicativo/site ou t.me/yourusername",
+ "apiAppInstructionsManual3": "qualquer coisa",
"apiAppInstructionsManual4": "Descreva seu aplicativo aqui",
"apiManualWeb": "Insira seu API ID e API hash",
"apiManualPrompt0": "Insira seu API ID: ",
"apiManualPrompt1": "Insira seu API hash: ",
- "loginWebQr1": "Abra o Telegram no seu telefone",
- "mmapErrorPart3": "Para manter a alteração após reinicializações: %s",
- "translate_madelineproto_web": "MadelineProto pode ser traduzido para o seu idioma (progresso atual da tradução: %d%%), clique aqui para contribuir com a tradução!",
- "loginWebQr": "Você também pode fazer login automaticamente abrindo o Telegram no seu telefone, acessando Configurações > Dispositivos > Conectar Desktop e digitalizando o seguinte código QR:",
- "extensionRecommended": "Aviso: a extensão %s não está instalada, instale-a para acelerar o MadelineProto!",
- "baseDirLimitation": "Uma limitação baseada está configurada: isso pode afetar o desempenho e causar alguns problemas, desative-o se possível!",
- "mmapErrorPart1": "O número máximo de regiões mapeadas de memória (mmap) foi atingido (%s): aumente a configuração do kernel vm.max_map_count para 262144 a corrigir.",
- "apiChooseManualAutoTip": "Observe que você também pode fornecer o ID/hash da API diretamente no código usando as configurações: %s",
- "apiChooseManualAutoTipWeb": "Observe que você também pode fornecer o ID/hash da API diretamente no código usando as configurações.",
- "mmapErrorPart4": "No Windows e no WSL, aumentar o tamanho do arquivo de paginação pode ajudar; mude para o Linux nativo se o problema persistir.",
- "apiAppInstructionsManual3": "qualquer coisa",
"apiAutoWeb": "Insira um número de telefone que já esteja registrado no Telegram para obter o ID da API",
"apiAutoPrompt0": "Digite um número de telefone que já esteja registrado no Telegram: ",
"apiAutoPrompt1": "Digite o código de verificação recebido pelo Telegram: ",
"apiAppWeb": "Insira as informações da API",
"apiAppInstructionsAuto0": "Digite o nome do app, pode ser qualquer coisa: ",
- "loginOptionUser": "Usuário",
- "signupFirstNameWeb": "Primeiro nome",
"apiAppInstructionsAuto1": "Digite o nome do seu aplicativo, alfanumérico, de 5 a 32 caracteres: ",
"apiAppInstructionsAuto2": "Digite a URL do seu aplicativo/site ou t.me/seuusuário: ",
"apiAppInstructionsAuto3": "Digite a plataforma do aplicativo: ",
@@ -44,12 +38,19 @@
"apiAppInstructionsAutoTypeOther": "Outro (especifique na descrição)",
"apiParamsError": "Você não forneceu todos os parâmetros necessários!",
"apiError": "ERRO: %s. Tente novamente.",
+ "loginChoosePromptWeb": "Deseja fazer login como Usuário ou como Bot?",
+ "loginWebQr": "Você também pode fazer login automaticamente abrindo o Telegram no seu telefone, acessando Configurações > Dispositivos > Conectar Desktop e digitalizando o seguinte código QR:",
+ "loginWebQr1": "Abra o Telegram no seu telefone",
"loginWebQr2": "Vá para Configurações > Dispositivos > Conectar Desktop",
"loginWebQr3": "Aponte seu telefone para tela para confirmar o login",
"loginOptionBot": "Bot",
+ "loginOptionUser": "Usuário",
"loginBot": "Digite o token do seu bot: ",
"loginUser": "Digite seu número de telefone: ",
+ "loginQr": "Abra o Telegram no seu telefone, vá para Configurações > Dispositivos > Conectar Desktop e escaneie o QR code acima para fazer login automaticamente.",
+ "loginQrCodeSuccessful": "Login efetuado com sucesso, utilizando QR code!",
"loginQrCodeExpired": "O QR code expirou, gerando um novo...",
+ "loginManual": "Alternativamente, você também pode inserir um token de bot ou número de telefone para fazer login manualmente: ",
"loginUserCode": "Digite o código: ",
"loginUserPass": "Digite sua senha (dica %s): ",
"loginUserPassWeb": "Digite sua senha: ",
@@ -57,27 +58,25 @@
"signupFirstName": "Digite seu primeiro nome: ",
"signupLastName": "Digite seu sobrenome (pode ficar em branco): ",
"signupWeb": "Faça seu cadastro, por favor",
+ "signupFirstNameWeb": "Primeiro nome",
"signupLastNameWeb": "Sobrenome",
"loginNoCode": "Você não forneceu o código do telefone!",
"loginNoPass": "Você não forneceu a senha!",
- "loginBotTokenWeb": "token do Bot",
- "loginUserPhoneWeb": "Número telefone",
+ "loginNoName": "Você não forneceu o primeiro nome!",
+ "loginBotTokenWeb": "Token do bot",
+ "loginUserPhoneWeb": "Número de telefone",
"loginUserPhoneCodeWeb": "Código",
"done": "Concluído!",
"nearest_dc": "Estamos em %s, o DC mais próximo é %d.",
+ "serialization_ofd": "A serialização está desatualizada, reconstruindo o objeto!",
"api_not_set": "Você deve fornecer uma chave de API e um ID de API, você pode obter em @ my.telegram.org",
"session_corrupted": "A sessão está corrompida!",
"value_bigger_than_2147483647": "O valor fornecido %s é maior que 2147483647",
"value_smaller_than_2147483648": "O valor fornecido %s é menor que -2147483648",
+ "value_bigger_than_9223372036854775807": "O valor fornecido %s é maior que 9223372036854775807",
"value_smaller_than_9223372036854775808": "O valor fornecido %s é menor que -9223372036854775808",
"value_bigger_than_4294967296": "O valor fornecido %s é maior que 4294967296",
"value_smaller_than_0": "O valor fornecido %s é menor que 0",
- "loginQr": "Abra o Telegram no seu telefone, vá para Configurações > Dispositivos > Conectar Desktop e escaneie o QR code acima para fazer login automaticamente.",
- "loginQrCodeSuccessful": "Login efetuado com sucesso, utilizando QR code!",
- "loginManual": "Alternativa, você também pode inserir um token de bot ou número de telefone para fazer login manualmente: ",
- "loginNoName": "Você não forneceu o primeiro nome!",
- "serialization_ofd": "A serialização está desatualizada, reconstruindo o objeto!",
- "value_bigger_than_9223372036854775807": "O valor fornecido %s é maior que 9223372036854775807",
"encode_double_error": "Não foi possível codificar o número decimal corretamente",
"file_not_exist": "Arquivo não existe",
"deserialization_error": "Ocorreu um erro na deserialização",
@@ -92,13 +91,13 @@
"login_code_sent": "Código enviado com sucesso! Assim que receber o código, você deve usar a função completePhoneLogin.",
"login_code_uncalled": "Não estou esperando pelo código! Por favor, chame primeiro o método phoneLogin",
"login_2fa_enabled": "Autenticação de dois fatores ativada, você terá que chamar a função complete2falogin...",
+ "login_need_signup": "Uma conta não foi criada para este número, você terá que chamar a função completeSignup...",
"login_auth_key": "Conectando-se usando a chave de autenticação...",
"not_loggedIn": "Não estou conectado!",
+ "signup_uncalled": "Não estou esperando para me cadastrar! Por favor, chame primeiro os métodos phoneLogin e completePhoneLogin!",
"signing_up": "Cadastrando-se como um usuário normal...",
"signup_ok": "Cadastro realizado com sucesso!",
"2fa_uncalled": "Não estou esperando pela senha! Por favor, chame primeiro os métodos phoneLogin e completePhoneLogin!",
- "login_need_signup": "Uma conta não foi criada para este número, você terá que chamar a função completeSignup...",
- "signup_uncalled": "Não estou esperando para me cadastrar! Por favor, chame primeiro os métodos phoneLogin e completePhoneLogin!",
"peer_not_in_db": "Este peer não está presente no banco de dados interno de peers",
"call_error_1": "Não foi possível encontrar e aceitar a chamada %s",
"accepting_call": "Aceitando chamada de %s...",
@@ -108,7 +107,7 @@
"call_confirming": "Confirmando chamada de %s...",
"call_error_3": "Não foi possível encontrar e completar a chamada %s",
"call_completing": "Completando chamada de %s...",
- "fingerprint_invalid": "Chave de impressão inválida!",
+ "fingerprint_invalid": "Impressão digital da chave inválida!",
"call_discarding": "Descartando chamada %s...",
"file_parsing": "Processando %s...",
"src_file_invalid": "Arquivo de origem inválido foi fornecido: ",
@@ -119,6 +118,7 @@
"long_not_64": "O valor fornecido não tem 64 bytes de comprimento",
"array_invalid": "Você não forneceu um array válido",
"predicate_not_set": "Predicado (valor sob _) não foi definido!",
+ "update_madelineproto": "Você está executando uma versão antiga do MadelineProto, uma atualização é necessária: atualmente rodando %s, mas a versão mais recente com várias correções de bugs e novos recursos é %s!",
"type_extract_error": "Não foi possível extrair o tipo \"%s\", você deve atualizar o MadelineProto!",
"method_not_found": "Não foi possível encontrar o método: ",
"params_missing": "Parâmetro obrigatório ausente",
@@ -126,8 +126,149 @@
"stream_handle_invalid": "Um identificador de fluxo inválido foi fornecido.",
"length_too_big": "O comprimento é muito grande",
"string_required": "Uma string era esperada!",
- "waveform_value": "Um between de waveform deve estar entre 0 e 31!",
- "could_not_convert_object": "Não foi possível converter o objeto do tipo %s",
"waveform_must_have_100_values": "Um array de waveform deve ter 100 valores!",
- "update_madelineproto": "Você está executando uma versão antiga do MadelineProto, uma atualização é necessária: atualmente rodando %s, mas a versão mais recente com várias correções de bugs e novos recursos é %s!"
+ "waveform_value": "Um valor de waveform deve estar entre 0 e 31!",
+ "could_not_convert_object": "Não foi possível converter o objeto do tipo %s",
+ "type_extract_error_id": "Não foi possível extrair o tipo: %s com id %s, você deve atualizar o MadelineProto!",
+ "constructor_not_found": "Construtor não encontrado para o tipo: ",
+ "botapi_conversion_error": "Não é possível converter %s em um objeto da API de bots",
+ "non_text_conversion": "Ainda não é possível converter mensagens que não sejam de texto!",
+ "file_type_invalid": "Tipo de arquivo inválido detectado (%s)",
+ "static_analysis_minor": "Um problema menor foi encontrado durante a análise estática de %s: %s",
+ "static_analysis_severe": "Um problema grave foi encontrado durante a análise estática de %s: %s",
+ "secret_chat_skipping": "Não tenho o chat secreto %s no banco de dados, ignorando a mensagem...",
+ "must_have_declare_types": "por motivos de desempenho, a primeira instrução de um arquivo de event handler deve ser \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "o arquivo MadelineProto.log nunca deve ser excluído; em vez disso, defina um tamanho máximo personalizado nas configurações!",
+ "do_not_remove_MadelineProto.log_phar": "Não remova madeline.phar nem madeline.php, ou o MadelineProto irá travar. Se tiver algum problema com o MadelineProto, reporte-o em https://github.com/danog/MadelineProto ou https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "por motivos de desempenho, os event handlers não podem usar a função bloqueante não assíncrona %s; use %s em vez disso",
+ "do_not_use_blocking_class": "por motivos de desempenho, os handlers não podem usar a classe bloqueante não assíncrona %s; use %s em vez disso",
+ "do_not_use_deprecated_function": "a função %s está obsoleta; use %s em vez disso",
+ "do_not_use_non_root_require_in_event_handler": "por motivos de desempenho, você não deve usar require ou include dentro de uma classe de event handler; somente requires no nível raiz são permitidos.",
+ "do_not_use_yield": "O MadelineProto 8 não requer nem suporta o uso de yield em funções assíncronas; você deve remover todas as palavras-chave yield usadas anteriormente para chamadas de funções assíncronas",
+ "recommend_not_use_filesystem_function": "o uso da função %s não é recomendado, pois acessar o sistema de arquivos durante o processamento de updates deixará seu bot mais lento. Consulte https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions para ver formas alternativas de armazenar dados que não deixarão seu bot mais lento!",
+ "plugins_do_not_use_require": "por motivos de desempenho, os plugins só podem incluir automaticamente (include ou require) outros arquivos presentes na pasta de plugins por meio do autoloader PSR-4 (e não usando require() manualmente).",
+ "plugins_must_have_exactly_one_class": "um plugin deve definir exatamente uma classe! Para definir várias classes, interfaces ou traits, crie arquivos separados; eles serão carregados automaticamente pelo MadelineProto.",
+ "cli_need_dl.php_link": "Especifique a URL de um script de download ao usar getDownloadLink pela CLI!",
+ "invalid_dl.php_session": "%s não é um script de download válido porque seu ID de sessão é diferente (esperado %s, recebido %s)",
+ "need_dl.php": "Não foi possível gerar o script de download padrão (%s); crie um arquivo dl.php com o seguinte conteúdo: %s e passe sua URL como segundo parâmetro de getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Servidor de download de arquivos do Telegram (até 4GB), desenvolvido com MadelineProto!
Clique aqui para mais informações sobre como configurar seu próprio servidor de download de arquivos do Telegram!",
+ "dl.php_check_logs_make_sure_session_running": "O bot EventHandler do MadelineProto associado ou o servidor IPC do MadelineProto está offline; verifique os logs e certifique-se de que pelo menos um deles esteja em execução!",
+ "account_banned": "!!!!!!! AVISO !!!!!!!\nO sistema de prevenção de flood do Telegram suspendeu esta conta.\nPara continuar, é necessária uma verificação manual.\nEnvie um e-mail para recover@telegram.org pedindo o desbanimento do número de telefone %s e descreva brevemente o que você fará com este número.\nDepois, faça login novamente.\nSe você excluiu esta conta intencionalmente, ignore esta mensagem.",
+ "plugin_path_does_not_exist": "O caminho do plugin %s não existe!",
+ "could_not_connect_to_MadelineProto": "Não foi possível conectar ao MadelineProto. Para corrigir, habilite proc_open e remova as restrições de open_basedir ou desative as reescritas de caminho do servidor web! Se você já fez isso, certifique-se de que a versão CLI do PHP seja exatamente igual à versão web (mesma versão, extensões etc.) e consulte o arquivo MadelineProto.log para mais informações sobre o erro que impediu a inicialização do servidor IPC.",
+ "translate_madelineproto_web": "MadelineProto pode ser traduzido para o seu idioma (progresso atual da tradução: %d%%), clique aqui para contribuir com a tradução!",
+ "translate_madelineproto_cli": "MadelineProto pode ser traduzido para o seu idioma (progresso atual da tradução: %d%%), acesse https://github.com/danog/MadelineProto/tree/v8/langs para contribuir com a tradução!",
+ "apiInvalidWeb": "O API ID é um número e o API hash tem 32 caracteres: copie-os novamente de my.telegram.org.",
+ "webDoneLead": "O MadelineProto continua em execução no servidor: você pode fechar esta página.",
+ "apiChooseManualAuto": "Deseja obter o API ID e o API hash automaticamente de my.telegram.org (a) ou inseri-los manualmente (m)?",
+ "apiAutoFallbackManual": "Em vez disso, insira o API ID e o API hash manualmente.",
+ "apiSetupTitleWeb": "Obtenha seu API ID e API hash",
+ "apiSetupLeadWeb": "Todo aplicativo do Telegram precisa de um API ID e um API hash. O MadelineProto pode obtê-los para você em my.telegram.org, com o número de telefone de uma conta do Telegram já existente.",
+ "apiAutoPhoneHintWeb": "O my.telegram.org envia o código de login para o seu aplicativo do Telegram, não por SMS.",
+ "apiSendCodeWeb": "Enviar código",
+ "apiChooseManualWeb": "Já tenho um API ID",
+ "apiChooseAutoWeb": "Obter automaticamente",
+ "apiStartOverWeb": "Recomeçar",
+ "apiAutoCodeTitleWeb": "Digite o código do Telegram",
+ "apiAutoCodeLeadWeb": "O my.telegram.org enviou um código de login para o seu aplicativo do Telegram, no chat com o Telegram (não por SMS).",
+ "apiAutoCodeLabelWeb": "Código de login",
+ "apiCreateTitleWeb": "Crie seu aplicativo",
+ "apiCreateLeadWeb": "Esta conta ainda não tem nenhum aplicativo em my.telegram.org. Estes dados são exibidos apenas para você e podem ser alterados depois.",
+ "apiAppTitleLabelWeb": "Nome do aplicativo",
+ "apiAppShortNameLabelWeb": "Nome abreviado",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Descrição",
+ "apiCreateWeb": "Criar aplicativo",
+ "apiSaveWeb": "Salvar e continuar",
+ "apiAutoErrorTitle": "O my.telegram.org retornou um erro",
+ "apiCreateErrorTitle": "O my.telegram.org não criou o aplicativo",
+ "apiCreateVpsWarning": "O Telegram não permite que IPs de VPS, VPN e outros datacenters criem novos aplicativos em my.telegram.org, e a solicitação foi feita a partir do IP da máquina que executa o MadelineProto. Crie o aplicativo manualmente em https://my.telegram.org usando uma conexão residencial (como o seu celular nos dados móveis) e depois insira o API ID e o API hash.",
+ "loginTitleWeb": "Entrar no Telegram",
+ "loginLeadWeb": "Escolha a conta ou o bot com que esta instância do MadelineProto será executada.",
+ "loginTypeWeb": "Entrar como",
+ "loginUserPhoneHintWeb": "Com o código do país, por exemplo +39 123 456 7890.",
+ "loginBotTokenHintWeb": "O token que o @BotFather forneceu quando você criou o bot.",
+ "loginCodeTitleWeb": "Digite o código de login",
+ "loginCodeLeadWeb": "O Telegram enviou um código de login para o seu aplicativo do Telegram, ou por SMS se você não estiver conectado em nenhum outro lugar.",
+ "loginPasswordTitleWeb": "Verificação em duas etapas",
+ "loginPasswordLeadWeb": "Esta conta está protegida por uma senha, definida em Configurações > Privacidade e Segurança > Verificação em Duas Etapas.",
+ "loginPasswordLabelWeb": "Senha",
+ "signupTitleWeb": "Crie sua conta",
+ "signupLeadWeb": "Este número de telefone ainda não está no Telegram: escolha o nome da nova conta.",
+ "webContinue": "Continuar",
+ "webLogin": "Entrar",
+ "webError": "%s. Verifique e tente novamente.",
+ "webStepApp": "API ID e API hash",
+ "webStepAccount": "Conta",
+ "webStepVerify": "Verificação",
+ "webStepDone": "Em execução",
+ "webProgress": "Progresso da configuração",
+ "webDocs": "Documentação",
+ "webOptional": "opcional",
+ "webShowPassword": "Mostrar",
+ "webHidePassword": "Ocultar",
+ "webQrTitle": "Entrar com um QR code",
+ "webQrWaiting": "Aguardando a leitura…",
+ "webFieldRequired": "Preencha este campo.",
+ "webPhoneInvalid": "Digite o número de telefone com o código do país, por exemplo +39 123 456 7890.",
+ "tweb.Login.Title": "Entrar no MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Número de telefone inválido",
+ "tweb.Login.StartText": "Confirme o código do seu país\ne digite seu número de telefone.",
+ "tweb.Login.Code.SentSms": "Enviamos um SMS\ncom o código.",
+ "tweb.Login.Code.SentInApp": "Enviamos uma mensagem no Telegram\ncom o código.",
+ "tweb.Login.Code.SentCall": "Vamos ligar para você e ditar\no código.",
+ "tweb.Login.Code.SentEmail": "Verifique seu e-mail **%s** (não se esqueça da pasta de spam) e digite o código que acabamos de enviar.",
+ "tweb.Login.Code.SentUnknown": "Procure o código\nem todos os lugares (tipo: %s)",
+ "tweb.Login.Code.SentMissedCall": "Nos próximos segundos, você deve receber\numa ligação curta de **%s**. Não atenda —\napenas digite os últimos dígitos desse número.",
+ "tweb.Login.Code.SentSmsWord": "Enviamos um SMS com uma palavra secreta\npara o seu telefone **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Enviamos um SMS com uma palavra secreta que começa\ncom \"**%2$s**\" para o seu telefone **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Enviamos um SMS com uma frase secreta\npara o seu telefone **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Enviamos um SMS com uma frase secreta que começa\ncom \"**%2$s**\" para o seu telefone **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Palavra secreta",
+ "tweb.Login.Code.SecretPhrase": "Frase secreta",
+ "tweb.Login.Code.WordInvalid": "Incorreto, tente novamente",
+ "tweb.Login.Code.WordBeginningInvalid": "Palavra incorreta",
+ "tweb.Login.Password.Title": "Digite sua senha",
+ "tweb.Login.Password.Subtitle": "Sua conta está protegida com\numa senha adicional",
+ "tweb.Login.Register.Subtitle": "Digite seu nome\npara criar sua conta",
+ "tweb.PleaseWait": "Aguarde...",
+ "tweb.Code": "Código",
+ "tweb.LoginPassword": "Senha",
+ "tweb.YourName": "Seu nome",
+ "tweb.FirstName": "Nome (obrigatório)",
+ "tweb.LastName": "Sobrenome (opcional)",
+ "tweb.StartMessaging": "Começar a conversar",
+ "tweb.Country": "País",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Número de telefone",
+ "tweb.Login.Next": "Avançar",
+ "tweb.Login.QR.Title": "Entrar com QR code",
+ "tweb.Login.QR.Help1": "Abra o Telegram no seu celular",
+ "tweb.Login.QR.Help2": "Vá para **Configurações** > **Dispositivos** > **Conectar Desktop**",
+ "tweb.Login.QR.Help3": "Aponte seu celular para esta tela para confirmar o login",
+ "tweb.Login.QR.Cancel": "Entrar com número de telefone >",
+ "tweb.Login.QR.Login": "Entrar com QR code >",
+ "tweb.Login.QR.Subtitle": "Escaneie com o app do Telegram no seu celular",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Obtenha o código na seção Números do [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Código inválido",
+ "tweb.PHONE_CODE_EXPIRED": "Código expirado",
+ "tweb.PASSWORD_HASH_INVALID": "Senha incorreta",
+ "tweb.DarkMode": "Modo escuro",
+ "tweb.Error.AnError": "Ocorreu um erro. Tente novamente mais tarde.",
+ "tweb.AccDescr.LoginCode": "Código de login",
+ "tweb.Login.Bot": "Entrar como bot >",
+ "tweb.Login.Bot.Title": "Entrar como bot",
+ "tweb.Login.Bot.Subtitle": "Digite o token que o @BotFather forneceu\nquando você criou o bot.",
+ "tweb.Login.Bot.Token": "Token do bot",
+ "tweb.Login.Bot.Cancel": "Entrar como usuário >",
+ "tweb.Optional": "opcional",
+ "tweb.PHONE_NUMBER_INVALID": "Número de telefone inválido",
+ "tweb.PHONE_NUMBER_BANNED": "Este número de telefone está banido",
+ "tweb.PHONE_NUMBER_FLOOD": "Muitas tentativas, tente novamente mais tarde",
+ "tweb.PHONE_CODE_EMPTY": "Código inválido",
+ "tweb.PHONE_PASSWORD_FLOOD": "Muitas tentativas, tente novamente mais tarde",
+ "tweb.ACCESS_TOKEN_INVALID": "Token do bot inválido",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Este token do bot foi revogado",
+ "tweb.FIRSTNAME_INVALID": "Nome inválido",
+ "tweb.LASTNAME_INVALID": "Sobrenome inválido",
+ "tweb.Close": "Fechar"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ru.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ru.json
index 9170a90..8e75f8f 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ru.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/ru.json
@@ -1,44 +1,62 @@
{
+ "baseDirLimitation": "Настройка basedir сконфигурирована: это может повлиять на производительность и вызвать некоторые проблемы, отключите её если это возможно!",
+ "noReportPeers": "Внимание: не настроен ни один юзер для сообщения ошибок, пожалуйста добавьте этот метод в Event Handler",
+ "manualAdminActionRequired": "!!!!!!!!! НЕОБХОДИМЫ РУЧНЫЕ ДЕЙСТВИЯ СИСТЕМНОГО АДМИНИСТРАТОРА !!!!!!!!!",
+ "mmapErrorPart1": "Превышено максимальное количество маппированных зон памяти (%s, это НЕ потребление памяти, а mmap): пожалуйста увеличьте значение настройки ядра vm.max_map_count до 262144, чтобы исправить проблему.",
+ "mmapErrorPart2": "Чтобы исправить, необходимо запустить эту команду как root: %s",
+ "mmapErrorPart3": "Чтобы сохранить настройки даже после перезапуска: %s",
+ "mmapErrorPart4": "На Windows и WSL, проблема может испариться при увеличении размера page file; пожалуйста перейдите на нативный Linux если это не исправит проблему.",
+ "botAlreadyRunning": "Бот уже запущен!",
+ "extensionRequired": "MadelineProto нуждается в расширении %s. %s",
+ "extensionRequiredInstallWithApt": "Попробуйте запустить sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Следуйте инструкциям в %s для установки.",
+ "extensionRecommended": "Внимание: расширение %s не установлено, просьба его установить для ускорения MadelineProto!",
"go": "ОК",
+ "apiChooseManualAutoTip": "Также можно указать API ID/hash сразу в коде используя настройки: %s",
+ "apiChooseManualAutoTipWeb": "Также можно указать API ID/hash сразу в коде с помощью настроек.",
"apiChoosePrompt": "Ваш выбор (m/a): ",
- "apiManualInstructions0": "Залогинтесь в https://my.telegram.org",
+ "apiManualInstructions0": "Войдите в https://my.telegram.org",
"apiManualInstructions1": "Нажмите на \"API development tools\"",
"apiManualInstructions2": "Выберите \"create application\"",
"apiAppInstructionsManual0": "Имя вашего приложения, что угодно",
- "apiAppInstructionsManual1": "короткое имя вашего приложения, латиница и цифры, 5-32 букв",
- "apiAppInstructionsManual2": "Ссылка на сайт важего приложения, или t.me/username",
+ "apiAppInstructionsManual1": "короткое имя вашего приложения, латиница и цифры, 5-32 символа",
+ "apiAppInstructionsManual2": "Ссылка на сайт вашего приложения, или t.me/username",
"apiAppInstructionsManual3": "что угодно",
+ "apiAppInstructionsManual4": "Опишите ваше приложение здесь",
"apiManualWeb": "Введите ваш API ID и API hash",
"apiManualPrompt0": "Введите ваш API ID: ",
"apiManualPrompt1": "Введите ваш API hash: ",
- "apiAutoPrompt0": "Введите номер телефона который уже записан в Telegram: ",
+ "apiAutoWeb": "Введите номер телефона, который уже зарегистрирован в Telegram, чтобы получить API ID",
+ "apiAutoPrompt0": "Введите номер телефона, который уже зарегистрирован в Telegram: ",
"apiAutoPrompt1": "Введите код проверки, который вы получили в Telegram: ",
"apiAppWeb": "Введите API информацию",
+ "apiAppInstructionsAuto0": "Введите имя приложения, может быть что угодно: ",
+ "apiAppInstructionsAuto1": "Введите короткое имя вашего приложения, латиница и цифры, 5-32 символа: ",
"apiAppInstructionsAuto2": "Введите ссылку на сайт вашего приложения, или t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Введите платформу приложения: ",
"apiAppInstructionsAuto4": "Опишите ваше приложение: ",
- "apiAppInstructionsAutoTypeOther": "Другое (указано в описании)",
+ "apiAppInstructionsAutoTypeOther": "Другое (укажите в описании)",
"apiParamsError": "Вы не заполнили все обязательные параметры!",
- "apiChooseManualAutoTip": "Также можно указать API ID/hash сразу в коде используя настройки: %s",
- "apiChooseManualAutoTipWeb": "Также можно указать API ID/hash сразу в коде с помощью настроек.",
- "apiAppInstructionsManual4": "Опишите ваше приложение сдесь",
- "apiAutoWeb": "Введите номер телефона который уже записан в Телеграме чтобы получить API ID",
- "apiAppInstructionsAuto0": "Введите имя приложения, может быть что угодно: ",
- "apiAppInstructionsAuto1": "Введите короткое имя вашего приложения, латиница и цифры, 5-32 букв: ",
- "apiAppInstructionsAuto3": "Введите платформу приложения: ",
"apiError": "ОШИБКА: %s. Попробуйте снова.",
+ "loginChoosePromptWeb": "Авторизоваться как пользователь или как бот?",
+ "loginWebQr": "Вы также можете войти автоматически: откройте Telegram на смартфоне, перейдите в Настройки > Устройства > Подключить устройство и отсканируйте этот QR код:",
"loginWebQr1": "Откройте Telegram в вашем смартфоне",
"loginWebQr2": "Откройте Настройки > Устройства > Подключить устройство",
+ "loginWebQr3": "Наведите ваш смартфон на этот экран чтобы подтвердить вход",
+ "loginOptionBot": "Бот",
+ "loginOptionUser": "Пользователь",
+ "loginBot": "Введите токен бота: ",
"loginUser": "Номер телефона: ",
- "loginQr": "Отсканируйте QR код выше чтобы войти автоматически.",
+ "loginQr": "Откройте Telegram на смартфоне, перейдите в Настройки > Устройства > Подключить устройство и отсканируйте QR код выше, чтобы войти автоматически.",
"loginQrCodeSuccessful": "Вход по QR коду прошел успешно!",
+ "loginQrCodeExpired": "QR код больше не действует, генерируем новый...",
+ "loginManual": "Вы также можете ввести токен бота или номер телефона чтобы войти вручную: ",
"loginUserCode": "Введите код: ",
"loginUserPass": "Введите ваш пароль (подсказка %s): ",
"loginUserPassWeb": "Введите ваш пароль: ",
"loginUserPassHint": "Подсказка: %s",
"signupFirstName": "Введите ваше имя: ",
- "loginOptionBot": "Бот",
- "loginOptionUser": "Пользователь",
- "loginBot": "Введите токен бота: ",
+ "signupLastName": "Введите вашу фамилию (может быть пустым): ",
"signupWeb": "Зарегистрируйтесь, пожалуйста",
"signupFirstNameWeb": "Имя",
"signupLastNameWeb": "Фамилия",
@@ -46,89 +64,211 @@
"loginNoPass": "Вы не ввели пароль!",
"loginNoName": "Вы не ввели имя!",
"loginBotTokenWeb": "Токен бота",
+ "loginUserPhoneWeb": "Номер телефона",
"loginUserPhoneCodeWeb": "Код",
"done": "Готово!",
"nearest_dc": "Вы в %s, ближайший ДЦ: %d.",
- "loginQrCodeExpired": "QR код больше не действует, генерируем новый...",
- "signupLastName": "Введите вашу фамилию (может быть пустым): ",
- "loginUserPhoneWeb": "Номер телефона",
- "loginManual": "Вы также можете ввести токен бота или номер телефона чтобы войти вручную: ",
- "loginChoosePromptWeb": "Авторизоваться как пользователь или как бот?",
- "loginWebQr": "Вы также можете войти, отсканировав QR код:",
- "loginWebQr3": "Наведите ваш смартфон на этот экран чтобы подтвердить вход",
- "api_not_set": "Необходимо указать свой api ключ, достаньте свой @ my.telegram.org",
- "value_smaller_than_2147483648": "Значение %s меньше чем -2147483648",
- "value_bigger_than_9223372036854775807": "Значение %s больше чем 9223372036854775807",
+ "serialization_ofd": "Сериализация устарела, объект реконструируется!",
+ "api_not_set": "Необходимо указать api key и api id, получите свои на my.telegram.org",
"session_corrupted": "Сессия повреждена!",
"value_bigger_than_2147483647": "Значение %s больше чем 2147483647",
+ "value_smaller_than_2147483648": "Значение %s меньше чем -2147483648",
+ "value_bigger_than_9223372036854775807": "Значение %s больше чем 9223372036854775807",
"value_smaller_than_9223372036854775808": "Значение %s меньше чем -9223372036854775808",
- "serialization_ofd": "Сериализация старая, реконструкция объекта!",
- "logout_ok": "Logout!",
- "already_loggedIn": "Этот инстанс MadelineProto уже залогинен!",
- "login_ok": "Мы залогинены!",
- "rpc_tg_error": "Телеграм возвратил RPC ошибку: %s (%s), из-за %s:%s%sTL trace:",
- "madelineproto_ready": "MadelineProto готов!",
- "mmapErrorPart1": "Превышено максимальное количество маппированных зон памяти (%s, это НЕ потребление памяти, а mmap): пожалуйста увеличьте значение настройки ядра vm.max_map_count до 262144, чтобы исправить проблему.",
- "mmapErrorPart2": "Чтобы исправить, необходимо запустить эту команду как root: %s",
- "mmapErrorPart3": "Чтобы сохранить настройки даже после перезапуска: %s",
- "mmapErrorPart4": "На Windows и WSL, проблема может испариться при увеличении размера page file; пожалуйста перейдите на нативный Linux если это не исправит проблему.",
- "extensionRequired": "MadelineProto нуждается в расширении %s. %s",
- "extensionRequiredInstallWithApt": "Попробуйте запустить sudo apt-get install %s.",
- "extensionRequiredInstallWithCustomInstructions": "Следуйте инструкциям в %s для установки.",
- "extensionRecommended": "Внимание: расширение %s не установлено, просьба его установить для ускорения MadelineProto!",
- "botAlreadyRunning": "Бот уже запущен!",
"value_bigger_than_4294967296": "Значение %s больше чем 4294967296",
"value_smaller_than_0": "Значение %s меньше нуля",
- "encode_double_error": "Невозможно создать double",
+ "encode_double_error": "Невозможно корректно закодировать double",
"file_not_exist": "Файл не существует",
- "deserialization_error": "Произошла ошибка при deserialization",
- "noReportPeers": "Внимание: не настроен ни один юзер для сообщения ошибок, пожалуйста добавьте этот метод в Event Handler",
- "manualAdminActionRequired": "!!!!!!!!! НЕОБХОДИМЫ РУЧНЫЕ ДЕЙСТВИЯ СИСТЕМНОГО АДМИНИСТРАТОРА !!!!!!!!!",
- "login_code_uncalled": "Я не ожидаю код! Пожалуйста сначала вызовите метод phoneLogin",
- "login_auth_key": "Вход с помощью ключа авторизации...",
- "signing_up": "Вход под нормальным пользователем...",
- "baseDirLimitation": "Настройка basedir сконфигурирована: это может повлиять на производительность и вызвать некоторые проблемы, отключите её если это возможно!",
+ "deserialization_error": "Произошла ошибка при десериализации",
+ "rpc_tg_error": "Телеграм возвратил RPC ошибку: %s (%s), из-за %s:%s%sTL trace:",
+ "madelineproto_ready": "MadelineProto готов!",
+ "logout_ok": "Выход выполнен успешно!",
+ "already_loggedIn": "Этот инстанс MadelineProto уже залогинен!",
+ "login_ok": "Мы залогинены!",
+ "login_user": "Вхожу как пользователь...",
+ "login_bot": "Вхожу как бот...",
"login_code_sending": "Отправка кода...",
"login_code_sent": "Код успешно отправлен! Как только Вы получите код Вам нужно использовать функцию completePhoneLogin.",
+ "login_code_uncalled": "Я не ожидаю код! Пожалуйста сначала вызовите метод phoneLogin",
"login_2fa_enabled": "2FA активно, вам необходимо сначала вызвать функцию complete2falogin...",
- "not_loggedIn": "Я вошёл в систему!",
+ "login_need_signup": "Для этого номера телефона не создана учётная запись, вам необходимо вызвать функцию completeSignup...",
+ "login_auth_key": "Вход с помощью ключа авторизации...",
+ "not_loggedIn": "Я не вошёл в систему!",
+ "signup_uncalled": "Я не ожидаю регистрации! Пожалуйста, вызовите сначала методы phoneLogin и completePhoneLogin!",
+ "signing_up": "Регистрация в качестве обычного пользователя...",
+ "signup_ok": "Регистрация прошла успешно!",
+ "2fa_uncalled": "Я не жду сейчас пароля! Вызовите сначала методы phoneLogin и completePhoneLogin!",
+ "peer_not_in_db": "Этот peer не находится во внутренней базе",
"call_error_1": "Не смог найти и принять звонок %s",
- "string_required": "Ожидана string!",
- "waveform_must_have_100_values": "Массив waveform должен иметь 100 значений!",
- "waveform_value": "Значение waveform должно быть между 0 и 31!",
- "method_not_found": "Невозможно найти метод: ",
- "params_missing": "Не хватает необходимого папаметра",
- "sec_peer_not_in_db": "Этого секретного чата нету во внутренней базе",
- "length_too_big": "Длина слишком большая",
- "login_user": "Вхожу как пользователь...",
- "signup_ok": "Запись прошла успешно!",
- "accepting_call": "Принимяю звонок от %s...",
+ "accepting_call": "Принимаю звонок от %s...",
+ "call_already_accepted": "Звонок %s уже был принят",
"call_already_declined": "Звонок %s уже был отвергнут",
- "call_error_3": "Невозможно найти и подтвердить звонок %s",
+ "call_error_2": "Невозможно найти и подтвердить звонок %s",
+ "call_confirming": "Подтверждаю звонок от %s...",
+ "call_error_3": "Невозможно найти и завершить звонок %s",
"call_completing": "Финализирую звонок от %s...",
"fingerprint_invalid": "Невалидный фингерпринт ключа!",
+ "call_discarding": "Отвергаю звонок %s...",
"file_parsing": "Чтение %s...",
"src_file_invalid": "Невалидный файл: ",
"bool_error": "Невозможно считать boolean",
- "not_numeric": "Данное значение не цифра",
- "long_not_32": "Длинна данного значения не равна 32 байтам",
+ "not_numeric": "Данное значение не является числом",
+ "long_not_16": "Длина данного значения не равна 16 байтам",
+ "long_not_32": "Длина данного значения не равна 32 байтам",
+ "long_not_64": "Длина данного значения не равна 64 байтам",
"array_invalid": "Вы указали невалидный массив",
"predicate_not_set": "Предикат (значение под ключом _) не был указан!",
- "login_bot": "Вхожу как бот...",
- "login_need_signup": "На этот номер телефона не найдена учётная запись Телеграм...",
- "long_not_16": "Длинна данного значения не равна 16 байтам",
- "signup_uncalled": "Я не в процессе записи! Пожалуйста, вызовите сначала методы phoneLogin и completePhoneLogin!",
- "2fa_uncalled": "Я не жду сейчас пароля! Вызовите сначала методы phoneLogin и completePhoneLogin!",
- "call_already_accepted": "Звонок %s уже был принят",
- "call_error_2": "Невозможно найти и подтвердить звонок %s",
- "call_confirming": "Подтверждаю звонок от %s...",
- "translate_madelineproto_cli": "MadelineProto можно локализировать на ваш язык (на данный момент переведено: %d%%), откройте https://weblate.madelineproto.xyz чтобы помочь с переводом!",
- "translate_madelineproto_web": "MadelineProto можно локализировать на ваш язык (на данный момент переведено: %d%%), кликните сюда чтобы помочь с переводом!",
- "peer_not_in_db": "Этот peer не находится во внутренней базе",
- "call_discarding": "Отвергаю звонок %s...",
- "stream_handle_invalid": "Использован невалидный стрим.",
- "long_not_64": "Длинна данного значения не равна 64 байтам",
- "update_madelineproto": "Вы используете старую версию MadelineProto, необходимо обновится: сейчас используется версия %s, но последняя версия со многими поправками и с новым функционалом - %s!",
+ "update_madelineproto": "Вы используете старую версию MadelineProto, необходимо обновиться: сейчас используется версия %s, но последняя версия со многими исправлениями и новым функционалом - %s!",
"type_extract_error": "Невозможно распаковать тип \"%s\", необходимо обновить MadelineProto!",
- "could_not_convert_object": "Невозможно сконвертировать объект типа %s"
+ "method_not_found": "Невозможно найти метод: ",
+ "params_missing": "Не хватает обязательного параметра",
+ "sec_peer_not_in_db": "Этого секретного чата нет во внутренней базе",
+ "stream_handle_invalid": "Использован невалидный стрим.",
+ "length_too_big": "Длина слишком большая",
+ "string_required": "Ожидалась строка!",
+ "waveform_must_have_100_values": "Массив waveform должен иметь 100 значений!",
+ "waveform_value": "Значение waveform должно быть между 0 и 31!",
+ "could_not_convert_object": "Невозможно сконвертировать объект типа %s",
+ "type_extract_error_id": "Невозможно распаковать тип %s с id %s, необходимо обновить MadelineProto!",
+ "constructor_not_found": "Не найден конструктор для типа: ",
+ "botapi_conversion_error": "Невозможно сконвертировать %s в объект Bot API",
+ "non_text_conversion": "Конвертация нетекстовых сообщений пока не поддерживается!",
+ "file_type_invalid": "Обнаружен невалидный тип файла (%s)",
+ "static_analysis_minor": "При статическом анализе %s обнаружена незначительная проблема: %s",
+ "static_analysis_severe": "При статическом анализе %s обнаружена серьёзная проблема: %s",
+ "secret_chat_skipping": "Секретного чата %s нет в базе, пропускаю сообщение...",
+ "must_have_declare_types": "по соображениям производительности первой инструкцией файла event handler'а должна быть \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "файл MadelineProto.log никогда нельзя удалять, вместо этого укажите свой максимальный размер в настройках!",
+ "do_not_remove_MadelineProto.log_phar": "Пожалуйста, не удаляйте madeline.phar или madeline.php, иначе MadelineProto упадёт. Если у вас возникли проблемы с MadelineProto, сообщите о них на https://github.com/danog/MadelineProto или в https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "по соображениям производительности event handler'ы не должны использовать неасинхронную блокирующую функцию %s, используйте вместо неё %s",
+ "do_not_use_blocking_class": "по соображениям производительности handler'ы не должны использовать неасинхронный блокирующий класс %s, используйте вместо него %s",
+ "do_not_use_deprecated_function": "функция %s устарела, используйте вместо неё %s",
+ "do_not_use_non_root_require_in_event_handler": "по соображениям производительности нельзя использовать require или include внутри класса event handler'а, разрешены только require на верхнем уровне файла.",
+ "do_not_use_yield": "MadelineProto 8 не требует и не поддерживает использование yield в асинхронных функциях, необходимо удалить все ключевые слова yield, которые ранее использовались для вызова асинхронных функций",
+ "recommend_not_use_filesystem_function": "не рекомендуется использовать функцию %s, так как обращение к файловой системе во время обработки апдейтов замедлит вашего бота, список альтернативных способов хранения данных, которые не замедлят вашего бота, смотрите на https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions!",
+ "plugins_do_not_use_require": "по соображениям производительности плагины могут подключать (include или require) другие файлы из папки плагинов только автоматически, через автозагрузчик PSR-4 (а не вручную через require()).",
+ "plugins_must_have_exactly_one_class": "плагин должен определять ровно один класс! Чтобы определить несколько классов, интерфейсов или трейтов, создайте отдельные файлы, MadelineProto загрузит их автоматически.",
+ "cli_need_dl.php_link": "Пожалуйста, укажите URL скрипта загрузки при использовании getDownloadLink через CLI!",
+ "invalid_dl.php_session": "%s не является валидным скриптом загрузки, так как его ID сессии отличается (ожидался %s, получен %s)",
+ "need_dl.php": "Не удалось сгенерировать скрипт загрузки по умолчанию (%s), пожалуйста, создайте файл dl.php со следующим содержимым: %s и передайте его URL вторым параметром getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Сервер загрузки файлов Telegram (до 4GB) на базе MadelineProto!
Нажмите сюда, чтобы узнать, как настроить свой собственный сервер загрузки файлов Telegram!",
+ "dl.php_check_logs_make_sure_session_running": "Связанный бот EventHandler MadelineProto или IPC сервер MadelineProto не запущен, пожалуйста, проверьте логи и убедитесь, что запущен хотя бы один из них!",
+ "account_banned": "!!!!!!! ВНИМАНИЕ !!!!!!!\nСистема защиты от флуда Telegram заблокировала этот аккаунт.\nДля продолжения необходима ручная проверка.\nОтправьте письмо на recover@telegram.org с просьбой разблокировать номер телефона %s и кратко опишите, для чего вы будете использовать этот номер.\nЗатем войдите снова.\nЕсли вы удалили этот аккаунт намеренно, проигнорируйте это сообщение.",
+ "plugin_path_does_not_exist": "Путь к плагину %s не существует!",
+ "could_not_connect_to_MadelineProto": "Не удалось подключиться к MadelineProto, чтобы исправить, включите proc_open и уберите ограничения open_basedir или отключите перезапись путей веб-сервера! Если вы уже это сделали, убедитесь, что CLI версия PHP точно такая же, как веб-версия (та же версия, расширения и т.д.), и посмотрите файл MadelineProto.log, чтобы узнать подробнее об ошибке, из-за которой не запустился IPC сервер.",
+ "translate_madelineproto_web": "MadelineProto можно локализировать на ваш язык (на данный момент переведено: %d%%), кликните сюда чтобы помочь с переводом!",
+ "translate_madelineproto_cli": "MadelineProto можно локализировать на ваш язык (на данный момент переведено: %d%%), откройте https://github.com/danog/MadelineProto/tree/v8/langs чтобы помочь с переводом!",
+ "apiInvalidWeb": "API ID — это число, а API hash состоит из 32 символов: скопируйте их ещё раз с my.telegram.org.",
+ "webDoneLead": "MadelineProto продолжает работать на сервере: эту страницу можно закрыть.",
+ "apiChooseManualAuto": "Получить API ID и API hash автоматически с my.telegram.org (a) или ввести их вручную (m)?",
+ "apiAutoFallbackManual": "Вместо этого введите API ID и API hash вручную.",
+ "apiSetupTitleWeb": "Получите API ID и API hash",
+ "apiSetupLeadWeb": "Каждому приложению Telegram нужны API ID и API hash. MadelineProto может получить их за вас с my.telegram.org по номеру телефона существующего аккаунта Telegram.",
+ "apiAutoPhoneHintWeb": "my.telegram.org отправляет код входа в приложение Telegram, а не по SMS.",
+ "apiSendCodeWeb": "Отправить код",
+ "apiChooseManualWeb": "У меня уже есть API ID",
+ "apiChooseAutoWeb": "Получить автоматически",
+ "apiStartOverWeb": "Начать заново",
+ "apiAutoCodeTitleWeb": "Введите код из Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org отправил код входа в ваше приложение Telegram, в чат с Telegram (не по SMS).",
+ "apiAutoCodeLabelWeb": "Код входа",
+ "apiCreateTitleWeb": "Создайте приложение",
+ "apiCreateLeadWeb": "У этого аккаунта пока нет приложения на my.telegram.org. Эти данные видны только вам, и их можно изменить позже.",
+ "apiAppTitleLabelWeb": "Название приложения",
+ "apiAppShortNameLabelWeb": "Короткое имя",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Описание",
+ "apiCreateWeb": "Создать приложение",
+ "apiSaveWeb": "Сохранить и продолжить",
+ "apiAutoErrorTitle": "my.telegram.org вернул ошибку",
+ "apiCreateErrorTitle": "my.telegram.org не создал приложение",
+ "apiCreateVpsWarning": "Telegram не позволяет создавать новые приложения на my.telegram.org с IP-адресов VPS, VPN и других дата-центров, а запрос был отправлен с IP машины, на которой работает MadelineProto. Создайте приложение вручную на https://my.telegram.org с домашнего подключения (например, с телефона через мобильный интернет), затем введите API ID и API hash.",
+ "loginTitleWeb": "Вход в Telegram",
+ "loginLeadWeb": "Выберите аккаунт или бота, от имени которого будет работать этот экземпляр MadelineProto.",
+ "loginTypeWeb": "Войти как",
+ "loginUserPhoneHintWeb": "С кодом страны, например +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Токен, который выдал @BotFather при создании бота.",
+ "loginCodeTitleWeb": "Введите код входа",
+ "loginCodeLeadWeb": "Telegram отправил код входа в ваше приложение Telegram или по SMS, если вы больше нигде не авторизованы.",
+ "loginPasswordTitleWeb": "Двухэтапная аутентификация",
+ "loginPasswordLeadWeb": "Этот аккаунт защищён паролем, заданным в разделе Настройки > Конфиденциальность > Облачный пароль.",
+ "loginPasswordLabelWeb": "Пароль",
+ "signupTitleWeb": "Создайте аккаунт",
+ "signupLeadWeb": "Этот номер телефона ещё не зарегистрирован в Telegram: выберите имя нового аккаунта.",
+ "webContinue": "Продолжить",
+ "webLogin": "Войти",
+ "webError": "%s. Проверьте и попробуйте снова.",
+ "webStepApp": "API ID и API hash",
+ "webStepAccount": "Аккаунт",
+ "webStepVerify": "Подтверждение",
+ "webStepDone": "Работает",
+ "webProgress": "Ход настройки",
+ "webDocs": "Документация",
+ "webOptional": "необязательно",
+ "webShowPassword": "Показать",
+ "webHidePassword": "Скрыть",
+ "webQrTitle": "Вход по QR-коду",
+ "webQrWaiting": "Ожидание сканирования…",
+ "webFieldRequired": "Заполните это поле.",
+ "webPhoneInvalid": "Введите номер телефона с кодом страны, например +39 123 456 7890.",
+ "tweb.Login.Title": "Вход в MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Неверный номер телефона",
+ "tweb.Login.StartText": "Пожалуйста, проверьте код страны\nи введите свой номер телефона.",
+ "tweb.Login.Code.SentSms": "Мы отправили вам SMS\nс кодом.",
+ "tweb.Login.Code.SentInApp": "Мы отправили вам сообщение в Telegram\nс кодом.",
+ "tweb.Login.Code.SentCall": "Мы позвоним вам и продиктуем\nкод.",
+ "tweb.Login.Code.SentEmail": "Проверьте почту **%s** (не забудьте про папку «Спам») и введите код, который мы только что отправили.",
+ "tweb.Login.Code.SentUnknown": "Поищите код\nвезде (тип: %s)",
+ "tweb.Login.Code.SentMissedCall": "В течение нескольких секунд вам поступит\nкороткий звонок с номера **%s**. Не отвечайте —\nпросто введите последние цифры этого номера.",
+ "tweb.Login.Code.SentSmsWord": "Мы отправили SMS с секретным словом\nна ваш номер **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Мы отправили SMS с секретным словом, которое начинается\nс «**%2$s**», на ваш номер **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Мы отправили SMS с секретной фразой\nна ваш номер **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Мы отправили SMS с секретной фразой, которая начинается\nс «**%2$s**», на ваш номер **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Секретное слово",
+ "tweb.Login.Code.SecretPhrase": "Секретная фраза",
+ "tweb.Login.Code.WordInvalid": "Неверно, попробуйте ещё раз",
+ "tweb.Login.Code.WordBeginningInvalid": "Неверное слово",
+ "tweb.Login.Password.Title": "Введите пароль",
+ "tweb.Login.Password.Subtitle": "Ваш аккаунт защищён\nдополнительным паролем",
+ "tweb.Login.Register.Subtitle": "Введите своё имя,\nчтобы создать аккаунт",
+ "tweb.PleaseWait": "Пожалуйста, подождите...",
+ "tweb.Code": "Код",
+ "tweb.LoginPassword": "Пароль",
+ "tweb.YourName": "Ваше имя",
+ "tweb.FirstName": "Имя (обязательно)",
+ "tweb.LastName": "Фамилия (необязательно)",
+ "tweb.StartMessaging": "Начать общение",
+ "tweb.Country": "Страна",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Номер телефона",
+ "tweb.Login.Next": "Далее",
+ "tweb.Login.QR.Title": "Вход по QR-коду",
+ "tweb.Login.QR.Help1": "Откройте Telegram на телефоне",
+ "tweb.Login.QR.Help2": "Перейдите в **Настройки** > **Устройства** > **Подключить устройство**",
+ "tweb.Login.QR.Help3": "Наведите телефон на этот экран, чтобы подтвердить вход",
+ "tweb.Login.QR.Cancel": "Вход по номеру телефона >",
+ "tweb.Login.QR.Login": "Вход по QR-коду >",
+ "tweb.Login.QR.Subtitle": "Отсканируйте приложением Telegram на телефоне",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Получите код в разделе Numbers на [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Неверный код",
+ "tweb.PHONE_CODE_EXPIRED": "Срок действия кода истёк",
+ "tweb.PASSWORD_HASH_INVALID": "Неверный пароль",
+ "tweb.DarkMode": "Тёмная тема",
+ "tweb.Error.AnError": "Произошла ошибка. Попробуйте позже.",
+ "tweb.AccDescr.LoginCode": "Код входа",
+ "tweb.Login.Bot": "Войти как бот >",
+ "tweb.Login.Bot.Title": "Вход как бот",
+ "tweb.Login.Bot.Subtitle": "Введите токен, который выдал @BotFather\nпри создании бота.",
+ "tweb.Login.Bot.Token": "Токен бота",
+ "tweb.Login.Bot.Cancel": "Войти как пользователь >",
+ "tweb.Optional": "необязательно",
+ "tweb.PHONE_NUMBER_INVALID": "Неверный номер телефона",
+ "tweb.PHONE_NUMBER_BANNED": "Этот номер телефона заблокирован",
+ "tweb.PHONE_NUMBER_FLOOD": "Слишком много попыток, попробуйте позже",
+ "tweb.PHONE_CODE_EMPTY": "Неверный код",
+ "tweb.PHONE_PASSWORD_FLOOD": "Слишком много попыток, попробуйте позже",
+ "tweb.ACCESS_TOKEN_INVALID": "Неверный токен бота",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Этот токен бота был отозван",
+ "tweb.FIRSTNAME_INVALID": "Недопустимое имя",
+ "tweb.LASTNAME_INVALID": "Недопустимая фамилия",
+ "tweb.Close": "Закрыть"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/tr.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/tr.json
new file mode 100644
index 0000000..ad933e4
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/tr.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "Bir basedir kısıtlaması yapılandırılmış: bu, performansı etkileyebilir ve bazı sorunlara yol açabilir, mümkünse lütfen devre dışı bırakın!",
+ "noReportPeers": "Uyarı: hiçbir rapor alıcısı (report peers) ayarlanmamış, lütfen olay işleyicinize aşağıdaki metodu ekleyin",
+ "manualAdminActionRequired": "!!!!!!!!! MANUEL SİSTEM YÖNETİCİSİ MÜDAHALESİ GEREKLİ !!!!!!!!!",
+ "mmapErrorPart1": "Belleğe eşlenmiş (mmap) bölge sayısının üst sınırına ulaşıldı (%s): düzeltmek için lütfen vm.max_map_count çekirdek ayarını 262144 değerine yükseltin.",
+ "mmapErrorPart2": "Düzeltmek için aşağıdaki komutu root olarak çalıştırın: %s",
+ "mmapErrorPart3": "Değişikliğin yeniden başlatmalardan sonra da kalıcı olması için: %s",
+ "mmapErrorPart4": "Windows ve WSL'de sayfa dosyasının (pagefile) boyutunu artırmak yardımcı olabilir; sorun devam ederse lütfen yerel (native) Linux'a geçin.",
+ "botAlreadyRunning": "Bot zaten çalışıyor!",
+ "extensionRequired": "MadelineProto'nun çalışması için %s eklentisi gereklidir. %s",
+ "extensionRequiredInstallWithApt": "sudo apt-get install %s komutunu çalıştırmayı deneyin.",
+ "extensionRequiredInstallWithCustomInstructions": "Kurmak için %s adresindeki talimatları izleyin.",
+ "extensionRecommended": "Uyarı: %s eklentisi kurulu değil, MadelineProto'yu hızlandırmak için lütfen kurun!",
+ "go": "Devam",
+ "apiChooseManualAutoTip": "API ID/hash bilgisini ayarlar aracılığıyla doğrudan kodda da sağlayabileceğinizi unutmayın: %s",
+ "apiChooseManualAutoTipWeb": "API ID/hash bilgisini ayarlar aracılığıyla doğrudan kodda da sağlayabileceğinizi unutmayın.",
+ "apiChoosePrompt": "Seçiminiz (m/a): ",
+ "apiManualInstructions0": "https://my.telegram.org adresinde oturum açın",
+ "apiManualInstructions1": "\"API development tools\" bölümüne gidin",
+ "apiManualInstructions2": "\"create application\" seçeneğine tıklayın",
+ "apiAppInstructionsManual0": "uygulamanızın adı, herhangi bir şey olabilir",
+ "apiAppInstructionsManual1": "uygulamanızın kısa adı, alfanümerik, 5-32 karakter",
+ "apiAppInstructionsManual2": "uygulamanızın/web sitenizin URL'si veya t.me/yourusername",
+ "apiAppInstructionsManual3": "herhangi bir şey",
+ "apiAppInstructionsManual4": "Uygulamanızı burada açıklayın",
+ "apiManualWeb": "API ID ve API hash bilgilerinizi girin",
+ "apiManualPrompt0": "API ID'nizi girin: ",
+ "apiManualPrompt1": "API hash'inizi girin: ",
+ "apiAutoWeb": "API ID'yi almak için Telegram'a zaten kayıtlı bir telefon numarası girin",
+ "apiAutoPrompt0": "Telegram'a zaten kayıtlı bir telefon numarası girin: ",
+ "apiAutoPrompt1": "Telegram'da aldığınız doğrulama kodunu girin: ",
+ "apiAppWeb": "API bilgilerini girin",
+ "apiAppInstructionsAuto0": "Uygulamanın adını girin, herhangi bir şey olabilir: ",
+ "apiAppInstructionsAuto1": "Uygulamanın kısa adını girin, alfanümerik, 5-32 karakter: ",
+ "apiAppInstructionsAuto2": "Uygulamanın/web sitesinin URL'sini veya t.me/yourusername girin: ",
+ "apiAppInstructionsAuto3": "Uygulamanın platformunu girin: ",
+ "apiAppInstructionsAuto4": "Uygulamanızı açıklayın: ",
+ "apiAppInstructionsAutoTypeOther": "Diğer (açıklamada belirtin)",
+ "apiParamsError": "Gerekli parametrelerin tümünü sağlamadınız!",
+ "apiError": "HATA: %s. Tekrar deneyin.",
+ "loginChoosePromptWeb": "Kullanıcı olarak mı yoksa bot olarak mı oturum açmak istiyorsunuz?",
+ "loginWebQr": "Telefonunuzda Telegram'ı açıp Ayarlar > Cihazlar > Masaüstü Cihazı Bağla bölümüne giderek aşağıdaki QR kodunu tarayarak da otomatik olarak oturum açabilirsiniz:",
+ "loginWebQr1": "Telefonunuzda Telegram'ı açın",
+ "loginWebQr2": "Ayarlar > Cihazlar > Masaüstü Cihazı Bağla bölümüne gidin",
+ "loginWebQr3": "Oturum açmayı onaylamak için telefonunuzu bu ekrana doğrultun",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Kullanıcı",
+ "loginBot": "Bot token'ınızı girin: ",
+ "loginUser": "Telefon numaranızı girin: ",
+ "loginQr": "Otomatik olarak oturum açmak için telefonunuzda Telegram'ı açın, Ayarlar > Cihazlar > Masaüstü Cihazı Bağla bölümüne gidin ve yukarıdaki QR kodunu tarayın.",
+ "loginQrCodeSuccessful": "QR kodu ile oturum açma başarılı!",
+ "loginQrCodeExpired": "QR kodunun süresi doldu, yenisi oluşturuluyor...",
+ "loginManual": "Alternatif olarak, manuel olarak oturum açmak için bir bot token'ı veya telefon numarası da girebilirsiniz: ",
+ "loginUserCode": "Kodu girin: ",
+ "loginUserPass": "Parolanızı girin (ipucu: %s): ",
+ "loginUserPassWeb": "Parolanızı girin: ",
+ "loginUserPassHint": "İpucu: %s",
+ "signupFirstName": "Adınızı girin: ",
+ "signupLastName": "Soyadınızı girin (boş bırakılabilir): ",
+ "signupWeb": "Lütfen kaydolun",
+ "signupFirstNameWeb": "Ad",
+ "signupLastNameWeb": "Soyad",
+ "loginNoCode": "Doğrulama kodunu girmediniz!",
+ "loginNoPass": "Parolayı girmediniz!",
+ "loginNoName": "Adı girmediniz!",
+ "loginBotTokenWeb": "Bot token'ı",
+ "loginUserPhoneWeb": "Telefon numarası",
+ "loginUserPhoneCodeWeb": "Kod",
+ "done": "Tamamlandı!",
+ "nearest_dc": "Konumumuz: %s, en yakın DC: %d.",
+ "serialization_ofd": "Serileştirme güncel değil, nesne yeniden oluşturuluyor!",
+ "api_not_set": "Bir api key ve api id sağlamanız gerekir, kendinizinkini my.telegram.org adresinden alın",
+ "session_corrupted": "Oturum bozuk!",
+ "value_bigger_than_2147483647": "Sağlanan %s değeri 2147483647'den büyük",
+ "value_smaller_than_2147483648": "Sağlanan %s değeri -2147483648'den küçük",
+ "value_bigger_than_9223372036854775807": "Sağlanan %s değeri 9223372036854775807'den büyük",
+ "value_smaller_than_9223372036854775808": "Sağlanan %s değeri -9223372036854775808'den küçük",
+ "value_bigger_than_4294967296": "Sağlanan %s değeri 4294967296'dan büyük",
+ "value_smaller_than_0": "Sağlanan %s değeri 0'dan küçük",
+ "encode_double_error": "double değeri düzgün kodlanamadı",
+ "file_not_exist": "Dosya mevcut değil",
+ "deserialization_error": "Serileştirmeyi çözme sırasında bir hata oluştu",
+ "rpc_tg_error": "Telegram bir RPC hatası döndürdü: %s (%s), kaynağı: %s:%s%sTL izi:",
+ "madelineproto_ready": "MadelineProto hazır!",
+ "logout_ok": "Oturum başarıyla kapatıldı!",
+ "already_loggedIn": "Bu MadelineProto örneğinde zaten oturum açılmış!",
+ "login_ok": "Oturum başarıyla açıldı!",
+ "login_user": "Normal kullanıcı olarak oturum açılıyor...",
+ "login_bot": "Bot olarak oturum açılıyor...",
+ "login_code_sending": "Kod gönderiliyor...",
+ "login_code_sent": "Kod başarıyla gönderildi! Kodu aldığınızda completePhoneLogin fonksiyonunu kullanmalısınız.",
+ "login_code_uncalled": "Kod beklemiyorum! Lütfen önce phoneLogin metodunu çağırın",
+ "login_2fa_enabled": "2FA etkin, complete2falogin fonksiyonunu çağırmanız gerekecek...",
+ "login_need_signup": "Bu numara için bir hesap oluşturulmamış, completeSignup fonksiyonunu çağırmanız gerekecek...",
+ "login_auth_key": "Yetkilendirme anahtarı (auth key) kullanılarak oturum açılıyor...",
+ "not_loggedIn": "Oturum açılmamış!",
+ "signup_uncalled": "Kayıt beklemiyorum! Lütfen önce phoneLogin ve completePhoneLogin metotlarını çağırın!",
+ "signing_up": "Normal kullanıcı olarak kaydolunuyor...",
+ "signup_ok": "Kayıt başarılı!",
+ "2fa_uncalled": "Parola beklemiyorum! Lütfen önce phoneLogin ve completePhoneLogin metotlarını çağırın!",
+ "peer_not_in_db": "Bu peer, dahili peer veritabanında bulunmuyor",
+ "call_error_1": "%s araması bulunup kabul edilemedi",
+ "accepting_call": "%s tarafından gelen arama kabul ediliyor...",
+ "call_already_accepted": "%s araması zaten kabul edildi",
+ "call_already_declined": "%s araması zaten reddedildi",
+ "call_error_2": "%s araması bulunup onaylanamadı",
+ "call_confirming": "%s tarafından gelen arama onaylanıyor...",
+ "call_error_3": "%s araması bulunup kurulumu tamamlanamadı",
+ "call_completing": "%s tarafından gelen aramanın kurulumu tamamlanıyor...",
+ "fingerprint_invalid": "Geçersiz anahtar parmak izi!",
+ "call_discarding": "%s araması sonlandırılıyor...",
+ "file_parsing": "%s ayrıştırılıyor...",
+ "src_file_invalid": "Geçersiz kaynak dosyası sağlandı: ",
+ "bool_error": "Boolean değer çıkarılamadı",
+ "not_numeric": "Verilen değer sayısal değil",
+ "long_not_16": "Verilen değer 16 bayt uzunluğunda değil",
+ "long_not_32": "Verilen değer 32 bayt uzunluğunda değil",
+ "long_not_64": "Verilen değer 64 bayt uzunluğunda değil",
+ "array_invalid": "Geçerli bir dizi sağlamadınız",
+ "predicate_not_set": "Predicate (_ altındaki değer) ayarlanmadı!",
+ "update_madelineproto": "MadelineProto'nun eski bir sürümünü kullanıyorsunuz, güncelleme gerekli: şu anda %s sürümü çalışıyor, ancak çok sayıda hata düzeltmesi ve yeni özellik içeren en son sürüm %s!",
+ "type_extract_error": "\"%s\" türü çıkarılamadı, MadelineProto'yu güncellemelisiniz!",
+ "method_not_found": "Metot bulunamadı: ",
+ "params_missing": "Gerekli parametre eksik",
+ "sec_peer_not_in_db": "Bu gizli peer, dahili peer veritabanında bulunmuyor",
+ "stream_handle_invalid": "Geçersiz bir akış tanıtıcısı (stream handle) sağlandı.",
+ "length_too_big": "Uzunluk çok büyük",
+ "string_required": "Bir dize (string) bekleniyordu!",
+ "waveform_must_have_100_values": "Bir waveform dizisi 100 değer içermelidir!",
+ "waveform_value": "Bir waveform değeri 0 ile 31 arasında olmalıdır!",
+ "could_not_convert_object": "%s türündeki nesne dönüştürülemedi",
+ "type_extract_error_id": "Tür çıkarılamadı: %s, id %s; MadelineProto'yu güncellemelisiniz!",
+ "constructor_not_found": "Şu tür için constructor bulunamadı: ",
+ "botapi_conversion_error": "%s bir bot API nesnesine dönüştürülemiyor",
+ "non_text_conversion": "Metin dışı mesajlar henüz dönüştürülemiyor!",
+ "file_type_invalid": "Geçersiz dosya türü algılandı (%s)",
+ "static_analysis_minor": "%s statik analizi sırasında küçük bir sorunla karşılaşıldı: %s",
+ "static_analysis_severe": "%s statik analizi sırasında ciddi bir sorunla karşılaşıldı: %s",
+ "secret_chat_skipping": "%s gizli sohbeti veritabanında yok, mesaj atlanıyor...",
+ "must_have_declare_types": "performans nedenleriyle, bir olay işleyici dosyasının ilk ifadesi \"declare(strict_types=1);\" olmalıdır",
+ "do_not_delete_MadelineProto.log": "MadelineProto.log dosyası asla silinmemelidir, bunun yerine lütfen ayarlarda özel bir maksimum boyut belirleyin!",
+ "do_not_remove_MadelineProto.log_phar": "Lütfen madeline.phar veya madeline.php dosyalarını silmeyin, aksi halde MadelineProto çöker. MadelineProto ile ilgili bir sorununuz varsa https://github.com/danog/MadelineProto veya https://t.me/pwrtelegramgroup adresine bildirin",
+ "do_not_use_blocking_function": "performans nedenleriyle, olay işleyiciler async olmayan, engelleyici %s fonksiyonunu kullanamaz, lütfen bunun yerine %s kullanın",
+ "do_not_use_blocking_class": "performans nedenleriyle, işleyiciler async olmayan, engelleyici %s sınıfını kullanamaz, lütfen bunun yerine %s kullanın",
+ "do_not_use_deprecated_function": "%s fonksiyonu kullanımdan kaldırılmıştır, lütfen bunun yerine %s kullanın",
+ "do_not_use_non_root_require_in_event_handler": "performans nedenleriyle, bir olay işleyici sınıfının içinde require veya include kullanmamalısınız, yalnızca kök düzeydeki require'lara izin verilir.",
+ "do_not_use_yield": "MadelineProto 8, async fonksiyonlarda yield kullanımını gerektirmez ve desteklemez; daha önce async fonksiyon çağrıları için kullanılan tüm yield anahtar sözcüklerini kaldırmalısınız",
+ "recommend_not_use_filesystem_function": "%s fonksiyonunun kullanılması önerilmez, çünkü güncellemeler işlenirken dosya sistemine erişmek botunuzu yavaşlatır; botunuzu yavaşlatmayan alternatif veri saklama yöntemlerinin listesi için lütfen https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions adresine bakın!",
+ "plugins_do_not_use_require": "performans nedenleriyle, eklentiler eklenti klasöründeki diğer dosyaları yalnızca PSR-4 otomatik yükleyicisini tetikleyerek otomatik olarak include veya require edebilir (require() ile elle dahil ederek değil).",
+ "plugins_must_have_exactly_one_class": "bir eklenti tam olarak bir sınıf tanımlamalıdır! Birden fazla sınıf, arayüz veya trait tanımlamak için ayrı dosyalar oluşturun; bunlar MadelineProto tarafından otomatik olarak yüklenecektir.",
+ "cli_need_dl.php_link": "getDownloadLink'i CLI üzerinden kullanırken lütfen bir indirme betiği URL'si belirtin!",
+ "invalid_dl.php_session": "%s geçerli bir indirme betiği değil, çünkü oturum kimliği farklı (beklenen %s, alınan %s)",
+ "need_dl.php": "Varsayılan indirme betiği oluşturulamadı (%s), lütfen aşağıdaki içeriğe sahip bir dl.php dosyası oluşturun: %s ve URL'sini getDownloadLink'in ikinci parametresine iletin",
+ "dl.php_powered_by_madelineproto": "MadelineProto tarafından desteklenen Telegram dosya indirme sunucusu (4 GB'a kadar)!
Kendi Telegram dosya indirme sunucunuzu nasıl kuracağınız hakkında daha fazla bilgi için buraya tıklayın!",
+ "dl.php_check_logs_make_sure_session_running": "İlişkili MadelineProto EventHandler botu veya MadelineProto IPC sunucusu çevrimdışı, lütfen günlükleri kontrol edin ve en az birinin çalıştığından emin olun!",
+ "account_banned": "!!!!!!! UYARI !!!!!!!\nTelegram'ın flood önleme sistemi bu hesabı askıya aldı.\nDevam etmek için manuel doğrulama gerekiyor.\nrecover@telegram.org adresine %s telefon numarasının engelinin kaldırılmasını isteyen bir e-posta gönderin ve bu telefon numarasıyla ne yapacağınızı kısaca açıklayın.\nArdından tekrar oturum açın.\nBu hesabı bilerek sildiyseniz bu mesajı dikkate almayın.",
+ "plugin_path_does_not_exist": "%s eklenti yolu mevcut değil!",
+ "could_not_connect_to_MadelineProto": "MadelineProto'ya bağlanılamadı, düzeltmek için lütfen proc_open'ı etkinleştirin ve open_basedir kısıtlamalarını kaldırın ya da web sunucusunun yol yeniden yazma (rewrite) özelliğini devre dışı bırakın! Bunu zaten yaptıysanız, PHP'nin CLI sürümünün web sürümüyle tamamen aynı olduğundan (aynı sürüm, eklentiler vb.) emin olun ve IPC sunucusunun başlamasını engelleyen hata hakkında daha fazla bilgi için MadelineProto.log dosyasına bakın.",
+ "translate_madelineproto_web": "MadelineProto sizin dilinize çevrilebilir (mevcut çeviri ilerlemesi: %%%d), çeviriye katkıda bulunmak için buraya tıklayın!",
+ "translate_madelineproto_cli": "MadelineProto sizin dilinize çevrilebilir (mevcut çeviri ilerlemesi: %%%d), çeviriye katkıda bulunmak için https://github.com/danog/MadelineProto/tree/v8/langs adresine gidin!",
+ "apiInvalidWeb": "API ID bir sayıdır, API hash ise 32 karakter uzunluğundadır: bunları my.telegram.org adresinden yeniden kopyalayın.",
+ "webDoneLead": "MadelineProto sunucuda çalışmaya devam ediyor: bu sayfayı kapatabilirsiniz.",
+ "apiChooseManualAuto": "API ID ve hash bilgilerini my.telegram.org adresinden otomatik olarak mı almak istersiniz (a), yoksa manuel olarak mı girmek istersiniz (m)?",
+ "apiAutoFallbackManual": "Bunun yerine API ID ve hash bilgilerini manuel olarak girin.",
+ "apiSetupTitleWeb": "API ID ve hash bilgilerinizi alın",
+ "apiSetupLeadWeb": "Her Telegram uygulamasının bir API ID ve hash bilgisine ihtiyacı vardır. MadelineProto, mevcut bir Telegram hesabının telefon numarasıyla bunları sizin için my.telegram.org adresinden alabilir.",
+ "apiAutoPhoneHintWeb": "my.telegram.org giriş kodunu SMS ile değil, Telegram uygulamanıza gönderir.",
+ "apiSendCodeWeb": "Kod gönder",
+ "apiChooseManualWeb": "Zaten bir API ID'm var",
+ "apiChooseAutoWeb": "Otomatik olarak al",
+ "apiStartOverWeb": "Baştan başla",
+ "apiAutoCodeTitleWeb": "Telegram'dan gelen kodu girin",
+ "apiAutoCodeLeadWeb": "my.telegram.org, Telegram uygulamanıza Telegram sohbetinde bir giriş kodu gönderdi (SMS ile değil).",
+ "apiAutoCodeLabelWeb": "Giriş kodu",
+ "apiCreateTitleWeb": "Uygulamanızı oluşturun",
+ "apiCreateLeadWeb": "Bu hesabın my.telegram.org üzerinde henüz bir uygulaması yok. Bu bilgiler yalnızca size gösterilir ve daha sonra değiştirilebilir.",
+ "apiAppTitleLabelWeb": "Uygulama adı",
+ "apiAppShortNameLabelWeb": "Kısa ad",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Açıklama",
+ "apiCreateWeb": "Uygulama oluştur",
+ "apiSaveWeb": "Kaydet ve devam et",
+ "apiAutoErrorTitle": "my.telegram.org bir hata döndürdü",
+ "apiCreateErrorTitle": "my.telegram.org uygulamayı oluşturmadı",
+ "apiCreateVpsWarning": "Telegram, VPS, VPN ve diğer veri merkezi IP aralıklarının my.telegram.org üzerinde yeni uygulama oluşturmasına izin vermez ve istek, MadelineProto'yu çalıştıran makinenin IP adresinden yapıldı. Uygulamayı bir ev bağlantısından (örneğin mobil veri kullanan telefonunuzdan) https://my.telegram.org adresinde manuel olarak oluşturun, ardından API ID ve hash bilgilerini girin.",
+ "loginTitleWeb": "Telegram'da oturum açın",
+ "loginLeadWeb": "Bu MadelineProto örneğinin hangi hesap veya bot olarak çalışacağını seçin.",
+ "loginTypeWeb": "Şu olarak oturum aç",
+ "loginUserPhoneHintWeb": "Ülke koduyla birlikte, örneğin +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Botu oluşturduğunuzda @BotFather'ın size verdiği token.",
+ "loginCodeTitleWeb": "Giriş kodunu girin",
+ "loginCodeLeadWeb": "Telegram, Telegram uygulamanıza bir giriş kodu gönderdi; başka hiçbir yerde oturum açmadıysanız kod SMS ile gönderilir.",
+ "loginPasswordTitleWeb": "İki adımlı doğrulama",
+ "loginPasswordLeadWeb": "Bu hesap, Ayarlar > Gizlilik ve Güvenlik > İki Adımlı Doğrulama bölümünde belirlenen bir parolayla korunuyor.",
+ "loginPasswordLabelWeb": "Parola",
+ "signupTitleWeb": "Hesabınızı oluşturun",
+ "signupLeadWeb": "Bu telefon numarası henüz Telegram'da değil: yeni hesabın adını seçin.",
+ "webContinue": "Devam",
+ "webLogin": "Oturum aç",
+ "webError": "%s. Kontrol edip tekrar deneyin.",
+ "webStepApp": "API ID ve hash",
+ "webStepAccount": "Hesap",
+ "webStepVerify": "Doğrulama",
+ "webStepDone": "Çalışıyor",
+ "webProgress": "Kurulum ilerlemesi",
+ "webDocs": "Belgeler",
+ "webOptional": "isteğe bağlı",
+ "webShowPassword": "Göster",
+ "webHidePassword": "Gizle",
+ "webQrTitle": "QR kodu ile oturum açın",
+ "webQrWaiting": "Taranması bekleniyor…",
+ "webFieldRequired": "Bu alanı doldurun.",
+ "webPhoneInvalid": "Telefon numarasını ülke koduyla birlikte girin, örneğin +39 123 456 7890.",
+ "tweb.Login.Title": "MadelineProto'da oturum açın",
+ "tweb.Login.PhoneLabelInvalid": "Geçersiz telefon numarası",
+ "tweb.Login.StartText": "Lütfen ülke kodunuzu onaylayın\nve telefon numaranızı girin.",
+ "tweb.Login.Code.SentSms": "Size kodu içeren\nbir SMS gönderdik.",
+ "tweb.Login.Code.SentInApp": "Size Telegram'da kodu içeren\nbir mesaj gönderdik.",
+ "tweb.Login.Code.SentCall": "Sizi arayıp kodu\nsesli olarak ileteceğiz.",
+ "tweb.Login.Code.SentEmail": "Lütfen **%s** e-posta adresinizi kontrol edin (spam klasörünü unutmayın) ve az önce gönderdiğimiz kodu girin.",
+ "tweb.Login.Code.SentUnknown": "Lütfen kod için her yeri\nkontrol edin (tür: %s)",
+ "tweb.Login.Code.SentMissedCall": "Birkaç saniye içinde **%s** numarasından\nkısa bir arama alacaksınız. Aramayı yanıtlamayın,\nyalnızca o numaranın son hanelerini girin.",
+ "tweb.Login.Code.SentSmsWord": "**%s** numaralı telefonunuza\ngizli kelimeyi içeren bir SMS gönderdik.",
+ "tweb.Login.Code.SentSmsWordBeginning": "**%1$s** numaralı telefonunuza \"**%2$s**\" ile\nbaşlayan gizli bir kelime içeren SMS gönderdik.",
+ "tweb.Login.Code.SentSmsPhrase": "**%s** numaralı telefonunuza\ngizli ifadeyi içeren bir SMS gönderdik.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "**%1$s** numaralı telefonunuza \"**%2$s**\" ile\nbaşlayan gizli bir ifade içeren SMS gönderdik.",
+ "tweb.Login.Code.SecretWord": "Gizli kelime",
+ "tweb.Login.Code.SecretPhrase": "Gizli ifade",
+ "tweb.Login.Code.WordInvalid": "Yanlış, lütfen tekrar deneyin",
+ "tweb.Login.Code.WordBeginningInvalid": "Yanlış kelime",
+ "tweb.Login.Password.Title": "Parolanızı girin",
+ "tweb.Login.Password.Subtitle": "Hesabınız ek bir parola\nile korunuyor",
+ "tweb.Login.Register.Subtitle": "Hesabınızı oluşturmak için\nadınızı girin",
+ "tweb.PleaseWait": "Lütfen bekleyin...",
+ "tweb.Code": "Kod",
+ "tweb.LoginPassword": "Parola",
+ "tweb.YourName": "Adınız",
+ "tweb.FirstName": "Ad (zorunlu)",
+ "tweb.LastName": "Soyad (isteğe bağlı)",
+ "tweb.StartMessaging": "Mesajlaşmaya başla",
+ "tweb.Country": "Ülke",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Telefon numarası",
+ "tweb.Login.Next": "İleri",
+ "tweb.Login.QR.Title": "QR kodu ile oturum açın",
+ "tweb.Login.QR.Help1": "Telefonunuzda Telegram'ı açın",
+ "tweb.Login.QR.Help2": "**Ayarlar** > **Cihazlar** > **Cihaz Ekle** bölümüne gidin",
+ "tweb.Login.QR.Help3": "Oturum açmayı onaylamak için telefonunuzu bu ekrana doğrultun",
+ "tweb.Login.QR.Cancel": "Telefon numarasıyla oturum aç >",
+ "tweb.Login.QR.Login": "QR kodu ile oturum aç >",
+ "tweb.Login.QR.Subtitle": "Telefonunuzdaki Telegram uygulamasıyla tarayın",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Kodu [Fragment]() üzerindeki Numaralar bölümünden alın",
+ "tweb.PHONE_CODE_INVALID": "Geçersiz kod",
+ "tweb.PHONE_CODE_EXPIRED": "Kodun süresi doldu",
+ "tweb.PASSWORD_HASH_INVALID": "Yanlış parola",
+ "tweb.DarkMode": "Karanlık mod",
+ "tweb.Error.AnError": "Bir hata oluştu. Lütfen daha sonra tekrar deneyin.",
+ "tweb.AccDescr.LoginCode": "Giriş kodu",
+ "tweb.Login.Bot": "Bot olarak oturum aç >",
+ "tweb.Login.Bot.Title": "Bot olarak oturum açın",
+ "tweb.Login.Bot.Subtitle": "Botu oluşturduğunuzda @BotFather'ın\nsize verdiği token'ı girin.",
+ "tweb.Login.Bot.Token": "Bot token'ı",
+ "tweb.Login.Bot.Cancel": "Kullanıcı olarak oturum aç >",
+ "tweb.Optional": "isteğe bağlı",
+ "tweb.PHONE_NUMBER_INVALID": "Geçersiz telefon numarası",
+ "tweb.PHONE_NUMBER_BANNED": "Bu telefon numarası yasaklanmış",
+ "tweb.PHONE_NUMBER_FLOOD": "Çok fazla deneme yapıldı, daha sonra tekrar deneyin",
+ "tweb.PHONE_CODE_EMPTY": "Geçersiz kod",
+ "tweb.PHONE_PASSWORD_FLOOD": "Çok fazla deneme yapıldı, daha sonra tekrar deneyin",
+ "tweb.ACCESS_TOKEN_INVALID": "Geçersiz bot token'ı",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Bu bot token'ı iptal edildi",
+ "tweb.FIRSTNAME_INVALID": "Geçersiz ad",
+ "tweb.LASTNAME_INVALID": "Geçersiz soyad",
+ "tweb.Close": "Kapat"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uk.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uk.json
new file mode 100644
index 0000000..99d9ae3
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uk.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "Налаштовано обмеження basedir: це може вплинути на продуктивність і спричинити певні проблеми, вимкніть його, якщо можливо!",
+ "noReportPeers": "Попередження: не задано одержувачів звітів (report peers), додайте до свого обробника подій такий метод",
+ "manualAdminActionRequired": "!!!!!!!!! ПОТРІБНЕ ВТРУЧАННЯ СИСТЕМНОГО АДМІНІСТРАТОРА !!!!!!!!!",
+ "mmapErrorPart1": "Досягнуто максимальної кількості відображених у пам'ять областей (mmap) (%s): щоб виправити це, збільште параметр ядра vm.max_map_count до 262144.",
+ "mmapErrorPart2": "Щоб виправити, виконайте від імені root таку команду: %s",
+ "mmapErrorPart3": "Щоб зміна зберігалася після перезавантаження: %s",
+ "mmapErrorPart4": "У Windows і WSL може допомогти збільшення файлу підкачки; якщо проблема не зникне, перейдіть на нативний Linux.",
+ "botAlreadyRunning": "Бот уже запущено!",
+ "extensionRequired": "Для роботи MadelineProto потрібне розширення %s. %s",
+ "extensionRequiredInstallWithApt": "Спробуйте виконати sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Щоб установити його, дотримуйтеся інструкцій за адресою %s.",
+ "extensionRecommended": "Попередження: розширення %s не встановлено, установіть його, щоб пришвидшити MadelineProto!",
+ "go": "Далі",
+ "apiChooseManualAutoTip": "Зверніть увагу, що API ID/hash також можна вказати безпосередньо в коді через налаштування: %s",
+ "apiChooseManualAutoTipWeb": "Зверніть увагу, що API ID/hash також можна вказати безпосередньо в коді через налаштування.",
+ "apiChoosePrompt": "Ваш вибір (m/a): ",
+ "apiManualInstructions0": "Увійдіть на https://my.telegram.org",
+ "apiManualInstructions1": "Перейдіть до розділу «API development tools»",
+ "apiManualInstructions2": "Натисніть «create application»",
+ "apiAppInstructionsManual0": "назва вашого застосунку, може бути будь-якою",
+ "apiAppInstructionsManual1": "коротка назва вашого застосунку, літери й цифри, 5-32 символи",
+ "apiAppInstructionsManual2": "URL вашого застосунку/вебсайту або t.me/yourusername",
+ "apiAppInstructionsManual3": "будь-що",
+ "apiAppInstructionsManual4": "Опишіть тут свій застосунок",
+ "apiManualWeb": "Введіть свої API ID та API hash",
+ "apiManualPrompt0": "Введіть свій API ID: ",
+ "apiManualPrompt1": "Введіть свій API hash: ",
+ "apiAutoWeb": "Введіть номер телефону, уже зареєстрований у Telegram, щоб отримати API ID",
+ "apiAutoPrompt0": "Введіть номер телефону, уже зареєстрований у Telegram: ",
+ "apiAutoPrompt1": "Введіть код підтвердження, отриманий у Telegram: ",
+ "apiAppWeb": "Введіть інформацію про API",
+ "apiAppInstructionsAuto0": "Введіть назву застосунку, може бути будь-якою: ",
+ "apiAppInstructionsAuto1": "Введіть коротку назву застосунку, літери й цифри, 5-32 символи: ",
+ "apiAppInstructionsAuto2": "Введіть URL застосунку/вебсайту або t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Введіть платформу застосунку: ",
+ "apiAppInstructionsAuto4": "Опишіть свій застосунок: ",
+ "apiAppInstructionsAutoTypeOther": "Інше (уточніть в описі)",
+ "apiParamsError": "Ви вказали не всі обов'язкові параметри!",
+ "apiError": "ПОМИЛКА: %s. Спробуйте ще раз.",
+ "loginChoosePromptWeb": "Увійти як користувач чи як бот?",
+ "loginWebQr": "Також можна увійти автоматично: відкрийте Telegram на телефоні, перейдіть у Налаштування > Пристрої > Підключити пристрій і відскануйте цей QR-код:",
+ "loginWebQr1": "Відкрийте Telegram на телефоні",
+ "loginWebQr2": "Перейдіть у Налаштування > Пристрої > Підключити пристрій",
+ "loginWebQr3": "Наведіть телефон на цей екран, щоб підтвердити вхід",
+ "loginOptionBot": "Бот",
+ "loginOptionUser": "Користувач",
+ "loginBot": "Введіть токен бота: ",
+ "loginUser": "Введіть свій номер телефону: ",
+ "loginQr": "Відкрийте Telegram на телефоні, перейдіть у Налаштування > Пристрої > Підключити пристрій і відскануйте QR-код вище, щоб увійти автоматично.",
+ "loginQrCodeSuccessful": "Вхід за QR-кодом виконано успішно!",
+ "loginQrCodeExpired": "Термін дії QR-коду минув, генерується новий...",
+ "loginManual": "Або ж введіть токен бота чи номер телефону, щоб увійти вручну: ",
+ "loginUserCode": "Введіть код: ",
+ "loginUserPass": "Введіть свій пароль (підказка: %s): ",
+ "loginUserPassWeb": "Введіть свій пароль: ",
+ "loginUserPassHint": "Підказка: %s",
+ "signupFirstName": "Введіть своє ім'я: ",
+ "signupLastName": "Введіть своє прізвище (можна залишити порожнім): ",
+ "signupWeb": "Зареєструйтеся",
+ "signupFirstNameWeb": "Ім'я",
+ "signupLastNameWeb": "Прізвище",
+ "loginNoCode": "Ви не вказали код підтвердження!",
+ "loginNoPass": "Ви не вказали пароль!",
+ "loginNoName": "Ви не вказали ім'я!",
+ "loginBotTokenWeb": "Токен бота",
+ "loginUserPhoneWeb": "Номер телефону",
+ "loginUserPhoneCodeWeb": "Код",
+ "done": "Готово!",
+ "nearest_dc": "Наше розташування: %s, найближчий DC: %d.",
+ "serialization_ofd": "Серіалізація застаріла, об'єкт реконструюється!",
+ "api_not_set": "Потрібно вказати api key та api id, отримайте власні на my.telegram.org",
+ "session_corrupted": "Сесію пошкоджено!",
+ "value_bigger_than_2147483647": "Передане значення %s більше за 2147483647",
+ "value_smaller_than_2147483648": "Передане значення %s менше за -2147483648",
+ "value_bigger_than_9223372036854775807": "Передане значення %s більше за 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "Передане значення %s менше за -9223372036854775808",
+ "value_bigger_than_4294967296": "Передане значення %s більше за 4294967296",
+ "value_smaller_than_0": "Передане значення %s менше за 0",
+ "encode_double_error": "Не вдалося правильно закодувати double",
+ "file_not_exist": "Файл не існує",
+ "deserialization_error": "Під час десеріалізації сталася помилка",
+ "rpc_tg_error": "Telegram повернув помилку RPC: %s (%s), спричинену в %s:%s%sTL-трасування:",
+ "madelineproto_ready": "MadelineProto готовий до роботи!",
+ "logout_ok": "Вихід виконано успішно!",
+ "already_loggedIn": "У цьому екземплярі MadelineProto вже виконано вхід!",
+ "login_ok": "Вхід виконано успішно!",
+ "login_user": "Вхід як звичайний користувач...",
+ "login_bot": "Вхід як бот...",
+ "login_code_sending": "Надсилання коду...",
+ "login_code_sent": "Код успішно надіслано! Отримавши код, скористайтеся функцією completePhoneLogin.",
+ "login_code_uncalled": "Я не очікую коду! Спочатку викличте метод phoneLogin",
+ "login_2fa_enabled": "Увімкнено 2FA, потрібно буде викликати функцію complete2falogin...",
+ "login_need_signup": "Для цього номера не створено обліковий запис, потрібно буде викликати функцію completeSignup...",
+ "login_auth_key": "Вхід за допомогою ключа авторизації...",
+ "not_loggedIn": "Вхід не виконано!",
+ "signup_uncalled": "Я не очікую реєстрації! Спочатку викличте методи phoneLogin і completePhoneLogin!",
+ "signing_up": "Реєстрація як звичайний користувач...",
+ "signup_ok": "Реєстрацію виконано успішно!",
+ "2fa_uncalled": "Я не очікую пароля! Спочатку викличте методи phoneLogin і completePhoneLogin!",
+ "peer_not_in_db": "Цього співрозмовника (peer) немає у внутрішній базі даних співрозмовників",
+ "call_error_1": "Не вдалося знайти й прийняти дзвінок %s",
+ "accepting_call": "Прийняття дзвінка від %s...",
+ "call_already_accepted": "Дзвінок %s уже прийнято",
+ "call_already_declined": "Дзвінок %s уже відхилено",
+ "call_error_2": "Не вдалося знайти й підтвердити дзвінок %s",
+ "call_confirming": "Підтвердження дзвінка від %s...",
+ "call_error_3": "Не вдалося знайти дзвінок %s і завершити його встановлення",
+ "call_completing": "Завершення встановлення дзвінка від %s...",
+ "fingerprint_invalid": "Недійсний відбиток ключа!",
+ "call_discarding": "Завершення дзвінка %s...",
+ "file_parsing": "Розбір %s...",
+ "src_file_invalid": "Передано недійсний вихідний файл: ",
+ "bool_error": "Не вдалося видобути булеве значення",
+ "not_numeric": "Передане значення не є числовим",
+ "long_not_16": "Довжина переданого значення не дорівнює 16 байтам",
+ "long_not_32": "Довжина переданого значення не дорівнює 32 байтам",
+ "long_not_64": "Довжина переданого значення не дорівнює 64 байтам",
+ "array_invalid": "Ви не передали дійсний масив",
+ "predicate_not_set": "Предикат (значення в _) не задано!",
+ "update_madelineproto": "Ви використовуєте стару версію MadelineProto, потрібне оновлення: поточна версія — %s, а остання версія з численними виправленнями помилок і новими функціями — %s!",
+ "type_extract_error": "Не вдалося видобути тип \"%s\", оновіть MadelineProto!",
+ "method_not_found": "Не вдалося знайти метод: ",
+ "params_missing": "Відсутній обов'язковий параметр",
+ "sec_peer_not_in_db": "Цього секретного співрозмовника немає у внутрішній базі даних співрозмовників",
+ "stream_handle_invalid": "Передано недійсний дескриптор потоку.",
+ "length_too_big": "Завелика довжина",
+ "string_required": "Очікувався рядок!",
+ "waveform_must_have_100_values": "Масив waveform має містити 100 значень!",
+ "waveform_value": "Значення waveform має бути від 0 до 31!",
+ "could_not_convert_object": "Не вдалося перетворити об'єкт типу %s",
+ "type_extract_error_id": "Не вдалося видобути тип: %s з id %s, оновіть MadelineProto!",
+ "constructor_not_found": "Не знайдено конструктор для типу: ",
+ "botapi_conversion_error": "Не вдається перетворити %s на об'єкт bot API",
+ "non_text_conversion": "Перетворення нетекстових повідомлень поки не підтримується!",
+ "file_type_invalid": "Виявлено недійсний тип файлу (%s)",
+ "static_analysis_minor": "Під час статичного аналізу %s виявлено незначну проблему: %s",
+ "static_analysis_severe": "Під час статичного аналізу %s виявлено серйозну проблему: %s",
+ "secret_chat_skipping": "Секретного чату %s немає в базі даних, повідомлення пропускається...",
+ "must_have_declare_types": "з міркувань продуктивності першою інструкцією файлу обробника подій має бути \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "файл MadelineProto.log ніколи не можна видаляти, натомість задайте власний максимальний розмір у налаштуваннях!",
+ "do_not_remove_MadelineProto.log_phar": "Не видаляйте madeline.phar або madeline.php, інакше MadelineProto аварійно завершить роботу. Якщо у вас виникли проблеми з MadelineProto, повідомте про них на https://github.com/danog/MadelineProto або https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "з міркувань продуктивності обробники подій не можуть використовувати неасинхронну блокувальну функцію %s, натомість використовуйте %s",
+ "do_not_use_blocking_class": "з міркувань продуктивності обробники не можуть використовувати неасинхронний блокувальний клас %s, натомість використовуйте %s",
+ "do_not_use_deprecated_function": "функція %s застаріла, натомість використовуйте %s",
+ "do_not_use_non_root_require_in_event_handler": "з міркувань продуктивності не можна використовувати require або include всередині класу обробника подій, дозволено лише require на кореневому рівні.",
+ "do_not_use_yield": "MadelineProto 8 не потребує й не підтримує використання yield в асинхронних функціях, вилучіть усі ключові слова yield, які раніше використовувалися для викликів асинхронних функцій",
+ "recommend_not_use_filesystem_function": "використовувати функцію %s не рекомендується, оскільки доступ до файлової системи під час обробки оновлень сповільнює вашого бота; перелік альтернативних способів зберігання даних, які не сповільнюють бота, див. на https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions!",
+ "plugins_do_not_use_require": "з міркувань продуктивності плагіни можуть автоматично підключати (include або require) інші файли з теки плагінів лише через автозавантажувач PSR-4 (а не вручну через require()).",
+ "plugins_must_have_exactly_one_class": "плагін має визначати рівно один клас! Щоб визначити кілька класів, інтерфейсів або трейтів, створіть окремі файли, MadelineProto завантажить їх автоматично.",
+ "cli_need_dl.php_link": "Під час використання getDownloadLink через CLI вкажіть URL скрипту завантаження!",
+ "invalid_dl.php_session": "%s не є дійсним скриптом завантаження, оскільки його ID сесії відрізняється (очікувався %s, отримано %s)",
+ "need_dl.php": "Не вдалося згенерувати стандартний скрипт завантаження (%s), створіть файл dl.php з таким вмістом: %s і передайте його URL другим параметром getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Сервер завантаження файлів Telegram (до 4 ГБ) на базі MadelineProto!
Натисніть тут, щоб дізнатися, як налаштувати власний сервер завантаження файлів Telegram!",
+ "dl.php_check_logs_make_sure_session_running": "Пов'язаний бот MadelineProto EventHandler або IPC-сервер MadelineProto не працюють, перевірте журнали й переконайтеся, що хоча б один із них запущено!",
+ "account_banned": "!!!!!!! ПОПЕРЕДЖЕННЯ !!!!!!!\nСистема захисту від флуду Telegram призупинила цей обліковий запис.\nЩоб продовжити, потрібна ручна перевірка.\nНадішліть лист на recover@telegram.org із проханням розблокувати номер телефону %s і коротко опишіть, як ви використовуватимете цей номер.\nПотім увійдіть знову.\nЯкщо ви навмисно видалили цей обліковий запис, проігноруйте це повідомлення.",
+ "plugin_path_does_not_exist": "Шлях до плагіна %s не існує!",
+ "could_not_connect_to_MadelineProto": "Не вдалося підключитися до MadelineProto: щоб виправити це, увімкніть proc_open і зніміть обмеження open_basedir або вимкніть перезапис шляхів вебсервера! Якщо ви вже це зробили, переконайтеся, що CLI-версія PHP точно така сама, як вебверсія (та сама версія, розширення тощо), і перегляньте файл MadelineProto.log, щоб дізнатися більше про помилку, через яку не вдалося запустити IPC-сервер.",
+ "translate_madelineproto_web": "MadelineProto можна перекласти вашою мовою (поточний прогрес перекладу: %d%%), натисніть тут, щоб долучитися до перекладу!",
+ "translate_madelineproto_cli": "MadelineProto можна перекласти вашою мовою (поточний прогрес перекладу: %d%%), перейдіть на https://github.com/danog/MadelineProto/tree/v8/langs, щоб долучитися до перекладу!",
+ "apiInvalidWeb": "API ID — це число, а API hash складається з 32 символів: скопіюйте їх ще раз з my.telegram.org.",
+ "webDoneLead": "MadelineProto продовжує працювати на сервері: цю сторінку можна закрити.",
+ "apiChooseManualAuto": "Отримати API ID та API hash автоматично з my.telegram.org (a) чи ввести їх вручну (m)?",
+ "apiAutoFallbackManual": "Натомість введіть API ID та API hash вручну.",
+ "apiSetupTitleWeb": "Отримайте API ID та API hash",
+ "apiSetupLeadWeb": "Кожному застосунку Telegram потрібні API ID та API hash. MadelineProto може отримати їх для вас з my.telegram.org за номером телефону наявного облікового запису Telegram.",
+ "apiAutoPhoneHintWeb": "my.telegram.org надсилає код входу в застосунок Telegram, а не SMS.",
+ "apiSendCodeWeb": "Надіслати код",
+ "apiChooseManualWeb": "У мене вже є API ID",
+ "apiChooseAutoWeb": "Отримати автоматично",
+ "apiStartOverWeb": "Почати спочатку",
+ "apiAutoCodeTitleWeb": "Введіть код із Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org надіслав код входу у ваш застосунок Telegram, у чат із Telegram (не SMS).",
+ "apiAutoCodeLabelWeb": "Код входу",
+ "apiCreateTitleWeb": "Створіть застосунок",
+ "apiCreateLeadWeb": "У цього облікового запису ще немає застосунку на my.telegram.org. Ці дані бачите лише ви, і їх можна змінити пізніше.",
+ "apiAppTitleLabelWeb": "Назва застосунку",
+ "apiAppShortNameLabelWeb": "Коротка назва",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Опис",
+ "apiCreateWeb": "Створити застосунок",
+ "apiSaveWeb": "Зберегти й продовжити",
+ "apiAutoErrorTitle": "my.telegram.org повернув помилку",
+ "apiCreateErrorTitle": "my.telegram.org не створив застосунок",
+ "apiCreateVpsWarning": "Telegram не дозволяє створювати нові застосунки на my.telegram.org з IP-адрес VPS, VPN та інших дата-центрів, а запит було надіслано з IP машини, на якій працює MadelineProto. Створіть застосунок вручну на https://my.telegram.org з домашнього підключення (наприклад, з телефона через мобільний інтернет), а потім введіть API ID та API hash.",
+ "loginTitleWeb": "Вхід у Telegram",
+ "loginLeadWeb": "Виберіть обліковий запис або бота, від імені якого працюватиме цей екземпляр MadelineProto.",
+ "loginTypeWeb": "Увійти як",
+ "loginUserPhoneHintWeb": "З кодом країни, наприклад +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Токен, який видав @BotFather під час створення бота.",
+ "loginCodeTitleWeb": "Введіть код входу",
+ "loginCodeLeadWeb": "Telegram надіслав код входу у ваш застосунок Telegram або SMS, якщо ви ніде більше не ввійшли.",
+ "loginPasswordTitleWeb": "Двоетапна перевірка",
+ "loginPasswordLeadWeb": "Цей обліковий запис захищено паролем, заданим у розділі Налаштування > Приватність і безпека > Двоетапна перевірка.",
+ "loginPasswordLabelWeb": "Пароль",
+ "signupTitleWeb": "Створіть обліковий запис",
+ "signupLeadWeb": "Цього номера телефону ще немає в Telegram: виберіть ім'я нового облікового запису.",
+ "webContinue": "Продовжити",
+ "webLogin": "Увійти",
+ "webError": "%s. Перевірте й спробуйте ще раз.",
+ "webStepApp": "API ID та API hash",
+ "webStepAccount": "Обліковий запис",
+ "webStepVerify": "Підтвердження",
+ "webStepDone": "Працює",
+ "webProgress": "Перебіг налаштування",
+ "webDocs": "Документація",
+ "webOptional": "необов'язково",
+ "webShowPassword": "Показати",
+ "webHidePassword": "Приховати",
+ "webQrTitle": "Вхід за QR-кодом",
+ "webQrWaiting": "Очікування сканування…",
+ "webFieldRequired": "Заповніть це поле.",
+ "webPhoneInvalid": "Введіть номер телефону з кодом країни, наприклад +39 123 456 7890.",
+ "tweb.Login.Title": "Вхід у MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Неправильний номер телефону",
+ "tweb.Login.StartText": "Перевірте код країни\nі введіть свій номер телефону.",
+ "tweb.Login.Code.SentSms": "Ми надіслали вам SMS\nз кодом.",
+ "tweb.Login.Code.SentInApp": "Ми надіслали вам повідомлення в Telegram\nз кодом.",
+ "tweb.Login.Code.SentCall": "Ми зателефонуємо вам і продиктуємо\nкод.",
+ "tweb.Login.Code.SentEmail": "Перевірте пошту **%s** (не забудьте про теку «Спам») і введіть код, який ми щойно надіслали.",
+ "tweb.Login.Code.SentUnknown": "Пошукайте код\nусюди (тип: %s)",
+ "tweb.Login.Code.SentMissedCall": "Протягом кількох секунд вам надійде\nкороткий дзвінок з номера **%s**. Не відповідайте —\nпросто введіть останні цифри цього номера.",
+ "tweb.Login.Code.SentSmsWord": "Ми надіслали SMS із секретним словом\nна ваш номер **%s**.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Ми надіслали SMS із секретним словом, яке починається\nз «**%2$s**», на ваш номер **%1$s**.",
+ "tweb.Login.Code.SentSmsPhrase": "Ми надіслали SMS із секретною фразою\nна ваш номер **%s**.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Ми надіслали SMS із секретною фразою, яка починається\nз «**%2$s**», на ваш номер **%1$s**.",
+ "tweb.Login.Code.SecretWord": "Секретне слово",
+ "tweb.Login.Code.SecretPhrase": "Секретна фраза",
+ "tweb.Login.Code.WordInvalid": "Неправильно, спробуйте ще раз",
+ "tweb.Login.Code.WordBeginningInvalid": "Неправильне слово",
+ "tweb.Login.Password.Title": "Введіть пароль",
+ "tweb.Login.Password.Subtitle": "Ваш обліковий запис захищено\nдодатковим паролем",
+ "tweb.Login.Register.Subtitle": "Введіть своє ім'я,\nщоб створити обліковий запис",
+ "tweb.PleaseWait": "Зачекайте...",
+ "tweb.Code": "Код",
+ "tweb.LoginPassword": "Пароль",
+ "tweb.YourName": "Ваше ім'я",
+ "tweb.FirstName": "Ім'я (обов'язково)",
+ "tweb.LastName": "Прізвище (необов'язково)",
+ "tweb.StartMessaging": "Почати спілкування",
+ "tweb.Country": "Країна",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Номер телефону",
+ "tweb.Login.Next": "Далі",
+ "tweb.Login.QR.Title": "Вхід за QR-кодом",
+ "tweb.Login.QR.Help1": "Відкрийте Telegram на телефоні",
+ "tweb.Login.QR.Help2": "Перейдіть у **Налаштування** > **Пристрої** > **Підключити пристрій**",
+ "tweb.Login.QR.Help3": "Наведіть телефон на цей екран, щоб підтвердити вхід",
+ "tweb.Login.QR.Cancel": "Вхід за номером телефону >",
+ "tweb.Login.QR.Login": "Вхід за QR-кодом >",
+ "tweb.Login.QR.Subtitle": "Відскануйте застосунком Telegram на телефоні",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Отримайте код у розділі Numbers на [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Неправильний код",
+ "tweb.PHONE_CODE_EXPIRED": "Термін дії коду минув",
+ "tweb.PASSWORD_HASH_INVALID": "Неправильний пароль",
+ "tweb.DarkMode": "Темна тема",
+ "tweb.Error.AnError": "Сталася помилка. Спробуйте пізніше.",
+ "tweb.AccDescr.LoginCode": "Код входу",
+ "tweb.Login.Bot": "Увійти як бот >",
+ "tweb.Login.Bot.Title": "Вхід як бот",
+ "tweb.Login.Bot.Subtitle": "Введіть токен, який видав @BotFather\nпід час створення бота.",
+ "tweb.Login.Bot.Token": "Токен бота",
+ "tweb.Login.Bot.Cancel": "Увійти як користувач >",
+ "tweb.Optional": "необов'язково",
+ "tweb.PHONE_NUMBER_INVALID": "Неправильний номер телефону",
+ "tweb.PHONE_NUMBER_BANNED": "Цей номер телефону заблоковано",
+ "tweb.PHONE_NUMBER_FLOOD": "Забагато спроб, спробуйте пізніше",
+ "tweb.PHONE_CODE_EMPTY": "Неправильний код",
+ "tweb.PHONE_PASSWORD_FLOOD": "Забагато спроб, спробуйте пізніше",
+ "tweb.ACCESS_TOKEN_INVALID": "Неправильний токен бота",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Цей токен бота відкликано",
+ "tweb.FIRSTNAME_INVALID": "Неприпустиме ім'я",
+ "tweb.LASTNAME_INVALID": "Неприпустиме прізвище",
+ "tweb.Close": "Закрити"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uz.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uz.json
index 422150a..a1c0e0a 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uz.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/uz.json
@@ -1,81 +1,93 @@
{
+ "baseDirLimitation": "Basedir cheklovi sozlangan: bu ishlashga taʼsir qilishi va baʼzi muammolarni keltirib chiqarishi mumkin, iloji boʻlsa, uni oʻchirib qoʻying!",
+ "noReportPeers": "Ogohlantirish: hech qanday hisobot tengdoshlari o'rnatilmagan, iltimos, voqea ishlov beruvchingizga quyidagi usulni qo'shing",
+ "manualAdminActionRequired": "!!!!!!!! QO'L QUVVAT TIZIMI ADMIN HARAKATI TALAB QILINADI !!!!!!!!!!!",
+ "mmapErrorPart1": "Xotira xaritalangan (mmap) mintaqalarining maksimal soniga erishildi (%s): tuzatish uchun vm.max_map_count yadro konfiguratsiyasini 262144 ga oshiring.",
+ "mmapErrorPart2": "Tuzatish uchun quyidagi buyruqni root sifatida ishga tushiring: %s",
+ "mmapErrorPart3": "Qayta yuklashda oʻzgarishlarni davom ettirish uchun: %s",
+ "mmapErrorPart4": "Windows va WSL da sahifa fayli hajmini oshirish yordam berishi mumkin; muammo davom etsa, mahalliy Linuxga o'ting.",
+ "botAlreadyRunning": "Bot allaqachon ishlayapti!",
+ "extensionRequired": "MadelineProto ishlashi uchun %s kengaytmasi talab qilinadi. %s",
+ "extensionRequiredInstallWithApt": "Sudo apt-get install %s ni ishga tushirib ko‘ring.",
+ "extensionRequiredInstallWithCustomInstructions": "Uni oʻrnatish uchun %s koʻrsatmalariga amal qiling.",
+ "extensionRecommended": "Ogohlantirish: %s kengaytmasi oʻrnatilmagan, MadelineProto tezligini oshirish uchun uni oʻrnating!",
+ "go": "Boshlash",
+ "apiChooseManualAutoTip": "Shuni esda tutingki, siz API ID/hashni to'g'ridan-to'g'ri kodda sozlamalardan foydalanib ko'rsatishingiz mumkin: %s",
+ "apiChooseManualAutoTipWeb": "Shuni esda tutingki, siz API identifikatorini/xesh-ni to'g'ridan-to'g'ri kodda sozlamalardan foydalanib ko'rsatishingiz mumkin.",
+ "apiChoosePrompt": "Sizning tanlovingiz (q/a): ",
+ "apiManualInstructions0": "https://my.telegram.org ga kirish",
+ "apiManualInstructions1": "API yaratish asboblariga o'tish",
+ "apiManualInstructions2": "Ilova yaratishga bosing",
+ "apiAppInstructionsManual0": "sizning ilovangizni nomi, u istalgan ko'rinishda bo'lishi mumkin",
"apiAppInstructionsManual1": "Ilovangizni qisqacha nomi, harflar va raqamlardan iborat 5-32 belgilar orasida",
"apiAppInstructionsManual2": "Ilova yoki vebsaytingiz manzili, yoki t.me/havola",
"apiAppInstructionsManual3": "istalgan narsa",
"apiAppInstructionsManual4": "Ilovangizni izoh bering",
"apiManualWeb": "API ID va API hash qiymatlaringizni kiriting",
+ "apiManualPrompt0": "API ID qiymatingizni kiriting ",
"apiManualPrompt1": "API hash qiymatingizni kiriting ",
+ "apiAutoWeb": "API ID olish uchun telegramdan oldin ro'yhatdan o'tkazilgan telefon raqamingizni kiriting",
"apiAutoPrompt0": "Telegram ro'yhatdan o'tkazilgan telefon raqamingizni kiriting ",
"apiAutoPrompt1": "Telegramdan olgan tasdiqlash kodingizni kiriting ",
"apiAppWeb": "API ma'lumotlarini kiriting",
+ "apiAppInstructionsAuto0": "Ilovangiz nomini kiriting: ",
+ "apiAppInstructionsAuto1": "Ilovani qisqacha nomini kiriting, harflar va raqamlardan iborat 5-32 belgilar orasida ",
+ "apiAppInstructionsAuto2": "Ilova yoki vebsay manzilini kiriting, yoki t.me/havola ",
+ "apiAppInstructionsAuto3": "Ilova platformasini kiriting: ",
+ "apiAppInstructionsAuto4": "Ilovangizni izohlang: ",
+ "apiAppInstructionsAutoTypeOther": "Boshqa (izohda ko'rsatiladi)",
+ "apiParamsError": "Siz barcha kerakli parametrlarni taqdim etmadingiz!",
+ "apiError": "Xatolik: %s. Qayta urinib ko'ring.",
+ "loginChoosePromptWeb": "Foydalanuvchi sifatida yoki bot sifatida kirmoqchimisiz?",
+ "loginWebQr": "Shuningdek, siz telefoningizda Telegram’ni ochib, Sozlamalar > Qurilmalar > Ish stoli qurilmasini bog‘lash bo‘limiga o‘tib, quyidagi QR kodni skanerlash orqali ham avtomatik tarzda kirishingiz mumkin:",
+ "loginWebQr1": "Telegram dasturini telefoningizda oching",
+ "loginWebQr2": "Sozlamalar > Uskunalar > Yangi qurilma ulashga o'ting",
+ "loginWebQr3": "Kirishni tasdiqlash uchun telefoningizni ushbu ekranga yo'naltiring",
"loginOptionBot": "Bot",
"loginOptionUser": "Foydalanuvchi",
"loginBot": "Bot tokeningizni kiriting ",
"loginUser": "Telefon raqamingizni kiriting ",
+ "loginQr": "Telefoningizda Telegram-ni oching, Sozlamalar > Qurilmalar > Ish stoli qurilmasini ulash-ga o‘ting va avtomatik kirish uchun yuqoridagi QR kodni skanerlang.",
"loginQrCodeSuccessful": "QR kod orqali muvaffaqiyatli kirish amalga oshirildi!",
"loginQrCodeExpired": "QR kod eskirdi, yangisini yaratish...",
+ "loginManual": "Shu bilan bir qatorda, qo'lda kirish uchun bot tokenini yoki telefon raqamini ham kiritishingiz mumkin: ",
"loginUserCode": "Kodni kiriting: ",
"loginUserPass": "Parolingizni kiriting (eslatma %s): ",
"loginUserPassWeb": "Parolingizni kiriting: ",
"loginUserPassHint": "Eslatma: %s",
"signupFirstName": "Ismingizni kiriting: ",
+ "signupLastName": "Familiyangizni kiriting (bo'sh qoldirish mumkin): ",
"signupWeb": "Iltimos, ro'yhatdan o'ting",
+ "signupFirstNameWeb": "Ism",
"signupLastNameWeb": "Familiya",
+ "loginNoCode": "Telefon raqamingiz kodini kiritmadingiz!",
"loginNoPass": "Parolingizni kiritmadingiz!",
"loginNoName": "Ismingizni kiritmadingiz!",
"loginBotTokenWeb": "Bot tokeni",
"loginUserPhoneWeb": "Telefon raqam",
"loginUserPhoneCodeWeb": "Kod",
"done": "Bajarildi!",
- "apiManualInstructions2": "Ilova yaratishga bosing",
- "apiAppInstructionsManual0": "sizning ilovangizni nomi, u istalgan ko'rinishda bo'lishi mumkin",
- "apiManualPrompt0": "API ID qiymatingizni kiriting ",
- "apiAutoWeb": "API ID olish uchun telegramdan oldin ro'yhatdan o'tkazilgan telefon raqamingizni kiriting",
- "loginQr": "Telefoningizda Telegram-ni oching, Sozlamalar > Qurilmalar > Ish stoli qurilmasini ulash-ga o‘ting va avtomatik kirish uchun yuqoridagi QR kodni skanerlang.",
- "signupLastName": "Familiyangizni kiriting (bo'sh qoldirish mumkin): ",
- "signupFirstNameWeb": "Ism",
- "loginNoCode": "Telefon raqamingiz kodini kiritmadingiz!",
+ "nearest_dc": "Biz %s ichidamiz, eng yaqin shahar %d.",
+ "serialization_ofd": "Seriyalash eskirgan, ob'ekt qayta tiklanmoqda!",
+ "api_not_set": "Siz api kaliti va api ID taqdim etishingiz kerak, o'zingiz @ my.telegram.org manzilidan oling",
+ "session_corrupted": "Sessiya buzilgan!",
"value_bigger_than_2147483647": "Taqdim etilgan %s qiymati 2147483647 dan katta",
"value_smaller_than_2147483648": "Taqdim etilgan %s qiymati -2147483648dan kichik",
"value_bigger_than_9223372036854775807": "Taqdim etilgan %s qiymati 9223372036854775807 dan katta",
"value_smaller_than_9223372036854775808": "Taqdim etilgan %s qiymati -9223372036854775808 dan kichik",
"value_bigger_than_4294967296": "Taqdim etilgan %s qiymati 4294967296 dan katta",
"value_smaller_than_0": "Taqdim etilgan %s qiymati 0 dan kichik",
+ "encode_double_error": "Doubleni toʻgʻri kodlab boʻlmadi",
"file_not_exist": "Fayl mavjud emas",
+ "deserialization_error": "Seriyadan chiqarishda xatolik yuz berdi",
+ "rpc_tg_error": "Telegram RPC xatosini qaytardi: %s (%s), %s:%s%s TL izidan kelib chiqqan:",
"madelineproto_ready": "MadelineProto tayyor!",
"logout_ok": "Chiqish muvaffaqiyatli amalga oshirildi!",
+ "already_loggedIn": "MadelineProto-ning bu nusxasi allaqachon tizimga kirgan!",
"login_ok": "Kirish muvaffaqiyatli amalga oshirildi!",
"login_user": "Odatiy foydalanuvchi kabi kirish...",
"login_bot": "Bot ko'rinishida kirish...",
"login_code_sending": "Kod yuborilmoqda...",
- "apiAppInstructionsAuto0": "Ilovangiz nomini kiriting: ",
- "apiAppInstructionsAuto1": "Ilovani qisqacha nomini kiriting, harflar va raqamlardan iborat 5-32 belgilar orasida ",
- "apiAppInstructionsAuto2": "Ilova yoki vebsay manzilini kiriting, yoki t.me/havola ",
- "apiAppInstructionsAuto3": "Ilova platformasini kiriting: ",
- "apiAppInstructionsAuto4": "Ilovangizni izohlang: ",
- "apiAppInstructionsAutoTypeOther": "Boshqa (izohda ko'rsatiladi)",
- "apiParamsError": "Siz barcha kerakli parametrlarni taqdim etmadingiz!",
- "apiError": "Xatolik: %s. Qayta urinib ko'ring.",
- "loginChoosePromptWeb": "Foydalanuvchi sifatida yoki bot sifatida kirmoqchimisiz?",
- "loginWebQr": "Shuningdek, siz telefoningizda Telegram’ni ochib, Sozlamalar > Qurilmalar > Ish stoli qurilmasini bog‘lash bo‘limiga o‘tib, quyidagi QR kodni skanerlash orqali ham avtomatik tarzda kirishingiz mumkin:",
- "go": "Boshlash",
- "apiChooseManualAutoTip": "Shuni esda tutingki, siz API ID/hashni to'g'ridan-to'g'ri kodda sozlamalardan foydalanib ko'rsatishingiz mumkin: %s",
- "apiChooseManualAutoTipWeb": "Shuni esda tutingki, siz API identifikatorini/xesh-ni to'g'ridan-to'g'ri kodda sozlamalardan foydalanib ko'rsatishingiz mumkin.",
- "apiChoosePrompt": "Sizning tanlovingiz (q/a): ",
- "apiManualInstructions0": "https://my.telegram.org ga kirish",
- "apiManualInstructions1": "API yaratish asboblariga o'tish",
- "loginWebQr1": "Telegram dasturini telefoningizda oching",
- "loginWebQr2": "Sozlamalar > Uskunalar > Yangi qurilma ulashga o'ting",
- "loginWebQr3": "Kirishni tasdiqlash uchun telefoningizni ushbu ekranga yo'naltiring",
- "loginManual": "Shu bilan bir qatorda, qo'lda kirish uchun bot tokenini yoki telefon raqamini ham kiritishingiz mumkin: ",
- "nearest_dc": "Biz %s ichidamiz, eng yaqin shahar %d.",
- "serialization_ofd": "Seriyalash eskirgan, ob'ekt qayta tiklanmoqda!",
- "api_not_set": "Siz api kaliti va api ID taqdim etishingiz kerak, o'zingiz @ my.telegram.org manzilidan oling",
- "session_corrupted": "Sessiya buzilgan!",
- "encode_double_error": "Doubleni toʻgʻri kodlab boʻlmadi",
- "deserialization_error": "Seriyadan chiqarishda xatolik yuz berdi",
- "rpc_tg_error": "Telegram RPC xatosini qaytardi: %s (%s), %s:%s%s TL izidan kelib chiqqan:",
- "already_loggedIn": "MadelineProto-ning bu nusxasi allaqachon tizimga kirgan!",
"login_code_sent": "Kod muvaffaqiyatli yuborildi! Kodni olganingizdan so'ng siz to'liq PhoneLogin funksiyasidan foydalanishingiz kerak.",
"login_code_uncalled": "Men kodni kutmayapman! Iltimos, avval phoneLogin funsksiyasini ishga tushuring",
"login_2fa_enabled": "2FA faollashtirilgan, siz complete2falogin funksiyasini chaqirishingiz kerak bo'ladi...",
@@ -106,57 +118,157 @@
"long_not_64": "Berilgan qiymat 64 bayt emas",
"array_invalid": "Siz toʻgʻri massiv taqdim qilmadingiz",
"predicate_not_set": "Predikat (_ ostidagi qiymat) belgilanmagan!",
+ "update_madelineproto": "Siz MadelineProto’ning eski versiyasini ishga tushiryapsiz, yangilash talab qilinadi: hozirda %s ishlayapti, lekin bir nechta xatoliklar tuzatilgan va yangi funksiyalarga ega so‘nggi versiya %s!",
"type_extract_error": "“%s” turini chiqarib bo‘lmadi, siz MadelineProtoni yangilashingiz kerak!",
"method_not_found": "Metodni topib bo'lmadi: ",
"params_missing": "Talab etiladigan parametr kiritilmagan",
"sec_peer_not_in_db": "Ushbu maxfiy obyekt ichki obyektlar bazasida mavjud emas",
"stream_handle_invalid": "Yaroqsiz oqim tutqichi taqdim etildi.",
"length_too_big": "Uzunlik juda katta",
+ "string_required": "Bir qator kutilgan edi!",
+ "waveform_must_have_100_values": "To'lqin shakli qatori 100 ta qiymatga ega bo'lishi kerak!",
+ "waveform_value": "To'lqin shakli qiymati 0 dan 31 gacha bo'lishi kerak!",
+ "could_not_convert_object": "%s turdagi obyektni aylantirib bo‘lmadi",
"type_extract_error_id": "Turni ajratib bo‘lmadi: %s identifikatori %s, siz MadelineProtoni yangilashingiz kerak!",
"constructor_not_found": "Ushbu tur uchun konstruktor topilmadi: ",
"botapi_conversion_error": "%s bot API obyektiga aylantirib bo‘lmadi",
"non_text_conversion": "Matnli boʻlmagan xabarlarni oʻzgartirib boʻlmaydi!",
"file_type_invalid": "Yaroqsiz fayl turi aniqlandi (%s)",
+ "static_analysis_minor": "%s: %s ni statik tahlil qilishda kichik muammoga duch keldi",
+ "static_analysis_severe": "%s: %s ni statik tahlil qilishda jiddiy muammoga duch keldi",
"secret_chat_skipping": "Menda %s maxfiy chati maʼlumotlar bazasida yoʻq, xabar oʻtkazib yuborilmoqda...",
- "botAlreadyRunning": "Bot allaqachon ishlayapti!",
- "mmapErrorPart2": "Tuzatish uchun quyidagi buyruqni root sifatida ishga tushiring: %s",
- "mmapErrorPart3": "Qayta yuklashda oʻzgarishlarni davom ettirish uchun: %s",
- "extensionRecommended": "Ogohlantirish: %s kengaytmasi oʻrnatilmagan, MadelineProto tezligini oshirish uchun uni oʻrnating!",
- "do_not_delete_MadelineProto.log": "MadelineProto.log fayli hech qachon o'chirilmasligi kerak, o'rniga sozlamalarda maxsus maksimal o'lchamni o'rnating!",
- "string_required": "Bir qator kutilgan edi!",
- "waveform_must_have_100_values": "To'lqin shakli qatori 100 ta qiymatga ega bo'lishi kerak!",
- "waveform_value": "To'lqin shakli qiymati 0 dan 31 gacha bo'lishi kerak!",
- "could_not_convert_object": "%s turdagi obyektni aylantirib bo‘lmadi",
"must_have_declare_types": "ishlash sabablariga ko'ra, voqea ishlov beruvchi faylining birinchi bayonoti \"declare(strict_types=1);\" bo'lishi kerak",
+ "do_not_delete_MadelineProto.log": "MadelineProto.log fayli hech qachon o'chirilmasligi kerak, o'rniga sozlamalarda maxsus maksimal o'lchamni o'rnating!",
+ "do_not_remove_MadelineProto.log_phar": "Iltimos, madeline.phar yoki madeline.php ni olib tashlamang, aks holda MadelineProto ishlamay qoladi. Agar sizda MadelineProto bilan bog'liq muammo bo'lsa, uni https://github.com/danog/MadelineProto yoki https://t.me/pwrtelegramgroup manziliga xabar qiling",
"do_not_use_blocking_function": "samaradorlik sabablariga ko‘ra, hodisa ishlov beruvchilari %s asinxron bo‘lmagan blokirovka funksiyasidan foydalanmasligi mumkin, o‘rniga %s dan foydalaning",
- "do_not_use_deprecated_function": "%s funksiyasi eskirgan, o‘rniga %s dan foydalaning",
"do_not_use_blocking_class": "ishlash sabablariga ko'ra, ishlov beruvchilar asinxron bo'lmagan bloklash sinfi %s dan foydalanmasligi mumkin, o'rniga %s dan foydalaning",
+ "do_not_use_deprecated_function": "%s funksiyasi eskirgan, o‘rniga %s dan foydalaning",
"do_not_use_non_root_require_in_event_handler": "ishlash sabablariga ko'ra, voqea ishlov beruvchisi sinfiga talab yoki qo'shmaslik kerak, faqat ildiz darajasidagi talablarga ruxsat beriladi.",
- "static_analysis_minor": "%s: %s ni statik tahlil qilishda kichik muammoga duch keldi",
- "static_analysis_severe": "%s: %s ni statik tahlil qilishda jiddiy muammoga duch keldi",
- "plugins_must_have_exactly_one_class": "plagin aynan bitta sinfni belgilashi kerak! Bir nechta sinflarni, interfeyslarni yoki xususiyatlarni aniqlash uchun alohida fayllar yarating, ular MadelineProto tomonidan avtomatik ravishda yuklanadi.",
- "translate_madelineproto_web": "MadelineProto oʻz tilingizga tarjima qilinishi mumkin (hozirgi tarjima jarayoni: %d%%), tarjimaga hissa qoʻshish uchun bu yerni bosing!",
- "noReportPeers": "Ogohlantirish: hech qanday hisobot tengdoshlari o'rnatilmagan, iltimos, voqea ishlov beruvchingizga quyidagi usulni qo'shing",
- "manualAdminActionRequired": "!!!!!!!! QO'L QUVVAT TIZIMI ADMIN HARAKATI TALAB QILINADI !!!!!!!!!!!",
- "extensionRequired": "MadelineProto ishlashi uchun %s kengaytmasi talab qilinadi. %s",
- "extensionRequiredInstallWithApt": "Sudo apt-get install %s ni ishga tushirib ko‘ring.",
- "plugin_path_does_not_exist": "%s plagin yoʻli mavjud emas!",
- "dl.php_check_logs_make_sure_session_running": "MadelineProto EventHandler boti yoki MadelineProto IPC serveri oflayn, iltimos jurnallarni tekshiring va ulardan kamida bittasi ishlayotganiga ishonch hosil qiling!",
- "baseDirLimitation": "Basedir cheklovi sozlangan: bu ishlashga taʼsir qilishi va baʼzi muammolarni keltirib chiqarishi mumkin, iloji boʻlsa, uni oʻchirib qoʻying!",
- "extensionRequiredInstallWithCustomInstructions": "Uni oʻrnatish uchun %s koʻrsatmalariga amal qiling.",
- "update_madelineproto": "Siz MadelineProto’ning eski versiyasini ishga tushiryapsiz, yangilash talab qilinadi: hozirda %s ishlayapti, lekin bir nechta xatoliklar tuzatilgan va yangi funksiyalarga ega so‘nggi versiya %s!",
"do_not_use_yield": "MadelineProto 8 asinx funksiyalarida yield dan foydalanishni talab qilmaydi yoki qo‘llab-quvvatlamaydi, avval asinxron funksiya chaqiruvlari uchun ishlatilgan barcha yield kalit so‘zlarini olib tashlashingiz kerak",
"recommend_not_use_filesystem_function": "%s funksiyasidan foydalanish tavsiya etilmaydi, chunki yangilanishni qayta ishlash jarayonida fayl tizimiga kirish botni sekinlashtiradi, botni sekinlashtirmaydigan maʼlumotlarni saqlashning muqobil usullari roʻyxatini https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions sahifasiga oʻting!",
"plugins_do_not_use_require": "ishlash sabablariga ko'ra, plaginlar faqat PSR-4 avtomatik yuklagichini ishga tushirish orqali plaginlar jildida mavjud bo'lgan boshqa fayllarni avtomatik ravishda kiritishi yoki talab qilishi mumkin (ularni qo'lda talab qilish orqali emas).",
- "could_not_connect_to_MadelineProto": "MadelineProto-ga ulanib bo'lmadi, iltimos, proc_open-ni yoqing va open_basedir cheklovlarini olib tashlang yoki tuzatish uchun veb-server yo'lini qayta yozishni o'chirib qo'ying! Agar siz buni allaqachon qilgan bo'lsangiz, PHP ning CLI versiyasi veb-versiyasi bilan bir xil ekanligiga ishonch hosil qiling (xuddi shu versiya, kengaytmalar va boshqalar) va IPC serverini ishga tushirishga to'sqinlik qilgan xato haqida ko'proq ma'lumot olish uchun MadelineProto.log faylini tekshiring.",
- "invalid_dl.php_session": "%s yuklab olish skripti noto‘g‘ri, chunki uning seans identifikatori boshqacha (kutilgan %s, %s oldi)",
- "dl.php_powered_by_madelineproto": "MadelineProto tomonidan quvvatlangan Telegram fayl yuklab olish serveri (4 GB gacha)!
Batafsil ma'lumot olish uchun MadelineProto tomonidan quvvatlangan Telegram fayl yuklab olish serveri (4 GB gacha)!
O'zingizning Telegram fayl yuklab olish serveringizni sozlash haqida batafsil ma'lumot olish uchun bu yerni bosing!",
+ "dl.php_check_logs_make_sure_session_running": "MadelineProto EventHandler boti yoki MadelineProto IPC serveri oflayn, iltimos jurnallarni tekshiring va ulardan kamida bittasi ishlayotganiga ishonch hosil qiling!",
"account_banned": "!!!!!!! OGOHLANTIRISH!!!!!!\nTelegram’ning suv toshqini oldini olish tizimi ushbu akkauntni to‘xtatib qo‘ydi.\nDavom etish uchun qo‘lda tekshirish kerak.\n%s telefon raqamini blokdan chiqarishni so‘rab, recover@telegram.org manziliga xat yuboring va bu telefon raqami bilan nima qilishingizni qisqacha tasvirlab bering.\nKeyin yana tizimga kiring.\nAgar siz ushbu hisobni ataylab o'chirib tashlagan bo'lsangiz, bu xabarni e'tiborsiz qoldiring.",
- "windows_warning": "Windows foydalanuvchilari uchun: agar bu bajarilmasa, Linuxga o'ting. Shuningdek, barcha PHP jarayonlariga rozetkalar yaratishga ruxsat berish uchun xavfsizlik devori sozlamalarini oʻzgartirishga urinib koʻrishingiz mumkin (Linux’ga oʻtish 100% oson, Linuxda MadelineProto shunchaki qutidan tashqarida ishlaydi, hech qanday oʻzgartirish kerak emas)",
- "mmapErrorPart1": "Xotira xaritalangan (mmap) mintaqalarining maksimal soniga erishildi (%s): tuzatish uchun vm.max_map_count yadro konfiguratsiyasini 262144 ga oshiring.",
- "mmapErrorPart4": "Windows va WSL da sahifa fayli hajmini oshirish yordam berishi mumkin; muammo davom etsa, mahalliy Linuxga o'ting.",
- "do_not_remove_MadelineProto.log_phar": "Iltimos, madeline.phar yoki madeline.php ni olib tashlamang, aks holda MadelineProto ishlamay qoladi. Agar sizda MadelineProto bilan bog'liq muammo bo'lsa, uni https://github.com/danog/MadelineProto yoki https://t.me/pwrtelegramgroup manziliga xabar qiling",
- "need_dl.php": "Standart yuklab olish skriptini (%s) yaratib bo‘lmadi, iltimos, quyidagi tarkibga ega dl.php faylini yarating: %s va uning URL manzilini getDownloadLink ikkinchi parametriga o‘tkazing"
+ "plugin_path_does_not_exist": "%s plagin yoʻli mavjud emas!",
+ "could_not_connect_to_MadelineProto": "MadelineProto-ga ulanib bo'lmadi, iltimos, proc_open-ni yoqing va open_basedir cheklovlarini olib tashlang yoki tuzatish uchun veb-server yo'lini qayta yozishni o'chirib qo'ying! Agar siz buni allaqachon qilgan bo'lsangiz, PHP ning CLI versiyasi veb-versiyasi bilan bir xil ekanligiga ishonch hosil qiling (xuddi shu versiya, kengaytmalar va boshqalar) va IPC serverini ishga tushirishga to'sqinlik qilgan xato haqida ko'proq ma'lumot olish uchun MadelineProto.log faylini tekshiring.",
+ "translate_madelineproto_web": "MadelineProto oʻz tilingizga tarjima qilinishi mumkin (hozirgi tarjima jarayoni: %d%%), tarjimaga hissa qoʻshish uchun bu yerni bosing!",
+ "translate_madelineproto_cli": "MadelineProto o'z tilingizga tarjima qilinishi mumkin (hozirgi tarjima jarayoni: %d%%), tarjimaga hissa qo'shish uchun https://github.com/danog/MadelineProto/tree/v8/langs saytiga o'ting!",
+ "apiInvalidWeb": "API ID raqamdan iborat, API hash esa 32 belgidan iborat: ularni my.telegram.org saytidan qaytadan nusxalang.",
+ "webDoneLead": "MadelineProto serverda ishlashda davom etmoqda: bu sahifani yopishingiz mumkin.",
+ "apiChooseManualAuto": "API ID va hashni my.telegram.org saytidan avtomatik olishni (a) yoki ularni qoʻlda kiritishni (m) xohlaysizmi?",
+ "apiAutoFallbackManual": "Buning oʻrniga API ID va hashni qoʻlda kiriting.",
+ "apiSetupTitleWeb": "API ID va hashni oling",
+ "apiSetupLeadWeb": "Har bir Telegram ilovasiga API ID va hash kerak. MadelineProto ularni mavjud Telegram akkauntining telefon raqami yordamida my.telegram.org saytidan siz uchun olib berishi mumkin.",
+ "apiAutoPhoneHintWeb": "my.telegram.org kirish kodini SMS orqali emas, Telegram ilovangizga yuboradi.",
+ "apiSendCodeWeb": "Kodni yuborish",
+ "apiChooseManualWeb": "Menda API ID allaqachon bor",
+ "apiChooseAutoWeb": "Avtomatik olish",
+ "apiStartOverWeb": "Boshidan boshlash",
+ "apiAutoCodeTitleWeb": "Telegramdan kelgan kodni kiriting",
+ "apiAutoCodeLeadWeb": "my.telegram.org Telegram ilovangizga, Telegram bilan chatga kirish kodini yubordi (SMS orqali emas).",
+ "apiAutoCodeLabelWeb": "Kirish kodi",
+ "apiCreateTitleWeb": "Ilovangizni yarating",
+ "apiCreateLeadWeb": "Bu akkauntda my.telegram.org saytida hali ilova yoʻq. Bu maʼlumotlar faqat sizga koʻrsatiladi va keyinroq ularni oʻzgartirish mumkin.",
+ "apiAppTitleLabelWeb": "Ilova nomi",
+ "apiAppShortNameLabelWeb": "Qisqa nom",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Tavsif",
+ "apiCreateWeb": "Ilova yaratish",
+ "apiSaveWeb": "Saqlash va davom etish",
+ "apiAutoErrorTitle": "my.telegram.org xatolik qaytardi",
+ "apiCreateErrorTitle": "my.telegram.org ilovani yaratmadi",
+ "apiCreateVpsWarning": "Telegram VPS, VPN va boshqa maʼlumotlar markazlari IP diapazonlaridan my.telegram.org saytida yangi ilova yaratishga ruxsat bermaydi, soʻrov esa MadelineProto ishlayotgan mashinaning IP manzilidan yuborildi. Ilovani uy internetidan (masalan, mobil internetdagi telefoningizdan) https://my.telegram.org saytida qoʻlda yarating, soʻngra API ID va hashni kiriting.",
+ "loginTitleWeb": "Telegramga kirish",
+ "loginLeadWeb": "Ushbu MadelineProto nusxasi qaysi akkaunt yoki bot sifatida ishlashini tanlang.",
+ "loginTypeWeb": "Kim sifatida kirish",
+ "loginUserPhoneHintWeb": "Davlat kodi bilan, masalan +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Botni yaratganingizda @BotFather bergan token.",
+ "loginCodeTitleWeb": "Kirish kodini kiriting",
+ "loginCodeLeadWeb": "Telegram kirish kodini Telegram ilovangizga yubordi, agar boshqa joyda kirmagan boʻlsangiz, SMS orqali yuboriladi.",
+ "loginPasswordTitleWeb": "Ikki bosqichli tasdiqlash",
+ "loginPasswordLeadWeb": "Bu akkaunt Sozlamalar > Maxfiylik va xavfsizlik > Ikki bosqichli tasdiqlash boʻlimida oʻrnatilgan parol bilan himoyalangan.",
+ "loginPasswordLabelWeb": "Parol",
+ "signupTitleWeb": "Akkauntingizni yarating",
+ "signupLeadWeb": "Bu telefon raqami hali Telegramda yoʻq: yangi akkaunt uchun ism tanlang.",
+ "webContinue": "Davom etish",
+ "webLogin": "Kirish",
+ "webError": "%s. Tekshirib, qayta urinib koʻring.",
+ "webStepApp": "API ID va hash",
+ "webStepAccount": "Akkaunt",
+ "webStepVerify": "Tasdiqlash",
+ "webStepDone": "Ishlamoqda",
+ "webProgress": "Sozlash jarayoni",
+ "webDocs": "Hujjatlar",
+ "webOptional": "ixtiyoriy",
+ "webShowPassword": "Koʻrsatish",
+ "webHidePassword": "Yashirish",
+ "webQrTitle": "QR kod orqali kirish",
+ "webQrWaiting": "Skanerlash kutilmoqda…",
+ "webFieldRequired": "Bu maydonni toʻldiring.",
+ "webPhoneInvalid": "Telefon raqamini davlat kodi bilan kiriting, masalan +39 123 456 7890.",
+ "tweb.Login.Title": "MadelineProto’ga kirish",
+ "tweb.Login.PhoneLabelInvalid": "Telefon raqami notoʻgʻri",
+ "tweb.Login.StartText": "Iltimos, davlat kodini tasdiqlang\nva telefon raqamingizni kiriting.",
+ "tweb.Login.Code.SentSms": "Sizga kod yozilgan\nSMS yubordik.",
+ "tweb.Login.Code.SentInApp": "Sizga Telegramda kod yozilgan\nxabar yubordik.",
+ "tweb.Login.Code.SentCall": "Sizga qoʻngʻiroq qilib,\nkodni aytib beramiz.",
+ "tweb.Login.Code.SentEmail": "Iltimos, **%s** elektron pochtangizni tekshiring (spam jildini ham unutmang) va hozirgina yuborgan kodimizni kiriting.",
+ "tweb.Login.Code.SentUnknown": "Iltimos, kodni hamma joydan\nqidirib koʻring (turi: %s)",
+ "tweb.Login.Code.SentMissedCall": "Bir necha soniya ichida **%s** raqamidan\nqisqa qoʻngʻiroq kelishi kerak. Javob bermang —\nshunchaki shu raqamning oxirgi raqamlarini kiriting.",
+ "tweb.Login.Code.SentSmsWord": "**%s** telefon raqamingizga\nmaxfiy soʻz yozilgan SMS yubordik.",
+ "tweb.Login.Code.SentSmsWordBeginning": "**%1$s** telefon raqamingizga \"**%2$s**\" bilan\nboshlanadigan maxfiy soʻz yozilgan SMS yubordik.",
+ "tweb.Login.Code.SentSmsPhrase": "**%s** telefon raqamingizga\nmaxfiy ibora yozilgan SMS yubordik.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "**%1$s** telefon raqamingizga \"**%2$s**\" bilan\nboshlanadigan maxfiy ibora yozilgan SMS yubordik.",
+ "tweb.Login.Code.SecretWord": "Maxfiy soʻz",
+ "tweb.Login.Code.SecretPhrase": "Maxfiy ibora",
+ "tweb.Login.Code.WordInvalid": "Notoʻgʻri, qayta urinib koʻring",
+ "tweb.Login.Code.WordBeginningInvalid": "Notoʻgʻri soʻz",
+ "tweb.Login.Password.Title": "Parolingizni kiriting",
+ "tweb.Login.Password.Subtitle": "Akkauntingiz qoʻshimcha\nparol bilan himoyalangan",
+ "tweb.Login.Register.Subtitle": "Akkaunt yaratish uchun\nismingizni kiriting",
+ "tweb.PleaseWait": "Iltimos, kuting...",
+ "tweb.Code": "Kod",
+ "tweb.LoginPassword": "Parol",
+ "tweb.YourName": "Ismingiz",
+ "tweb.FirstName": "Ism (majburiy)",
+ "tweb.LastName": "Familiya (ixtiyoriy)",
+ "tweb.StartMessaging": "Yozishmani boshlash",
+ "tweb.Country": "Davlat",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Telefon raqami",
+ "tweb.Login.Next": "Keyingi",
+ "tweb.Login.QR.Title": "QR kod orqali kirish",
+ "tweb.Login.QR.Help1": "Telefoningizda Telegramni oching",
+ "tweb.Login.QR.Help2": "**Sozlamalar** > **Qurilmalar** > **Qurilma qoʻshish** boʻlimiga oʻting",
+ "tweb.Login.QR.Help3": "Kirishni tasdiqlash uchun telefoningizni ushbu ekranga yoʻnaltiring",
+ "tweb.Login.QR.Cancel": "Telefon raqami orqali kirish >",
+ "tweb.Login.QR.Login": "QR kod orqali kirish >",
+ "tweb.Login.QR.Subtitle": "Telefoningizdagi Telegram ilovasi bilan skanerlang",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Kodni [Fragment]() saytidagi Raqamlar boʻlimidan oling",
+ "tweb.PHONE_CODE_INVALID": "Kod notoʻgʻri",
+ "tweb.PHONE_CODE_EXPIRED": "Kod muddati tugagan",
+ "tweb.PASSWORD_HASH_INVALID": "Parol notoʻgʻri",
+ "tweb.DarkMode": "Tungi rejim",
+ "tweb.Error.AnError": "Xatolik yuz berdi. Keyinroq qayta urinib koʻring.",
+ "tweb.AccDescr.LoginCode": "Kirish kodi",
+ "tweb.Login.Bot": "Bot sifatida kirish >",
+ "tweb.Login.Bot.Title": "Bot sifatida kirish",
+ "tweb.Login.Bot.Subtitle": "Botni yaratganingizda @BotFather\nbergan tokenni kiriting.",
+ "tweb.Login.Bot.Token": "Bot tokeni",
+ "tweb.Login.Bot.Cancel": "Foydalanuvchi sifatida kirish >",
+ "tweb.Optional": "ixtiyoriy",
+ "tweb.PHONE_NUMBER_INVALID": "Telefon raqami notoʻgʻri",
+ "tweb.PHONE_NUMBER_BANNED": "Bu telefon raqami bloklangan",
+ "tweb.PHONE_NUMBER_FLOOD": "Urinishlar juda koʻp, keyinroq qayta urinib koʻring",
+ "tweb.PHONE_CODE_EMPTY": "Kod notoʻgʻri",
+ "tweb.PHONE_PASSWORD_FLOOD": "Urinishlar juda koʻp, keyinroq qayta urinib koʻring",
+ "tweb.ACCESS_TOKEN_INVALID": "Bot tokeni notoʻgʻri",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Bu bot tokeni bekor qilingan",
+ "tweb.FIRSTNAME_INVALID": "Ism notoʻgʻri",
+ "tweb.LASTNAME_INVALID": "Familiya notoʻgʻri",
+ "tweb.Close": "Yopish"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/vi.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/vi.json
new file mode 100644
index 0000000..004ac26
--- /dev/null
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/vi.json
@@ -0,0 +1,274 @@
+{
+ "baseDirLimitation": "Đã cấu hình giới hạn basedir: điều này có thể ảnh hưởng đến hiệu năng và gây ra một số vấn đề, vui lòng tắt nó nếu có thể!",
+ "noReportPeers": "Cảnh báo: chưa thiết lập peer nhận báo cáo nào, vui lòng thêm phương thức sau vào event handler của bạn",
+ "manualAdminActionRequired": "!!!!!!!!! CẦN QUẢN TRỊ VIÊN HỆ THỐNG THAO TÁC THỦ CÔNG !!!!!!!!!",
+ "mmapErrorPart1": "Đã đạt đến số lượng tối đa vùng bộ nhớ ánh xạ (mmap) (%s): vui lòng tăng cấu hình kernel vm.max_map_count lên 262144 để khắc phục.",
+ "mmapErrorPart2": "Để khắc phục, hãy chạy lệnh sau với quyền root: %s",
+ "mmapErrorPart3": "Để giữ thay đổi sau khi khởi động lại: %s",
+ "mmapErrorPart4": "Trên Windows và WSL, tăng kích thước pagefile có thể giúp ích; vui lòng chuyển sang Linux gốc nếu sự cố vẫn tiếp diễn.",
+ "botAlreadyRunning": "Bot đang chạy rồi!",
+ "extensionRequired": "MadelineProto cần extension %s để chạy. %s",
+ "extensionRequiredInstallWithApt": "Hãy thử chạy sudo apt-get install %s.",
+ "extensionRequiredInstallWithCustomInstructions": "Làm theo hướng dẫn tại %s để cài đặt.",
+ "extensionRecommended": "Cảnh báo: extension %s chưa được cài đặt, vui lòng cài đặt để tăng tốc MadelineProto!",
+ "go": "Tiếp tục",
+ "apiChooseManualAutoTip": "Lưu ý rằng bạn cũng có thể cung cấp API ID/hash trực tiếp trong code bằng phần cài đặt: %s",
+ "apiChooseManualAutoTipWeb": "Lưu ý rằng bạn cũng có thể cung cấp API ID/hash trực tiếp trong code bằng phần cài đặt.",
+ "apiChoosePrompt": "Lựa chọn của bạn (m/a): ",
+ "apiManualInstructions0": "Đăng nhập vào https://my.telegram.org",
+ "apiManualInstructions1": "Vào API development tools",
+ "apiManualInstructions2": "Nhấn vào create application",
+ "apiAppInstructionsManual0": "tên ứng dụng của bạn, đặt tùy ý",
+ "apiAppInstructionsManual1": "tên ngắn của ứng dụng, chỉ gồm chữ và số, 5-32 ký tự",
+ "apiAppInstructionsManual2": "URL của ứng dụng/trang web của bạn, hoặc t.me/yourusername",
+ "apiAppInstructionsManual3": "tùy ý",
+ "apiAppInstructionsManual4": "Mô tả ứng dụng của bạn tại đây",
+ "apiManualWeb": "Nhập API ID và API hash của bạn",
+ "apiManualPrompt0": "Nhập API ID của bạn: ",
+ "apiManualPrompt1": "Nhập API hash của bạn: ",
+ "apiAutoWeb": "Nhập số điện thoại đã được đăng ký trên Telegram để lấy API ID",
+ "apiAutoPrompt0": "Nhập số điện thoại đã được đăng ký trên Telegram: ",
+ "apiAutoPrompt1": "Nhập mã xác minh bạn nhận được trong Telegram: ",
+ "apiAppWeb": "Nhập thông tin API",
+ "apiAppInstructionsAuto0": "Nhập tên ứng dụng, đặt tùy ý: ",
+ "apiAppInstructionsAuto1": "Nhập tên ngắn của ứng dụng, chỉ gồm chữ và số, 5-32 ký tự: ",
+ "apiAppInstructionsAuto2": "Nhập URL của ứng dụng/trang web, hoặc t.me/yourusername: ",
+ "apiAppInstructionsAuto3": "Nhập nền tảng của ứng dụng: ",
+ "apiAppInstructionsAuto4": "Mô tả ứng dụng của bạn: ",
+ "apiAppInstructionsAutoTypeOther": "Khác (ghi rõ trong phần mô tả)",
+ "apiParamsError": "Bạn chưa cung cấp đủ các tham số bắt buộc!",
+ "apiError": "LỖI: %s. Vui lòng thử lại.",
+ "loginChoosePromptWeb": "Bạn muốn đăng nhập với tư cách người dùng hay bot?",
+ "loginWebQr": "Bạn cũng có thể đăng nhập tự động bằng cách mở Telegram trên điện thoại, vào Cài đặt > Thiết bị > Liên kết thiết bị máy tính và quét mã QR sau:",
+ "loginWebQr1": "Mở Telegram trên điện thoại của bạn",
+ "loginWebQr2": "Vào Cài đặt > Thiết bị > Liên kết thiết bị máy tính",
+ "loginWebQr3": "Hướng điện thoại vào màn hình này để xác nhận đăng nhập",
+ "loginOptionBot": "Bot",
+ "loginOptionUser": "Người dùng",
+ "loginBot": "Nhập token bot của bạn: ",
+ "loginUser": "Nhập số điện thoại của bạn: ",
+ "loginQr": "Mở Telegram trên điện thoại, vào Cài đặt > Thiết bị > Liên kết thiết bị máy tính và quét mã QR ở trên để đăng nhập tự động.",
+ "loginQrCodeSuccessful": "Đăng nhập bằng mã QR thành công!",
+ "loginQrCodeExpired": "Mã QR đã hết hạn, đang tạo mã mới...",
+ "loginManual": "Ngoài ra, bạn cũng có thể nhập token bot hoặc số điện thoại để đăng nhập thủ công: ",
+ "loginUserCode": "Nhập mã: ",
+ "loginUserPass": "Nhập mật khẩu của bạn (gợi ý %s): ",
+ "loginUserPassWeb": "Nhập mật khẩu của bạn: ",
+ "loginUserPassHint": "Gợi ý: %s",
+ "signupFirstName": "Nhập tên của bạn: ",
+ "signupLastName": "Nhập họ của bạn (có thể để trống): ",
+ "signupWeb": "Vui lòng đăng ký",
+ "signupFirstNameWeb": "Tên",
+ "signupLastNameWeb": "Họ",
+ "loginNoCode": "Bạn chưa cung cấp mã điện thoại!",
+ "loginNoPass": "Bạn chưa cung cấp mật khẩu!",
+ "loginNoName": "Bạn chưa cung cấp tên!",
+ "loginBotTokenWeb": "Token bot",
+ "loginUserPhoneWeb": "Số điện thoại",
+ "loginUserPhoneCodeWeb": "Mã",
+ "done": "Xong!",
+ "nearest_dc": "Chúng ta đang ở %s, DC gần nhất là %d.",
+ "serialization_ofd": "Dữ liệu tuần tự hóa đã lỗi thời, đang tái tạo đối tượng!",
+ "api_not_set": "Bạn phải cung cấp api key và api id, hãy lấy của riêng bạn tại my.telegram.org",
+ "session_corrupted": "Phiên bị hỏng!",
+ "value_bigger_than_2147483647": "Giá trị %s được cung cấp lớn hơn 2147483647",
+ "value_smaller_than_2147483648": "Giá trị %s được cung cấp nhỏ hơn -2147483648",
+ "value_bigger_than_9223372036854775807": "Giá trị %s được cung cấp lớn hơn 9223372036854775807",
+ "value_smaller_than_9223372036854775808": "Giá trị %s được cung cấp nhỏ hơn -9223372036854775808",
+ "value_bigger_than_4294967296": "Giá trị %s được cung cấp lớn hơn 4294967296",
+ "value_smaller_than_0": "Giá trị %s được cung cấp nhỏ hơn 0",
+ "encode_double_error": "Không thể mã hóa double đúng cách",
+ "file_not_exist": "Tệp không tồn tại",
+ "deserialization_error": "Đã xảy ra lỗi khi giải tuần tự hóa",
+ "rpc_tg_error": "Telegram trả về lỗi RPC: %s (%s), gây ra bởi %s:%s%sTruy vết TL:",
+ "madelineproto_ready": "MadelineProto đã sẵn sàng!",
+ "logout_ok": "Đăng xuất thành công!",
+ "already_loggedIn": "Instance MadelineProto này đã đăng nhập rồi!",
+ "login_ok": "Đăng nhập thành công!",
+ "login_user": "Đang đăng nhập với tư cách người dùng thông thường...",
+ "login_bot": "Đang đăng nhập với tư cách bot...",
+ "login_code_sending": "Đang gửi mã...",
+ "login_code_sent": "Đã gửi mã thành công! Khi nhận được mã, bạn cần sử dụng hàm completePhoneLogin.",
+ "login_code_uncalled": "Tôi không đang chờ mã! Vui lòng gọi phương thức phoneLogin trước",
+ "login_2fa_enabled": "2FA đã được bật, bạn sẽ phải gọi hàm complete2falogin...",
+ "login_need_signup": "Chưa có tài khoản nào được tạo cho số này, bạn sẽ phải gọi hàm completeSignup...",
+ "login_auth_key": "Đang đăng nhập bằng auth key...",
+ "not_loggedIn": "Tôi chưa đăng nhập!",
+ "signup_uncalled": "Tôi không đang chờ đăng ký! Vui lòng gọi các phương thức phoneLogin và completePhoneLogin trước!",
+ "signing_up": "Đang đăng ký với tư cách người dùng thông thường...",
+ "signup_ok": "Đăng ký thành công!",
+ "2fa_uncalled": "Tôi không đang chờ mật khẩu! Vui lòng gọi các phương thức phoneLogin và completePhoneLogin trước!",
+ "peer_not_in_db": "Peer này không có trong cơ sở dữ liệu peer nội bộ",
+ "call_error_1": "Không thể tìm và chấp nhận cuộc gọi %s",
+ "accepting_call": "Đang chấp nhận cuộc gọi từ %s...",
+ "call_already_accepted": "Cuộc gọi %s đã được chấp nhận",
+ "call_already_declined": "Cuộc gọi %s đã bị từ chối",
+ "call_error_2": "Không thể tìm và xác nhận cuộc gọi %s",
+ "call_confirming": "Đang xác nhận cuộc gọi từ %s...",
+ "call_error_3": "Không thể tìm và hoàn tất cuộc gọi %s",
+ "call_completing": "Đang hoàn tất cuộc gọi từ %s...",
+ "fingerprint_invalid": "Fingerprint của khóa không hợp lệ!",
+ "call_discarding": "Đang kết thúc cuộc gọi %s...",
+ "file_parsing": "Đang phân tích %s...",
+ "src_file_invalid": "Tệp nguồn được cung cấp không hợp lệ: ",
+ "bool_error": "Không thể trích xuất giá trị boolean",
+ "not_numeric": "Giá trị đã cho không phải là số",
+ "long_not_16": "Giá trị đã cho không dài 16 byte",
+ "long_not_32": "Giá trị đã cho không dài 32 byte",
+ "long_not_64": "Giá trị đã cho không dài 64 byte",
+ "array_invalid": "Bạn chưa cung cấp một mảng hợp lệ",
+ "predicate_not_set": "Predicate (giá trị trong _) chưa được thiết lập!",
+ "update_madelineproto": "Bạn đang chạy phiên bản cũ của MadelineProto, cần phải cập nhật: phiên bản hiện tại là %s, nhưng phiên bản mới nhất với nhiều bản sửa lỗi và tính năng mới là %s!",
+ "type_extract_error": "Không thể trích xuất kiểu \"%s\", bạn nên cập nhật MadelineProto!",
+ "method_not_found": "Không tìm thấy phương thức: ",
+ "params_missing": "Thiếu tham số bắt buộc",
+ "sec_peer_not_in_db": "Peer bí mật này không có trong cơ sở dữ liệu peer nội bộ",
+ "stream_handle_invalid": "Stream handle được cung cấp không hợp lệ.",
+ "length_too_big": "Độ dài quá lớn",
+ "string_required": "Yêu cầu một chuỗi (string)!",
+ "waveform_must_have_100_values": "Mảng waveform phải có 100 giá trị!",
+ "waveform_value": "Giá trị waveform phải nằm trong khoảng từ 0 đến 31!",
+ "could_not_convert_object": "Không thể chuyển đổi đối tượng kiểu %s",
+ "type_extract_error_id": "Không thể trích xuất kiểu: %s với id %s, bạn nên cập nhật MadelineProto!",
+ "constructor_not_found": "Không tìm thấy constructor cho kiểu: ",
+ "botapi_conversion_error": "Không thể chuyển đổi %s thành đối tượng bot API",
+ "non_text_conversion": "Chưa thể chuyển đổi tin nhắn không phải văn bản!",
+ "file_type_invalid": "Phát hiện loại tệp không hợp lệ (%s)",
+ "static_analysis_minor": "Phát hiện một vấn đề nhỏ trong quá trình phân tích tĩnh %s: %s",
+ "static_analysis_severe": "Phát hiện một vấn đề nghiêm trọng trong quá trình phân tích tĩnh %s: %s",
+ "secret_chat_skipping": "Tôi không có cuộc trò chuyện bí mật %s trong cơ sở dữ liệu, bỏ qua tin nhắn...",
+ "must_have_declare_types": "vì lý do hiệu năng, câu lệnh đầu tiên của tệp event handler phải là \"declare(strict_types=1);\"",
+ "do_not_delete_MadelineProto.log": "tuyệt đối không được xóa tệp MadelineProto.log, thay vào đó hãy đặt kích thước tối đa tùy chỉnh trong phần cài đặt!",
+ "do_not_remove_MadelineProto.log_phar": "Vui lòng không xóa madeline.phar hoặc madeline.php, nếu không MadelineProto sẽ bị crash. Nếu bạn gặp bất kỳ vấn đề nào với MadelineProto, hãy báo cáo tại https://github.com/danog/MadelineProto hoặc https://t.me/pwrtelegramgroup",
+ "do_not_use_blocking_function": "vì lý do hiệu năng, event handler không được sử dụng hàm blocking không async %s, thay vào đó hãy sử dụng %s",
+ "do_not_use_blocking_class": "vì lý do hiệu năng, handler không được sử dụng lớp blocking không async %s, thay vào đó hãy sử dụng %s",
+ "do_not_use_deprecated_function": "hàm %s đã lỗi thời (deprecated), thay vào đó hãy sử dụng %s",
+ "do_not_use_non_root_require_in_event_handler": "vì lý do hiệu năng, bạn không được sử dụng require hoặc include bên trong lớp event handler, chỉ cho phép require ở cấp gốc.",
+ "do_not_use_yield": "MadelineProto 8 không yêu cầu cũng không hỗ trợ việc sử dụng yield trong các hàm async, bạn phải xóa tất cả các từ khóa yield đã dùng trước đây cho các lời gọi hàm async",
+ "recommend_not_use_filesystem_function": "không khuyến khích sử dụng hàm %s, vì truy cập hệ thống tệp trong khi xử lý update sẽ làm chậm bot của bạn, vui lòng xem https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions để biết danh sách các cách lưu trữ dữ liệu thay thế không làm chậm bot của bạn!",
+ "plugins_do_not_use_require": "vì lý do hiệu năng, plugin chỉ có thể tự động include hoặc require các tệp khác có trong thư mục plugins bằng cách kích hoạt autoloader PSR-4 (không phải bằng cách require() thủ công).",
+ "plugins_must_have_exactly_one_class": "một plugin phải định nghĩa chính xác một lớp! Để định nghĩa nhiều lớp, interface hoặc trait, hãy tạo các tệp riêng biệt, chúng sẽ được MadelineProto tự động nạp.",
+ "cli_need_dl.php_link": "Vui lòng chỉ định URL của script tải xuống khi sử dụng getDownloadLink qua CLI!",
+ "invalid_dl.php_session": "%s không phải là script tải xuống hợp lệ vì ID phiên của nó khác (mong đợi %s, nhận được %s)",
+ "need_dl.php": "Không thể tạo script tải xuống mặc định (%s), vui lòng tạo tệp dl.php với nội dung sau: %s và truyền URL của nó vào tham số thứ hai của getDownloadLink",
+ "dl.php_powered_by_madelineproto": "Máy chủ tải xuống tệp Telegram (tối đa 4GB), được cung cấp bởi MadelineProto!
Nhấn vào đây để biết thêm thông tin về cách thiết lập máy chủ tải xuống tệp Telegram của riêng bạn!",
+ "dl.php_check_logs_make_sure_session_running": "Bot EventHandler MadelineProto liên quan hoặc máy chủ IPC MadelineProto đang ngoại tuyến, vui lòng kiểm tra log và đảm bảo ít nhất một trong số chúng đang chạy!",
+ "account_banned": "!!!!!!! CẢNH BÁO !!!!!!!\nHệ thống chống flood của Telegram đã tạm khóa tài khoản này.\nĐể tiếp tục, cần xác minh thủ công.\nHãy gửi email đến recover@telegram.org, yêu cầu gỡ chặn số điện thoại %s, và mô tả ngắn gọn bạn sẽ làm gì với số điện thoại này.\nSau đó đăng nhập lại.\nNếu bạn cố ý xóa tài khoản này, hãy bỏ qua thông báo này.",
+ "plugin_path_does_not_exist": "Đường dẫn plugin %s không tồn tại!",
+ "could_not_connect_to_MadelineProto": "Không thể kết nối đến MadelineProto, vui lòng bật proc_open và gỡ bỏ giới hạn open_basedir hoặc tắt tính năng rewrite đường dẫn của webserver để khắc phục! Nếu bạn đã làm vậy, hãy đảm bảo phiên bản CLI của PHP giống hệt phiên bản web (cùng phiên bản, extension, v.v.) và xem tệp MadelineProto.log để biết thêm thông tin về lỗi đã ngăn máy chủ IPC khởi động.",
+ "translate_madelineproto_web": "MadelineProto có thể được dịch sang ngôn ngữ của bạn (tiến độ dịch hiện tại: %d%%), nhấn vào đây để đóng góp bản dịch!",
+ "translate_madelineproto_cli": "MadelineProto có thể được dịch sang ngôn ngữ của bạn (tiến độ dịch hiện tại: %d%%), hãy truy cập https://github.com/danog/MadelineProto/tree/v8/langs để đóng góp bản dịch!",
+ "apiInvalidWeb": "API ID là một số, còn API hash dài 32 ký tự: hãy sao chép lại chúng từ my.telegram.org.",
+ "webDoneLead": "MadelineProto vẫn tiếp tục chạy trên máy chủ: bạn có thể đóng trang này.",
+ "apiChooseManualAuto": "Bạn muốn lấy API ID và hash tự động từ my.telegram.org (a), hay tự nhập thủ công (m)?",
+ "apiAutoFallbackManual": "Thay vào đó, hãy nhập API ID và hash thủ công.",
+ "apiSetupTitleWeb": "Lấy API ID và hash của bạn",
+ "apiSetupLeadWeb": "Mọi ứng dụng Telegram đều cần API ID và hash. MadelineProto có thể lấy chúng giúp bạn từ my.telegram.org, bằng số điện thoại của một tài khoản Telegram hiện có.",
+ "apiAutoPhoneHintWeb": "my.telegram.org gửi mã đăng nhập đến ứng dụng Telegram của bạn, không phải qua SMS.",
+ "apiSendCodeWeb": "Gửi mã",
+ "apiChooseManualWeb": "Tôi đã có API ID",
+ "apiChooseAutoWeb": "Lấy tự động",
+ "apiStartOverWeb": "Bắt đầu lại",
+ "apiAutoCodeTitleWeb": "Nhập mã từ Telegram",
+ "apiAutoCodeLeadWeb": "my.telegram.org đã gửi mã đăng nhập đến ứng dụng Telegram của bạn, trong cuộc trò chuyện với Telegram (không phải qua SMS).",
+ "apiAutoCodeLabelWeb": "Mã đăng nhập",
+ "apiCreateTitleWeb": "Tạo ứng dụng của bạn",
+ "apiCreateLeadWeb": "Tài khoản này chưa có ứng dụng nào trên my.telegram.org. Các thông tin này chỉ hiển thị với bạn và có thể thay đổi sau.",
+ "apiAppTitleLabelWeb": "Tên ứng dụng",
+ "apiAppShortNameLabelWeb": "Tên ngắn",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "Mô tả",
+ "apiCreateWeb": "Tạo ứng dụng",
+ "apiSaveWeb": "Lưu và tiếp tục",
+ "apiAutoErrorTitle": "my.telegram.org đã trả về lỗi",
+ "apiCreateErrorTitle": "my.telegram.org không tạo được ứng dụng",
+ "apiCreateVpsWarning": "Telegram không cho phép các dải IP của VPS, VPN và các trung tâm dữ liệu khác tạo ứng dụng mới trên my.telegram.org, và yêu cầu này được gửi từ IP của máy đang chạy MadelineProto. Hãy tạo ứng dụng thủ công tại https://my.telegram.org từ một kết nối gia đình (ví dụ điện thoại của bạn dùng dữ liệu di động), sau đó nhập API ID và hash.",
+ "loginTitleWeb": "Đăng nhập vào Telegram",
+ "loginLeadWeb": "Chọn tài khoản hoặc bot sẽ được dùng để chạy phiên bản MadelineProto này.",
+ "loginTypeWeb": "Đăng nhập với tư cách",
+ "loginUserPhoneHintWeb": "Kèm mã quốc gia, ví dụ +39 123 456 7890.",
+ "loginBotTokenHintWeb": "Token mà @BotFather đã cung cấp khi bạn tạo bot.",
+ "loginCodeTitleWeb": "Nhập mã đăng nhập",
+ "loginCodeLeadWeb": "Telegram đã gửi mã đăng nhập đến ứng dụng Telegram của bạn, hoặc qua SMS nếu bạn chưa đăng nhập ở nơi nào khác.",
+ "loginPasswordTitleWeb": "Xác minh hai bước",
+ "loginPasswordLeadWeb": "Tài khoản này được bảo vệ bằng mật khẩu, được đặt trong Cài đặt > Quyền riêng tư và bảo mật > Xác minh hai bước.",
+ "loginPasswordLabelWeb": "Mật khẩu",
+ "signupTitleWeb": "Tạo tài khoản của bạn",
+ "signupLeadWeb": "Số điện thoại này chưa có trên Telegram: hãy chọn tên cho tài khoản mới.",
+ "webContinue": "Tiếp tục",
+ "webLogin": "Đăng nhập",
+ "webError": "%s. Hãy kiểm tra và thử lại.",
+ "webStepApp": "API ID và hash",
+ "webStepAccount": "Tài khoản",
+ "webStepVerify": "Xác minh",
+ "webStepDone": "Đang chạy",
+ "webProgress": "Tiến trình thiết lập",
+ "webDocs": "Tài liệu",
+ "webOptional": "không bắt buộc",
+ "webShowPassword": "Hiện",
+ "webHidePassword": "Ẩn",
+ "webQrTitle": "Đăng nhập bằng mã QR",
+ "webQrWaiting": "Đang chờ quét…",
+ "webFieldRequired": "Vui lòng điền vào trường này.",
+ "webPhoneInvalid": "Nhập số điện thoại kèm mã quốc gia, ví dụ +39 123 456 7890.",
+ "tweb.Login.Title": "Đăng nhập vào MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "Số điện thoại không hợp lệ",
+ "tweb.Login.StartText": "Vui lòng xác nhận mã quốc gia\nvà nhập số điện thoại của bạn.",
+ "tweb.Login.Code.SentSms": "Chúng tôi đã gửi cho bạn một SMS\nchứa mã.",
+ "tweb.Login.Code.SentInApp": "Chúng tôi đã gửi cho bạn một tin nhắn\ntrên Telegram chứa mã.",
+ "tweb.Login.Code.SentCall": "Chúng tôi sẽ gọi cho bạn và đọc\nmã.",
+ "tweb.Login.Code.SentEmail": "Vui lòng kiểm tra email **%s** của bạn (đừng quên thư mục spam) và nhập mã chúng tôi vừa gửi.",
+ "tweb.Login.Code.SentUnknown": "Vui lòng kiểm tra mọi nơi\nđể tìm mã (loại: %s)",
+ "tweb.Login.Code.SentMissedCall": "Trong vài giây tới, bạn sẽ nhận được\nmột cuộc gọi ngắn từ **%s**. Đừng trả lời —\nchỉ cần nhập các chữ số cuối của số đó.",
+ "tweb.Login.Code.SentSmsWord": "Chúng tôi đã gửi một SMS chứa từ bí mật\nđến số điện thoại **%s** của bạn.",
+ "tweb.Login.Code.SentSmsWordBeginning": "Chúng tôi đã gửi một SMS chứa từ bí mật bắt đầu\nbằng \"**%2$s**\" đến số điện thoại **%1$s** của bạn.",
+ "tweb.Login.Code.SentSmsPhrase": "Chúng tôi đã gửi một SMS chứa cụm từ bí mật\nđến số điện thoại **%s** của bạn.",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "Chúng tôi đã gửi một SMS chứa cụm từ bí mật bắt đầu\nbằng \"**%2$s**\" đến số điện thoại **%1$s** của bạn.",
+ "tweb.Login.Code.SecretWord": "Từ bí mật",
+ "tweb.Login.Code.SecretPhrase": "Cụm từ bí mật",
+ "tweb.Login.Code.WordInvalid": "Không đúng, vui lòng thử lại",
+ "tweb.Login.Code.WordBeginningInvalid": "Từ không đúng",
+ "tweb.Login.Password.Title": "Nhập mật khẩu của bạn",
+ "tweb.Login.Password.Subtitle": "Tài khoản của bạn được bảo vệ bằng\nmột mật khẩu bổ sung",
+ "tweb.Login.Register.Subtitle": "Nhập tên của bạn\nđể tạo tài khoản",
+ "tweb.PleaseWait": "Vui lòng chờ...",
+ "tweb.Code": "Mã",
+ "tweb.LoginPassword": "Mật khẩu",
+ "tweb.YourName": "Tên của bạn",
+ "tweb.FirstName": "Tên (bắt buộc)",
+ "tweb.LastName": "Họ (không bắt buộc)",
+ "tweb.StartMessaging": "Bắt đầu nhắn tin",
+ "tweb.Country": "Quốc gia",
+ "tweb.Contacts.PhoneNumber.Placeholder": "Số điện thoại",
+ "tweb.Login.Next": "Tiếp",
+ "tweb.Login.QR.Title": "Đăng nhập bằng mã QR",
+ "tweb.Login.QR.Help1": "Mở Telegram trên điện thoại của bạn",
+ "tweb.Login.QR.Help2": "Vào **Cài đặt** > **Thiết bị** > **Thêm thiết bị**",
+ "tweb.Login.QR.Help3": "Hướng điện thoại vào màn hình này để xác nhận đăng nhập",
+ "tweb.Login.QR.Cancel": "Đăng nhập bằng số điện thoại >",
+ "tweb.Login.QR.Login": "Đăng nhập bằng mã QR >",
+ "tweb.Login.QR.Subtitle": "Quét bằng ứng dụng Telegram trên điện thoại của bạn",
+ "tweb.PhoneNumber.Code.Fragment.Info": "Lấy mã trong mục Numbers trên [Fragment]()",
+ "tweb.PHONE_CODE_INVALID": "Mã không hợp lệ",
+ "tweb.PHONE_CODE_EXPIRED": "Mã đã hết hạn",
+ "tweb.PASSWORD_HASH_INVALID": "Mật khẩu không đúng",
+ "tweb.DarkMode": "Chế độ tối",
+ "tweb.Error.AnError": "Đã xảy ra lỗi. Vui lòng thử lại sau.",
+ "tweb.AccDescr.LoginCode": "Mã đăng nhập",
+ "tweb.Login.Bot": "Đăng nhập với tư cách bot >",
+ "tweb.Login.Bot.Title": "Đăng nhập với tư cách bot",
+ "tweb.Login.Bot.Subtitle": "Nhập token mà @BotFather đã cung cấp\nkhi bạn tạo bot.",
+ "tweb.Login.Bot.Token": "Token bot",
+ "tweb.Login.Bot.Cancel": "Đăng nhập với tư cách người dùng >",
+ "tweb.Optional": "không bắt buộc",
+ "tweb.PHONE_NUMBER_INVALID": "Số điện thoại không hợp lệ",
+ "tweb.PHONE_NUMBER_BANNED": "Số điện thoại này đã bị cấm",
+ "tweb.PHONE_NUMBER_FLOOD": "Quá nhiều lần thử, vui lòng thử lại sau",
+ "tweb.PHONE_CODE_EMPTY": "Mã không hợp lệ",
+ "tweb.PHONE_PASSWORD_FLOOD": "Quá nhiều lần thử, vui lòng thử lại sau",
+ "tweb.ACCESS_TOKEN_INVALID": "Token bot không hợp lệ",
+ "tweb.ACCESS_TOKEN_EXPIRED": "Token bot này đã bị thu hồi",
+ "tweb.FIRSTNAME_INVALID": "Tên không hợp lệ",
+ "tweb.LASTNAME_INVALID": "Họ không hợp lệ",
+ "tweb.Close": "Đóng"
+}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh_Hans.json b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh.json
similarity index 60%
rename from resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh_Hans.json
rename to resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh.json
index 1781bdb..fb539a5 100644
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh_Hans.json
+++ b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/langs/zh.json
@@ -1,24 +1,45 @@
{
+ "baseDirLimitation": "配置了 basedir 限制:这可能会影响性能并导致一些问题,请尽可能禁用它!",
"noReportPeers": "警告:未设置报告对等体,请将以下方法添加到您的事件处理程序中",
- "mmapErrorPart1": "已达到内存映射(mmap)区域的最大数量(%s):请将 vm.max_map_count 内核配置增加到 262144 进行修复。",
- "mmapErrorPart2": "要修复此问题,请以 root 身份运行以下命令:%s",
- "mmapErrorPart3": "要在重启后保留更改:%s",
+ "manualAdminActionRequired": "!!!!!!!!! 需要系统管理员手动操作 !!!!!!!!!",
+ "mmapErrorPart1": "已达到内存映射(mmap)区域的最大数量(%s):请将 vm.max_map_count 内核配置增加到 262144 进行修复。",
+ "mmapErrorPart2": "要修复此问题,请以 root 身份运行以下命令:%s",
+ "mmapErrorPart3": "要在重启后保留更改:%s",
+ "mmapErrorPart4": "在 Windows 和 WSL 上,增加页面文件的大小可能会有所帮助;如果问题仍然存在,请切换到原生 Linux。",
"botAlreadyRunning": "机器人已开始运行!",
- "extensionRequiredInstallWithApt": "尝试运行 sudo apt-get install %s.",
"extensionRequired": "MadelineProto 需要 %s 扩展才能运行.%s",
+ "extensionRequiredInstallWithApt": "尝试运行 sudo apt-get install %s.",
"extensionRequiredInstallWithCustomInstructions": "按照 %s 中的说明进行安装。",
+ "extensionRecommended": "警告:未安装 %s 扩展,请安装它以加快 MadelineProto 的速度!",
+ "go": "去",
+ "apiChooseManualAutoTip": "请注意,您也可以使用以下设置直接在代码中提供 API ID/hash:%s",
+ "apiChooseManualAutoTipWeb": "请注意,您还可以使用设置直接在代码中提供 API ID/hash。",
+ "apiChoosePrompt": "您的选择 (m/a): ",
+ "apiManualInstructions0": "登录 https://my.telegram.org",
+ "apiManualInstructions1": "前往API 开发工具",
+ "apiManualInstructions2": "点击创建应用程序",
+ "apiAppInstructionsManual0": "你的应用名称,可以是任意名称",
+ "apiAppInstructionsManual1": "您的应用的简称,字母数字,5-32 个字符",
+ "apiAppInstructionsManual2": "你的应用/网站的 URL,或者 t.me/yourusername",
+ "apiAppInstructionsManual3": "任何事",
+ "apiAppInstructionsManual4": "在此描述您的应用",
+ "apiManualWeb": "输入您的 API ID 和 API hash",
"apiManualPrompt0": "输入您的 API ID: ",
+ "apiManualPrompt1": "输入您的 API hash: ",
"apiAutoWeb": "输入已在电报上注册的电话号码以获取 API ID",
"apiAutoPrompt0": "输入已经在 Telegram 注册的电话号码: ",
+ "apiAutoPrompt1": "输入您在 Telegram 中收到的验证码: ",
"apiAppWeb": "输入 API 信息",
"apiAppInstructionsAuto0": "输入应用程序的名称,可以是任何内容: ",
"apiAppInstructionsAuto1": "输入应用程序的简称,字母数字,5-32个字符: ",
+ "apiAppInstructionsAuto2": "输入应用程序/网站的 URL,或 t.me/yourusername: ",
"apiAppInstructionsAuto3": "输入应用纲领: ",
"apiAppInstructionsAuto4": "描述你的应用: ",
"apiAppInstructionsAutoTypeOther": "其他(在描述中指定)",
"apiParamsError": "您没有提供所有必需的参数!",
"apiError": "错误:%s. 请重试。",
"loginChoosePromptWeb": "您想以用户身份还是机器人身份登录?",
+ "loginWebQr": "您也可以通过扫描以下二维码自动登录:",
"loginWebQr1": "在手机上打开 Telegram",
"loginWebQr2": "前往“设置”>“设备”>“链接桌面设备”",
"loginWebQr3": "将你的手机对准此屏幕以确认登录",
@@ -26,72 +47,78 @@
"loginOptionUser": "用户",
"loginBot": "输入您的机器人令牌: ",
"loginUser": "输入你的电话号码: ",
+ "loginQr": "扫描以上二维码即可自动登录。",
"loginQrCodeSuccessful": "二维码登录成功!",
"loginQrCodeExpired": "QR 码已过期,正在生成新的 QR 码...",
"loginManual": "或者,您也可以输入机器人令牌或电话号码手动登录: ",
"loginUserCode": "输入验证码: ",
+ "loginUserPass": "输入您的密码(提示 %s): ",
"loginUserPassWeb": "输入您的密码: ",
"loginUserPassHint": "提示:%s",
"signupFirstName": "输入您的名字: ",
- "go": "去",
- "apiChooseManualAutoTip": "请注意,您也可以使用以下设置直接在代码中提供 API ID/hash:%s",
- "apiChooseManualAutoTipWeb": "请注意,您还可以使用设置直接在代码中提供 API ID/hash。",
- "apiChoosePrompt": "您的选择 (m/a): ",
- "apiManualInstructions0": "登录 https://my.telegram.org",
- "apiManualInstructions1": "前往API 开发工具",
- "apiManualInstructions2": "点击创建应用程序",
- "apiAppInstructionsManual1": "您的应用的简称,字母数字,5-32 个字符",
- "apiAppInstructionsManual2": "你的应用/网站的 URL,或者 t.me/yourusername",
- "apiAppInstructionsManual3": "任何事",
- "apiAppInstructionsManual4": "在此描述您的应用",
+ "signupLastName": "输入您的姓氏(可以为空): ",
+ "signupWeb": "请注册",
+ "signupFirstNameWeb": "名字",
"signupLastNameWeb": "姓氏",
+ "loginNoCode": "您没有提供电话代码!",
"loginNoPass": "您没有提供密码!",
"loginNoName": "您没有提供名字!",
"loginBotTokenWeb": "机器人令牌",
"loginUserPhoneWeb": "电话号码",
"loginUserPhoneCodeWeb": "验证码",
"done": "完成!",
+ "nearest_dc": "我们在 %s,最近的 DC 是 %d。",
"serialization_ofd": "序列化已过时,正在重建对象!",
"api_not_set": "您必须提供一个 api key 和一个 api id,请获取您自己的 @ my.telegram.org",
"session_corrupted": "会话已损坏!",
+ "value_bigger_than_2147483647": "提供的值 %s 大于 2147483647",
"value_smaller_than_2147483648": "提供的值 %s 小于 -2147483648",
"value_bigger_than_9223372036854775807": "提供的值 %s 大于 9223372036854775807",
"value_smaller_than_9223372036854775808": "提供的值 %s 小于 -9223372036854775808",
"value_bigger_than_4294967296": "提供的值 %s 大于 4294967296",
"value_smaller_than_0": "提供的值 %s 小于 0",
+ "encode_double_error": "无法正确编码双重",
"file_not_exist": "文件不存在",
"deserialization_error": "反序列化时发生错误",
"rpc_tg_error": "Telegram 返回了 RPC 错误:%s(%s),由 %s:%s%sTL 跟踪导致:",
"madelineproto_ready": "MadelineProto 已准备好!",
"logout_ok": "退出成功!",
+ "already_loggedIn": "MadelineProto 的这个实例已经登录!",
"login_ok": "登录成功!",
"login_user": "以普通用户身份登录...",
- "peer_not_in_db": "内部对等数据库中不存在此对等点",
- "call_error_1": "无法找到并接受呼叫 %s",
- "accepting_call": "正在接听来自 %s 的电话...",
- "call_already_accepted": "呼叫 %s 已被接受",
"login_bot": "以机器人身份登录...",
"login_code_sending": "正在发送代码...",
"login_code_sent": "代码发送成功!收到代码后,您应该使用 completePhoneLogin 函数。",
+ "login_code_uncalled": "我不等代码了!请先调用 phoneLogin 方法",
"login_2fa_enabled": "启用 2FA 后,您将必须调用 complete2falogin 函数...",
"login_need_signup": "尚未为此号码创建帐户,您必须调用 completeSignup 函数...",
"login_auth_key": "使用身份验证密钥登录...",
"not_loggedIn": "我还没有登录!",
+ "signup_uncalled": "我不等着注册!请先调用 phoneLogin 和 completePhoneLogin 方法!",
"signing_up": "正在注册为普通用户...",
"signup_ok": "报名成功!",
+ "2fa_uncalled": "我不等你输入密码!请先调用 phoneLogin 和 completePhoneLogin 方法!",
+ "peer_not_in_db": "内部对等数据库中不存在此对等点",
+ "call_error_1": "无法找到并接受呼叫 %s",
+ "accepting_call": "正在接听来自 %s 的电话...",
+ "call_already_accepted": "呼叫 %s 已被接受",
"call_already_declined": "已拒绝来电 %s",
"call_error_2": "无法找到并确认呼叫 %s",
+ "call_confirming": "确认来自 %s 的呼叫...",
"call_error_3": "无法找到并完成呼叫 %s",
+ "call_completing": "正在完成来自 %s 的呼叫...",
"fingerprint_invalid": "密钥指纹无效!",
"call_discarding": "正在丢弃呼叫 %s...",
"file_parsing": "正在解析 %s...",
"src_file_invalid": "提供的源文件无效: ",
"bool_error": "无法提取布尔值",
"not_numeric": "给定值不是数字",
+ "long_not_16": "给定值的长度不是 16 个字节",
"long_not_32": "给定值的长度不是 32 个字节",
"long_not_64": "给定值的长度不是 64 个字节",
"array_invalid": "您没有提供有效的数组",
"predicate_not_set": "谓词(_ 下的值)未设置!",
+ "update_madelineproto": "您正在运行旧版本的 MadelineProto,需要更新:当前运行 %s,但最新版本具有多项错误修复和新功能是 %s!",
"type_extract_error": "无法提取类型“%s”,您应该更新 MadelineProto!",
"method_not_found": "找不到方法: ",
"params_missing": "缺少必需参数",
@@ -101,62 +128,147 @@
"string_required": "期望的是字符串!",
"waveform_must_have_100_values": "波形数组必须有 100 个值!",
"waveform_value": "波形值必须介于0至31之间!",
+ "could_not_convert_object": "无法转换 %s 类型的对象",
"type_extract_error_id": "无法提取类型:%s,ID 为 %s,您应该更新 MadelineProto!",
"constructor_not_found": "未找到该类型的构造函数: ",
"botapi_conversion_error": "无法将 %s 转换为机器人 API 对象",
+ "non_text_conversion": "尚无法转换非文本信息!",
"file_type_invalid": "检测到无效的文件类型 (%s)",
"static_analysis_minor": "对 %s 进行静态分析时遇到一个小问题:%s",
"static_analysis_severe": "对 %s 进行静态分析时遇到严重问题:%s",
+ "secret_chat_skipping": "我的数据库中没有秘密聊天 %s,跳过消息...",
"must_have_declare_types": "出于性能原因,事件处理程序文件的第一个语句必须是“declare(strict_types=1);”",
+ "do_not_delete_MadelineProto.log": "绝不能删除 MadelineProto.log 文件,请在设置中设置自定义最大大小!",
+ "do_not_remove_MadelineProto.log_phar": "请不要删除 madeline.phar 或 madeline.php,否则 MadelineProto 将崩溃。如果您对 MadelineProto 有任何问题,请报告给 https://github.com/danog/MadelineProto 或 https://t.me/pwrtelegramgroup",
"do_not_use_blocking_function": "出于性能原因,事件处理程序可能不会使用非异步阻塞函数 %s,请改用 %s",
"do_not_use_blocking_class": "出于性能原因,处理程序可能不会使用非异步阻塞类 %s,请改用 %s",
"do_not_use_deprecated_function": "%s 函数已弃用,请使用 %s 代替",
"do_not_use_non_root_require_in_event_handler": "出于性能原因,您不能在事件处理程序类中使用 require 或 include,只允许使用根级需要。",
"do_not_use_yield": "MadelineProto 8 不要求或支持在异步函数中使用 Yield,您必须删除以前用于异步函数调用的所有 Yield 关键字",
- "baseDirLimitation": "配置了 basedir 限制:这可能会影响性能并导致一些问题,请尽可能禁用它!",
- "manualAdminActionRequired": "!!!!!!!!! 需要系统管理员手动操作 !!!!!!!!!",
- "mmapErrorPart4": "在 Windows 和 WSL 上,增加页面文件的大小可能会有所帮助;如果问题仍然存在,请切换到原生 Linux。",
- "apiManualWeb": "输入您的 API ID 和 API hash",
- "apiManualPrompt1": "输入您的 API hash: ",
- "apiAutoPrompt1": "输入您在 Telegram 中收到的验证码: ",
- "apiAppInstructionsAuto2": "输入应用程序/网站的 URL,或 t.me/yourusername: ",
- "loginWebQr": "您也可以通过扫描以下二维码自动登录:",
- "loginQr": "扫描以上二维码即可自动登录。",
- "loginUserPass": "输入您的密码(提示 %s): ",
- "signupLastName": "输入您的姓氏(可以为空): ",
- "signupWeb": "请注册",
- "signupFirstNameWeb": "名字",
+ "recommend_not_use_filesystem_function": "不建议使用 %s 函数,因为在更新处理期间访问文件系统会减慢您的机器人速度,请参阅 https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions 以获取不会减慢您的机器人速度的替代数据存储方法列表!",
"plugins_do_not_use_require": "出于性能原因,插件只能通过触发 PSR-4 自动加载器来自动包含或需要插件文件夹中的其他文件(而不是通过手动 require() 它们)。",
+ "plugins_must_have_exactly_one_class": "一个插件必须定义一个类!要定义多个类、接口或特征,请创建单独的文件,它们将由 MadelineProto 自动加载。",
"cli_need_dl.php_link": "通过 CLI 使用 getDownloadLink 时,请指定下载脚本 URL!",
"invalid_dl.php_session": "%s 不是有效的下载脚本,因为其会话 ID 不同(预期为 %s,实际为 %s)",
- "need_dl.php": "无法生成默认下载脚本(%s),请创建一个包含以下内容的 dl.php 文件:%s 并将其 URL 传递给 getDownloadLink 的第二个参数",
+ "need_dl.php": "无法生成默认下载脚本(%s),请创建一个包含以下内容的 dl.php 文件:%s 并将其 URL 传递给 getDownloadLink 的第二个参数",
+ "dl.php_powered_by_madelineproto": "Telegram 文件下载服务器(最高 4GB),由 MadelineProto 提供支持!
单击此处了解有关如何设置您自己的 Telegram 文件下载服务器的更多信息!",
"dl.php_check_logs_make_sure_session_running": "相关的 MadelineProto EventHandler 机器人或 MadelineProto IPC 服务器处于离线状态,请检查日志并确保其中至少有一个正在运行!",
- "plugin_path_does_not_exist": "插件路径 %s 不存在!",
- "windows_warning": "对于 Windows 用户:如果失败,请切换到 Linux。您还可以尝试修改防火墙设置以允许所有 PHP 进程创建套接字(切换到 Linux 更容易,在 Linux 上 MadelineProto 开箱即用,无需进行任何更改)",
- "translate_madelineproto_web": "MadelineProto 可以翻译成您的语言(当前翻译进度:%d%%),点击此处为翻译做出贡献!",
- "translate_madelineproto_cli": "MadelineProto 可以翻译成您的语言(当前翻译进度:%d%%),请访问 https://weblate.madelineproto.xyz 为翻译做出贡献!",
- "loginNoCode": "您没有提供电话代码!",
- "2fa_uncalled": "我不等你输入密码!请先调用 phoneLogin 和 completePhoneLogin 方法!",
"account_banned": "!!!!!!! 警告 !!!!!!!\nTelegram 的防洪系统已暂停此帐户。\n要继续,需要手动验证。\n发送电子邮件至 recovery@telegram.org,要求解禁电话号码 %s,并简要描述您将如何处理此电话号码。\n然后重新登录。\n如果您有意删除此帐户,请忽略此消息。",
+ "plugin_path_does_not_exist": "插件路径 %s 不存在!",
"could_not_connect_to_MadelineProto": "无法连接到 MadelineProto,请启用 proc_open 并删除 open_basedir 限制或禁用 webserver 路径重写以进行修复!如果您已经这样做了,请确保 PHP 的 CLI 版本与 web 版本完全相同(相同的版本、扩展等),并查看 MadelineProto.log 文件以获取有关阻止 IPC 服务器启动的错误的更多信息。",
- "nearest_dc": "我们在 %s,最近的 DC 是 %d。",
- "value_bigger_than_2147483647": "提供的值 %s 大于 2147483647",
- "encode_double_error": "无法正确编码双重",
- "already_loggedIn": "MadelineProto 的这个实例已经登录!",
- "extensionRecommended": "警告:未安装 %s 扩展,请安装它以加快 MadelineProto 的速度!",
- "apiAppInstructionsManual0": "你的应用名称,可以是任意名称",
- "login_code_uncalled": "我不等代码了!请先调用 phoneLogin 方法",
- "call_confirming": "确认来自 %s 的呼叫...",
- "call_completing": "正在完成来自 %s 的呼叫...",
- "long_not_16": "给定值的长度不是 16 个字节",
- "could_not_convert_object": "无法转换 %s 类型的对象",
- "non_text_conversion": "尚无法转换非文本信息!",
- "secret_chat_skipping": "我的数据库中没有秘密聊天 %s,跳过消息...",
- "do_not_delete_MadelineProto.log": "绝不能删除 MadelineProto.log 文件,请在设置中设置自定义最大大小!",
- "do_not_remove_MadelineProto.log_phar": "请不要删除 madeline.phar 或 madeline.php,否则 MadelineProto 将崩溃。如果您对 MadelineProto 有任何问题,请报告给 https://github.com/danog/MadelineProto 或 https://t.me/pwrtelegramgroup",
- "recommend_not_use_filesystem_function": "不建议使用 %s 函数,因为在更新处理期间访问文件系统会减慢您的机器人速度,请参阅 https://docs.madelineproto.xyz/docs/UPDATES.html#avoiding-the-use-of-filesystem-functions 以获取不会减慢您的机器人速度的替代数据存储方法列表!",
- "signup_uncalled": "我不等着注册!请先调用 phoneLogin 和 completePhoneLogin 方法!",
- "update_madelineproto": "您正在运行旧版本的 MadelineProto,需要更新:当前运行 %s,但最新版本具有多项错误修复和新功能是 %s!",
- "plugins_must_have_exactly_one_class": "一个插件必须定义一个类!要定义多个类、接口或特征,请创建单独的文件,它们将由 MadelineProto 自动加载。",
- "dl.php_powered_by_madelineproto": "Telegram 文件下载服务器(最高 4GB),由 MadelineProto 提供支持!
单击此处了解有关如何设置您自己的 Telegram 文件下载服务器的更多信息!"
+ "translate_madelineproto_web": "MadelineProto 可以翻译成您的语言(当前翻译进度:%d%%),点击此处为翻译做出贡献!",
+ "translate_madelineproto_cli": "MadelineProto 可以翻译成您的语言(当前翻译进度:%d%%),请访问 https://github.com/danog/MadelineProto/tree/v8/langs 为翻译做出贡献!",
+ "apiInvalidWeb": "API ID 是一个数字,API hash 长度为 32 个字符:请从 my.telegram.org 重新复制。",
+ "webDoneLead": "MadelineProto 会在服务器上继续运行:您可以关闭此页面。",
+ "apiChooseManualAuto": "您想从 my.telegram.org 自动获取 API ID 和 hash(a),还是手动输入(m)?",
+ "apiAutoFallbackManual": "请改为手动输入 API ID 和 hash。",
+ "apiSetupTitleWeb": "获取您的 API ID 和 hash",
+ "apiSetupLeadWeb": "每个 Telegram 应用都需要 API ID 和 hash。MadelineProto 可以使用现有 Telegram 帐户的电话号码,为您从 my.telegram.org 获取。",
+ "apiAutoPhoneHintWeb": "my.telegram.org 会将登录码发送到您的 Telegram 应用,而不是通过短信发送。",
+ "apiSendCodeWeb": "发送验证码",
+ "apiChooseManualWeb": "我已有 API ID",
+ "apiChooseAutoWeb": "自动获取",
+ "apiStartOverWeb": "重新开始",
+ "apiAutoCodeTitleWeb": "输入 Telegram 发送的验证码",
+ "apiAutoCodeLeadWeb": "my.telegram.org 已将登录码发送到您的 Telegram 应用中与 Telegram 的对话里(不是通过短信)。",
+ "apiAutoCodeLabelWeb": "登录码",
+ "apiCreateTitleWeb": "创建您的应用",
+ "apiCreateLeadWeb": "此帐户在 my.telegram.org 上还没有应用。这些信息仅对您可见,以后也可以修改。",
+ "apiAppTitleLabelWeb": "应用名称",
+ "apiAppShortNameLabelWeb": "简称",
+ "apiAppUrlLabelWeb": "URL",
+ "apiAppDescLabelWeb": "描述",
+ "apiCreateWeb": "创建应用",
+ "apiSaveWeb": "保存并继续",
+ "apiAutoErrorTitle": "my.telegram.org 返回了错误",
+ "apiCreateErrorTitle": "my.telegram.org 未能创建应用",
+ "apiCreateVpsWarning": "Telegram 不允许来自 VPS、VPN 及其他数据中心 IP 段的请求在 my.telegram.org 上创建新应用,而此请求是从运行 MadelineProto 的机器的 IP 发出的。请使用家庭网络(例如使用移动数据的手机)访问 https://my.telegram.org 手动创建应用,然后输入 API ID 和 hash。",
+ "loginTitleWeb": "登录 Telegram",
+ "loginLeadWeb": "选择此 MadelineProto 实例要使用的帐户或机器人。",
+ "loginTypeWeb": "登录身份",
+ "loginUserPhoneHintWeb": "请包含国家代码,例如 +39 123 456 7890。",
+ "loginBotTokenHintWeb": "创建机器人时 @BotFather 提供给您的令牌。",
+ "loginCodeTitleWeb": "输入登录码",
+ "loginCodeLeadWeb": "Telegram 已将登录码发送到您的 Telegram 应用;如果您未在其他地方登录,则会通过短信发送。",
+ "loginPasswordTitleWeb": "两步验证",
+ "loginPasswordLeadWeb": "此帐户受密码保护,该密码在“设置”>“隐私与安全”>“两步验证”中设置。",
+ "loginPasswordLabelWeb": "密码",
+ "signupTitleWeb": "创建您的帐户",
+ "signupLeadWeb": "此电话号码尚未注册 Telegram:请为新帐户设置名字。",
+ "webContinue": "继续",
+ "webLogin": "登录",
+ "webError": "%s。请检查后重试。",
+ "webStepApp": "API ID 和 hash",
+ "webStepAccount": "帐户",
+ "webStepVerify": "验证",
+ "webStepDone": "运行中",
+ "webProgress": "设置进度",
+ "webDocs": "文档",
+ "webOptional": "可选",
+ "webShowPassword": "显示",
+ "webHidePassword": "隐藏",
+ "webQrTitle": "使用二维码登录",
+ "webQrWaiting": "等待扫描…",
+ "webFieldRequired": "请填写此字段。",
+ "webPhoneInvalid": "请输入包含国家代码的电话号码,例如 +39 123 456 7890。",
+ "tweb.Login.Title": "登录 MadelineProto",
+ "tweb.Login.PhoneLabelInvalid": "电话号码无效",
+ "tweb.Login.StartText": "请确认您的国家代码\n并输入您的电话号码。",
+ "tweb.Login.Code.SentSms": "我们已通过短信\n向您发送验证码。",
+ "tweb.Login.Code.SentInApp": "我们已通过 Telegram 消息\n向您发送验证码。",
+ "tweb.Login.Code.SentCall": "我们将致电您\n并告知验证码。",
+ "tweb.Login.Code.SentEmail": "请查看您的邮箱 **%s**(别忘了查看垃圾邮件文件夹),并输入我们刚刚发送给您的验证码。",
+ "tweb.Login.Code.SentUnknown": "请在各处查找\n验证码(类型:%s)",
+ "tweb.Login.Code.SentMissedCall": "几秒钟内您将收到来自 **%s** 的\n一个短暂来电。请不要接听——\n只需输入该号码的最后几位数字。",
+ "tweb.Login.Code.SentSmsWord": "我们已向您的手机 **%s**\n发送了一条包含密语的短信。",
+ "tweb.Login.Code.SentSmsWordBeginning": "我们已向您的手机 **%1$s** 发送了一条短信,\n其中包含以“**%2$s**”开头的密语。",
+ "tweb.Login.Code.SentSmsPhrase": "我们已向您的手机 **%s**\n发送了一条包含密语短句的短信。",
+ "tweb.Login.Code.SentSmsPhraseBeginning": "我们已向您的手机 **%1$s** 发送了一条短信,\n其中包含以“**%2$s**”开头的密语短句。",
+ "tweb.Login.Code.SecretWord": "密语",
+ "tweb.Login.Code.SecretPhrase": "密语短句",
+ "tweb.Login.Code.WordInvalid": "不正确,请重试",
+ "tweb.Login.Code.WordBeginningInvalid": "单词不正确",
+ "tweb.Login.Password.Title": "输入您的密码",
+ "tweb.Login.Password.Subtitle": "您的帐户受\n附加密码保护",
+ "tweb.Login.Register.Subtitle": "请输入您的名字\n以创建帐户",
+ "tweb.PleaseWait": "请稍候...",
+ "tweb.Code": "验证码",
+ "tweb.LoginPassword": "密码",
+ "tweb.YourName": "您的名字",
+ "tweb.FirstName": "名字(必填)",
+ "tweb.LastName": "姓氏(可选)",
+ "tweb.StartMessaging": "开始聊天",
+ "tweb.Country": "国家/地区",
+ "tweb.Contacts.PhoneNumber.Placeholder": "电话号码",
+ "tweb.Login.Next": "下一步",
+ "tweb.Login.QR.Title": "使用二维码登录",
+ "tweb.Login.QR.Help1": "在手机上打开 Telegram",
+ "tweb.Login.QR.Help2": "前往 **设置** > **设备** > **添加设备**",
+ "tweb.Login.QR.Help3": "将手机对准此屏幕以确认登录",
+ "tweb.Login.QR.Cancel": "使用电话号码登录 >",
+ "tweb.Login.QR.Login": "使用二维码登录 >",
+ "tweb.Login.QR.Subtitle": "使用手机上的 Telegram 应用扫描",
+ "tweb.PhoneNumber.Code.Fragment.Info": "在 [Fragment]() 的 Numbers 栏目中获取验证码",
+ "tweb.PHONE_CODE_INVALID": "验证码无效",
+ "tweb.PHONE_CODE_EXPIRED": "验证码已过期",
+ "tweb.PASSWORD_HASH_INVALID": "密码不正确",
+ "tweb.DarkMode": "深色模式",
+ "tweb.Error.AnError": "发生错误,请稍后重试。",
+ "tweb.AccDescr.LoginCode": "登录码",
+ "tweb.Login.Bot": "以机器人身份登录 >",
+ "tweb.Login.Bot.Title": "以机器人身份登录",
+ "tweb.Login.Bot.Subtitle": "输入创建机器人时\n@BotFather 提供给您的令牌。",
+ "tweb.Login.Bot.Token": "机器人令牌",
+ "tweb.Login.Bot.Cancel": "以用户身份登录 >",
+ "tweb.Optional": "可选",
+ "tweb.PHONE_NUMBER_INVALID": "电话号码无效",
+ "tweb.PHONE_NUMBER_BANNED": "此电话号码已被封禁",
+ "tweb.PHONE_NUMBER_FLOOD": "尝试次数过多,请稍后重试",
+ "tweb.PHONE_CODE_EMPTY": "验证码无效",
+ "tweb.PHONE_PASSWORD_FLOOD": "尝试次数过多,请稍后重试",
+ "tweb.ACCESS_TOKEN_INVALID": "机器人令牌无效",
+ "tweb.ACCESS_TOKEN_EXPIRED": "此机器人令牌已被撤销",
+ "tweb.FIRSTNAME_INVALID": "名字无效",
+ "tweb.LASTNAME_INVALID": "姓氏无效",
+ "tweb.Close": "关闭"
}
diff --git a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/schemas/TL_telegram_v225.tl b/resources/release/preferred-source/additional-source/madelineproto-build-inputs/schemas/TL_telegram_v225.tl
deleted file mode 100644
index 2ad8d9c..0000000
--- a/resources/release/preferred-source/additional-source/madelineproto-build-inputs/schemas/TL_telegram_v225.tl
+++ /dev/null
@@ -1,2979 +0,0 @@
-boolFalse#bc799737 = Bool;
-boolTrue#997275b5 = Bool;
-
-true#3fedd339 = True;
-
-vector#1cb5c415 {t:Type} # [ t ] = Vector t;
-
-error#c4b9f9bb code:int text:string = Error;
-
-null#56730bcc = Null;
-
-inputPeerEmpty#7f3b18ea = InputPeer;
-inputPeerSelf#7da07ec9 = InputPeer;
-inputPeerChat#35a95cb9 chat_id:long = InputPeer;
-inputPeerUser#dde8a54c user_id:long access_hash:long = InputPeer;
-inputPeerChannel#27bcbbfc channel_id:long access_hash:long = InputPeer;
-inputPeerUserFromMessage#a87b0a1c peer:InputPeer msg_id:int user_id:long = InputPeer;
-inputPeerChannelFromMessage#bd2a0840 peer:InputPeer msg_id:int channel_id:long = InputPeer;
-
-inputUserEmpty#b98886cf = InputUser;
-inputUserSelf#f7c1b13f = InputUser;
-inputUser#f21158c6 user_id:long access_hash:long = InputUser;
-inputUserFromMessage#1da448e2 peer:InputPeer msg_id:int user_id:long = InputUser;
-
-inputPhoneContact#6a1dc4be flags:# client_id:long phone:string first_name:string last_name:string note:flags.0?TextWithEntities = InputContact;
-
-inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
-inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;
-inputFileStoryDocument#62dc8b48 id:InputDocument = InputFile;
-
-inputMediaEmpty#9664f57f = InputMedia;
-inputMediaUploadedPhoto#7d8375da flags:# spoiler:flags.2?true live_photo:flags.3?true file:InputFile stickers:flags.0?Vector ttl_seconds:flags.1?int video:flags.3?InputDocument = InputMedia;
-inputMediaPhoto#e3af4434 flags:# spoiler:flags.1?true live_photo:flags.2?true id:InputPhoto ttl_seconds:flags.0?int video:flags.2?InputDocument = InputMedia;
-inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
-inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
-inputMediaUploadedDocument#37c9330 flags:# nosound_video:flags.3?true force_file:flags.4?true spoiler:flags.5?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector stickers:flags.0?Vector video_cover:flags.6?InputPhoto video_timestamp:flags.7?int ttl_seconds:flags.1?int = InputMedia;
-inputMediaDocument#a8763ab5 flags:# spoiler:flags.2?true id:InputDocument video_cover:flags.3?InputPhoto video_timestamp:flags.4?int ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
-inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
-inputMediaPhotoExternal#e5bbfe1a flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int = InputMedia;
-inputMediaDocumentExternal#779600f9 flags:# spoiler:flags.1?true url:string ttl_seconds:flags.0?int video_cover:flags.2?InputPhoto video_timestamp:flags.3?int = InputMedia;
-inputMediaGame#d33f43f3 id:InputGame = InputMedia;
-inputMediaInvoice#405fef0d flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:flags.3?string provider_data:DataJSON start_param:flags.1?string extended_media:flags.2?InputMedia = InputMedia;
-inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
-inputMediaPoll#883a4108 flags:# poll:Poll correct_answers:flags.0?Vector attached_media:flags.3?InputMedia solution:flags.1?string solution_entities:flags.1?Vector solution_media:flags.2?InputMedia = InputMedia;
-inputMediaDice#e66fbf7b emoticon:string = InputMedia;
-inputMediaStory#89fdd778 peer:InputPeer id:int = InputMedia;
-inputMediaWebPage#c21b8849 flags:# force_large_media:flags.0?true force_small_media:flags.1?true optional:flags.2?true url:string = InputMedia;
-inputMediaPaidMedia#c4103386 flags:# stars_amount:long extended_media:Vector payload:flags.0?string = InputMedia;
-inputMediaTodo#9fc55fde todo:TodoList = InputMedia;
-inputMediaStakeDice#f3a9244a game_hash:string ton_amount:long client_seed:bytes = InputMedia;
-
-inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
-inputChatUploadedPhoto#bdcdaec0 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double video_emoji_markup:flags.3?VideoSize = InputChatPhoto;
-inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;
-
-inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
-inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint;
-
-inputPhotoEmpty#1cd7bf0d = InputPhoto;
-inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;
-
-inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
-inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
-inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
-inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
-inputTakeoutFileLocation#29be5899 = InputFileLocation;
-inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
-inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
-inputPeerPhotoFileLocation#37257e99 flags:# big:flags.0?true peer:InputPeer photo_id:long = InputFileLocation;
-inputStickerSetThumb#9d84f3db stickerset:InputStickerSet thumb_version:int = InputFileLocation;
-inputGroupCallStream#598a92a flags:# call:InputGroupCall time_ms:long scale:int video_channel:flags.0?int video_quality:flags.0?int = InputFileLocation;
-
-peerUser#59511722 user_id:long = Peer;
-peerChat#36c6019a chat_id:long = Peer;
-peerChannel#a2a5371e channel_id:long = Peer;
-
-storage.fileUnknown#aa963b05 = storage.FileType;
-storage.filePartial#40bc6f52 = storage.FileType;
-storage.fileJpeg#7efe0e = storage.FileType;
-storage.fileGif#cae1aadf = storage.FileType;
-storage.filePng#a4f63c0 = storage.FileType;
-storage.filePdf#ae1e508d = storage.FileType;
-storage.fileMp3#528a0677 = storage.FileType;
-storage.fileMov#4b09ebbc = storage.FileType;
-storage.fileMp4#b3cea0e4 = storage.FileType;
-storage.fileWebp#1081464c = storage.FileType;
-
-userEmpty#d3bc4b7a id:long = User;
-user#31774388 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true bot_attach_menu:flags.27?true premium:flags.28?true attach_menu_enabled:flags.29?true flags2:# bot_can_edit:flags2.1?true close_friend:flags2.2?true stories_hidden:flags2.3?true stories_unavailable:flags2.4?true contact_require_premium:flags2.10?true bot_business:flags2.11?true bot_has_main_app:flags2.13?true bot_forum_view:flags2.16?true bot_forum_can_manage_topics:flags2.17?true bot_can_manage_bots:flags2.18?true bot_guestchat:flags2.19?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector bot_inline_placeholder:flags.19?string lang_code:flags.22?string emoji_status:flags.30?EmojiStatus usernames:flags2.0?Vector stories_max_id:flags2.5?RecentStory color:flags2.8?PeerColor profile_color:flags2.9?PeerColor bot_active_users:flags2.12?int bot_verification_icon:flags2.14?long send_paid_messages_stars:flags2.15?long = User;
-
-userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
-userProfilePhoto#82d1f706 flags:# has_video:flags.0?true personal:flags.2?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
-
-userStatusEmpty#9d05049 = UserStatus;
-userStatusOnline#edb93949 expires:int = UserStatus;
-userStatusOffline#8c703f was_online:int = UserStatus;
-userStatusRecently#7b197dc8 flags:# by_me:flags.0?true = UserStatus;
-userStatusLastWeek#541a1d1a flags:# by_me:flags.0?true = UserStatus;
-userStatusLastMonth#65899777 flags:# by_me:flags.0?true = UserStatus;
-
-chatEmpty#29562865 id:long = Chat;
-chat#41cbf256 flags:# creator:flags.0?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
-chatForbidden#6592a1a7 id:long title:string = Chat;
-channel#1c32b11c flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true join_to_send:flags.28?true join_request:flags.29?true forum:flags.30?true flags2:# stories_hidden:flags2.1?true stories_hidden_min:flags2.2?true stories_unavailable:flags2.3?true signature_profiles:flags2.12?true autotranslation:flags2.15?true broadcast_messages_allowed:flags2.16?true monoforum:flags2.17?true forum_tabs:flags2.19?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int usernames:flags2.0?Vector stories_max_id:flags2.4?RecentStory color:flags2.7?PeerColor profile_color:flags2.8?PeerColor emoji_status:flags2.9?EmojiStatus level:flags2.10?int subscription_until_date:flags2.11?int bot_verification_icon:flags2.13?long send_paid_messages_stars:flags2.14?long linked_monoforum_id:flags2.18?long = Chat;
-channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true monoforum:flags.10?true id:long access_hash:long title:string until_date:flags.16?int = Chat;
-
-chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull;
-channelFull#e4e0b29d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true can_view_stars_revenue:flags2.15?true paid_reactions_available:flags2.16?true stargifts_available:flags2.19?true paid_messages_available:flags2.20?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet bot_verification:flags2.17?BotVerification stargifts_count:flags2.18?int send_paid_messages_stars:flags2.21?long main_tab:flags2.22?ProfileTab = ChatFull;
-
-chatParticipant#38e79fde flags:# user_id:long inviter_id:long date:int rank:flags.0?string = ChatParticipant;
-chatParticipantCreator#e1f867b8 flags:# user_id:long rank:flags.0?string = ChatParticipant;
-chatParticipantAdmin#360d5d2 flags:# user_id:long inviter_id:long date:int rank:flags.0?string = ChatParticipant;
-
-chatParticipantsForbidden#8763d3e1 flags:# chat_id:long self_participant:flags.0?ChatParticipant = ChatParticipants;
-chatParticipants#3cbc93f8 chat_id:long participants:Vector version:int = ChatParticipants;
-
-chatPhotoEmpty#37c1011c = ChatPhoto;
-chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
-
-messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
-message#95ef6f2b flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true invert_media:flags.27?true flags2:# offline:flags2.1?true video_processing_pending:flags2.4?true paid_suggested_post_stars:flags2.8?true paid_suggested_post_ton:flags2.9?true id:int from_id:flags.8?Peer from_boosts_applied:flags.29?int from_rank:flags2.12?string peer_id:Peer saved_peer_id:flags.28?Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long via_business_bot_id:flags2.0?long guestchat_via_from:flags2.19?Peer reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector ttl_period:flags.25?int quick_reply_shortcut_id:flags.30?int effect:flags2.2?long factcheck:flags2.3?FactCheck report_delivery_until_date:flags2.5?int paid_message_stars:flags2.6?long suggested_post:flags2.7?SuggestedPost schedule_repeat_period:flags2.10?int summary_from_language:flags2.11?string = Message;
-messageService#7a800e0a flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true reactions_are_possible:flags.9?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer saved_peer_id:flags.28?Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction reactions:flags.20?MessageReactions ttl_period:flags.25?int = Message;
-
-messageMediaEmpty#3ded6320 = MessageMedia;
-messageMediaPhoto#e216eb63 flags:# spoiler:flags.3?true live_photo:flags.4?true photo:flags.0?Photo ttl_seconds:flags.2?int video:flags.4?Document = MessageMedia;
-messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
-messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
-messageMediaUnsupported#9f84f49e = MessageMedia;
-messageMediaDocument#52d8ccd9 flags:# nopremium:flags.3?true spoiler:flags.4?true video:flags.6?true round:flags.7?true voice:flags.8?true document:flags.0?Document alt_documents:flags.5?Vector video_cover:flags.9?Photo video_timestamp:flags.10?int ttl_seconds:flags.2?int = MessageMedia;
-messageMediaWebPage#ddf10c3b flags:# force_large_media:flags.0?true force_small_media:flags.1?true manual:flags.3?true safe:flags.4?true webpage:WebPage = MessageMedia;
-messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
-messageMediaGame#fdb19008 game:Game = MessageMedia;
-messageMediaInvoice#f6a548d3 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string extended_media:flags.4?MessageExtendedMedia = MessageMedia;
-messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int proximity_notification_radius:flags.1?int = MessageMedia;
-messageMediaPoll#773f4e66 flags:# poll:Poll results:PollResults attached_media:flags.0?MessageMedia = MessageMedia;
-messageMediaDice#8cbec07 flags:# value:int emoticon:string game_outcome:flags.0?messages.EmojiGameOutcome = MessageMedia;
-messageMediaStory#68cb6283 flags:# via_mention:flags.1?true peer:Peer id:int story:flags.0?StoryItem = MessageMedia;
-messageMediaGiveaway#aa073beb flags:# only_new_subscribers:flags.0?true winners_are_visible:flags.2?true channels:Vector countries_iso2:flags.1?Vector prize_description:flags.3?string quantity:int months:flags.4?int stars:flags.5?long until_date:int = MessageMedia;
-messageMediaGiveawayResults#ceaa3ea1 flags:# only_new_subscribers:flags.0?true refunded:flags.2?true channel_id:long additional_peers_count:flags.3?int launch_msg_id:int winners_count:int unclaimed_count:int winners:Vector months:flags.4?int stars:flags.5?long prize_description:flags.1?string until_date:int = MessageMedia;
-messageMediaPaidMedia#a8852491 stars_amount:long extended_media:Vector = MessageMedia;
-messageMediaToDo#8a53b014 flags:# todo:TodoList completions:flags.0?Vector = MessageMedia;
-messageMediaVideoStream#ca5cab89 flags:# rtmp_stream:flags.0?true call:InputGroupCall = MessageMedia;
-
-messageActionEmpty#b6aef7b0 = MessageAction;
-messageActionChatCreate#bd47cbad title:string users:Vector = MessageAction;
-messageActionChatEditTitle#b5a1ce5a title:string = MessageAction;
-messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction;
-messageActionChatDeletePhoto#95e3fbef = MessageAction;
-messageActionChatAddUser#15cefd00 users:Vector = MessageAction;
-messageActionChatDeleteUser#a43f30cc user_id:long = MessageAction;
-messageActionChatJoinedByLink#31224c3 inviter_id:long = MessageAction;
-messageActionChannelCreate#95d2ac92 title:string = MessageAction;
-messageActionChatMigrateTo#e1037f92 channel_id:long = MessageAction;
-messageActionChannelMigrateFrom#ea3948e9 title:string chat_id:long = MessageAction;
-messageActionPinMessage#94bd38ed = MessageAction;
-messageActionHistoryClear#9fbab604 = MessageAction;
-messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
-messageActionPaymentSentMe#ffa00ccc flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge subscription_until_date:flags.4?int = MessageAction;
-messageActionPaymentSent#c624b16e flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long invoice_slug:flags.0?string subscription_until_date:flags.4?int = MessageAction;
-messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
-messageActionScreenshotTaken#4792929b = MessageAction;
-messageActionCustomAction#fae69f56 message:string = MessageAction;
-messageActionBotAllowed#c516d679 flags:# attach_menu:flags.1?true from_request:flags.3?true domain:flags.0?string app:flags.2?BotApp = MessageAction;
-messageActionSecureValuesSentMe#1b287353 values:Vector credentials:SecureCredentialsEncrypted = MessageAction;
-messageActionSecureValuesSent#d95c6154 types:Vector = MessageAction;
-messageActionContactSignUp#f3f25f76 = MessageAction;
-messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int = MessageAction;
-messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int = MessageAction;
-messageActionInviteToGroupCall#502f92f7 call:InputGroupCall users:Vector = MessageAction;
-messageActionSetMessagesTTL#3c134d7b flags:# period:int auto_setting_from:flags.0?long = MessageAction;
-messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction;
-messageActionSetChatTheme#b91bbd3a theme:ChatTheme = MessageAction;
-messageActionChatJoinedByRequest#ebbca3cb = MessageAction;
-messageActionWebViewDataSentMe#47dd8079 text:string data:string = MessageAction;
-messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction;
-messageActionGiftPremium#48e91302 flags:# currency:string amount:long days:int crypto_currency:flags.0?string crypto_amount:flags.0?long message:flags.1?TextWithEntities = MessageAction;
-messageActionTopicCreate#d999256 flags:# title_missing:flags.1?true title:string icon_color:int icon_emoji_id:flags.0?long = MessageAction;
-messageActionTopicEdit#c0944820 flags:# title:flags.0?string icon_emoji_id:flags.1?long closed:flags.2?Bool hidden:flags.3?Bool = MessageAction;
-messageActionSuggestProfilePhoto#57de635e photo:Photo = MessageAction;
-messageActionRequestedPeer#31518e9b button_id:int peers:Vector = MessageAction;
-messageActionSetChatWallPaper#5060a3f4 flags:# same:flags.0?true for_both:flags.1?true wallpaper:WallPaper = MessageAction;
-messageActionGiftCode#31c48347 flags:# via_giveaway:flags.0?true unclaimed:flags.5?true boost_peer:flags.1?Peer days:int slug:string currency:flags.2?string amount:flags.2?long crypto_currency:flags.3?string crypto_amount:flags.3?long message:flags.4?TextWithEntities = MessageAction;
-messageActionGiveawayLaunch#a80f51e4 flags:# stars:flags.0?long = MessageAction;
-messageActionGiveawayResults#87e2f155 flags:# stars:flags.0?true winners_count:int unclaimed_count:int = MessageAction;
-messageActionBoostApply#cc02aa6d boosts:int = MessageAction;
-messageActionRequestedPeerSentMe#93b31848 button_id:int peers:Vector = MessageAction;
-messageActionPaymentRefunded#41b3e202 flags:# peer:Peer currency:string total_amount:long payload:flags.0?bytes charge:PaymentCharge = MessageAction;
-messageActionGiftStars#45d5b021 flags:# currency:string amount:long stars:long crypto_currency:flags.0?string crypto_amount:flags.0?long transaction_id:flags.1?string = MessageAction;
-messageActionPrizeStars#b00c47a2 flags:# unclaimed:flags.0?true stars:long transaction_id:string boost_peer:Peer giveaway_msg_id:int = MessageAction;
-messageActionStarGift#ea2c31d3 flags:# name_hidden:flags.0?true saved:flags.2?true converted:flags.3?true upgraded:flags.5?true refunded:flags.9?true can_upgrade:flags.10?true prepaid_upgrade:flags.13?true upgrade_separate:flags.16?true auction_acquired:flags.17?true gift:StarGift message:flags.1?TextWithEntities convert_stars:flags.4?long upgrade_msg_id:flags.5?int upgrade_stars:flags.8?long from_id:flags.11?Peer peer:flags.12?Peer saved_id:flags.12?long prepaid_upgrade_hash:flags.14?string gift_msg_id:flags.15?int to_id:flags.18?Peer gift_num:flags.19?int = MessageAction;
-messageActionStarGiftUnique#e6c31522 flags:# upgrade:flags.0?true transferred:flags.1?true saved:flags.2?true refunded:flags.5?true prepaid_upgrade:flags.11?true assigned:flags.13?true from_offer:flags.14?true craft:flags.16?true gift:StarGift can_export_at:flags.3?int transfer_stars:flags.4?long from_id:flags.6?Peer peer:flags.7?Peer saved_id:flags.7?long resale_amount:flags.8?StarsAmount can_transfer_at:flags.9?int can_resell_at:flags.10?int drop_original_details_stars:flags.12?long can_craft_at:flags.15?int = MessageAction;
-messageActionPaidMessagesRefunded#ac1f1fcd count:int stars:long = MessageAction;
-messageActionPaidMessagesPrice#84b88578 flags:# broadcast_messages_allowed:flags.0?true stars:long = MessageAction;
-messageActionConferenceCall#2ffe2f7a flags:# missed:flags.0?true active:flags.1?true video:flags.4?true call_id:long duration:flags.2?int other_participants:flags.3?Vector = MessageAction;
-messageActionTodoCompletions#cc7c5c89 completed:Vector incompleted:Vector = MessageAction;
-messageActionTodoAppendTasks#c7edbc83 list:Vector = MessageAction;
-messageActionSuggestedPostApproval#ee7a1596 flags:# rejected:flags.0?true balance_too_low:flags.1?true reject_comment:flags.2?string schedule_date:flags.3?int price:flags.4?StarsAmount = MessageAction;
-messageActionSuggestedPostSuccess#95ddcf69 price:StarsAmount = MessageAction;
-messageActionSuggestedPostRefund#69f916f8 flags:# payer_initiated:flags.0?true = MessageAction;
-messageActionGiftTon#a8a3c699 flags:# currency:string amount:long crypto_currency:string crypto_amount:long transaction_id:flags.0?string = MessageAction;
-messageActionSuggestBirthday#2c8f2a25 birthday:Birthday = MessageAction;
-messageActionStarGiftPurchaseOffer#774278d4 flags:# accepted:flags.0?true declined:flags.1?true gift:StarGift price:StarsAmount expires_at:int = MessageAction;
-messageActionStarGiftPurchaseOfferDeclined#73ada76b flags:# expired:flags.0?true gift:StarGift price:StarsAmount = MessageAction;
-messageActionNewCreatorPending#b07ed085 new_creator_id:long = MessageAction;
-messageActionChangeCreator#e188503b new_creator_id:long = MessageAction;
-messageActionNoForwardsToggle#bf7d6572 prev_value:Bool new_value:Bool = MessageAction;
-messageActionNoForwardsRequest#3e2793ba flags:# expired:flags.0?true prev_value:Bool new_value:Bool = MessageAction;
-messageActionPollAppendAnswer#9da1cd6c answer:PollAnswer = MessageAction;
-messageActionPollDeleteAnswer#399674dc answer:PollAnswer = MessageAction;
-messageActionManagedBotCreated#16605e3e bot_id:long = MessageAction;
-
-dialog#fc89f7f3 flags:# pinned:flags.2?true unread_mark:flags.3?true view_forum_as_messages:flags.6?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int unread_poll_votes_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int ttl_period:flags.5?int = Dialog;
-dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;
-
-photoEmpty#2331b22d id:long = Photo;
-photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector video_sizes:flags.1?Vector dc_id:int = Photo;
-
-photoSizeEmpty#e17e23c type:string = PhotoSize;
-photoSize#75c78e60 type:string w:int h:int size:int = PhotoSize;
-photoCachedSize#21e1ad6 type:string w:int h:int bytes:bytes = PhotoSize;
-photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
-photoSizeProgressive#fa3efb95 type:string w:int h:int sizes:Vector = PhotoSize;
-photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;
-
-geoPointEmpty#1117dd5f = GeoPoint;
-geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;
-
-auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;
-auth.sentCodeSuccess#2390fe44 authorization:auth.Authorization = auth.SentCode;
-auth.sentCodePaymentRequired#f8827ebf store_product:string phone_code_hash:string support_email_address:string support_email_subject:string premium_days:int currency:string amount:long = auth.SentCode;
-
-auth.authorization#2ea2c0d4 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int future_auth_token:flags.2?bytes user:User = auth.Authorization;
-auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;
-
-auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;
-
-inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
-inputNotifyUsers#193b4417 = InputNotifyPeer;
-inputNotifyChats#4a95e84e = InputNotifyPeer;
-inputNotifyBroadcasts#b1db7c7e = InputNotifyPeer;
-inputNotifyForumTopic#5c467992 peer:InputPeer top_msg_id:int = InputNotifyPeer;
-
-inputPeerNotifySettings#cacb6ae2 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?NotificationSound stories_muted:flags.6?Bool stories_hide_sender:flags.7?Bool stories_sound:flags.8?NotificationSound = InputPeerNotifySettings;
-
-peerNotifySettings#99622c0c flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int ios_sound:flags.3?NotificationSound android_sound:flags.4?NotificationSound other_sound:flags.5?NotificationSound stories_muted:flags.6?Bool stories_hide_sender:flags.7?Bool stories_ios_sound:flags.8?NotificationSound stories_android_sound:flags.9?NotificationSound stories_other_sound:flags.10?NotificationSound = PeerNotifySettings;
-
-peerSettings#f47741f7 flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true autoarchived:flags.7?true invite_members:flags.8?true request_chat_broadcast:flags.10?true business_bot_paused:flags.11?true business_bot_can_reply:flags.12?true geo_distance:flags.6?int request_chat_title:flags.9?string request_chat_date:flags.9?int business_bot_id:flags.13?long business_bot_manage_url:flags.13?string charge_paid_message_stars:flags.14?long registration_month:flags.15?string phone_country:flags.16?string name_change_date:flags.17?int photo_change_date:flags.18?int = PeerSettings;
-
-wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
-wallPaperNoFile#e0804116 id:long flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;
-
-inputReportReasonSpam#58dbcab8 = ReportReason;
-inputReportReasonViolence#1e22c78d = ReportReason;
-inputReportReasonPornography#2e59d922 = ReportReason;
-inputReportReasonChildAbuse#adf44ee3 = ReportReason;
-inputReportReasonOther#c1e4a2b1 = ReportReason;
-inputReportReasonCopyright#9b89f93a = ReportReason;
-inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
-inputReportReasonFake#f5ddd6e7 = ReportReason;
-inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
-inputReportReasonPersonalDetails#9ec7863d = ReportReason;
-
-userFull#6cbe645 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true display_gifts_button:flags2.16?true noforwards_my_enabled:flags2.23?true noforwards_peer_enabled:flags2.24?true unofficial_security_risk:flags2.26?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme:flags.15?ChatTheme private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram bot_verification:flags2.12?BotVerification send_paid_messages_stars:flags2.14?long disallowed_gifts:flags2.15?DisallowedGiftsSettings stars_rating:flags2.17?StarsRating stars_my_pending_rating:flags2.18?StarsRating stars_my_pending_rating_date:flags2.18?int main_tab:flags2.20?ProfileTab saved_music:flags2.21?Document note:flags2.22?TextWithEntities bot_manager_id:flags2.25?long = UserFull;
-
-contact#145ade0b user_id:long mutual:Bool = Contact;
-
-importedContact#c13e3c50 user_id:long client_id:long = ImportedContact;
-
-contactStatus#16d9703b user_id:long status:UserStatus = ContactStatus;
-
-contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
-contacts.contacts#eae87e42 contacts:Vector saved_count:int users:Vector = contacts.Contacts;
-
-contacts.importedContacts#77d01c3b imported:Vector popular_invites:Vector retry_contacts:Vector users:Vector = contacts.ImportedContacts;
-
-contacts.blocked#ade1591 blocked:Vector chats:Vector users:Vector = contacts.Blocked;
-contacts.blockedSlice#e1664194 count:int blocked:Vector chats:Vector users:Vector = contacts.Blocked;
-
-messages.dialogs#15ba6c40 dialogs:Vector