# Bridge Bot Debugging Session Audit - 2026-05-14

This document records the issues investigated, tests run, conclusions reached, and fixes applied during the debugging session.

## Starting Symptoms

- Telegram messages were not reliably syncing to Eitaa and Rubika.
- Rubika file sending failed while Rubika text messages generally worked.
- Bale, Rubika, and Eitaa did not preserve Telegram formatting such as bold/italic.
- Eitaa was reported as fully failing in some sync attempts.
- Admin management was too manual for editing channel mappings and rules.
- A cPanel-ready release package was needed.

## Local Log Audit

File reviewed:

- `C:/Users/Home/Documents/git/bridge/debug_log.txt`

Main findings:

- Rubika `requestSendFile` often returned `OK` and produced an `upload_url`, but upload to `messengerg2f1.rubika.ir` often returned HTTP `502`.
- Eitaa failures included cURL timeouts and DNS/resolve timeouts to `eitaayar.ir`.
- Some older Eitaa rows used invalid route values such as `skip`, producing `Bad Request: chat not found`.
- Rubika admin alerts were attempted against `u...` user GUIDs, but Rubika `sendMessage` expects a `c...` chat id.
- The code referenced `DB::deleteMap()` but the method did not exist.
- Failed API alerts returned generic `request_failed`, making diagnosis difficult.

## Web/API Research

Rubika Bot API flow used by the bot:

- Main API base: `https://botapi.rubika.ir/v3/{TOKEN}/{METHOD}`
- File flow:
  1. `requestSendFile`
  2. upload multipart file to the returned `upload_url`
  3. `sendFile` with returned `file_id`

Observed upload host from Rubika:

- `messengerg2f1.rubika.ir`

Local DNS observed:

- `botapi.rubika.ir` -> `46.51.38.3`
- `messengerg2f1.rubika.ir` -> `5.106.10.35`

Conclusion:

- Rubika chat id was not the issue because `getChat` returned `200 OK` and local/server `sendFile` succeeded after upload.
- The failing part was the upload gateway, before `sendFile` used the chat id.

## Server Requirement Checks

Tool added:

- `tools/server_requirements.php`

Server output passed all checks:

- PHP version OK
- `curl` extension OK
- `mbstring` extension OK
- `fileinfo` extension OK
- `pdo_sqlite` and `sqlite3` OK
- `json` OK
- HTTPS/cURL usable
- vendored CA bundle present
- debug log writable
- SQLite database writable
- `config.php` present
- Rubika `getMe` HTTPS probe returned HTTP `200`

Conclusion:

- Server PHP/cPanel requirements were not the reason Rubika upload failed.

## Rubika File Canary

Tool added:

- `tools/rubika_file_canary.php`

Purpose:

- Test Rubika file sending end-to-end without waiting for Telegram sync.
- Phases: `getMe`, `getChat`, `requestSendFile`, upload, `sendFile`, optional `deleteMessage`.
- Supports `--tries=N` to request fresh upload URLs and retry upload.

Initial cPanel test:

- `getMe`: HTTP `200`, status `OK`
- `getChat`: HTTP `200`, status `OK`
- `requestSendFile`: HTTP `200`, status `OK`
- Upload: repeated HTTP `502` from `messengerg2f1.rubika.ir`

Local machine test:

- First several upload attempts returned HTTP `502`.
- Later attempt returned HTTP `200`, produced `file_id`, and `sendFile` succeeded.

Later cPanel test with `--tries=10`:

- Attempts 1-5 returned HTTP `502`.
- Attempt 6 returned HTTP `200`, produced `file_id`, `sendFile` succeeded, and `deleteMessage` succeeded.

Conclusion:

- Rubika upload works from cPanel, but the upload gateway is flaky and needs more retries.

## Rubika Fixes Applied

Files changed:

- `sync_bot.php`
- `config.example.php`
- `vendor/cacert.pem`
- `tools/rubika_file_canary.php`

Fixes:

- Added vendored CA bundle support via `vendor/cacert.pem`.
- Added cURL default application for CA bundle.
- Forced Rubika upload cURL to HTTP/1.1.
- Disabled `Expect: 100-continue` for Rubika upload requests.
- Added repeated Rubika upload attempts using fresh `requestSendFile` URLs.
- Added configurable `network.rubika_upload_retry_count`.
- Default Rubika upload retry count was raised to `10` after cPanel succeeded on attempt 6.
- Added caption fallback: if Rubika media upload completely fails and there is a caption, send the caption as text instead of losing the message.
- Added better Rubika upload logging, including host, HTTP code, attempt number, MIME type, and chosen Rubika type.

Reason:

- The observed failure was HTTP `502` from Rubika upload gateway, not bad token/chat id. Retrying with fresh upload URLs is the only code-level mitigation that proved effective.

## Rubika Filename Improvement

Issue:

- Rubika displayed temporary filenames such as `s_177...ogg` for voice files uploaded as generic files.

Fix:

- Added a display filename derived from source channel/chat title, media type, timestamp, and extension.
- Rubika uploads now pass this clean display name into `CURLFile` instead of the local temp filename.

Expected result:

