Tài liệu nhà phát triển
Tiếng Việt

Pabal API

Pabal API (MTProto)

Khi xây dựng client kết nối đến máy chủ theo cùng cách với ứng dụng: thông tin kết nối, khóa công khai của máy chủ, luồng xác thực, update và phạm vi hỗ trợ.

Ứng dụng Pabal giao tiếp với máy chủ bằng MTProto 2.0. Hãy đọc tài liệu này khi bạn xây dựng chương trình kết nối theo cùng cách đó — một ứng dụng khác, công cụ tự động hóa chạy bằng tài khoản người dùng, hay client phục vụ nghiên cứu. Nếu bạn tạo bot, Bot API đơn giản hơn là đủ dùng.

Hãy xem cả tài liệu của Telegram

Pabal tuân theo giao thức công khai của Telegram, nên định nghĩa chi tiết của giao thức và các phương thức lấy tài liệu MTProtophương thức API làm chuẩn. Tài liệu này ghi lại những điểm khác biệt và phạm vi hỗ trợ khi kết nối đến máy chủ Pabal.

Thông tin kết nối

MụcGiá trị
Địa chỉ122.34.175.215
Cổng8443 (TCP)
DCCả DC 1–5 đều cùng một địa chỉ. Kết nối vào DC nào cũng được, thường dùng DC 2
Giao thứcMTProto 2.0, API layer 216
Kiểu truyền tảiAbridged, Intermediate, Padded Intermediate, Full — mỗi kiểu đều có bản làm rối (obfuscated2)
Khóa công khai máy chủserver-key.pem · fingerprint 8724853375441383205
api_id · api_hashKhông được kiểm tra. Điền giá trị nào cũng được

Hiện chưa có truyền tải qua HTTP, WebSocket, cũng như MTProxy. Đồng hồ trên thiết bị client phải chính xác — số hiệu tin nhắn MTProto được tạo từ thời gian, nên nếu đồng hồ lệch nhiều, máy chủ sẽ bỏ các tin nhắn đó.

Khóa công khai của máy chủ

Khi kết nối lần đầu, client MTProto dùng khóa công khai RSA của máy chủ để mã hóa quá trình trao đổi khóa xác thực. Client Telegram có sẵn khóa công khai của Telegram bên trong, nên muốn kết nối đến Pabal thì phải nhúng khóa này thay vào (hoặc thêm vào). Chính khóa này ngăn máy chủ khác giả làm máy chủ Pabal.

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA4hH74xPQsUwr/pyXPdF4tVicYr6QbfeDrKC7mUOVrPLSL4FtmgGn
w+O4u6lVvOf3Udd1KY6+OL4fUZdMBlLzwsoGLoniiVR09dnvyXHE8LhQSS+i1LmI
oJbhQwXplLnUJf272fLXkD23e7ppKLkjYk+jeYObueCy5HYMSThklVeXEzbZVGZv
47o/mjU2vyFoRpa6wCIE4rpj1UIPtOMpekMI/TocIlGVJ+ch6cAVNxIDro53a1eG
/1oZRLQH4oViEGxeMMjBMY5gk5HPkZvjbqy4h8TjXEz7O5o0BRsSqG/OPtP/dRQV
X4ewPhj2WCU4e6l5X59ZKIcv4sQLOwClqQIDAQAB
-----END RSA PUBLIC KEY-----
curl -s -o server-key.pem https://pabal.me/docs/server-key.pem

Khóa này được tạo một lần khi máy chủ chạy lần đầu và không thay đổi. Hãy kiểm tra giá trị Loaded RSA key … (fingerprint …) trong log máy chủ có khớp với fingerprint ở trên không.

Kết nối bằng Telethon

Ví dụ dùng Telethon của Python để đăng nhập bằng tài khoản người dùng và nhắn tin qua lại. Hãy đăng ký tài khoản trong ứng dụng trước (xem bên dưới).

