mirror of
https://github.com/danog/TelegramApiServer.git
synced 2024-11-26 11:54:42 +01:00
361 lines
16 KiB
Markdown
361 lines
16 KiB
Markdown
# TelegramApiServer
|
|
Fast, simple, async php telegram api server:
|
|
[MadelineProto](https://github.com/danog/MadelineProto) and [Amp](https://github.com/amphp/amp) Http Server
|
|
|
|
* Online demo (getHistory + Media Download): [tg.i-c-a.su](https://tg.i-c-a.su)
|
|
* My content aggregator: [i-c-a.su](https://i-c-a.su)
|
|
* Get telegram channels in RSS: [TelegramRSS](https://github.com/xtrime-ru/TelegramRSS)
|
|
|
|
## Features
|
|
|
|
* Fast async Amp Http Server
|
|
* Full access to telegram api: bot and user
|
|
* Multiple sessions
|
|
* Stream media (view files in a browser)
|
|
* Upload media
|
|
* Websocket endpoints for events and logs
|
|
* MadelineProto optimized settings to reduce memory consumption
|
|
|
|
**Architecture Example**
|
|
![Architecture Example](https://hsto.org/webt/j-/ob/ky/j-obkye1dv68ngsrgi12qevutra.png)
|
|
|
|
## Installation
|
|
|
|
```shell
|
|
git clone https://github.com/xtrime-ru/TelegramApiServer.git TelegramApiServer
|
|
cd TelegramApiServer
|
|
cp .env.docker.example .env.docker
|
|
docker compose pull
|
|
```
|
|
|
|
## Authorization
|
|
1. Get app_id and app_hash at [my.telegram.org](https://my.telegram.org/).
|
|
Only one app_id needed for any amount of users and bots.
|
|
1. Fill app_id and app_hash in `.env.docker`.
|
|
1. Start TelegramApiServer in cli:
|
|
1. Start container interactively: `docker compose run --rm api`
|
|
2. If you need to start multiple sessions, create docker-compose.override.yml. Add additional containers there. Use unique ports and session names in `command`.
|
|
1. Authorize your session:
|
|
1. After promt fill your phone number, or bot hash.
|
|
1. Follow instructions
|
|
1. Wait 10-30 seconds until session is started.
|
|
You will see logs:
|
|
```text
|
|
TelegramApiServer ready.
|
|
Number of sessions: 1.
|
|
```
|
|
1. Exit with `Ctrl + C`
|
|
1. Run container in background `docker compose up -d`.
|
|
|
|
## Update
|
|
* `git pull` or `git fetch && git reset --hard origin/master`
|
|
* `rm -rf vendor/`
|
|
* Compare `.env.docker` or `.env` with corresponding `.env.example`. Update if needed.
|
|
* Recreate containers:
|
|
```shell
|
|
docker compose pull
|
|
docker compose down
|
|
docker compose up -d
|
|
```
|
|
|
|
## Security
|
|
Please be careful with settings, otherwise you can expose your telegram session and lose control.
|
|
Default settings allow to access API only from localhost/127.0.0.1.
|
|
|
|
.env settings:
|
|
- `IP_WHITELIST` - allow specific IP's to make requests without password.
|
|
- `PASSWORDS` - protect your api with basic auth.
|
|
Request with correct username and password overrides IP_WHITELIST.
|
|
If you specify password, then `IP_WHITELIST` is ignored
|
|
How to make requests with basic auth:
|
|
```shell
|
|
curl --user 'username:password' "http://127.0.0.1:9503/getSelf"
|
|
curl "http://username:password@127.0.0.1:9503/getSelf"
|
|
```
|
|
|
|
docker-compose.yml:
|
|
- `port` - port forwarding rules from host to docker container.
|
|
Remove 127.0.0.1 to listen all interfaces and forward all requests to container.
|
|
Make sure to use IP_WHITELIST and/or PASSWORDS settings to protect your account.
|
|
|
|
## Usage
|
|
Access Telegram API with simple GET/POST requests.
|
|
Regular and application/json POST supported.
|
|
It's recommended to use http_build_query, when using GET requests.
|
|
|
|
**Rules:**
|
|
* All methods from MadelineProto supported: [Methods List](https://docs.madelineproto.xyz/API_docs/methods/)
|
|
* Url: `http://%address%:%port%/api[/%session%]/%class%.%method%/?%param%=%val%`
|
|
* <b>Important: api available only from ip in whitelist.</b>
|
|
By default it is: `127.0.0.1`
|
|
You can add a client IP in .env file to `IP_WHITELIST` (separate with a comma)
|
|
|
|
In docker version by default api available only from localhost (127.0.0.1).
|
|
To allow connections from the internet, need to change ports in docker-compose.yml to `9503:9503` and recreate the container: `docker compose up -d`.
|
|
This is very insecure, because this will open TAS port to anyone from the internet.
|
|
Only protection is the `IP_WHITELIST`, and there are no warranties that it will secure your accounts.
|
|
* If method is inside class (messages, contacts and etc.) use '.' to separate class from method:
|
|
`http://127.0.0.1:9503/api/contacts.getContacts`
|
|
* If method requires array of values, use any name of array, for example 'data':
|
|
`?data[peer]=@xtrime&data[message]=Hello!`. Order of parameters does't matter in this case.
|
|
* If method requires one or multiple separate parameters (not inside array) then pass parameters with any names but **in strict order**:
|
|
`http://127.0.0.1:9503/api/getInfo/?id=@xtrime` or `http://127.0.0.1:9503/api/getInfo/?abcd=@xtrime` works the same
|
|
|
|
**Examples:**
|
|
* get_info about channel/user: `http://127.0.0.1:9503/api/getInfo/?id=@xtrime`
|
|
* get_info about currect account: `http://127.0.0.1:9503/api/getSelf`
|
|
* repost: `http://127.0.0.1:9503/api/messages.forwardMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id]=1234`
|
|
* get messages from channel/user: `http://127.0.0.1:9503/api/getHistory/?data[peer]=@breakingmash&data[limit]=10`
|
|
* get messages with text in HTML: `http://127.0.0.1:9503/api/getHistoryHtml/?data[peer]=@breakingmash&data[limit]=10`
|
|
* search: `http://127.0.0.1:9503/api/searchGlobal/?data[q]=Hello%20World&data[limit]=10`
|
|
* sendMessage: `http://127.0.0.1:9503/api/sendMessage/?data[peer]=@xtrime&data[message]=Hello!`
|
|
* copy message from one channel to another (not repost): `http://127.0.0.1:9503/api/copyMessages/?data[from_peer]=@xtrime&data[to_peer]=@xtrime&data[id][0]=1`
|
|
|
|
## Advanced features
|
|
### Get events/updates
|
|
Telegram is event driven platform. For example: every time your account receives a message you immediately get an update.
|
|
There are multiple ways of [getting updates](https://docs.madelineproto.xyz/docs/UPDATES.html) in TelegramApiServer / MadelineProto:
|
|
1. [Websocket](#eventhandler-updates-webhooks)
|
|
2. Long Polling:
|
|
send request to getUpdates endpoint
|
|
`curl "127.0.0.1:9503/api/getUpdates?data[limit]=3&data[offset]=0&data[timeout]=10.0" -g`
|
|
3. Webhook:
|
|
Redirect all updates to your endpoint, just like bot api!
|
|
`curl "127.0.0.1:9503/api/setWebhook?url=http%3A%2F%2Fexample.com%2Fsome_webhook" -g `
|
|
Example uses urlencoded url in query.
|
|
|
|
### Uploading files.
|
|
|
|
There are few options to upload and send media files:
|
|
- Custom method `sendMedia` supports upload from form:
|
|
```shell script
|
|
curl "http://127.0.0.1:9503/api/sendMedia?data[peer]=xtrime&data[message]=Hello" -g \
|
|
-F "file=@/Users/xtrime/Downloads/test.txt"
|
|
```
|
|
- use custom `uploadMediaForm` method and then pass result to `messages.sendMedia`:
|
|
1. `curl "http://127.0.0.1:9503/api/uploadMediaForm" -g -F "file=@/Users/xtrime/Downloads/test.txt"`
|
|
Method supports `application/x-www-form-urlencoded` and `multipart/form-data`.
|
|
|
|
2. Send result from `uploadMediaForm` to `messages.sendMedia` or `sendMedia`:
|
|
```shell script
|
|
curl --location --request POST 'http://127.0.0.1:9503/api/sendMedia' \
|
|
--header 'Content-Type: application/json' \
|
|
--data-raw '{
|
|
"data":{
|
|
"peer": "@xtrime",
|
|
"media": {
|
|
"_": "inputMediaUploadedDocument",
|
|
"file": {
|
|
"_": "inputFile",
|
|
"id": 1164670976363200575,
|
|
"parts": 1,
|
|
"name": "test.txt",
|
|
"mime_type": "text/plain",
|
|
"md5_checksum": ""
|
|
},
|
|
"attributes": [
|
|
{
|
|
"_": "documentAttributeFilename",
|
|
"file_name": "test.txt"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}'
|
|
```
|
|
- See other options: https://docs.madelineproto.xyz/docs/FILES.html#uploading-files
|
|
|
|
### Downloading files
|
|
|
|
```shell script
|
|
curl --location --request POST '127.0.0.1:9503/api/downloadToResponse' \
|
|
--header 'Content-Type: application/json' \
|
|
--data-raw '{
|
|
"media": {
|
|
"_": "messageMediaDocument",
|
|
"document": {
|
|
"_": "document",
|
|
"id": 5470079466401169993,
|
|
"access_hash": -6754208767885394084,
|
|
"file_reference": {
|
|
"_": "bytes",
|
|
"bytes": "AkKdqJkAACnyXshwzMhdzeC5RkdVZeh58sAB/UU="
|
|
},
|
|
"date": 1551713685,
|
|
"mime_type": "video/mp4",
|
|
"size": 400967,
|
|
"dc_id": 2,
|
|
"attributes": [
|
|
{
|
|
"_": "documentAttributeFilename",
|
|
"file_name": "одолдол.mp4"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}'
|
|
```
|
|
|
|
Also see: https://docs.madelineproto.xyz/docs/FILES.html#downloading-files
|
|
|
|
### Multiple sessions support
|
|
Its recommended to run every session in separate container.
|
|
|
|
To add more containers create `docker-compose.override.yml` file.
|
|
Docker will [automatically merge](https://docs.docker.com/compose/multiple-compose-files/merge/) it with default docker-compose file.
|
|
|
|
Example of `docker-compose.override.yml` with two additional containers/sessions (3 in total):
|
|
```yaml
|
|
services:
|
|
api-2:
|
|
extends:
|
|
file: docker-compose.base.yml
|
|
service: base-api
|
|
ports:
|
|
- "127.0.0.1:9512:9503"
|
|
command:
|
|
- "-s=session-2"
|
|
api-3:
|
|
extends:
|
|
file: docker-compose.base.yml
|
|
service: base-api
|
|
ports:
|
|
- "127.0.0.1:9513:9503"
|
|
command:
|
|
- "-s=session-3"
|
|
|
|
```
|
|
### Multiple sessions in one container (deprecated)
|
|
**WARNING: running multiple sessions in one instance/container is unstable.**
|
|
Crash/error in one session will crash all of them.
|
|
|
|
When running multiple sessions, need to define which session to use for request.
|
|
Each session stored in `sessions/{$session}.madeline`. Nested folders supported.
|
|
**Examples:**
|
|
* `php server.php --session=bot --session=users/xtrime --session=users/user1`
|
|
* `http://127.0.0.1:9503/api/bot/getSelf`
|
|
* `http://127.0.0.1:9503/api/users/xtrime/getSelf`
|
|
* `http://127.0.0.1:9503/api/users/user1/getSelf`
|
|
* sessions file paths are: `sessions/bot.madeline`, `sessions/users/xtrime.madeline` and `sessions/users/user1.madeline`
|
|
* glob syntax for sessions:
|
|
* `--session=*` to use all `sessions/*.madeline` files (in subfolders too).
|
|
* `--session=users/* --session=bots/*` to use all session files from `sessions/bots` and `sessions/users` folders.
|
|
|
|
### Different settings for sessions
|
|
* Use `--env` argument to define the relative path to env file.
|
|
Example: ```php server.php --env=.env```, ```php server.php --env=sessions/.env.session```
|
|
This is helpful to define unique settings for different instances of TelegramApiServer.
|
|
You can start multiple instances of TelegramApiServer with different sessions on different ports with their own settings.
|
|
|
|
* Another way to manage settings - put %sessionName%.settings.json in sessions folder.
|
|
Example of `session.settings.json` to add proxy for the one session:
|
|
|
|
```json
|
|
{
|
|
"connection": {
|
|
"proxies": {
|
|
"\\danog\\MadelineProto\\Stream\\Proxy\\SocksProxy": [
|
|
{
|
|
"address": "127.0.0.1",
|
|
"port": 1234,
|
|
"username": "user",
|
|
"password": "pass"
|
|
}
|
|
],
|
|
"\\danog\\MadelineProto\\Stream\\Proxy\\HttpProxy": [
|
|
{
|
|
"address": "127.0.0.1",
|
|
"port": 1234,
|
|
"username": "user",
|
|
"password": "pass"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
Methods to work with settings files:
|
|
* `http://127.0.0.1:9503/system/saveSessionSettings?session=session&settings[app_info][app_id]=xxx&settings[app_info][app_hash]=xxx`
|
|
* `http://127.0.0.1:9503/system/unlinkSessionSettings?session=session`
|
|
* Provide settings as second argument when adding session: `http://127.0.0.1:9503/system/addSession?session=users/xtrime&settings[app_info][app_id]=xxx&&settings[app_info][app_hash]=xxx`
|
|
These settings will be saved into json file and will apply after the restart.
|
|
|
|
### Session management
|
|
|
|
**Examples:**
|
|
* Session list: `http://127.0.0.1:9503/system/getSessionList`
|
|
* Adding session: `http://127.0.0.1:9503/system/addSession?session=users/xtrime`
|
|
* ~~Removing session (session file will remain): `http://127.0.0.1:9503/system/removeSession?session=users/xtrime`
|
|
Due to madelineProto issue its instance still might be in memory and continue working even after the remove.~~
|
|
* ~~Remove session file: `http://127.0.0.1:9503/system/unlinkSessionFile?session=users/xtrime`
|
|
Don`t forget to logout and call removeSession first!~~
|
|
* Close TelegramApiServer (end process): `http://127.0.0.1:9503/system/exit`
|
|
|
|
Full list of system methods available in [SystemApiExtensions class](https://github.com/xtrime-ru/TelegramApiServer/blob/master/src/MadelineProtoExtensions/SystemApiExtensions.php)
|
|
|
|
### Authorizing session remotely
|
|
WARNING: it is recomended to use interactive mode to authorize sessions!
|
|
If there is no authorization in session, or session file is blank, authorization required:
|
|
|
|
User:
|
|
* `http://127.0.0.1:9503/api/users/xtrime/phoneLogin?phone=%2B7123...`, %2B - is urlencoded "+" sign
|
|
* `http://127.0.0.1:9503/api/users/xtrime/completePhoneLogin?code=123456`
|
|
* (optional) `http://127.0.0.1:9503/api/users/xtrime/complete2falogin?password=123456`
|
|
* (optional) `http://127.0.0.1:9503/api/users/xtrime/completeSignup?firstName=MyExampleName`
|
|
|
|
Bot:
|
|
* `http://127.0.0.1:9503/api/bot/botLogin?token=34298141894:aflknsaflknLKNFS`
|
|
|
|
Save new session to file immediately: `http://127.0.0.1:9503/api/bot/serialize`
|
|
|
|
Also, session can be authorized in cli/shell on server start.
|
|
|
|
### Websocket
|
|
#### EventHandler updates (webhooks).
|
|
|
|
Connect to `ws://127.0.0.1:9503/events` to get all events in json.
|
|
This is efficient alternative for webhooks.
|
|
Each event is json object in [json-rpc 2.0 format](https://www.jsonrpc.org/specification#response_object). Example:
|
|
|
|
When using multiple sessions, name of session can be added to path of websocket endpoint:
|
|
This endpoint will send events only from `users/xtrime` session: `ws://127.0.0.1:9503/events/users/xtrime`
|
|
|
|
PHP websocket client example: [websocket-events.php](https://github.com/xtrime-ru/TelegramApiServer/blob/master/examples/websocket-events.php)
|
|
|
|
`php examples/websocket-events.php --url=ws://127.0.0.1:9503/events`
|
|
|
|
#### Logs.
|
|
|
|
Connect to `ws://127.0.0.1:9503/log[/%level%]` to get logs in real time.
|
|
|
|
`%level%` is optional parameter to filter logs.
|
|
If filter is specified, then only messages with equal or greater level will be send.
|
|
This endpoint will send only alert and emergency logs: `ws://127.0.0.1:9503/log/alert`
|
|
|
|
Available levels: debug, info, notice, warning, error, critical, alert, emergency.
|
|
|
|
PHP websocket client example: [websocket-events.php](https://github.com/xtrime-ru/TelegramApiServer/blob/master/examples/websocket-events.php)
|
|
|
|
`php examples/websocket-events.php --url=ws://127.0.0.1:9503/log`
|
|
|
|
|
|
### Custom methods
|
|
|
|
TelegramApiServer extends madelineProto with some handful methods.
|
|
Full list of custom methods and their parameters available in [ApiExtensions class](https://github.com/xtrime-ru/TelegramApiServer/blob/master/src/MadelineProtoExtensions/ApiExtensions.php#L19)
|
|
|
|
* `getHistoryHtml` - message entities converted to html
|
|
* `formatMessage` - converts entities to html
|
|
* `copyMessages` - copy message from one peer to onother. Like forwardMessages, but without the link to original.
|
|
* `getMedia` - download media to stream/browser
|
|
* `getMediaPreview` - download media preview to stream/browser
|
|
* `uploadMediaForm` - upload document from POST request.
|
|
|
|
## Contacts
|
|
|
|
* Telegram:
|
|
* Author: [@xtrime](https://t.me/xtrime)
|
|
* [MadelineProto and Amp Support Groups](https://t.me/pwrtelegramgroup)
|
|
* Use madelineProto support groups to get support for TelegramApiServer.
|
|
* Email: alexander(at)i-c-a.su
|