- Files should show names like `ChannelTitle_voice_20260514_231500.ogg` instead of `s_177...ogg`.
- If Rubika must treat Telegram `ogg/opus` voices as generic files, a filename may still be visible, but it should be meaningful.

## Eitaa Findings

Observed failure:

- `curl: Connection timed out after 10002 milliseconds`

Conclusion:

- The failure is a connection timeout to Eitaa/Eitaayar, not a payload formatting error.
- The previous code still used the global `connect_timeout` of 10 seconds, even though file timeout had been raised.

Eitaa fixes:

- Added Eitaa-specific network settings:
  - `network.eitaa_connect_timeout`
  - `network.eitaa_text_timeout`
  - `network.eitaa_file_timeout`
  - `network.eitaa_retry_count`
- Defaults:
  - connect timeout: `30`
  - text timeout: `35`
  - file timeout: `90`
  - retries: `2`

Reason:

- Shared hosting and Iranian messaging APIs may need longer connection setup time. The reported `10002 ms` showed the connection phase was still being cut off at 10 seconds.

## Formatting Fixes

Issue:

- Telegram bold/italic and other entities did not apply to Bale, Rubika, and Eitaa.

Fix:

- Added Telegram entity to Markdown conversion for outgoing non-Telegram destinations.
- Supported conversions:
  - bold
  - italic
  - underline mapped to Markdown underline-style text where supported
  - strikethrough
  - spoiler
  - inline code
  - pre/code block
  - text links
- Applied formatted conversion to both text messages and captions.
- Preserved plain Telegram behavior separately.

Reason:

- Telegram sends formatting as entities, not literal Markdown. Other APIs needed formatted text generated from those entities.

## Sync/Behavior Fixes

Fixes:

- `#nosync` now works in captions as well as text.
- Numeric `message_id` and `reply_to_message_id` are cast for non-Rubika platforms to avoid malformed edit/reply payloads.
- Added `DB::deleteMap()` to prevent missing-method failures during delete/replace flows.
- Improved API failure descriptions:
  - cURL errors now return messages like `curl: Connection timed out after ...`
  - bad JSON includes HTTP code
  - API failure includes HTTP code/status/description
- Improved logging for API calls, failures, and media flow.

## Admin Improvements

Added faster admin commands and UI:

- `⚡ اتصال سریع`
- `/add tg=... bale=... eitaa=... rubika=...`
- `/set 3 telegram -100...`
- `/set 3 bale 486...`
- `/set 3 eitaa 110...`
- `/set 3 rubika c0...`
- `/set 3 rubika skip`
- `/rules 3 sync_media=0 route_rubika=1 prefix=VIP suffix=skip`
- `/show 3`
- `/help`
- `راهنما`

Added validation:

- Rubika chat ids are validated before saving.
- `skip` can be used to clear optional routes.
- Eitaa values starting with `@` are normalized by removing `@`.

Reason:

- The user wanted easier admin ability to edit rules and add other channels across platforms.

## cPanel Release Package

Tool added:

- `tools/make_release.py`

Purpose:

- Create a cPanel-ready ZIP package.
- Excludes live secrets, debug logs, runtime DB, and error logs by default.
- Includes:
  - `sync_bot.php`
  - webhook setup scripts
  - `config.example.php`
  - `vendor/cacert.pem`
  - diagnostic tools
  - deployment README
  - this audit document

Latest release package after these fixes:

- `dist/bridge-deploy-20260514-230634.zip` was created before the Eitaa timeout/name/audit changes.
- A newer package should be created after this document and final lint checks.

## Local Environment Changes

Local PHP was configured so tests could run:

- Enabled `curl`
- Enabled `mbstring`
- Enabled `pdo_sqlite`
- Enabled `sqlite3`
- Enabled `fileinfo`
- Added a CA bundle for HTTPS testing.

Project vendor file added:

- `vendor/cacert.pem`

Reason:

- The bot relies on cURL HTTPS calls and SQLite locally and on cPanel.

## Current Operational Recommendations

Rubika:

- Keep `network.rubika_upload_retry_count` at `10`.
- If all 10 upload attempts fail repeatedly, the remaining issue is Rubika gateway/network routing, not PHP.
- Relevant host for hosting support: `messengerg2f1.rubika.ir:443`.

Eitaa:

- Use the new Eitaa timeout defaults.
- If Eitaa still fails after `30` second connect timeout and retries, ask hosting support to check outbound HTTPS/DNS to `eitaayar.ir`.
- The failure is consistent with route/DNS/API reachability.

Deployment:

- Upload the latest release ZIP to cPanel.
- Preserve the existing live `config.php` unless intentionally replacing tokens.
- Run:

```bash
php tools/server_requirements.php
php tools/rubika_file_canary.php --chat-id=c0DJYc205d3abf26ef31bc66ead9439e --type=File --tries=10
```

Optional server config:

```php
'network' => [
    'telegram_proxy' => '',
    'connect_timeout' => 10,
    'timeout' => 60,
    'retry_count' => 2,
    'retry_delay_ms' => 600,
    'eitaa_connect_timeout' => 30,
    'eitaa_text_timeout' => 35,
    'eitaa_file_timeout' => 90,
    'eitaa_retry_count' => 2,
    'rubika_upload_retry_count' => 10,
],
```