# pabal_client.py — pip install telethon==1.42.0
# Đặt server-key.pem (khóa công khai máy chủ đã tải ở trên) trong cùng thư mục
import asyncio

from telethon import TelegramClient, events
from telethon.crypto import rsa

rsa.add_key(open("server-key.pem").read(), old=False)          # khóa công khai của máy chủ Pabal

client = TelegramClient("pabal", api_id=1, api_hash="0" * 32)  # lưu trạng thái đăng nhập vào pabal.session
client.session.set_dc(2, "122.34.175.215", 8443)


@client.on(events.NewMessage(incoming=True))
async def show(event):
    sender = await event.get_sender()
    print(f"{sender.first_name}: {event.raw_text}")


async def main():
    await client.start(phone=lambda: input("Số điện thoại (+849…): "))   # nhập mã một lần đầu tiên
    me = await client.get_me()
    print(f"Đã đăng nhập: {me.first_name} (id {me.id})")
    await client.send_message("BotFather", "/help")
    await client.run_until_disconnected()


asyncio.run(main())
  • Hãy dùng Telethon 1.42. Đây là bản dùng layer 216. Các bản mới hơn cố đọc phản hồi theo layer cao hơn nên thất bại với TypeNotFoundError.
  • Telethon đã chặn việc đăng ký tài khoản mới (sign_up()). Hãy đăng ký trong ứng dụng, hoặc tự gọi auth.signUp.
  • Trạng thái đăng nhập được lưu vào tệp pabal.session, nên từ lần sau sẽ không hỏi mã nữa. Tệp này là chìa khóa của tài khoản, hãy giữ nó cẩn thận.

Luồng đăng nhập

1 · Khóa xác thực (một lần) req_pq_multi → req_DH_params set_client_DH_params Khóa xác thực 2048 bitBảo vệ bằng khóa công khai máy chủ 2 · Đăng nhập (mỗi khóa xác thực một lần) auth.sendCodeSố điện thoại sentCodeTypeSmsSMS hoặc quản trị viên chuyển SetUpEmailRequiredKiểu email → hỏi địa chỉ account.sendVerifyEmailCodepurpose: loginSetup auth.signInphone_code hoặc mã email auth.authorizationĐăng nhập xong authorizationSignUpRequiredSố mới → auth.signUp(tên) Khi nhận được mã
Tạo khóa xác thực, rồi đăng nhập bằng mã

Giải thích sơ đồ

  • Hai giai đoạn: phía trên là giai đoạn tạo khóa xác thực dùng để mã hóa (giao thức), phía dưới là giai đoạn đăng nhập gắn tài khoản vào khóa đó (API). Thư viện sẽ tự lo giai đoạn phía trên.
  • Trạng thái đăng nhập gắn với khóa xác thực: dù mở nhiều phiên bằng khóa đã đăng nhập, tất cả đều ở trạng thái đăng nhập. Nếu mất khóa (xóa tệp phiên) thì phải đăng nhập lại.
  • Mã được gửi theo đường nào là do người vận hành máy chủ quyết định: nếu là SMS hoặc quản trị viên chuyển thì nhận sentCodeTypeSms; nếu là email thì nhận sentCodeTypeSetUpEmailRequired, khi đó client hỏi địa chỉ email rồi gọi account.sendVerifyEmailCode (hàng giữa).
  • Nét đứt màu đỏ là đường của số mới: nếu mã đúng nhưng chưa có tài khoản, bạn nhận authorizationSignUpRequired; nhập tên và gọi auth.signUp là hoàn tất đăng ký. Chỉ đăng ký được sau khi đã nhập đúng mã.
  • Bot không đi qua giai đoạn phía dưới mà đăng nhập bằng một lần gọi auth.importBotAuthorization (token bot).
