Telescope is an enterprise account management system for Telegram accounts, created by Zellic. It allows organizations to manage multiple organization-controlled Telegram accounts with role-based access control (RBAC) and single sign-on (SSO) authentication.
- Features
- Requirements
- Usage
- Configuration
- Build Instructions
- Role-Based Access Control (RBAC)
- Telegram Policies
- Development Using the Telegram Test Server
- Pluggable Module System
- Disclaimer
- License
- Role-Based Access Control: Assign privileges based on SSO email.
- Contact Management: Stores all one-on-one contacts found on an account in Postgres.
- Employee Account Takeover: Allows privileged users to retrieve two-factor codes to log into accounts. Stores 2FA passwords encrypted with a master key on disk.
- Pluggable Module System: Extend functionality by adding custom modules.
- PostgreSQL
- Docker
- Telegram API tokens (see here)
- Cloudflare Access (PRs welcome for other providers.)
Telegram accounts may be added using the "Add Account" button on the main route (/
), or added through the self-serve onboarding interface at /onboarding
.
When you add a new account, Telescope will proceed through the authentication steps one-by-one. If it requires more information, like an authentication code or two-factor password, the stage indicator will turn red, and the 'Provide' button will become available. Simply click that button and provide the required information so authentication can continue.
Currently, not completing authentication in a timely manner will cause the Telegram authentication code to expire. As authenticating too often is prohibited by Telegram, Telescope will not try again on its own. You must explicitly click the disconnect and reconnect buttons to begin authentication again.
The visibility of accounts, or actions related to accounts, is determined by the RBAC system privileges.
Set the following environment variables in a .env
file, which will be loaded by Docker Compose, or read from the project root if run without a container.
They may also be defined as environment variables by your shell.
HOST
The hostname to listen on (defaults tolocalhost
).PORT
The port to listen on (defaults to8888
).CORS_POLICY
The allowed origins for interacting with the websocket (e.g.,"https://example.com;https://example2.com"
)API_ID
Your Telegram API ID from your Telegram app.API_HASH
Your Telegram API hash from your Telegram app.DB_DSN
Database connection string (e.g.,user=postgres dbname=your_dbname host=your_postgres_ip password=your_password
).TWO_FACTOR_ENCRYPTION_KEY
A 32-character encryption key.SSO_MODE
Authentication mode. Options are:cloudflare
For Cloudflare Access.mock
For development only; hardcodes email totest@test.com
.disable
Skips privileges altogether, as if every user had administrator privileges.
CLOUDFLARE_ACCESS_CERTS
Your Cloudflare Access team subdomain (see Cloudflare documentation).CLOUDFLARE_POLICY_AUD
Your Cloudflare AccessAUD
tag (see Cloudflare documentation).
Example config (all keys are correctly sized random strings for demonstration purposes):
API_ID=12345678
API_HASH=bce79c00b935bc325432991f88a19f0d
DB_DSN="user=postgres dbname=telescope_prod host=192.168.1.1 password=CorrectHorseBatteryStaple"
TWO_FACTOR_ENCRYPTION_KEY="dEMHhIw2jscdbKDq4orzevzlt7i7B3Rt"
CLOUDFLARE_ACCESS_CERTS="https://yourteam.cloudflareaccess.com/cdn-cgi/access/certs"
CLOUDFLARE_POLICY_AUD="e490adb9f86599ae40e26783d31e878ac69b85ab04ab04c67a0608f25181e872"
SSO_MODE="cloudflare"
-
Postgres
Install and configure Postgres - a DSN will be required.
-
Build Docker image
docker compose build
-
Create accounts directory
This is where TDLib data will live, including Telegram session persistence. This folder must be mounted into the container via Docker Compose.
mkdir accounts
-
Define environment variables
Create a
.env
file with the environment variables listed in the Configuration section. -
Start the application
docker compose up
-
Grant yourself admin privileges
No accounts will be visible unless you have privileges on them. As the operating user, you must set yourself as an administrator (granting all privileges), or configure role-based access control (see here.)
To grant administrator access visit your deployed instance once so a corresponding row in the
users
is created in the Postgres database.Set the
is_admin
field totrue
using your SSO email:UPDATE users SET is_admin=true WHERE email='person@yourdomain.com';
Wait five minutes for the cache to clear, or restart Telescope.
-
Build the TDLib Python JSON library
Follow the build instructions for the TDLib Python JSON library from the official TDLib documentation.
-
Copy TDLib to natives/
Copy the contents of
td/tdlib
to the following platform-specific folders:- Windows:
natives/windows
- Linux:
natives/linux
- macOS:
natives/darwin
The resulting paths should look like:
- Windows:
natives/windows/tdjson.dll
- Linux:
natives/linux/lib/libtdjson.so
- macOS:
natives/darwin/lib/libtdjson.dylib
- Windows:
-
Set up Python virtualenv
Remember to always activate the virtualenv before running Telescope.
virtualenv .venv . .venv/bin/activate python3 -m pip install -r requirements.txt
-
Set environment variables
Define the necessary environment variables as detailed in the Configuration section.
-
Development
See the development section for more details.
Currently the web UI is not built automatically by this repository's Dockerfile. In order to update the web UI, you must build a static export of the web UI repository and copy the contents of the out
folder to the telescope-webui-dist
folder in this repository. PRs to improve this process are welcome.
Telescope uses an RBAC system to manage user privileges, which are defined in the following Postgres tables:
-
roles
Maps role IDs to human readable names. -
users
When you first visit the application, a row is added to theusers
table using your SSO email. This account can be set asis_admin=true
, granting total permissions, or have one or more role IDs assigned using PostgreSQL array syntax (e.g.,{1, 2}
). -
telegram_groups
Maps Telegram group IDs to human readable names. -
telegram_accounts
Telegram accounts may be assigned one or more group IDs in thegroup
field. -
telegram_privileges
Assign specific privileges to roles for Telegram accounts within specific groups.
For example, to grant the sales
role (ID: 1) privileges on the sales
account group (ID: 1):
INSERT INTO telegram_privileges (group_id, role_id, privileges) VALUES (1, 1, '{"view", "login", "manage_connection_state"}');
But the management
role (ID: 2) may also have privileges on the sales
account group (ID: 1):
INSERT INTO telegram_privileges (group_id, role_id, privileges) VALUES (1, 2, '{"view", "login", "manage_connection_state", "remove_account"}');
Privileges are cached and refresh every five minutes. The current set of privileges are:
-
view
Whether this user may see this account at all.
-
edit_two_factor_password
Whether this user may edit the account's two-factor password.
-
login
Whether this user may retrieve the most recent authentication code for this account, allowing them to log in to Telegram with this account. (Note: There is currently no way to retrieve two-factor passwords, Telescope only uses them internally if provided.)
-
manage_connection_state
Whether this user may connect or disconnect Telescope's Telegram session for this account. Note that this does not clear the tdlib session token, so this will not count as authenticating again, rather, it is the same as closing and reopening your Telegram app on desktop.
-
remove_account
Whether this user may remove this account from Telegram (drop the row from the database).
On the Telegram production servers, if you authenticate on an account more than five times in a day - whether successful or not - you will not be able to authenticate again on that account for that day.
Unusual numbers of authentications, especially failed attempts, may risk your Telegram API key being banned. Telescope does not attempt to prevent this.
Note that restarting Telescope will not cause any accounts to authenticate again. Telegram session tokens are stored by tdlib in the accounts/
folder. Deleting that folder will cause all accounts to authenticate again.
Please use responsibly.
Telescope supports using the Telegram test environment during development.
-
Database:
Real Telegram accounts should not try to authenticate to the test environment. Instead, configure a separate DSN for testing.
-
Run test entry point:
Instead of running
main.py
, usetest.py
. -
Add test account:
Use the "Add Test Account" button in the web UI to automatically add a test account.
-
Note: You will likely not see the test account due to the default RBAC configuration lacking the VIEW privilege.
It will be visible if:
- You are in
SSO_MODE=MOCK
and the Telegram account is set totest@test.com
. - You are in
SSO_MODE=MOCK
and thetest@test.com
user hasis_admin
in theusers
table set totrue
. - You are in
SSO_MODE=MOCK
and you have configured RBAC privileges that would allow you to see the account. - You are in
SSO_MODE=cloudflare
and use Cloudflare Access during development. - You are in
SSO_MODE=disable
, so the RBAC system grants all privileges universally.
- You are in
-
-
Authenticate test account:
Telegram test accounts have authentication codes automatically set based on their phone number. The web UI will display each account's authentication code in the leftmost column of the main page.
Test accounts do not have two-factor passwords set by default, however, other Telegram developers may happen to use the same random phone number and set a two-factor password on it while testing. If you are prompted for a two-factor password, simply remove that account and add another one.
Similarly, test accounts may have inappropriate names set by third parties during their use of the Telegram test environment. As these servers are operated by the Telegram corporation, this is outside our control.
Telescope features a pluggable module system that allows for extending functionality. For example, the SaveContacts
module handles storing contacts.
Event types used in the @OnEvent
decorator come directly from the official TDLib API documentation.
Note: You may set LOG_ALL=True
at the top of tdlib.py
to dump all TDLib JSON messages if the TDLib documentation is insufficient or unclear.
Zellic makes no warranties, express or implied, regarding this project's performance or fitness for a particular purpose. Use at your own risk. We disclaim any liability for damages arising from improper use, software malfunction, or unforeseen consequences.