LỗiKhi nào
PHONE_NUMBER_INVALIDSố sai, hoặc là số mới trong lúc máy chủ đang đóng đăng ký mới
PHONE_NUMBER_BANNEDSố đã bị người vận hành chặn
FLOOD_WAIT_n (420)Yêu cầu mã quá thường xuyên. Thử lại sau n giây
PHONE_CODE_INVALIDMã sai (vượt quá số lần cho phép thì bị khóa)
PHONE_CODE_EXPIREDMã đã hết hạn hoặc bị khóa, hoặc phone_code_hash không xác định — bắt đầu lại từ sendCode
EMAIL_INVALID, EMAIL_NOT_ALLOWEDĐịa chỉ email sai / tài khoản đã tồn tại nhưng đây không phải email đăng nhập đã đăng ký
AUTH_KEY_UNREGISTERED (401)Gọi phương thức cần đăng nhập bằng khóa chưa đăng nhập
Số thử nghiệm

Trên máy chủ mà người vận hành bật số thử nghiệm, các số có dạng +99966XYYYY đăng nhập được bằng mã XXXXX (lặp X năm lần) mà không cần gửi mã thật. Tính năng này chỉ dùng cho máy chủ phát triển và bị tắt trên máy chủ vận hành thật.

Nhận update

  • Thời gian thực: khi kết nối đang mở, máy chủ gửi ngay tin nhắn mới, sửa, xóa dưới dạng updateShortMessage, updates. Phiên đã gửi request nhận kết quả qua phản hồi RPC, nên sẽ không nhận thêm một lần nữa qua thông báo đẩy.
  • pts: mỗi thay đổi của từng người dùng được gắn một số thứ tự (pts). Nếu pts nhận được có khoảng trống thì client đã bỏ lỡ điều gì đó.
  • Bắt kịp: ghi nhớ pts hiện tại bằng updates.getState, và khi kết nối lại thì dùng updates.getDifference(pts, date, qts) để nhận tin nhắn mới, lượt xóa trong khoảng đó cùng người dùng và nhóm liên quan. Nếu pts mà client đang giữ vượt trước máy chủ (ví dụ khi dữ liệu máy chủ đã bị khởi tạo lại), bạn sẽ nhận differenceTooLong, khi đó hãy tải lại danh sách trò chuyện.
  • Các thư viện như Telethon tự lo toàn bộ quá trình này.

ID và peer

Đối tượngIDGhi chú
NgườiTừ 100001peerUser. @BotFather là 100000
BotCùng hệ thống số với ngườiuser.bot = true. Dãy số trước token là ID của bot
Nhóm thườngTừ 1000001peerChat. Trong Bot API hiển thị là số âm (-chat_id)
Tin nhắnTừ 1 trong mỗi hộp thưTrong trò chuyện 1:1, mỗi người tham gia có bản sao và số hiệu riêng. Cùng một tin nhắn có thể mang số khác nhau đối với hai người

Hãy lưu nguyên giá trị access_hash mà máy chủ cấp để dùng về sau (nó đi kèm khi tra cứu tên người dùng, trong danh sách trò chuyện và trong update).

Tệp

  • Tải lên: tải từng phần bằng upload.saveFilePart và tham chiếu bằng inputFileUploaded…. Chưa có upload.saveBigFilePart cho tệp lớn, nên trên thực tế tối đa là 10MB.
  • Gửi: dùng messages.sendMedia với inputMediaUploadedPhoto (ảnh mới) hoặc inputMediaPhoto (ảnh đã có trên máy chủ). Các phương tiện khác trả về MEDIA_INVALID.
  • Nhận: dùng upload.getFile với inputPhotoFileLocation (ảnh trong tin nhắn), inputPeerPhotoFileLocation (ảnh đại diện). Tối đa 1MB mỗi lần.
  • Ảnh đại diện: photos.uploadProfilePhoto, photos.updateProfilePhoto, photos.getUserPhotos, photos.deletePhotos.
  • Ảnh chỉ được lưu ở một kích thước gốc (không tạo ảnh thu nhỏ riêng).

Phạm vi hỗ trợ

Máy chủ có bộ xử lý cho 408 phương thức của layer 216 và tất cả đều đọc được request, nhưng những phương thức đã được kiểm chứng trọn vẹn bằng client thật là các phương thức dưới đây. Các phương thức còn lại trả lời đúng định dạng nhưng nội dung có thể rỗng hoặc không được ghi lại.

Lĩnh vựcPhương thức đã kiểm chứng
Kết nốiinitConnection, invokeWithLayer, help.getConfig, auth.bindTempAuthKey (khóa tạm thời PFS), auth.exportAuthorization/importAuthorization
Đăng nhậpauth.sendCode, auth.signIn, auth.signUp, auth.logOut, auth.importBotAuthorization, account.sendVerifyEmailCode
Người dùng, danh bạusers.getUsers, users.getFullUser, contacts.resolveUsername, contacts.importContacts, contacts.search
Tin nhắnmessages.sendMessage, messages.sendMedia (ảnh), messages.getHistory, messages.getDialogs, messages.getMessages, messages.editMessage, messages.deleteMessages
Nhómmessages.createChat, messages.deleteChatUser, messages.editChatTitle (messages.addChatUser chỉ mới kiểm chứng bằng ứng dụng chính thức)
Botmessages.getBotCallbackAnswer, messages.setBotCallbackAnswer, tin nhắn có gắn nút (reply_markup)
Updateupdates.getState, updates.getDifference, thông báo đẩy thời gian thực
Tệp, ảnhupload.saveFilePart, upload.getFile, photos.* (ở trên)

Chúng tôi cũng đã kiểm chứng Telegram Desktop chính thức 6.2.6 hoạt động không cần sửa đổi, từ đăng ký, đăng nhập, trò chuyện, ảnh, nhóm cho đến kết nối lại. Khoảng 60 phương thức mà ứng dụng gọi khi khởi động được kiểm tra định dạng phản hồi riêng.

Lỗi

Lỗi được trả về dưới dạng rpc_error chuẩn (error_code + error_message). error_message luôn có dạng chữ hoa, chữ số và dấu gạch dưới (PEER_ID_INVALID), và khi cần sẽ có thêm : mô tả phía sau.

Ý nghĩa
400Request sai — PEER_ID_INVALID, MESSAGE_ID_INVALID, MEDIA_INVALID, USERNAME_NOT_OCCUPIED
401Cần đăng nhập — AUTH_KEY_UNREGISTERED
403Không có quyền — ví dụ nhóm mà bạn không phải thành viên
420FLOOD_WAIT_n — chờ n giây
500Lỗi nội bộ máy chủ
Lỗi truyền tải -404Máy chủ không biết khóa xác thực này — tạo khóa mới rồi đăng nhập lại (khóa vĩnh viễn) hoặc gắn lại (khóa tạm thời)

Những gì chưa có

  • Kênh và siêu nhóm (channels.* có trả lời nhưng không hiển thị đúng trong ứng dụng), trò chuyện bí mật, cuộc gọi
  • Phương tiện ngoài ảnh, upload.saveBigFilePart, ảnh thu nhỏ
  • Xác minh hai bước (SRP) — không thể thiết lập, và các thao tác cần xác minh hai bước đều bị từ chối
  • Truyền tải qua HTTP và WebSocket, MTProxy, gửi msgs_ack, thay bad_server_salt
  • Chia ra nhiều máy chủ — một máy chủ đảm nhận cả DC 1–5

Để kết nối ứng dụng Telegram chính thức với Pabal

Ứng dụng Telegram nhúng địa chỉ máy chủ và khóa công khai vào bên trong lúc build. Vì vậy không đổi được trong màn hình cài đặt mà phải sửa mã nguồn rồi build lại. Ứng dụng Pabal (Pabal.app) chính là được làm như vậy. Nếu bạn là người vận hành máy chủ, hãy xem Cài đặt máy chủ — kết nối ứng dụng.