Merge commit 'ed20a51ed2067053e59ad30d2688350a4c5df88e'

This commit is contained in:
Isaac 2025-04-04 22:17:32 +04:00
commit f0bb504b6c
716 changed files with 217504 additions and 6 deletions

View File

@ -753,13 +753,13 @@ public final class OngoingGroupCallContext {
statsLogPath: tempStatsLogPath,
audioDevice: nil,
isConference: isConference,
isActiveByDefault: true,
isActiveByDefault: audioIsActiveByDefault,
encryptDecrypt: encryptionContext.flatMap { encryptionContext in
return { data, isEncrypt in
return { data, userId, isEncrypt in
if isEncrypt {
return encryptionContext.encrypt(data)
return encryptionContext.encrypt(message: data)
} else {
return encryptionContext.decrypt(data)
return encryptionContext.decrypt(message: data, userId: userId)
}
}
}
@ -899,7 +899,6 @@ public final class OngoingGroupCallContext {
}
return OngoingGroupCallRequestedVideoChannel(
audioSsrc: channel.audioSsrc,
userId: channel.peerId,
endpointId: channel.endpointId,
ssrcGroups: channel.ssrcGroups.map { group in
return OngoingGroupCallSsrcGroup(

View File

@ -74,8 +74,9 @@ public final class OngoingCallContextPresentationCallVideoView {
public final class OngoingCallVideoCapturer {
public let impl: OngoingCallThreadLocalContextVideoCapturer
public let deviceId: String
public init(_ deviceId: String = "", keepLandscape: Bool = true) {
self.deviceId = deviceId
self.impl = OngoingCallThreadLocalContextVideoCapturer(deviceId: deviceId, keepLandscape: keepLandscape)
}

28
third-party/td/TdBinding/Package.swift vendored Normal file
View File

@ -0,0 +1,28 @@
// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "TdBinding",
platforms: [
.macOS(.v10_13)
],
products: [
.library(
name: "TdBinding",
targets: ["TdBinding"]),
],
targets: [
.target(
name: "TdBinding",
dependencies: [],
path: ".",
publicHeadersPath: "Public",
cxxSettings: [
.headerSearchPath("SharedHeaders/td/tde2e"),
]),
],
cxxLanguageStandard: .cxx20
)

View File

@ -0,0 +1,9 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "td/telegram/td_json_client.h"
#include "td/telegram/td_log.h"

View File

@ -0,0 +1,27 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include <array>
#include <cstddef>
#include <functional>
constexpr std::size_t BACKTRACE_SHIFT = 1;
constexpr std::size_t BACKTRACE_HASHED_LENGTH = 6;
constexpr std::size_t BACKTRACE_LENGTH = 10;
using Backtrace = std::array<void *, BACKTRACE_LENGTH>;
struct AllocInfo {
Backtrace backtrace;
std::size_t size;
};
bool is_memprof_on();
std::size_t get_ht_size();
double get_fast_backtrace_success_rate();
void dump_alloc(const std::function<void(const AllocInfo &)> &func);
std::size_t get_used_memory_size();

View File

@ -0,0 +1,13 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include <cstddef>
bool is_memprof_on();
std::size_t get_used_memory_size();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,650 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef SQLITE3EXT_H
#define SQLITE3EXT_H
#include "sqlite3.h"
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each other's shared
** libraries!
*/
struct tdsqlite3_api_routines {
void * (*aggregate_context)(tdsqlite3_context*,int nBytes);
int (*aggregate_count)(tdsqlite3_context*);
int (*bind_blob)(tdsqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(tdsqlite3_stmt*,int,double);
int (*bind_int)(tdsqlite3_stmt*,int,int);
int (*bind_int64)(tdsqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(tdsqlite3_stmt*,int);
int (*bind_parameter_count)(tdsqlite3_stmt*);
int (*bind_parameter_index)(tdsqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(tdsqlite3_stmt*,int);
int (*bind_text)(tdsqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(tdsqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(tdsqlite3_stmt*,int,const tdsqlite3_value*);
int (*busy_handler)(tdsqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(tdsqlite3*,int ms);
int (*changes)(tdsqlite3*);
int (*close)(tdsqlite3*);
int (*collation_needed)(tdsqlite3*,void*,void(*)(void*,tdsqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(tdsqlite3*,void*,void(*)(void*,tdsqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(tdsqlite3_stmt*,int iCol);
int (*column_bytes)(tdsqlite3_stmt*,int iCol);
int (*column_bytes16)(tdsqlite3_stmt*,int iCol);
int (*column_count)(tdsqlite3_stmt*pStmt);
const char * (*column_database_name)(tdsqlite3_stmt*,int);
const void * (*column_database_name16)(tdsqlite3_stmt*,int);
const char * (*column_decltype)(tdsqlite3_stmt*,int i);
const void * (*column_decltype16)(tdsqlite3_stmt*,int);
double (*column_double)(tdsqlite3_stmt*,int iCol);
int (*column_int)(tdsqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(tdsqlite3_stmt*,int iCol);
const char * (*column_name)(tdsqlite3_stmt*,int);
const void * (*column_name16)(tdsqlite3_stmt*,int);
const char * (*column_origin_name)(tdsqlite3_stmt*,int);
const void * (*column_origin_name16)(tdsqlite3_stmt*,int);
const char * (*column_table_name)(tdsqlite3_stmt*,int);
const void * (*column_table_name16)(tdsqlite3_stmt*,int);
const unsigned char * (*column_text)(tdsqlite3_stmt*,int iCol);
const void * (*column_text16)(tdsqlite3_stmt*,int iCol);
int (*column_type)(tdsqlite3_stmt*,int iCol);
tdsqlite3_value* (*column_value)(tdsqlite3_stmt*,int iCol);
void * (*commit_hook)(tdsqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(tdsqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(tdsqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(tdsqlite3*,const char*,int,int,void*,
void (*xFunc)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xStep)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xFinal)(tdsqlite3_context*));
int (*create_function16)(tdsqlite3*,const void*,int,int,void*,
void (*xFunc)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xStep)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xFinal)(tdsqlite3_context*));
int (*create_module)(tdsqlite3*,const char*,const tdsqlite3_module*,void*);
int (*data_count)(tdsqlite3_stmt*pStmt);
tdsqlite3 * (*db_handle)(tdsqlite3_stmt*);
int (*declare_vtab)(tdsqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(tdsqlite3*db);
const char * (*errmsg)(tdsqlite3*);
const void * (*errmsg16)(tdsqlite3*);
int (*exec)(tdsqlite3*,const char*,tdsqlite3_callback,void*,char**);
int (*expired)(tdsqlite3_stmt*);
int (*finalize)(tdsqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(tdsqlite3*);
void * (*get_auxdata)(tdsqlite3_context*,int);
int (*get_table)(tdsqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(tdsqlite3*);
sqlite_int64 (*last_insert_rowid)(tdsqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,tdsqlite3**);
int (*open16)(const void*,tdsqlite3**);
int (*prepare)(tdsqlite3*,const char*,int,tdsqlite3_stmt**,const char**);
int (*prepare16)(tdsqlite3*,const void*,int,tdsqlite3_stmt**,const void**);
void * (*profile)(tdsqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(tdsqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(tdsqlite3_stmt*pStmt);
void (*result_blob)(tdsqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(tdsqlite3_context*,double);
void (*result_error)(tdsqlite3_context*,const char*,int);
void (*result_error16)(tdsqlite3_context*,const void*,int);
void (*result_int)(tdsqlite3_context*,int);
void (*result_int64)(tdsqlite3_context*,sqlite_int64);
void (*result_null)(tdsqlite3_context*);
void (*result_text)(tdsqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(tdsqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(tdsqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(tdsqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(tdsqlite3_context*,tdsqlite3_value*);
void * (*rollback_hook)(tdsqlite3*,void(*)(void*),void*);
int (*set_authorizer)(tdsqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(tdsqlite3_context*,int,void*,void (*)(void*));
char * (*xsnprintf)(int,char*,const char*,...);
int (*step)(tdsqlite3_stmt*);
int (*table_column_metadata)(tdsqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(tdsqlite3*);
void * (*trace)(tdsqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(tdsqlite3_stmt*,tdsqlite3_stmt*);
void * (*update_hook)(tdsqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(tdsqlite3_context*);
const void * (*value_blob)(tdsqlite3_value*);
int (*value_bytes)(tdsqlite3_value*);
int (*value_bytes16)(tdsqlite3_value*);
double (*value_double)(tdsqlite3_value*);
int (*value_int)(tdsqlite3_value*);
sqlite_int64 (*value_int64)(tdsqlite3_value*);
int (*value_numeric_type)(tdsqlite3_value*);
const unsigned char * (*value_text)(tdsqlite3_value*);
const void * (*value_text16)(tdsqlite3_value*);
const void * (*value_text16be)(tdsqlite3_value*);
const void * (*value_text16le)(tdsqlite3_value*);
int (*value_type)(tdsqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(tdsqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(tdsqlite3*,const char*,int,tdsqlite3_stmt**,const char**);
int (*prepare16_v2)(tdsqlite3*,const void*,int,tdsqlite3_stmt**,const void**);
int (*clear_bindings)(tdsqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(tdsqlite3*,const char*,const tdsqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(tdsqlite3_stmt*,int,int);
int (*blob_bytes)(tdsqlite3_blob*);
int (*blob_close)(tdsqlite3_blob*);
int (*blob_open)(tdsqlite3*,const char*,const char*,const char*,tdsqlite3_int64,
int,tdsqlite3_blob**);
int (*blob_read)(tdsqlite3_blob*,void*,int,int);
int (*blob_write)(tdsqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(tdsqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(tdsqlite3*,const char*,int,void*);
tdsqlite3_int64 (*memory_highwater)(int);
tdsqlite3_int64 (*memory_used)(void);
tdsqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(tdsqlite3_mutex*);
void (*mutex_free)(tdsqlite3_mutex*);
void (*mutex_leave)(tdsqlite3_mutex*);
int (*mutex_try)(tdsqlite3_mutex*);
int (*open_v2)(const char*,tdsqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(tdsqlite3_context*);
void (*result_error_toobig)(tdsqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
tdsqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(tdsqlite3_vfs*,int);
int (*vfs_unregister)(tdsqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(tdsqlite3_context*,int);
void (*result_error_code)(tdsqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
tdsqlite3 *(*context_db_handle)(tdsqlite3_context*);
int (*extended_result_codes)(tdsqlite3*,int);
int (*limit)(tdsqlite3*,int,int);
tdsqlite3_stmt *(*next_stmt)(tdsqlite3*,tdsqlite3_stmt*);
const char *(*sql)(tdsqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(tdsqlite3_backup*);
tdsqlite3_backup *(*backup_init)(tdsqlite3*,const char*,tdsqlite3*,const char*);
int (*backup_pagecount)(tdsqlite3_backup*);
int (*backup_remaining)(tdsqlite3_backup*);
int (*backup_step)(tdsqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(tdsqlite3*,const char*,int,int,void*,
void (*xFunc)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xStep)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xFinal)(tdsqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(tdsqlite3*,int,...);
tdsqlite3_mutex *(*db_mutex)(tdsqlite3*);
int (*db_status)(tdsqlite3*,int,int*,int*,int);
int (*extended_errcode)(tdsqlite3*);
void (*log)(int,const char*,...);
tdsqlite3_int64 (*soft_heap_limit64)(tdsqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(tdsqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(tdsqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(tdsqlite3*,int);
int (*wal_checkpoint)(tdsqlite3*,const char*);
void *(*wal_hook)(tdsqlite3*,int(*)(void*,tdsqlite3*,const char*,int),void*);
int (*blob_reopen)(tdsqlite3_blob*,tdsqlite3_int64);
int (*vtab_config)(tdsqlite3*,int op,...);
int (*vtab_on_conflict)(tdsqlite3*);
/* Version 3.7.16 and later */
int (*close_v2)(tdsqlite3*);
const char *(*db_filename)(tdsqlite3*,const char*);
int (*db_readonly)(tdsqlite3*,const char*);
int (*db_release_memory)(tdsqlite3*);
const char *(*errstr)(int);
int (*stmt_busy)(tdsqlite3_stmt*);
int (*stmt_readonly)(tdsqlite3_stmt*);
int (*stricmp)(const char*,const char*);
int (*uri_boolean)(const char*,const char*,int);
tdsqlite3_int64 (*uri_int64)(const char*,const char*,tdsqlite3_int64);
const char *(*uri_parameter)(const char*,const char*);
char *(*xvsnprintf)(int,char*,const char*,va_list);
int (*wal_checkpoint_v2)(tdsqlite3*,const char*,int,int*,int*);
/* Version 3.8.7 and later */
int (*auto_extension)(void(*)(void));
int (*bind_blob64)(tdsqlite3_stmt*,int,const void*,tdsqlite3_uint64,
void(*)(void*));
int (*bind_text64)(tdsqlite3_stmt*,int,const char*,tdsqlite3_uint64,
void(*)(void*),unsigned char);
int (*cancel_auto_extension)(void(*)(void));
int (*load_extension)(tdsqlite3*,const char*,const char*,char**);
void *(*malloc64)(tdsqlite3_uint64);
tdsqlite3_uint64 (*msize)(void*);
void *(*realloc64)(void*,tdsqlite3_uint64);
void (*reset_auto_extension)(void);
void (*result_blob64)(tdsqlite3_context*,const void*,tdsqlite3_uint64,
void(*)(void*));
void (*result_text64)(tdsqlite3_context*,const char*,tdsqlite3_uint64,
void(*)(void*), unsigned char);
int (*strglob)(const char*,const char*);
/* Version 3.8.11 and later */
tdsqlite3_value *(*value_dup)(const tdsqlite3_value*);
void (*value_free)(tdsqlite3_value*);
int (*result_zeroblob64)(tdsqlite3_context*,tdsqlite3_uint64);
int (*bind_zeroblob64)(tdsqlite3_stmt*, int, tdsqlite3_uint64);
/* Version 3.9.0 and later */
unsigned int (*value_subtype)(tdsqlite3_value*);
void (*result_subtype)(tdsqlite3_context*,unsigned int);
/* Version 3.10.0 and later */
int (*status64)(int,tdsqlite3_int64*,tdsqlite3_int64*,int);
int (*strlike)(const char*,const char*,unsigned int);
int (*db_cacheflush)(tdsqlite3*);
/* Version 3.12.0 and later */
int (*system_errno)(tdsqlite3*);
/* Version 3.14.0 and later */
int (*trace_v2)(tdsqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*);
char *(*expanded_sql)(tdsqlite3_stmt*);
/* Version 3.18.0 and later */
void (*set_last_insert_rowid)(tdsqlite3*,tdsqlite3_int64);
/* Version 3.20.0 and later */
int (*prepare_v3)(tdsqlite3*,const char*,int,unsigned int,
tdsqlite3_stmt**,const char**);
int (*prepare16_v3)(tdsqlite3*,const void*,int,unsigned int,
tdsqlite3_stmt**,const void**);
int (*bind_pointer)(tdsqlite3_stmt*,int,void*,const char*,void(*)(void*));
void (*result_pointer)(tdsqlite3_context*,void*,const char*,void(*)(void*));
void *(*value_pointer)(tdsqlite3_value*,const char*);
int (*vtab_nochange)(tdsqlite3_context*);
int (*value_nochange)(tdsqlite3_value*);
const char *(*vtab_collation)(tdsqlite3_index_info*,int);
/* Version 3.24.0 and later */
int (*keyword_count)(void);
int (*keyword_name)(int,const char**,int*);
int (*keyword_check)(const char*,int);
tdsqlite3_str *(*str_new)(tdsqlite3*);
char *(*str_finish)(tdsqlite3_str*);
void (*str_appendf)(tdsqlite3_str*, const char *zFormat, ...);
void (*str_vappendf)(tdsqlite3_str*, const char *zFormat, va_list);
void (*str_append)(tdsqlite3_str*, const char *zIn, int N);
void (*str_appendall)(tdsqlite3_str*, const char *zIn);
void (*str_appendchar)(tdsqlite3_str*, int N, char C);
void (*str_reset)(tdsqlite3_str*);
int (*str_errcode)(tdsqlite3_str*);
int (*str_length)(tdsqlite3_str*);
char *(*str_value)(tdsqlite3_str*);
/* Version 3.25.0 and later */
int (*create_window_function)(tdsqlite3*,const char*,int,int,void*,
void (*xStep)(tdsqlite3_context*,int,tdsqlite3_value**),
void (*xFinal)(tdsqlite3_context*),
void (*xValue)(tdsqlite3_context*),
void (*xInv)(tdsqlite3_context*,int,tdsqlite3_value**),
void(*xDestroy)(void*));
/* Version 3.26.0 and later */
const char *(*normalized_sql)(tdsqlite3_stmt*);
/* Version 3.28.0 and later */
int (*stmt_isexplain)(tdsqlite3_stmt*);
int (*value_frombind)(tdsqlite3_value*);
/* Version 3.30.0 and later */
int (*drop_modules)(tdsqlite3*,const char**);
/* Version 3.31.0 and later */
tdsqlite3_int64 (*hard_heap_limit64)(tdsqlite3_int64);
const char *(*uri_key)(const char*,int);
const char *(*filename_database)(const char*);
const char *(*filename_journal)(const char*);
const char *(*filename_wal)(const char*);
};
/*
** This is the function signature used for all extension entry points. It
** is also defined in the file "loadext.c".
*/
typedef int (*tdsqlite3_loadext_entry)(
tdsqlite3 *db, /* Handle to the database. */
char **pzErrMsg, /* Used to set error string on failure. */
const tdsqlite3_api_routines *pThunk /* Extension API function pointers. */
);
/*
** The following macros redefine the API routines so that they are
** redirected through the global tdsqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the tdsqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
#define tdsqlite3_aggregate_context tdsqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define tdsqlite3_aggregate_count tdsqlite3_api->aggregate_count
#endif
#define tdsqlite3_bind_blob tdsqlite3_api->bind_blob
#define tdsqlite3_bind_double tdsqlite3_api->bind_double
#define tdsqlite3_bind_int tdsqlite3_api->bind_int
#define tdsqlite3_bind_int64 tdsqlite3_api->bind_int64
#define tdsqlite3_bind_null tdsqlite3_api->bind_null
#define tdsqlite3_bind_parameter_count tdsqlite3_api->bind_parameter_count
#define tdsqlite3_bind_parameter_index tdsqlite3_api->bind_parameter_index
#define tdsqlite3_bind_parameter_name tdsqlite3_api->bind_parameter_name
#define tdsqlite3_bind_text tdsqlite3_api->bind_text
#define tdsqlite3_bind_text16 tdsqlite3_api->bind_text16
#define tdsqlite3_bind_value tdsqlite3_api->bind_value
#define tdsqlite3_busy_handler tdsqlite3_api->busy_handler
#define tdsqlite3_busy_timeout tdsqlite3_api->busy_timeout
#define tdsqlite3_changes tdsqlite3_api->changes
#define tdsqlite3_close tdsqlite3_api->close
#define tdsqlite3_collation_needed tdsqlite3_api->collation_needed
#define tdsqlite3_collation_needed16 tdsqlite3_api->collation_needed16
#define tdsqlite3_column_blob tdsqlite3_api->column_blob
#define tdsqlite3_column_bytes tdsqlite3_api->column_bytes
#define tdsqlite3_column_bytes16 tdsqlite3_api->column_bytes16
#define tdsqlite3_column_count tdsqlite3_api->column_count
#define tdsqlite3_column_database_name tdsqlite3_api->column_database_name
#define tdsqlite3_column_database_name16 tdsqlite3_api->column_database_name16
#define tdsqlite3_column_decltype tdsqlite3_api->column_decltype
#define tdsqlite3_column_decltype16 tdsqlite3_api->column_decltype16
#define tdsqlite3_column_double tdsqlite3_api->column_double
#define tdsqlite3_column_int tdsqlite3_api->column_int
#define tdsqlite3_column_int64 tdsqlite3_api->column_int64
#define tdsqlite3_column_name tdsqlite3_api->column_name
#define tdsqlite3_column_name16 tdsqlite3_api->column_name16
#define tdsqlite3_column_origin_name tdsqlite3_api->column_origin_name
#define tdsqlite3_column_origin_name16 tdsqlite3_api->column_origin_name16
#define tdsqlite3_column_table_name tdsqlite3_api->column_table_name
#define tdsqlite3_column_table_name16 tdsqlite3_api->column_table_name16
#define tdsqlite3_column_text tdsqlite3_api->column_text
#define tdsqlite3_column_text16 tdsqlite3_api->column_text16
#define tdsqlite3_column_type tdsqlite3_api->column_type
#define tdsqlite3_column_value tdsqlite3_api->column_value
#define tdsqlite3_commit_hook tdsqlite3_api->commit_hook
#define tdsqlite3_complete tdsqlite3_api->complete
#define tdsqlite3_complete16 tdsqlite3_api->complete16
#define tdsqlite3_create_collation tdsqlite3_api->create_collation
#define tdsqlite3_create_collation16 tdsqlite3_api->create_collation16
#define tdsqlite3_create_function tdsqlite3_api->create_function
#define tdsqlite3_create_function16 tdsqlite3_api->create_function16
#define tdsqlite3_create_module tdsqlite3_api->create_module
#define tdsqlite3_create_module_v2 tdsqlite3_api->create_module_v2
#define tdsqlite3_data_count tdsqlite3_api->data_count
#define tdsqlite3_db_handle tdsqlite3_api->db_handle
#define tdsqlite3_declare_vtab tdsqlite3_api->declare_vtab
#define tdsqlite3_enable_shared_cache tdsqlite3_api->enable_shared_cache
#define tdsqlite3_errcode tdsqlite3_api->errcode
#define tdsqlite3_errmsg tdsqlite3_api->errmsg
#define tdsqlite3_errmsg16 tdsqlite3_api->errmsg16
#define tdsqlite3_exec tdsqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define tdsqlite3_expired tdsqlite3_api->expired
#endif
#define tdsqlite3_finalize tdsqlite3_api->finalize
#define tdsqlite3_free tdsqlite3_api->free
#define tdsqlite3_free_table tdsqlite3_api->free_table
#define tdsqlite3_get_autocommit tdsqlite3_api->get_autocommit
#define tdsqlite3_get_auxdata tdsqlite3_api->get_auxdata
#define tdsqlite3_get_table tdsqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define tdsqlite3_global_recover tdsqlite3_api->global_recover
#endif
#define tdsqlite3_interrupt tdsqlite3_api->interruptx
#define tdsqlite3_last_insert_rowid tdsqlite3_api->last_insert_rowid
#define tdsqlite3_libversion tdsqlite3_api->libversion
#define tdsqlite3_libversion_number tdsqlite3_api->libversion_number
#define tdsqlite3_malloc tdsqlite3_api->malloc
#define tdsqlite3_mprintf tdsqlite3_api->mprintf
#define tdsqlite3_open tdsqlite3_api->open
#define tdsqlite3_open16 tdsqlite3_api->open16
#define tdsqlite3_prepare tdsqlite3_api->prepare
#define tdsqlite3_prepare16 tdsqlite3_api->prepare16
#define tdsqlite3_prepare_v2 tdsqlite3_api->prepare_v2
#define tdsqlite3_prepare16_v2 tdsqlite3_api->prepare16_v2
#define tdsqlite3_profile tdsqlite3_api->profile
#define tdsqlite3_progress_handler tdsqlite3_api->progress_handler
#define tdsqlite3_realloc tdsqlite3_api->realloc
#define tdsqlite3_reset tdsqlite3_api->reset
#define tdsqlite3_result_blob tdsqlite3_api->result_blob
#define tdsqlite3_result_double tdsqlite3_api->result_double
#define tdsqlite3_result_error tdsqlite3_api->result_error
#define tdsqlite3_result_error16 tdsqlite3_api->result_error16
#define tdsqlite3_result_int tdsqlite3_api->result_int
#define tdsqlite3_result_int64 tdsqlite3_api->result_int64
#define tdsqlite3_result_null tdsqlite3_api->result_null
#define tdsqlite3_result_text tdsqlite3_api->result_text
#define tdsqlite3_result_text16 tdsqlite3_api->result_text16
#define tdsqlite3_result_text16be tdsqlite3_api->result_text16be
#define tdsqlite3_result_text16le tdsqlite3_api->result_text16le
#define tdsqlite3_result_value tdsqlite3_api->result_value
#define tdsqlite3_rollback_hook tdsqlite3_api->rollback_hook
#define tdsqlite3_set_authorizer tdsqlite3_api->set_authorizer
#define tdsqlite3_set_auxdata tdsqlite3_api->set_auxdata
#define tdsqlite3_snprintf tdsqlite3_api->xsnprintf
#define tdsqlite3_step tdsqlite3_api->step
#define tdsqlite3_table_column_metadata tdsqlite3_api->table_column_metadata
#define tdsqlite3_thread_cleanup tdsqlite3_api->thread_cleanup
#define tdsqlite3_total_changes tdsqlite3_api->total_changes
#define tdsqlite3_trace tdsqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define tdsqlite3_transfer_bindings tdsqlite3_api->transfer_bindings
#endif
#define tdsqlite3_update_hook tdsqlite3_api->update_hook
#define tdsqlite3_user_data tdsqlite3_api->user_data
#define tdsqlite3_value_blob tdsqlite3_api->value_blob
#define tdsqlite3_value_bytes tdsqlite3_api->value_bytes
#define tdsqlite3_value_bytes16 tdsqlite3_api->value_bytes16
#define tdsqlite3_value_double tdsqlite3_api->value_double
#define tdsqlite3_value_int tdsqlite3_api->value_int
#define tdsqlite3_value_int64 tdsqlite3_api->value_int64
#define tdsqlite3_value_numeric_type tdsqlite3_api->value_numeric_type
#define tdsqlite3_value_text tdsqlite3_api->value_text
#define tdsqlite3_value_text16 tdsqlite3_api->value_text16
#define tdsqlite3_value_text16be tdsqlite3_api->value_text16be
#define tdsqlite3_value_text16le tdsqlite3_api->value_text16le
#define tdsqlite3_value_type tdsqlite3_api->value_type
#define tdsqlite3_vmprintf tdsqlite3_api->vmprintf
#define tdsqlite3_vsnprintf tdsqlite3_api->xvsnprintf
#define tdsqlite3_overload_function tdsqlite3_api->overload_function
#define tdsqlite3_prepare_v2 tdsqlite3_api->prepare_v2
#define tdsqlite3_prepare16_v2 tdsqlite3_api->prepare16_v2
#define tdsqlite3_clear_bindings tdsqlite3_api->clear_bindings
#define tdsqlite3_bind_zeroblob tdsqlite3_api->bind_zeroblob
#define tdsqlite3_blob_bytes tdsqlite3_api->blob_bytes
#define tdsqlite3_blob_close tdsqlite3_api->blob_close
#define tdsqlite3_blob_open tdsqlite3_api->blob_open
#define tdsqlite3_blob_read tdsqlite3_api->blob_read
#define tdsqlite3_blob_write tdsqlite3_api->blob_write
#define tdsqlite3_create_collation_v2 tdsqlite3_api->create_collation_v2
#define tdsqlite3_file_control tdsqlite3_api->file_control
#define tdsqlite3_memory_highwater tdsqlite3_api->memory_highwater
#define tdsqlite3_memory_used tdsqlite3_api->memory_used
#define tdsqlite3_mutex_alloc tdsqlite3_api->mutex_alloc
#define tdsqlite3_mutex_enter tdsqlite3_api->mutex_enter
#define tdsqlite3_mutex_free tdsqlite3_api->mutex_free
#define tdsqlite3_mutex_leave tdsqlite3_api->mutex_leave
#define tdsqlite3_mutex_try tdsqlite3_api->mutex_try
#define tdsqlite3_open_v2 tdsqlite3_api->open_v2
#define tdsqlite3_release_memory tdsqlite3_api->release_memory
#define tdsqlite3_result_error_nomem tdsqlite3_api->result_error_nomem
#define tdsqlite3_result_error_toobig tdsqlite3_api->result_error_toobig
#define tdsqlite3_sleep tdsqlite3_api->sleep
#define tdsqlite3_soft_heap_limit tdsqlite3_api->soft_heap_limit
#define tdsqlite3_vfs_find tdsqlite3_api->vfs_find
#define tdsqlite3_vfs_register tdsqlite3_api->vfs_register
#define tdsqlite3_vfs_unregister tdsqlite3_api->vfs_unregister
#define tdsqlite3_threadsafe tdsqlite3_api->xthreadsafe
#define tdsqlite3_result_zeroblob tdsqlite3_api->result_zeroblob
#define tdsqlite3_result_error_code tdsqlite3_api->result_error_code
#define tdsqlite3_test_control tdsqlite3_api->test_control
#define tdsqlite3_randomness tdsqlite3_api->randomness
#define tdsqlite3_context_db_handle tdsqlite3_api->context_db_handle
#define tdsqlite3_extended_result_codes tdsqlite3_api->extended_result_codes
#define tdsqlite3_limit tdsqlite3_api->limit
#define tdsqlite3_next_stmt tdsqlite3_api->next_stmt
#define tdsqlite3_sql tdsqlite3_api->sql
#define tdsqlite3_status tdsqlite3_api->status
#define tdsqlite3_backup_finish tdsqlite3_api->backup_finish
#define tdsqlite3_backup_init tdsqlite3_api->backup_init
#define tdsqlite3_backup_pagecount tdsqlite3_api->backup_pagecount
#define tdsqlite3_backup_remaining tdsqlite3_api->backup_remaining
#define tdsqlite3_backup_step tdsqlite3_api->backup_step
#define tdsqlite3_compileoption_get tdsqlite3_api->compileoption_get
#define tdsqlite3_compileoption_used tdsqlite3_api->compileoption_used
#define tdsqlite3_create_function_v2 tdsqlite3_api->create_function_v2
#define tdsqlite3_db_config tdsqlite3_api->db_config
#define tdsqlite3_db_mutex tdsqlite3_api->db_mutex
#define tdsqlite3_db_status tdsqlite3_api->db_status
#define tdsqlite3_extended_errcode tdsqlite3_api->extended_errcode
#define tdsqlite3_log tdsqlite3_api->log
#define tdsqlite3_soft_heap_limit64 tdsqlite3_api->soft_heap_limit64
#define tdsqlite3_sourceid tdsqlite3_api->sourceid
#define tdsqlite3_stmt_status tdsqlite3_api->stmt_status
#define tdsqlite3_strnicmp tdsqlite3_api->strnicmp
#define tdsqlite3_unlock_notify tdsqlite3_api->unlock_notify
#define tdsqlite3_wal_autocheckpoint tdsqlite3_api->wal_autocheckpoint
#define tdsqlite3_wal_checkpoint tdsqlite3_api->wal_checkpoint
#define tdsqlite3_wal_hook tdsqlite3_api->wal_hook
#define tdsqlite3_blob_reopen tdsqlite3_api->blob_reopen
#define tdsqlite3_vtab_config tdsqlite3_api->vtab_config
#define tdsqlite3_vtab_on_conflict tdsqlite3_api->vtab_on_conflict
/* Version 3.7.16 and later */
#define tdsqlite3_close_v2 tdsqlite3_api->close_v2
#define tdsqlite3_db_filename tdsqlite3_api->db_filename
#define tdsqlite3_db_readonly tdsqlite3_api->db_readonly
#define tdsqlite3_db_release_memory tdsqlite3_api->db_release_memory
#define tdsqlite3_errstr tdsqlite3_api->errstr
#define tdsqlite3_stmt_busy tdsqlite3_api->stmt_busy
#define tdsqlite3_stmt_readonly tdsqlite3_api->stmt_readonly
#define tdsqlite3_stricmp tdsqlite3_api->stricmp
#define tdsqlite3_uri_boolean tdsqlite3_api->uri_boolean
#define tdsqlite3_uri_int64 tdsqlite3_api->uri_int64
#define tdsqlite3_uri_parameter tdsqlite3_api->uri_parameter
#define tdsqlite3_uri_vsnprintf tdsqlite3_api->xvsnprintf
#define tdsqlite3_wal_checkpoint_v2 tdsqlite3_api->wal_checkpoint_v2
/* Version 3.8.7 and later */
#define tdsqlite3_auto_extension tdsqlite3_api->auto_extension
#define tdsqlite3_bind_blob64 tdsqlite3_api->bind_blob64
#define tdsqlite3_bind_text64 tdsqlite3_api->bind_text64
#define tdsqlite3_cancel_auto_extension tdsqlite3_api->cancel_auto_extension
#define tdsqlite3_load_extension tdsqlite3_api->load_extension
#define tdsqlite3_malloc64 tdsqlite3_api->malloc64
#define tdsqlite3_msize tdsqlite3_api->msize
#define tdsqlite3_realloc64 tdsqlite3_api->realloc64
#define tdsqlite3_reset_auto_extension tdsqlite3_api->reset_auto_extension
#define tdsqlite3_result_blob64 tdsqlite3_api->result_blob64
#define tdsqlite3_result_text64 tdsqlite3_api->result_text64
#define tdsqlite3_strglob tdsqlite3_api->strglob
/* Version 3.8.11 and later */
#define tdsqlite3_value_dup tdsqlite3_api->value_dup
#define tdsqlite3_value_free tdsqlite3_api->value_free
#define tdsqlite3_result_zeroblob64 tdsqlite3_api->result_zeroblob64
#define tdsqlite3_bind_zeroblob64 tdsqlite3_api->bind_zeroblob64
/* Version 3.9.0 and later */
#define tdsqlite3_value_subtype tdsqlite3_api->value_subtype
#define tdsqlite3_result_subtype tdsqlite3_api->result_subtype
/* Version 3.10.0 and later */
#define tdsqlite3_status64 tdsqlite3_api->status64
#define tdsqlite3_strlike tdsqlite3_api->strlike
#define tdsqlite3_db_cacheflush tdsqlite3_api->db_cacheflush
/* Version 3.12.0 and later */
#define tdsqlite3_system_errno tdsqlite3_api->system_errno
/* Version 3.14.0 and later */
#define tdsqlite3_trace_v2 tdsqlite3_api->trace_v2
#define tdsqlite3_expanded_sql tdsqlite3_api->expanded_sql
/* Version 3.18.0 and later */
#define tdsqlite3_set_last_insert_rowid tdsqlite3_api->set_last_insert_rowid
/* Version 3.20.0 and later */
#define tdsqlite3_prepare_v3 tdsqlite3_api->prepare_v3
#define tdsqlite3_prepare16_v3 tdsqlite3_api->prepare16_v3
#define tdsqlite3_bind_pointer tdsqlite3_api->bind_pointer
#define tdsqlite3_result_pointer tdsqlite3_api->result_pointer
#define tdsqlite3_value_pointer tdsqlite3_api->value_pointer
/* Version 3.22.0 and later */
#define tdsqlite3_vtab_nochange tdsqlite3_api->vtab_nochange
#define tdsqlite3_value_nochange tdsqlite3_api->value_nochange
#define tdsqlite3_vtab_collation tdsqlite3_api->vtab_collation
/* Version 3.24.0 and later */
#define tdsqlite3_keyword_count tdsqlite3_api->keyword_count
#define tdsqlite3_keyword_name tdsqlite3_api->keyword_name
#define tdsqlite3_keyword_check tdsqlite3_api->keyword_check
#define tdsqlite3_str_new tdsqlite3_api->str_new
#define tdsqlite3_str_finish tdsqlite3_api->str_finish
#define tdsqlite3_str_appendf tdsqlite3_api->str_appendf
#define tdsqlite3_str_vappendf tdsqlite3_api->str_vappendf
#define tdsqlite3_str_append tdsqlite3_api->str_append
#define tdsqlite3_str_appendall tdsqlite3_api->str_appendall
#define tdsqlite3_str_appendchar tdsqlite3_api->str_appendchar
#define tdsqlite3_str_reset tdsqlite3_api->str_reset
#define tdsqlite3_str_errcode tdsqlite3_api->str_errcode
#define tdsqlite3_str_length tdsqlite3_api->str_length
#define tdsqlite3_str_value tdsqlite3_api->str_value
/* Version 3.25.0 and later */
#define tdsqlite3_create_window_function tdsqlite3_api->create_window_function
/* Version 3.26.0 and later */
#define tdsqlite3_normalized_sql tdsqlite3_api->normalized_sql
/* Version 3.28.0 and later */
#define tdsqlite3_stmt_isexplain tdsqlite3_api->isexplain
#define tdsqlite3_value_frombind tdsqlite3_api->frombind
/* Version 3.30.0 and later */
#define tdsqlite3_drop_modules tdsqlite3_api->drop_modules
/* Version 3.31.0 andn later */
#define tdsqlite3_hard_heap_limit64 tdsqlite3_api->hard_heap_limit64
#define tdsqlite3_uri_key tdsqlite3_api->uri_key
#define tdsqlite3_filename_database tdsqlite3_api->filename_database
#define tdsqlite3_filename_journal tdsqlite3_api->filename_journal
#define tdsqlite3_filename_wal tdsqlite3_api->filename_wal
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
/* This case when the file really is being compiled as a loadable
** extension */
# define SQLITE_EXTENSION_INIT1 const tdsqlite3_api_routines *tdsqlite3_api=0;
# define SQLITE_EXTENSION_INIT2(v) tdsqlite3_api=v;
# define SQLITE_EXTENSION_INIT3 \
extern const tdsqlite3_api_routines *tdsqlite3_api;
#else
/* This case when the file is being statically linked into the
** application */
# define SQLITE_EXTENSION_INIT1 /*no-op*/
# define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */
# define SQLITE_EXTENSION_INIT3 /*no-op*/
#endif
#endif /* SQLITE3EXT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,888 @@
#pragma once
#include "td/tl/TlObject.h"
#include "td/utils/UInt.h"
#include <cstdint>
#include <utility>
#include <vector>
namespace td {
class TlStorerCalcLength;
class TlStorerUnsafe;
class TlStorerToString;
class TlParser;
namespace e2e_api {
using int32 = std::int32_t;
using int53 = std::int64_t;
using int64 = std::int64_t;
using string = std::string;
using bytes = std::string;
using secure_string = std::string;
using secure_bytes = std::string;
template <class Type>
using array = std::vector<Type>;
using BaseObject = ::td::TlObject;
template <class Type>
using object_ptr = ::td::tl_object_ptr<Type>;
template <class Type, class... Args>
object_ptr<Type> make_object(Args &&... args) {
return object_ptr<Type>(new Type(std::forward<Args>(args)...));
}
template <class ToType, class FromType>
object_ptr<ToType> move_object_as(FromType &&from) {
return object_ptr<ToType>(static_cast<ToType *>(from.release()));
}
std::string to_string(const BaseObject &value);
template <class T>
std::string to_string(const object_ptr<T> &value) {
if (value == nullptr) {
return "null";
}
return to_string(*value);
}
template <class T>
std::string to_string(const std::vector<object_ptr<T>> &values) {
std::string result = "{\n";
for (const auto &value : values) {
if (value == nullptr) {
result += "null\n";
} else {
result += to_string(*value);
}
}
result += "}\n";
return result;
}
class Object: public TlObject {
public:
static object_ptr<Object> fetch(TlParser &p);
};
class Function: public TlObject {
public:
static object_ptr<Function> fetch(TlParser &p);
};
class ok final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
static const std::int32_t ID = -722616727;
static object_ptr<ok> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_HandshakePrivate: public Object {
public:
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
};
class e2e_handshakePrivateAccept final : public e2e_HandshakePrivate {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 alice_PK_;
UInt256 bob_PK_;
int64 alice_user_id_;
int64 bob_user_id_;
UInt256 alice_nonce_;
UInt256 bob_nonce_;
e2e_handshakePrivateAccept(UInt256 const &alice_PK_, UInt256 const &bob_PK_, int64 alice_user_id_, int64 bob_user_id_, UInt256 const &alice_nonce_, UInt256 const &bob_nonce_);
static const std::int32_t ID = -1711729321;
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
explicit e2e_handshakePrivateAccept(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakePrivateFinish final : public e2e_HandshakePrivate {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 alice_PK_;
UInt256 bob_PK_;
int64 alice_user_id_;
int64 bob_user_id_;
UInt256 alice_nonce_;
UInt256 bob_nonce_;
e2e_handshakePrivateFinish(UInt256 const &alice_PK_, UInt256 const &bob_PK_, int64 alice_user_id_, int64 bob_user_id_, UInt256 const &alice_nonce_, UInt256 const &bob_nonce_);
static const std::int32_t ID = 353768245;
static object_ptr<e2e_HandshakePrivate> fetch(TlParser &p);
explicit e2e_handshakePrivateFinish(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_HandshakePublic: public Object {
public:
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
};
class e2e_handshakeQR final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 bob_ephemeral_PK_;
UInt256 bob_nonce_;
e2e_handshakeQR(UInt256 const &bob_ephemeral_PK_, UInt256 const &bob_nonce_);
static const std::int32_t ID = -746741414;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeQR(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakeEncryptedMessage final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
bytes message_;
explicit e2e_handshakeEncryptedMessage(bytes const &message_);
static const std::int32_t ID = -1757409540;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeEncryptedMessage(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_handshakeLoginExport final : public e2e_HandshakePublic {
std::int32_t get_id() const final {
return ID;
}
public:
bytes accept_;
bytes encrypted_key_;
e2e_handshakeLoginExport(bytes const &accept_, bytes const &encrypted_key_);
static const std::int32_t ID = -152012972;
static object_ptr<e2e_HandshakePublic> fetch(TlParser &p);
explicit e2e_handshakeLoginExport(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Key: public Object {
public:
static object_ptr<e2e_Key> fetch(TlParser &p);
};
class e2e_keyContactByUserId final : public e2e_Key {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
explicit e2e_keyContactByUserId(int64 user_id_);
static const std::int32_t ID = 1925266987;
static object_ptr<e2e_Key> fetch(TlParser &p);
explicit e2e_keyContactByUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_keyContactByPublicKey final : public e2e_Key {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 public_key_;
explicit e2e_keyContactByPublicKey(UInt256 const &public_key_);
static const std::int32_t ID = 1817152664;
static object_ptr<e2e_Key> fetch(TlParser &p);
explicit e2e_keyContactByPublicKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal: public Object {
public:
static object_ptr<e2e_Personal> fetch(TlParser &p);
};
class e2e_personalUserId final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
explicit e2e_personalUserId(int64 user_id_);
static const std::int32_t ID = 380090592;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalName final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
string first_name_;
string last_name_;
e2e_personalName(string const &first_name_, string const &last_name_);
static const std::int32_t ID = 1760192213;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalName(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalPhoneNumber final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
string phone_number_;
explicit e2e_personalPhoneNumber(string const &phone_number_);
static const std::int32_t ID = 1124597274;
static object_ptr<e2e_Personal> fetch(TlParser &p);
explicit e2e_personalPhoneNumber(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalContactState final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
bool is_contact_;
enum Flags : std::int32_t { IS_CONTACT_MASK = 1 };
e2e_personalContactState();
e2e_personalContactState(int32 flags_, bool is_contact_);
static const std::int32_t ID = -1052064682;
static object_ptr<e2e_Personal> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalEmojiNonces final : public e2e_Personal {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
UInt256 self_nonce_;
UInt256 contact_nonce_hash_;
UInt256 contact_nonce_;
enum Flags : std::int32_t { SELF_NONCE_MASK = 1, CONTACT_NONCE_HASH_MASK = 2, CONTACT_NONCE_MASK = 4 };
e2e_personalEmojiNonces();
e2e_personalEmojiNonces(int32 flags_, UInt256 const &self_nonce_, UInt256 const &contact_nonce_hash_, UInt256 const &contact_nonce_);
static const std::int32_t ID = -2046934345;
static object_ptr<e2e_Personal> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalOnServer;
class e2e_personalData final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 public_key_;
array<object_ptr<e2e_personalOnServer>> data_;
e2e_personalData(UInt256 const &public_key_, array<object_ptr<e2e_personalOnServer>> &&data_);
static const std::int32_t ID = 1037793350;
static object_ptr<e2e_personalData> fetch(TlParser &p);
explicit e2e_personalData(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal;
class e2e_personalOnClient final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int32 signed_at_;
object_ptr<e2e_Personal> personal_;
e2e_personalOnClient(int32 signed_at_, object_ptr<e2e_Personal> &&personal_);
static const std::int32_t ID = -341421551;
static object_ptr<e2e_personalOnClient> fetch(TlParser &p);
explicit e2e_personalOnClient(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_Personal;
class e2e_personalOnServer final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int32 signed_at_;
object_ptr<e2e_Personal> personal_;
e2e_personalOnServer(UInt512 const &signature_, int32 signed_at_, object_ptr<e2e_Personal> &&personal_);
static const std::int32_t ID = -800248701;
static object_ptr<e2e_personalOnServer> fetch(TlParser &p);
explicit e2e_personalOnServer(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_personalOnClient;
class e2e_Value: public Object {
public:
static object_ptr<e2e_Value> fetch(TlParser &p);
};
class e2e_valueContactByUserId final : public e2e_Value {
std::int32_t get_id() const final {
return ID;
}
public:
array<UInt256> public_keys_;
explicit e2e_valueContactByUserId(array<UInt256> &&public_keys_);
static const std::int32_t ID = 113903379;
static object_ptr<e2e_Value> fetch(TlParser &p);
explicit e2e_valueContactByUserId(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_valueContactByPublicKey final : public e2e_Value {
std::int32_t get_id() const final {
return ID;
}
public:
array<object_ptr<e2e_personalOnClient>> entries_;
explicit e2e_valueContactByPublicKey(array<object_ptr<e2e_personalOnClient>> &&entries_);
static const std::int32_t ID = -1418478879;
static object_ptr<e2e_Value> fetch(TlParser &p);
explicit e2e_valueContactByPublicKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_Change;
class e2e_chain_stateProof;
class e2e_chain_block final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int32 flags_;
UInt256 prev_block_hash_;
array<object_ptr<e2e_chain_Change>> changes_;
int32 height_;
object_ptr<e2e_chain_stateProof> state_proof_;
UInt256 signature_public_key_;
enum Flags : std::int32_t { SIGNATURE_PUBLIC_KEY_MASK = 1 };
e2e_chain_block();
e2e_chain_block(UInt512 const &signature_, int32 flags_, UInt256 const &prev_block_hash_, array<object_ptr<e2e_chain_Change>> &&changes_, int32 height_, object_ptr<e2e_chain_stateProof> &&state_proof_, UInt256 const &signature_public_key_);
static const std::int32_t ID = 1671052726;
static object_ptr<e2e_chain_block> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupState;
class e2e_chain_sharedKey;
class e2e_chain_Change: public Object {
public:
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
};
class e2e_chain_changeNoop final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 nonce_;
explicit e2e_chain_changeNoop(UInt256 const &nonce_);
static const std::int32_t ID = -558586853;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeNoop(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetValue final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
bytes key_;
bytes value_;
e2e_chain_changeSetValue(bytes const &key_, bytes const &value_);
static const std::int32_t ID = -33474100;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetValue(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetGroupState final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
object_ptr<e2e_chain_groupState> group_state_;
explicit e2e_chain_changeSetGroupState(object_ptr<e2e_chain_groupState> &&group_state_);
static const std::int32_t ID = 754020678;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetGroupState(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_changeSetSharedKey final : public e2e_chain_Change {
std::int32_t get_id() const final {
return ID;
}
public:
object_ptr<e2e_chain_sharedKey> shared_key_;
explicit e2e_chain_changeSetSharedKey(object_ptr<e2e_chain_sharedKey> &&shared_key_);
static const std::int32_t ID = -1736826536;
static object_ptr<e2e_chain_Change> fetch(TlParser &p);
explicit e2e_chain_changeSetSharedKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_GroupBroadcast: public Object {
public:
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
};
class e2e_chain_groupBroadcastNonceCommit final : public e2e_chain_GroupBroadcast {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int64 user_id_;
int32 chain_height_;
UInt256 chain_hash_;
UInt256 nonce_hash_;
e2e_chain_groupBroadcastNonceCommit(UInt512 const &signature_, int64 user_id_, int32 chain_height_, UInt256 const &chain_hash_, UInt256 const &nonce_hash_);
static const std::int32_t ID = -783209753;
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
explicit e2e_chain_groupBroadcastNonceCommit(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupBroadcastNonceReveal final : public e2e_chain_GroupBroadcast {
std::int32_t get_id() const final {
return ID;
}
public:
UInt512 signature_;
int64 user_id_;
int32 chain_height_;
UInt256 chain_hash_;
UInt256 nonce_;
e2e_chain_groupBroadcastNonceReveal(UInt512 const &signature_, int64 user_id_, int32 chain_height_, UInt256 const &chain_hash_, UInt256 const &nonce_);
static const std::int32_t ID = -2081097256;
static object_ptr<e2e_chain_GroupBroadcast> fetch(TlParser &p);
explicit e2e_chain_groupBroadcastNonceReveal(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupParticipant final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int64 user_id_;
UInt256 public_key_;
int32 flags_;
bool add_users_;
bool remove_users_;
int32 version_;
enum Flags : std::int32_t { ADD_USERS_MASK = 1, REMOVE_USERS_MASK = 2 };
e2e_chain_groupParticipant();
e2e_chain_groupParticipant(int64 user_id_, UInt256 const &public_key_, int32 flags_, bool add_users_, bool remove_users_, int32 version_);
static const std::int32_t ID = 418617119;
static object_ptr<e2e_chain_groupParticipant> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupParticipant;
class e2e_chain_groupState final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
array<object_ptr<e2e_chain_groupParticipant>> participants_;
int32 external_permissions_;
e2e_chain_groupState(array<object_ptr<e2e_chain_groupParticipant>> &&participants_, int32 external_permissions_);
static const std::int32_t ID = 500987268;
static object_ptr<e2e_chain_groupState> fetch(TlParser &p);
explicit e2e_chain_groupState(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_sharedKey final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
UInt256 ek_;
string encrypted_shared_key_;
array<int64> dest_user_id_;
array<bytes> dest_header_;
e2e_chain_sharedKey(UInt256 const &ek_, string const &encrypted_shared_key_, array<int64> &&dest_user_id_, array<bytes> &&dest_header_);
static const std::int32_t ID = -1971028353;
static object_ptr<e2e_chain_sharedKey> fetch(TlParser &p);
explicit e2e_chain_sharedKey(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_chain_groupState;
class e2e_chain_sharedKey;
class e2e_chain_stateProof final : public Object {
std::int32_t get_id() const final {
return ID;
}
public:
int32 flags_;
UInt256 kv_hash_;
object_ptr<e2e_chain_groupState> group_state_;
object_ptr<e2e_chain_sharedKey> shared_key_;
enum Flags : std::int32_t { GROUP_STATE_MASK = 1, SHARED_KEY_MASK = 2 };
e2e_chain_stateProof();
e2e_chain_stateProof(int32 flags_, UInt256 const &kv_hash_, object_ptr<e2e_chain_groupState> &&group_state_, object_ptr<e2e_chain_sharedKey> &&shared_key_);
static const std::int32_t ID = -692684314;
static object_ptr<e2e_chain_stateProof> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
};
class e2e_nop final : public Function {
std::int32_t get_id() const final {
return ID;
}
public:
static const std::int32_t ID = 1479594067;
using ReturnType = bool;
static object_ptr<e2e_nop> fetch(TlParser &p);
void store(TlStorerCalcLength &s) const final;
void store(TlStorerUnsafe &s) const final;
void store(TlStorerToString &s, const char *field_name) const final;
static ReturnType fetch_result(TlParser &p);
};
} // namespace e2e_api
} // namespace td

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
/*
This file is part of VK/KittenPHP-DB-Engine Library.
VK/KittenPHP-DB-Engine Library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine Library 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with VK/KittenPHP-DB-Engine Library. If not, see <http://www.gnu.org/licenses/>.
Copyright 2009-2012 Vkontakte Ltd
2009-2012 Nikolai Durov
2009-2012 Andrei Lopatin
2012 Anton Maydell
*/
#ifndef __CRC32_H__
#define __CRC32_H__
#ifdef __cplusplus
extern "C" {
#endif
unsigned int compute_crc32 (const void *data, int len);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,88 @@
// "License": Public Domain
// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to
// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it
// an example on how to get the endian conversion functions on different platforms.
/* Originally cloned from https://gist.github.com/PkmX/63dd23f28ba885be53a5
* Commit was: 1eca2ab34f2301b9641aa73d1016b951fff3fc39
* Re-published at https://github.com/BenWiederhake/portable-endian.h to provide a means to submit patches and report issues. */
#ifndef PORTABLE_ENDIAN_H__
#define PORTABLE_ENDIAN_H__
#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
# define __WINDOWS__
#endif
#if defined(__linux__) || defined(__CYGWIN__) || defined(__sun)
# include <endian.h>
#elif defined(__APPLE__)
# include <libkern/OSByteOrder.h>
# define htobe32(x) OSSwapHostToBigInt32(x)
# define htole32(x) OSSwapHostToLittleInt32(x)
# define htobe64(x) OSSwapHostToBigInt64(x)
# define htole64(x) OSSwapHostToLittleInt64(x)
# define __BYTE_ORDER BYTE_ORDER
# define __BIG_ENDIAN BIG_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __PDP_ENDIAN PDP_ENDIAN
#elif defined(__OpenBSD__)
# include <sys/endian.h>
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
# include <sys/endian.h>
#elif defined(__WINDOWS__)
# include <winsock2.h>
#ifdef __MINGW32__
# include <sys/param.h>
#endif
# if BYTE_ORDER == LITTLE_ENDIAN
# define htobe32(x) htonl(x)
# define htole32(x) (x)
# define htobe64(x) htonll(x)
# define htole64(x) (x)
# elif BYTE_ORDER == BIG_ENDIAN
/* that would be xbox 360 */
# define htobe32(x) (x)
# define htole32(x) __builtin_bswap32(x)
# define htobe64(x) (x)
# define htole64(x) __builtin_bswap64(x)
# else
# error byte order not supported
# endif
# define __BYTE_ORDER BYTE_ORDER
# define __BIG_ENDIAN BIG_ENDIAN
# define __LITTLE_ENDIAN LITTLE_ENDIAN
# define __PDP_ENDIAN PDP_ENDIAN
#else
# error platform not supported
#endif
#endif

View File

@ -0,0 +1,178 @@
/*
This file is part of tgl-library
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Copyright Vitaly Valtman 2013-2014
*/
#ifndef __TREE_H__
#define __TREE_H__
#include <stdio.h>
#include <memory.h>
#include <assert.h>
#pragma pack(push,4)
#define DEFINE_TREE(X_NAME, X_TYPE, X_CMP, X_UNSET) \
struct tree_ ## X_NAME { \
struct tree_ ## X_NAME *left, *right;\
X_TYPE x;\
int y;\
};\
\
static struct tree_ ## X_NAME *new_tree_node_ ## X_NAME (X_TYPE x, int y) {\
struct tree_ ## X_NAME *T = malloc (sizeof (*T));\
T->x = x;\
T->y = y;\
T->left = T->right = 0;\
return T;\
}\
\
static void delete_tree_node_ ## X_NAME (struct tree_ ## X_NAME *T) {\
free (T);\
}\
\
static void tree_split_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, struct tree_ ## X_NAME **L, struct tree_ ## X_NAME **R) {\
if (!T) {\
*L = *R = 0;\
} else {\
int c = X_CMP (x, T->x);\
if (c < 0) {\
tree_split_ ## X_NAME (T->left, x, L, &T->left);\
*R = T;\
} else {\
tree_split_ ## X_NAME (T->right, x, &T->right, R);\
*L = T;\
}\
}\
}\
\
static struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) __attribute__ ((warn_unused_result,unused));\
static struct tree_ ## X_NAME *tree_insert_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x, int y) {\
if (!T) {\
return new_tree_node_ ## X_NAME (x, y);\
} else {\
if (y > T->y) {\
struct tree_ ## X_NAME *N = new_tree_node_ ## X_NAME (x, y);\
tree_split_ ## X_NAME (T, x, &N->left, &N->right);\
return N;\
} else {\
int c = X_CMP (x, T->x);\
assert (c);\
if (c < 0) { \
T->left = tree_insert_ ## X_NAME (T->left, x, y);\
} else { \
T->right = tree_insert_ ## X_NAME (T->right, x, y);\
} \
return T; \
}\
}\
}\
\
static struct tree_ ## X_NAME *tree_merge_ ## X_NAME (struct tree_ ## X_NAME *L, struct tree_ ## X_NAME *R) {\
if (!L || !R) {\
return L ? L : R;\
} else {\
if (L->y > R->y) {\
L->right = tree_merge_ ## X_NAME (L->right, R);\
return L;\
} else {\
R->left = tree_merge_ ## X_NAME (L, R->left);\
return R;\
}\
}\
}\
\
static struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((warn_unused_result,unused));\
static struct tree_ ## X_NAME *tree_delete_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
assert (T);\
int c = X_CMP (x, T->x);\
if (!c) {\
struct tree_ ## X_NAME *N = tree_merge_ ## X_NAME (T->left, T->right);\
delete_tree_node_ ## X_NAME (T);\
return N;\
} else {\
if (c < 0) { \
T->left = tree_delete_ ## X_NAME (T->left, x); \
} else { \
T->right = tree_delete_ ## X_NAME (T->right, x); \
} \
return T; \
}\
}\
\
static X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *t) __attribute__ ((unused));\
static X_TYPE tree_get_min_ ## X_NAME (struct tree_ ## X_NAME *T) {\
if (!T) { return X_UNSET; } \
while (T->left) { T = T->left; }\
return T->x; \
} \
\
static X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) __attribute__ ((unused));\
static X_TYPE tree_lookup_ ## X_NAME (struct tree_ ## X_NAME *T, X_TYPE x) {\
int c;\
while (T && (c = X_CMP (x, T->x))) {\
T = (c < 0 ? T->left : T->right);\
}\
return T ? T->x : X_UNSET;\
}\
\
static void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) __attribute__ ((unused));\
static void tree_act_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE)) {\
if (!T) { return; } \
tree_act_ ## X_NAME (T->left, act); \
act (T->x); \
tree_act_ ## X_NAME (T->right, act); \
}\
\
static void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) __attribute__ ((unused));\
static void tree_act_ex_ ## X_NAME (struct tree_ ## X_NAME *T, void (*act)(X_TYPE, void *), void *extra) {\
if (!T) { return; } \
tree_act_ex_ ## X_NAME (T->left, act, extra); \
act (T->x, extra); \
tree_act_ex_ ## X_NAME (T->right, act, extra); \
}\
\
static int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\
static int tree_count_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return 0; }\
return 1 + tree_count_ ## X_NAME (T->left) + tree_count_ ## X_NAME (T->right); \
}\
static void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\
static void tree_check_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return; }\
if (T->left) { \
assert (T->left->y <= T->y);\
assert (X_CMP (T->left->x, T->x) < 0); \
}\
if (T->right) { \
assert (T->right->y <= T->y);\
assert (X_CMP (T->right->x, T->x) > 0); \
}\
tree_check_ ## X_NAME (T->left); \
tree_check_ ## X_NAME (T->right); \
}\
static struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) __attribute__ ((unused));\
static struct tree_ ## X_NAME *tree_clear_ ## X_NAME (struct tree_ ## X_NAME *T) { \
if (!T) { return 0; }\
tree_clear_ ## X_NAME (T->left); \
tree_clear_ ## X_NAME (T->right); \
delete_tree_node_ ## X_NAME (T); \
return 0; \
} \
#define int_cmp(a,b) ((a) - (b))
#pragma pack(pop)
#endif

View File

@ -0,0 +1,223 @@
/*
This file is part of tgl-libary/tlc
Tgl-library/tlc is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
Tgl-library/tlc 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with this tgl-library/tlc. If not, see <http://www.gnu.org/licenses/>.
Copyright Vitaly Valtman 2014
It is derivative work of VK/KittenPHP-DB-Engine (https://github.com/vk-com/kphp-kdb/)
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#ifndef __TL_PARSER_NEW_H__
#define __TL_PARSER_NEW_H__
#include <stdio.h>
enum lex_type {
lex_error,
lex_char,
lex_triple_minus,
lex_uc_ident,
lex_lc_ident,
lex_eof,
lex_final,
lex_new,
lex_none,
lex_num,
lex_empty
};
struct curlex {
char *ptr;
int len;
enum lex_type type;
int flags;
};
struct parse {
char *text;
int pos;
int len;
int line;
int line_pos;
struct curlex lex;
};
enum tree_type {
type_tl_program,
type_fun_declarations,
type_constr_declarations,
type_declaration,
type_combinator_decl,
type_equals,
type_partial_app_decl,
type_final_decl,
type_full_combinator_id,
type_opt_args,
type_args,
type_args1,
type_args2,
type_args3,
type_args4,
type_boxed_type_ident,
type_subexpr,
type_partial_comb_app_decl,
type_partial_type_app_decl,
type_final_new,
type_final_final,
type_final_empty,
// type_type,
type_var_ident,
type_var_ident_opt,
type_multiplicity,
type_type_term,
type_term,
type_percent,
type_result_type,
type_expr,
type_nat_term,
type_combinator_id,
type_nat_const,
type_type_ident,
type_builtin_combinator_decl,
type_exclam,
type_optional_arg_def
};
struct tree {
char *text;
int len;
enum tree_type type;
int lex_line;
int lex_line_pos;
int flags;
int size;
int nc;
struct tree **c;
};
#define TL_ACT(x) (x == act_var ? "act_var" : x == act_field ? "act_field" : x == act_plus ? "act_plus" : x == act_type ? "act_type" : x == act_nat_const ? "act_nat_const" : x == act_array ? "act_array" : x == act_question_mark ? "act_question_mark" : \
x == act_union ? "act_union" : x == act_arg ? "act_arg" : x == act_opt_field ? "act_opt_field" : "act_unknown")
#define TL_TYPE(x) (x == type_num ? "type_num" : x == type_type ? "type_type" : x == type_list_item ? "type_list_item" : x == type_list ? "type_list" : x == type_num_value ? "type_num_value" : "type_unknown")
enum combinator_tree_action {
act_var,
act_field,
act_plus,
act_type,
act_nat_const,
act_array,
act_question_mark,
act_union,
act_arg,
act_opt_field
};
enum combinator_tree_type {
type_num,
type_num_value,
type_type,
type_list_item,
type_list
};
struct tl_combinator_tree {
enum combinator_tree_action act;
struct tl_combinator_tree *left, *right;
char *name;
void *data;
long long flags;
enum combinator_tree_type type;
int type_len;
long long type_flags;
};
struct tl_program {
int types_num;
int functions_num;
int constructors_num;
struct tl_type **types;
struct tl_function **functions;
// struct tl_constuctor **constructors;
};
struct tl_type {
char *id;
char *print_id;
char *real_id;
unsigned name;
int flags;
int params_num;
long long params_types;
int constructors_num;
struct tl_constructor **constructors;
};
struct tl_constructor {
char *id;
char *print_id;
char *real_id;
unsigned name;
struct tl_type *type;
struct tl_combinator_tree *left;
struct tl_combinator_tree *right;
};
struct tl_var {
char *id;
struct tl_combinator_tree *ptr;
int type;
int flags;
};
struct parse *tl_init_parse_file (const char *fname);
struct tree *tl_parse_lex (struct parse *P);
void tl_print_parse_error (void);
struct tl_program *tl_parse (struct tree *T);
void write_types (FILE *f);
#define FLAG_BARE 1
#define FLAG_OPT_VAR (1 << 17)
#define FLAG_EXCL (1 << 18)
#define FLAG_OPT_FIELD (1 << 20)
#define FLAG_IS_VAR (1 << 21)
#define FLAG_DEFAULT_CONSTRUCTOR (1 << 25)
#define FLAG_EMPTY (1 << 10)
#ifdef NDEBUG
#undef assert
#define assert(x) if (!(x)) { fprintf(stderr, "Assertion error!\n"); abort(); }
#endif
#ifdef _WIN32
#include "wgetopt.h"
#define __attribute__(x)
#define lrand48() rand()
#define strdup _strdup
#endif
#endif

View File

@ -0,0 +1,55 @@
/*
This file is part of VK/KittenPHP-DB-Engine.
VK/KittenPHP-DB-Engine is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
VK/KittenPHP-DB-Engine 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with VK/KittenPHP-DB-Engine. If not, see <http://www.gnu.org/licenses/>.
This program is released under the GPL with the additional exemption
that compiling, linking, and/or using OpenSSL is allowed.
You are free to remove this exemption from derived works.
Copyright 2012-2013 Vkontakte Ltd
2012-2013 Vitaliy Valtman
*/
#ifndef __TL_TL_H__
#define __TL_TL_H__
// Current tl-tl schema is V2
// See https://core.telegram.org/mtproto/TL-tl
#define TLS_SCHEMA_V2 0x3a2f9be2
#define TLS_TYPE 0x12eb4386
#define TLS_COMBINATOR 0x5c0a1ed5
#define TLS_COMBINATOR_LEFT_BUILTIN 0xcd211f63
#define TLS_COMBINATOR_LEFT 0x4c12c6d9
#define TLS_COMBINATOR_RIGHT_V2 0x2c064372
#define TLS_ARG_V2 0x29dfe61b
#define TLS_EXPR_TYPE 0xecc9da78
#define TLS_EXPR_NAT 0xdcb49bd8
#define TLS_NAT_CONST 0xdcb49bd8
#define TLS_NAT_VAR 0x4e8a14f0
#define TLS_TYPE_VAR 0x0142ceae
#define TLS_ARRAY 0xd9fb20de
#define TLS_TYPE_EXPR 0xc1863d08
/* Deprecated (old versions), read-only */
#define TLS_TREE_NAT_CONST 0xc09f07d7
#define TLS_TREE_NAT_VAR 0x90ea6f58
#define TLS_TREE_TYPE_VAR 0x1caa237a
#define TLS_TREE_ARRAY 0x80479360
#define TLS_TREE_TYPE 0x10f32190
#endif

View File

@ -0,0 +1,193 @@
/* Declarations for getopt.
Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2009,2010
Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#ifndef _GETOPT_H
#ifndef __need_getopt
# define _GETOPT_H 1
#endif
/* If __GNU_LIBRARY__ is not already defined, either we are being used
standalone, or this is the first header included in the source file.
If we are being used with glibc, we need to include <features.h>, but
that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
not defined, include <ctype.h>, which will pull in <features.h> for us
if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
doesn't flood the namespace with stuff the way some other headers do.) */
#if !defined __GNU_LIBRARY__
# include <ctype.h>
#endif
#ifndef __THROW
# ifndef __GNUC_PREREQ
# define __GNUC_PREREQ(maj, min) (0)
# endif
# if defined __cplusplus && __GNUC_PREREQ (2,8)
# define __THROW throw ()
# else
# define __THROW
# endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns -1, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
#ifndef __need_getopt
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
const char *name;
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
# define no_argument 0
# define required_argument 1
# define optional_argument 2
#endif /* need getopt */
/* Get definitions and prototypes for functions to process the
arguments in ARGV (ARGC of them, minus the program name) for
options given in OPTS.
Return the option character from OPTS just read. Return -1 when
there are no more options. For unrecognized options, or options
missing arguments, `optopt' is set to the option letter, and '?' is
returned.
The OPTS string is a list of characters which are recognized option
letters, optionally followed by colons, specifying that that letter
takes an argument, to be placed in `optarg'.
If a letter in OPTS is followed by two colons, its argument is
optional. This behavior is specific to the GNU `getopt'.
The argument `--' causes premature termination of argument
scanning, explicitly telling `getopt' that there are no more
options.
If OPTS begins with `--', then non-option arguments are treated as
arguments to the option '\0'. This behavior is specific to the GNU
`getopt'. */
#ifdef __GNU_LIBRARY__
/* Many other libraries have conflicting prototypes for getopt, with
differences in the consts, in stdlib.h. To avoid compilation
errors, only prototype getopt for the GNU C library. */
extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
__THROW;
# if defined __need_getopt && defined __USE_POSIX2 \
&& !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
/* The GNU getopt has more functionality than the standard version. The
additional functionality can be disable at runtime. This redirection
helps to also do this at runtime. */
# ifdef __REDIRECT
extern int __REDIRECT_NTH (getopt, (int ___argc, char *const *___argv,
const char *__shortopts),
__posix_getopt);
# else
extern int __posix_getopt (int ___argc, char *const *___argv,
const char *__shortopts) __THROW;
# define getopt __posix_getopt
# endif
# endif
#else /* not __GNU_LIBRARY__ */
extern int getopt ();
#endif /* __GNU_LIBRARY__ */
#ifndef __need_getopt
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind)
__THROW;
#endif
#ifdef __cplusplus
}
#endif
/* Make sure we later can get all the definitions and declarations. */
#undef __need_getopt
#endif /* getopt.h */

View File

@ -0,0 +1,18 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/tl/tl_config.h"
#include "td/tl/tl_writer.h"
#include <string>
namespace td {
void gen_json_converter(const tl::tl_config &config, const std::string &file_name, tl::TL_writer::Mode mode);
} // namespace td

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_cpp : public TD_TL_writer {
std::string gen_constructor_id_store_raw(const std::string &id) const;
std::string gen_fetch_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_full_fetch_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_store_class_name(const tl::tl_tree_type *tree_type) const;
std::string gen_full_store_class_name(const tl::tl_tree_type *tree_type) const;
std::vector<std::string> ext_include;
protected:
std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const;
virtual std::string get_pretty_field_name(std::string field_name) const;
virtual std::string get_pretty_class_name(std::string class_name) const;
public:
TD_TL_writer_cpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer(tl_name, string_type, bytes_type), ext_include(ext_include) {
}
std::string gen_output_begin(const std::string &additional_imports) const override;
std::string gen_output_begin_once() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, const std::vector<tl::arg> &args,
std::vector<tl::var_description> &vars, bool flat, int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int field_count, bool is_default) const override;
};
} // namespace td

View File

@ -0,0 +1,582 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/tl/tl_writer.h"
#include <cassert>
#include <cstdint>
#include <sstream>
#include <string>
#include <vector>
namespace td {
namespace tl {
class TlWriterDotNet final : public TL_writer {
bool is_header_;
std::string prefix_;
public:
TlWriterDotNet(const std::string &name, bool is_header, const std::string &prefix)
: TL_writer(name), is_header_(is_header), prefix_(prefix) {
}
int get_max_arity() const final {
return 0;
}
bool is_built_in_simple_type(const std::string &name) const final {
return name == "Bool" || name == "Int32" || name == "Int53" || name == "Int64" || name == "Double" ||
name == "String" || name == "Bytes";
}
bool is_built_in_complex_type(const std::string &name) const final {
return name == "Vector";
}
bool is_type_bare(const tl_type *t) const final {
return t->simple_constructors <= 1 || (is_built_in_simple_type(t->name) && t->name != "Bool") ||
is_built_in_complex_type(t->name);
}
std::vector<std::string> get_parsers() const final {
return {"FromUnmanaged"};
}
int get_parser_type(const tl_combinator *t, const std::string &name) const final {
return 0;
}
Mode get_parser_mode(int type) const final {
return All; // Server;
}
std::vector<std::string> get_storers() const final {
return {"ToUnmanaged", "ToString"};
}
std::vector<std::string> get_additional_functions() const final {
return {"ToUnmanaged", "FromUnmanaged"};
}
int get_storer_type(const tl_combinator *t, const std::string &name) const final {
return name == "ToString";
}
Mode get_storer_mode(int type) const final {
return type <= 1 ? All : Server;
}
std::string gen_base_tl_class_name() const final {
return "BaseObject";
}
std::string gen_base_type_class_name(int arity) const final {
assert(arity == 0);
return "Object";
}
std::string gen_base_function_class_name() const final {
return "Function";
}
static std::string to_camelCase(const std::string &name) {
return to_cCamelCase(name, false);
}
static std::string to_CamelCase(const std::string &name) {
return to_cCamelCase(name, true);
}
static std::string to_cCamelCase(const std::string &name, bool flag) {
bool next_to_upper = flag;
std::string result;
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
next_to_upper = true;
continue;
}
if (next_to_upper) {
result += to_upper(name[i]);
next_to_upper = false;
} else {
result += name[i];
}
}
return result;
}
std::string gen_native_field_name(std::string name) const {
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
name[i] = '_';
}
}
assert(name.size() > 0);
assert(name[name.size() - 1] != '_');
return name + "_";
}
std::string gen_native_class_name(std::string name) const {
if (name == "Object") {
assert(0);
}
if (name == "#") {
return "int32_t";
}
for (std::size_t i = 0; i < name.size(); i++) {
if (!is_alnum(name[i])) {
name[i] = '_';
}
}
return name;
}
std::string gen_class_name(std::string name) const final {
if (name == "Object" || name == "#") {
assert(0);
}
return to_CamelCase(name);
}
std::string gen_field_name(std::string name) const final {
assert(name.size() > 0);
assert(is_alnum(name.back()));
return to_CamelCase(name);
}
std::string gen_type_name(const tl_tree_type *tree_type) const final {
const tl_type *t = tree_type->type;
const std::string &name = t->name;
if (name == "#") {
assert(0);
}
if (name == "Bool") {
return "bool";
}
if (name == "Int32") {
return "int32";
}
if (name == "Int53" || name == "Int64") {
return "int64";
}
if (name == "Double") {
return "float64";
}
if (name == "String") {
return "String^";
}
if (name == "Bytes") {
return "Array<BYTE>^";
}
if (name == "Vector") {
assert(t->arity == 1);
assert(tree_type->children.size() == 1);
assert(tree_type->children[0]->get_type() == NODE_TYPE_TYPE);
const tl_tree_type *child = static_cast<const tl_tree_type *>(tree_type->children[0]);
return "Array<" + gen_type_name(child) + ">^";
}
assert(!is_built_in_simple_type(name) && !is_built_in_complex_type(name));
for (std::size_t i = 0; i < tree_type->children.size(); i++) {
assert(tree_type->children[i]->get_type() == NODE_TYPE_NAT_CONST);
}
return gen_main_class_name(t) + "^";
}
std::string gen_output_begin(const std::string &additional_imports) const final {
return prefix_ + "#include \"td/tl/tl_dotnet_object.h\"\n\n" + additional_imports +
"namespace Telegram {\n"
"namespace Td {\n"
"namespace Api {\n";
}
std::string gen_output_begin_once() const final {
return std::string();
}
std::string gen_output_end() const final {
return "}\n"
"}\n"
"}\n";
}
std::string gen_import_declaration(const std::string &name, bool is_system) const final {
if (is_system) {
return "#include <" + name + ">\n";
} else {
return "#include \"" + name + "\"\n";
}
}
std::string gen_package_suffix() const final {
return ".h";
}
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final {
if (!is_header_) {
return "";
}
std::stringstream ss;
ss << (is_proxy ? "interface" : "ref") << " class " << class_name << ";\n";
return ss.str();
}
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const final {
if (!is_header_) {
return "";
}
std::stringstream ss;
ss << "\npublic " << (is_proxy ? "interface" : "ref") << " class " << class_name << (is_proxy ? "" : " sealed")
<< (class_name == gen_base_tl_class_name() ? "" : " : " + base_class_name) << " {\n"
<< " public:\n";
return ss.str();
}
std::string gen_class_end() const final {
return "";
}
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const final {
if (!is_header_) {
return "";
}
auto fixed_field_name = field_name;
if (field_name == class_name) {
fixed_field_name += "Value";
}
auto is_web_page_stickers =
(class_name == "WebPage" && field_name == "Stickers" && type_name == "Array<Sticker^>^");
if (type_name == field_name + "^" || (type_name == "Message^" && field_name == "ReplyToMessage") ||
is_web_page_stickers) {
auto fixed_type_name =
is_web_page_stickers ? "Array<::Telegram::Td::Api::Sticker^>^" : "::Telegram::Td::Api::" + type_name;
std::stringstream ss;
ss << "private:\n";
ss << " " << fixed_type_name << " " << fixed_field_name << "PrivateField;\n";
ss << "public:\n";
ss << " property " << fixed_type_name << " " << fixed_field_name << " {\n";
ss << " " << fixed_type_name << " get() {\n";
ss << " return " << fixed_field_name << "PrivateField;\n";
ss << " }\n";
ss << " void set(" << fixed_type_name << " newValue) {\n";
ss << " " << fixed_field_name << "PrivateField = newValue;\n";
ss << " }\n";
ss << " }\n";
return ss.str();
}
return " property " + type_name + " " + fixed_field_name + ";\n";
}
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<var_description> &vars, int storer_type) const final {
if (storer_type < 0) {
return "";
}
std::stringstream ss;
ss << "\n";
if (storer_type) {
ss << (is_header_ ? " virtual " : "") << "String^ " << (is_header_ ? "" : gen_class_name(class_name) + "::")
<< "ToString()" << (is_header_ ? " override;" : " {\n return ::Telegram::Td::Api::ToString(this);\n}")
<< "\n";
} else {
ss << (is_header_ ? " virtual " : "") << "NativeObject^ "
<< (is_header_ ? "" : gen_class_name(class_name) + "::") << "ToUnmanaged()";
if (is_header_) {
ss << ";\n";
} else {
ss << " {\n return REF_NEW NativeObject(::Telegram::Td::Api::ToUnmanaged(this).release());\n}\n";
}
}
return ss.str();
}
std::string gen_store_function_end(const std::vector<var_description> &vars, int storer_type) const final {
return "";
}
std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const final {
std::stringstream ss;
ss << "\n";
ss << (is_header_ ? " " : gen_class_name(class_name) + "::") << gen_class_name(class_name) << "(";
return ss.str();
}
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const arg &a,
bool is_default) const final {
if (is_default) {
return "";
}
std::stringstream ss;
ss << (field_num == 0 ? "" : ", ");
auto field_type = gen_field_type(a);
auto pos = 0;
while (field_type.substr(pos, 6) == "Array<") {
pos += 6;
}
if (field_type.substr(pos, 4) != "BYTE" && field_type.substr(pos, 6) != "String" &&
to_upper(field_type[pos]) == field_type[pos]) {
field_type = field_type.substr(0, pos) + "::Telegram::Td::Api::" + field_type.substr(pos);
}
ss << field_type << " " << to_camelCase(a.name);
return ss.str();
}
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const arg &a,
bool is_default) const final {
if (is_default || is_header_) {
return "";
}
std::stringstream ss;
if (field_num == 0) {
ss << ") {\n";
}
auto field_name = gen_field_name(a.name);
if (field_name == class_name) {
field_name += "Value";
}
ss << " " << field_name << " = " << to_camelCase(a.name) << ";\n";
return ss.str();
}
std::string gen_constructor_end(const tl_combinator *t, int field_count, bool is_default) const final {
if (is_header_) {
return ");\n";
}
std::stringstream ss;
if (field_count == 0) {
ss << ") {\n";
}
ss << "}\n";
return ss.str();
}
std::string gen_additional_function(const std::string &function_name, const tl_combinator *t,
bool is_function) const final {
std::stringstream ss;
if (is_header_ && function_name == "ToUnmanaged") {
ss << "};\n";
}
ss << "\n";
if (function_name == "ToUnmanaged") {
gen_to_unmanaged(ss, t);
} else {
gen_from_unmanaged(ss, t);
}
return ss.str();
}
void gen_to_unmanaged(std::stringstream &ss, const tl_combinator *t) const {
auto native_class_name = gen_native_class_name(t->name);
auto class_name = gen_class_name(t->name);
ss << "td::td_api::object_ptr<td::td_api::" << native_class_name << "> ToUnmanaged(" << class_name << "^ from)";
if (is_header_) {
ss << ";\n";
return;
}
ss << " {\n"
<< " if (!from) {\n"
<< " return nullptr;\n"
<< " }\n"
<< " return td::td_api::make_object<td::td_api::" << native_class_name << ">(";
bool is_first = true;
for (auto &it : t->args) {
if (is_first) {
is_first = false;
} else {
ss << ", ";
}
auto field_name = gen_field_name(it.name);
if (field_name == class_name) {
field_name += "Value";
}
ss << "ToUnmanaged(from->" << field_name << ")";
}
ss << ");\n}\n";
}
void gen_from_unmanaged(std::stringstream &ss, const tl_combinator *t) const {
auto native_class_name = gen_native_class_name(t->name);
auto class_name = gen_class_name(t->name);
ss << class_name << "^ FromUnmanaged(td::td_api::" << native_class_name << " &from)";
if (is_header_) {
ss << ";\n";
return;
}
ss << " {\n"
<< " return REF_NEW " << class_name << "(";
bool is_first = true;
for (auto &it : t->args) {
if (is_first) {
is_first = false;
} else {
ss << ", ";
}
bool need_bytes = gen_field_type(it) == "Array<BYTE>^" || gen_field_type(it) == "Array<Array<BYTE>^>^";
ss << (need_bytes ? "Bytes" : "") << "FromUnmanaged(from." << gen_native_field_name(it.name) << ")";
}
ss << ");\n}\n";
}
std::string gen_array_type_name(const tl_tree_array *arr, const std::string &field_name) const final {
assert(0);
return std::string();
}
std::string gen_var_type_name() const final {
assert(0);
return std::string();
}
std::string gen_int_const(const tl_tree *tree_c, const std::vector<var_description> &vars) const final {
assert(0);
return std::string();
}
std::string gen_var_name(const var_description &desc) const final {
assert(0);
return "";
}
std::string gen_parameter_name(int index) const final {
assert(0);
return "";
}
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const final {
return "";
}
std::string gen_vars(const tl_combinator *t, const tl_tree_type *result_type,
std::vector<var_description> &vars) const final {
assert(vars.empty());
return "";
}
std::string gen_function_vars(const tl_combinator *t, std::vector<var_description> &vars) const final {
assert(vars.empty());
return "";
}
std::string gen_uni(const tl_tree_type *result_type, std::vector<var_description> &vars,
bool check_negative) const final {
assert(result_type->children.empty());
return "";
}
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const final {
return "";
}
std::string gen_field_fetch(int field_num, const arg &a, std::vector<var_description> &vars, bool flat,
int parser_type) const final {
return "";
// std::stringstream ss;
// ss << gen_field_name(a.name) << " = from_unmanaged(from->" <<
// gen_native_field_name(a.name) << ");\n"; return ss.str();
}
std::string gen_field_store(const arg &a, const std::vector<tl::arg> &args, std::vector<var_description> &vars,
bool flat, int storer_type) const final {
return "";
// std::stringstream ss;
// ss << "to_unmanaged(" << gen_field_name(a.name) << ")";
// return ss.str();
}
std::string gen_type_fetch(const std::string &field_name, const tl_tree_type *tree_type,
const std::vector<var_description> &vars, int parser_type) const final {
assert(vars.empty());
return "";
}
std::string gen_type_store(const std::string &field_name, const tl_tree_type *tree_type,
const std::vector<var_description> &vars, int storer_type) const final {
return "";
}
std::string gen_var_type_fetch(const arg &a) const final {
assert(0);
return "";
}
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const final {
return "";
}
std::string gen_function_result_type(const tl_tree *result) const final {
return "";
}
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<var_description> &vars, int parser_type) const final {
return "";
}
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<var_description> &vars,
int parser_type) const final {
return "";
}
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl_tree *result) const final {
return "";
}
std::string gen_fetch_function_result_end() const final {
return "";
}
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const final {
return "";
}
std::string gen_fetch_function_result_any_end(bool is_proxy) const final {
return "";
}
std::string gen_fetch_switch_begin() const final {
return "";
}
std::string gen_fetch_switch_case(const tl_combinator *t, int arity) const final {
return "";
}
std::string gen_fetch_switch_end() const final {
return "";
}
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl_type *type,
const std::string &name, int arity, bool is_function) const final {
std::stringstream ss;
if (is_header_ && function_name == "ToUnmanaged") {
ss << "};\n";
}
if (type == nullptr) {
return ss.str();
}
auto native_class_name = gen_native_class_name(type->name);
auto class_name = gen_class_name(type->name);
if (function_name == "ToUnmanaged") {
ss << "td::td_api::object_ptr<td::td_api::" << native_class_name << "> ToUnmanaged(" << class_name << "^ from)";
if (is_header_) {
ss << ";\n";
return ss.str();
}
ss << " {\n"
<< " if (!from) {\n"
<< " return nullptr;\n"
<< " }\n"
<< " return td::td_api::move_object_as<td::td_api::" << native_class_name
<< ">(from->ToUnmanaged()->get_object_ptr());\n}\n";
} else {
ss << class_name << "^ FromUnmanaged(td::td_api::" << native_class_name << " &from)";
if (is_header_) {
ss << ";\n";
return ss.str();
}
ss << " {\n";
ss << " return DoFromUnmanaged<" << class_name << "^>(from);\n";
ss << "}\n";
}
return ss.str();
}
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
const std::string &class_name, int arity) const final {
return "";
}
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl_type *type,
const tl_combinator *t, int arity, bool is_function) const final {
return "";
}
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl_type *type,
bool is_function) const final {
return "";
}
};
} // namespace tl
} // namespace td

View File

@ -0,0 +1,95 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_h : public TD_TL_writer {
protected:
const std::vector<std::string> ext_include;
static std::string forward_declaration(std::string type);
bool need_arg_mask(const tl::arg &a, bool can_be_stored) const;
public:
TD_TL_writer_h(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer(tl_name, string_type, bytes_type), ext_include(ext_include) {
}
std::string gen_output_begin(const std::string &additional_imports) const override;
std::string gen_output_begin_once() const override;
std::string gen_output_end() const override;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const override;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const override;
std::string gen_class_end() const override;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const override;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const override;
std::string gen_flags_definitions(const tl::tl_combinator *t, bool can_be_stored) const override;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const override;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const override;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const override;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const override;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const override;
std::string gen_field_store(const tl::arg &a, const std::vector<tl::arg> &args,
std::vector<tl::var_description> &vars, bool flat, int storer_type) const override;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_var_type_fetch(const tl::arg &a) const override;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const override;
std::string gen_function_result_type(const tl::tl_tree *result) const override;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<tl::var_description> &vars, int parser_type) const override;
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<tl::var_description> &vars,
int parser_type) const override;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const override;
std::string gen_fetch_function_result_end() const override;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const override;
std::string gen_fetch_function_result_any_end(bool is_proxy) const override;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const override;
std::string gen_fetch_switch_begin() const override;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const override;
std::string gen_fetch_switch_end() const override;
std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const override;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
std::string gen_constructor_end(const tl::tl_combinator *t, int field_count, bool is_default) const override;
};
} // namespace td

View File

@ -0,0 +1,108 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "tl_writer_td.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_hpp final : public TD_TL_writer {
public:
TD_TL_writer_hpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type)
: TD_TL_writer(tl_name, string_type, bytes_type) {
}
bool is_documentation_generated() const final;
int get_additional_function_type(const std::string &additional_function_name) const final;
std::vector<std::string> get_additional_functions() const final;
std::string gen_base_type_class_name(int arity) const final;
std::string gen_base_tl_class_name() const final;
std::string gen_output_begin(const std::string &additional_imports) const final;
std::string gen_output_begin_once() const final;
std::string gen_output_end() const final;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const final;
std::string gen_class_end() const final;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const final;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const final;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const final;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const final;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const final;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const final;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const final;
std::string gen_field_store(const tl::arg &a, const std::vector<tl::arg> &args,
std::vector<tl::var_description> &vars, bool flat, int storer_type) const final;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_var_type_fetch(const tl::arg &a) const final;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const final;
std::string gen_function_result_type(const tl::tl_tree *result) const final;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<tl::var_description> &vars,
int parser_type) const final;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const final;
std::string gen_fetch_function_result_end() const final;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const final;
std::string gen_fetch_function_result_any_end(bool is_proxy) const final;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_fetch_switch_begin() const final;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const final;
std::string gen_fetch_switch_end() const final;
std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const final;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const final;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const final;
std::string gen_constructor_end(const tl::tl_combinator *t, int field_count, bool is_default) const final;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const final;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity, bool is_function) const final;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const final;
};
} // namespace td

View File

@ -0,0 +1,124 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/tl/tl_writer.h"
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_java final : public tl::TL_writer {
static const int MAX_ARITY = 0;
static const std::string base_type_class_names[MAX_ARITY + 1];
static const std::string base_tl_class_name;
static const std::string base_function_class_name;
const std::string package_name;
public:
TD_TL_writer_java(const std::string &tl_name, const std::string &package_name)
: TL_writer(tl_name), package_name(package_name) {
}
int get_max_arity() const final;
bool is_built_in_simple_type(const std::string &name) const final;
bool is_built_in_complex_type(const std::string &name) const final;
bool is_type_bare(const tl::tl_type *t) const final;
bool is_combinator_supported(const tl::tl_combinator *constructor) const final;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const final;
int get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const final;
std::vector<std::string> get_parsers() const final;
std::vector<std::string> get_storers() const final;
std::string gen_base_tl_class_name() const final;
std::string gen_base_type_class_name(int arity) const final;
std::string gen_base_function_class_name() const final;
std::string gen_class_name(std::string name) const final;
std::string gen_field_name(std::string name) const final;
std::string gen_var_name(const tl::var_description &desc) const final;
std::string gen_parameter_name(int index) const final;
std::string gen_type_name(const tl::tl_tree_type *tree_type) const final;
std::string gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const final;
std::string gen_var_type_name() const final;
std::string gen_int_const(const tl::tl_tree *tree_c, const std::vector<tl::var_description> &vars) const final;
std::string gen_output_begin(const std::string &additional_imports) const final;
std::string gen_output_begin_once() const final;
std::string gen_output_end() const final;
std::string gen_import_declaration(const std::string &name, bool is_system) const final;
std::string gen_package_suffix() const final;
std::string gen_forward_class_declaration(const std::string &class_name, bool is_proxy) const final;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const final;
std::string gen_class_end() const final;
std::string gen_class_alias(const std::string &class_name, const std::string &alias_name) const final;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const final;
std::string gen_vars(const tl::tl_combinator *t, const tl::tl_tree_type *result_type,
std::vector<tl::var_description> &vars) const final;
std::string gen_function_vars(const tl::tl_combinator *t, std::vector<tl::var_description> &vars) const final;
std::string gen_uni(const tl::tl_tree_type *result_type, std::vector<tl::var_description> &vars,
bool check_negative) const final;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const final;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const final;
std::string gen_field_store(const tl::arg &a, const std::vector<tl::arg> &args,
std::vector<tl::var_description> &vars, bool flat, int storer_type) const final;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_var_type_fetch(const tl::arg &a) const final;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const final;
std::string gen_function_result_type(const tl::tl_tree *result) const final;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<tl::var_description> &vars,
int parser_type) const final;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const final;
std::string gen_fetch_function_result_end() const final;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const final;
std::string gen_fetch_function_result_any_end(bool is_proxy) const final;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_store_function_end(const std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_fetch_switch_begin() const final;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const final;
std::string gen_fetch_switch_end() const final;
std::string gen_constructor_begin(int field_count, const std::string &class_name, bool is_default) const final;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const final;
std::string gen_constructor_field_init(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const final;
std::string gen_constructor_end(const tl::tl_combinator *t, int field_count, bool is_default) const final;
};
} // namespace td

View File

@ -0,0 +1,109 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "tl_writer_cpp.h"
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_jni_cpp final : public TD_TL_writer_cpp {
std::string gen_output_begin_once() const final;
std::string gen_vector_fetch(std::string field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int parser_type) const;
std::string gen_vector_store(const std::string &field_name, const tl::tl_tree_type *t,
const std::vector<tl::var_description> &vars, int storer_type) const;
std::string gen_java_field_name(std::string name) const;
std::string gen_basic_java_class_name(std::string name) const;
std::string gen_java_class_name(std::string name) const;
std::string gen_type_signature(const tl::tl_tree_type *tree_type) const;
std::string get_pretty_field_name(std::string field_name) const final;
std::string get_pretty_class_name(std::string class_name) const final;
public:
TD_TL_writer_jni_cpp(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer_cpp(tl_name, string_type, bytes_type, ext_include) {
}
bool is_built_in_simple_type(const std::string &name) const final;
bool is_built_in_complex_type(const std::string &name) const final;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const final;
int get_additional_function_type(const std::string &additional_function_name) const final;
std::vector<std::string> get_parsers() const final;
std::vector<std::string> get_storers() const final;
std::vector<std::string> get_additional_functions() const final;
std::string gen_base_type_class_name(int arity) const final;
std::string gen_base_tl_class_name() const final;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const final;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const final;
std::string gen_constructor_id_store(std::int32_t id, int storer_type) const final;
std::string gen_field_fetch(int field_num, const tl::arg &a, std::vector<tl::var_description> &vars, bool flat,
int parser_type) const final;
std::string gen_field_store(const tl::arg &a, const std::vector<tl::arg> &args,
std::vector<tl::var_description> &vars, bool flat, int storer_type) const final;
std::string gen_type_fetch(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_type_store(const std::string &field_name, const tl::tl_tree_type *tree_type,
const std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_get_id(const std::string &class_name, std::int32_t id, bool is_proxy) const final;
std::string gen_fetch_function_begin(const std::string &parser_name, const std::string &class_name,
const std::string &parent_class_name, int arity, int field_count,
std::vector<tl::var_description> &vars, int parser_type) const final;
std::string gen_fetch_function_end(bool has_parent, int field_count, const std::vector<tl::var_description> &vars,
int parser_type) const final;
std::string gen_fetch_function_result_begin(const std::string &parser_name, const std::string &class_name,
const tl::tl_tree *result) const final;
std::string gen_fetch_function_result_end() const final;
std::string gen_fetch_function_result_any_begin(const std::string &parser_name, const std::string &class_name,
bool is_proxy) const final;
std::string gen_fetch_function_result_any_end(bool is_proxy) const final;
std::string gen_store_function_begin(const std::string &storer_name, const std::string &class_name, int arity,
std::vector<tl::var_description> &vars, int storer_type) const final;
std::string gen_fetch_switch_begin() const final;
std::string gen_fetch_switch_case(const tl::tl_combinator *t, int arity) const final;
std::string gen_fetch_switch_end() const final;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const final;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity, bool is_function) const final;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const final;
};
} // namespace td

View File

@ -0,0 +1,57 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "tl_writer_h.h"
#include <string>
#include <vector>
namespace td {
class TD_TL_writer_jni_h final : public TD_TL_writer_h {
public:
TD_TL_writer_jni_h(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type,
const std::vector<std::string> &ext_include)
: TD_TL_writer_h(tl_name, string_type, bytes_type, ext_include) {
}
bool is_built_in_simple_type(const std::string &name) const final;
bool is_built_in_complex_type(const std::string &name) const final;
int get_parser_type(const tl::tl_combinator *t, const std::string &parser_name) const final;
int get_additional_function_type(const std::string &additional_function_name) const final;
std::vector<std::string> get_parsers() const final;
std::vector<std::string> get_storers() const final;
std::vector<std::string> get_additional_functions() const final;
std::string gen_base_type_class_name(int arity) const final;
std::string gen_base_tl_class_name() const final;
std::string gen_output_begin(const std::string &additional_imports) const final;
std::string gen_output_begin_once() const final;
std::string gen_class_begin(const std::string &class_name, const std::string &base_class_name, bool is_proxy,
const tl::tl_tree *result) const final;
std::string gen_field_definition(const std::string &class_name, const std::string &type_name,
const std::string &field_name) const final;
std::string gen_additional_function(const std::string &function_name, const tl::tl_combinator *t,
bool is_function) const final;
std::string gen_additional_proxy_function_begin(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity,
bool is_function) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const std::string &class_name, int arity) const final;
std::string gen_additional_proxy_function_case(const std::string &function_name, const tl::tl_type *type,
const tl::tl_combinator *t, int arity, bool is_function) const final;
std::string gen_additional_proxy_function_end(const std::string &function_name, const tl::tl_type *type,
bool is_function) const final;
};
} // namespace td

View File

@ -0,0 +1,67 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/tl/tl_writer.h"
#include <string>
#include <vector>
namespace td {
class TD_TL_writer : public tl::TL_writer {
static const int MAX_ARITY = 0;
static const std::string base_type_class_names[MAX_ARITY + 1];
static const std::string base_tl_class_name;
static const std::string base_function_class_name;
protected:
const std::string string_type;
const std::string bytes_type;
public:
TD_TL_writer(const std::string &tl_name, const std::string &string_type, const std::string &bytes_type)
: TL_writer(tl_name), string_type(string_type), bytes_type(bytes_type) {
}
int get_max_arity() const override;
bool is_built_in_simple_type(const std::string &name) const override;
bool is_built_in_complex_type(const std::string &name) const override;
bool is_type_bare(const tl::tl_type *t) const override;
bool is_combinator_supported(const tl::tl_combinator *constructor) const override;
bool is_default_constructor_generated(const tl::tl_combinator *t, bool can_be_parsed,
bool can_be_stored) const override;
bool is_full_constructor_generated(const tl::tl_combinator *t, bool can_be_parsed, bool can_be_stored) const override;
int get_storer_type(const tl::tl_combinator *t, const std::string &storer_name) const override;
Mode get_parser_mode(int type) const override;
Mode get_storer_mode(int type) const override;
std::vector<std::string> get_parsers() const override;
std::vector<std::string> get_storers() const override;
std::string gen_import_declaration(const std::string &package_name, bool is_system) const override;
std::string gen_package_suffix() const override;
std::string gen_base_tl_class_name() const override;
std::string gen_base_type_class_name(int arity) const override;
std::string gen_base_function_class_name() const override;
std::string gen_class_name(std::string name) const override;
std::string gen_field_name(std::string name) const override;
std::string gen_var_name(const tl::var_description &desc) const override;
std::string gen_parameter_name(int index) const override;
std::string gen_type_name(const tl::tl_tree_type *tree_type) const override;
std::string gen_array_type_name(const tl::tl_tree_array *arr, const std::string &field_name) const override;
std::string gen_var_type_name() const override;
std::string gen_int_const(const tl::tl_tree *tree_c, const std::vector<tl::var_description> &vars) const override;
std::string gen_constructor_parameter(int field_num, const std::string &class_name, const tl::arg &a,
bool is_default) const override;
};
} // namespace td

View File

@ -0,0 +1,295 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthKey.h"
#include "td/mtproto/MessageId.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include <array>
namespace td {
namespace mtproto {
struct ServerSalt {
int64 salt;
double valid_since;
double valid_until;
};
template <class StorerT>
void store(const ServerSalt &salt, StorerT &storer) {
storer.template store_binary<int64>(salt.salt);
storer.template store_binary<double>(salt.valid_since);
storer.template store_binary<double>(salt.valid_until);
}
template <class ParserT>
void parse(ServerSalt &salt, ParserT &parser) {
salt.salt = parser.fetch_long();
salt.valid_since = parser.fetch_double();
salt.valid_until = parser.fetch_double();
}
Status check_message_id_duplicates(MessageId *saved_message_ids, size_t max_size, size_t &end_pos,
MessageId message_id);
template <size_t max_size>
class MessageIdDuplicateChecker {
public:
Status check(MessageId message_id) {
return check_message_id_duplicates(&saved_message_ids_[0], max_size, end_pos_, message_id);
}
private:
std::array<MessageId, 2 * max_size> saved_message_ids_;
size_t end_pos_ = 0;
};
class AuthData {
public:
AuthData();
AuthData(const AuthData &) = default;
AuthData &operator=(const AuthData &) = delete;
AuthData(AuthData &&) = delete;
AuthData &operator=(AuthData &&) = delete;
~AuthData() = default;
bool is_ready(double now);
void set_main_auth_key(AuthKey auth_key) {
main_auth_key_ = std::move(auth_key);
}
void break_main_auth_key() {
main_auth_key_.break_key();
}
const AuthKey &get_main_auth_key() const {
// CHECK(has_main_auth_key());
return main_auth_key_;
}
bool has_main_auth_key() const {
return !main_auth_key_.empty();
}
bool need_main_auth_key() const {
return !has_main_auth_key();
}
void set_tmp_auth_key(AuthKey auth_key) {
CHECK(!auth_key.empty());
tmp_auth_key_ = std::move(auth_key);
}
const AuthKey &get_tmp_auth_key() const {
return tmp_auth_key_;
}
bool was_tmp_auth_key() const {
return use_pfs() && !tmp_auth_key_.empty();
}
bool need_tmp_auth_key(double now, double refresh_margin) const {
if (!use_pfs()) {
return false;
}
if (tmp_auth_key_.empty()) {
return true;
}
if (now > tmp_auth_key_.expires_at() - refresh_margin) {
return true;
}
return false;
}
void drop_main_auth_key() {
main_auth_key_ = AuthKey();
}
void drop_tmp_auth_key() {
tmp_auth_key_ = AuthKey();
}
bool has_tmp_auth_key(double now) const {
if (!use_pfs()) {
return false;
}
if (tmp_auth_key_.empty()) {
return false;
}
if (now > tmp_auth_key_.expires_at()) {
return false;
}
return true;
}
const AuthKey &get_auth_key() const {
if (use_pfs()) {
return get_tmp_auth_key();
}
return get_main_auth_key();
}
bool has_auth_key(double now) const {
if (use_pfs()) {
return has_tmp_auth_key(now);
}
return has_main_auth_key();
}
bool get_auth_flag() const {
return main_auth_key_.auth_flag();
}
void set_auth_flag(bool auth_flag) {
main_auth_key_.set_auth_flag(auth_flag);
if (!auth_flag) {
drop_tmp_auth_key();
}
}
bool get_bind_flag() const {
return !use_pfs() || tmp_auth_key_.auth_flag();
}
void on_bind() {
CHECK(use_pfs());
tmp_auth_key_.set_auth_flag(true);
}
Slice get_header() const {
if (use_pfs()) {
return tmp_auth_key_.need_header() ? Slice(header_) : Slice();
} else {
return main_auth_key_.need_header() ? Slice(header_) : Slice();
}
}
void set_header(std::string header) {
header_ = std::move(header);
}
void on_api_response() {
if (use_pfs()) {
tmp_auth_key_.remove_header();
} else {
main_auth_key_.remove_header();
}
}
void on_connection_not_inited() {
if (use_pfs()) {
tmp_auth_key_.restore_header();
} else {
main_auth_key_.restore_header();
}
}
void set_session_id(uint64 session_id) {
session_id_ = session_id;
}
uint64 get_session_id() const {
CHECK(session_id_ != 0);
return session_id_;
}
double get_server_time(double now) const {
return server_time_difference_ + now;
}
double get_server_time_difference() const {
return server_time_difference_;
}
// diff == msg_id / 2^32 - now == old_server_now - now <= server_now - now
// server_time_difference >= max{diff}
bool update_server_time_difference(double diff);
void reset_server_time_difference(double diff);
uint64 get_server_salt(double now) {
update_salt(now);
return server_salt_.salt;
}
void set_server_salt(uint64 salt, double now) {
server_salt_.salt = salt;
double server_time = get_server_time(now);
server_salt_.valid_since = server_time;
server_salt_.valid_until = server_time + 60 * 10;
future_salts_.clear();
}
bool is_server_salt_valid(double now) const {
return server_salt_.valid_until > get_server_time(now) + 60;
}
bool has_salt(double now) {
update_salt(now);
return is_server_salt_valid(now);
}
bool need_future_salts(double now) {
update_salt(now);
return future_salts_.empty() || !is_server_salt_valid(now);
}
void set_future_salts(const std::vector<ServerSalt> &salts, double now);
std::vector<ServerSalt> get_future_salts() const;
MessageId next_message_id(double now);
bool is_valid_outbound_msg_id(MessageId message_id, double now) const;
bool is_valid_inbound_msg_id(MessageId message_id, double now) const;
Status check_packet(uint64 session_id, MessageId message_id, double now, bool &time_difference_was_updated);
Status check_update(MessageId message_id) {
return updates_duplicate_checker_.check(message_id);
}
Status recheck_update(MessageId message_id) {
return updates_duplicate_rechecker_.check(message_id);
}
int32 next_seq_no(bool is_content_related) {
int32 res = seq_no_;
if (is_content_related) {
res |= 1;
seq_no_ += 2;
}
return res;
}
void clear_seq_no() {
seq_no_ = 0;
}
void set_use_pfs(bool use_pfs) {
use_pfs_ = use_pfs;
}
bool use_pfs() const {
return use_pfs_;
}
private:
bool use_pfs_ = true;
AuthKey main_auth_key_;
AuthKey tmp_auth_key_;
bool server_time_difference_was_updated_ = false;
double server_time_difference_ = 0;
ServerSalt server_salt_;
MessageId last_message_id_;
int32 seq_no_ = 0;
string header_;
uint64 session_id_ = 0;
std::vector<ServerSalt> future_salts_;
MessageIdDuplicateChecker<1000> duplicate_checker_;
MessageIdDuplicateChecker<1000> updates_duplicate_checker_;
MessageIdDuplicateChecker<100> updates_duplicate_rechecker_;
void update_salt(double now);
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,134 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/port/Clocks.h"
#include "td/utils/Time.h"
namespace td {
namespace mtproto {
class AuthKey {
public:
AuthKey() = default;
AuthKey(uint64 auth_key_id, string &&auth_key) : auth_key_id_(auth_key_id), auth_key_(auth_key) {
}
void break_key() {
auth_key_id_++;
auth_key_[0]++;
}
bool empty() const {
return auth_key_.empty();
}
const string &key() const {
return auth_key_;
}
uint64 id() const {
return auth_key_id_;
}
bool auth_flag() const {
return auth_flag_;
}
void set_auth_flag(bool new_auth_flag) {
auth_flag_ = new_auth_flag;
}
bool need_header() const {
return have_header_ || Time::now() < header_expires_at_;
}
void remove_header() {
if (auth_flag_ && have_header_) {
have_header_ = false;
header_expires_at_ = Time::now() + 3;
}
}
void restore_header() {
have_header_ = true;
}
double expires_at() const {
return expires_at_;
}
double created_at() const {
return created_at_;
}
void set_expires_at(double expires_at) {
expires_at_ = expires_at;
}
void set_created_at(double created_at) {
created_at_ = created_at;
}
void clear() {
auth_key_.clear();
}
static constexpr int32 AUTH_FLAG = 1;
static constexpr int32 HAS_CREATED_AT = 4;
static constexpr int32 HAS_EXPIRES_AT = 8;
template <class StorerT>
void store(StorerT &storer) const {
storer.store_binary(auth_key_id_);
bool has_created_at = created_at_ != 0;
bool has_expires_at = expires_at_ != 0;
int32 flags = 0;
if (auth_flag_) {
flags |= AUTH_FLAG;
}
if (has_created_at) {
flags |= HAS_CREATED_AT;
}
if (has_expires_at) {
flags |= HAS_EXPIRES_AT;
}
storer.store_binary(flags);
storer.store_string(auth_key_);
if (has_created_at) {
storer.store_binary(created_at_);
}
if (has_expires_at) {
double time_left = max(expires_at_ - Time::now(), 0.0);
storer.store_binary(time_left);
storer.store_binary(Clocks::system());
}
}
template <class ParserT>
void parse(ParserT &parser) {
auth_key_id_ = parser.fetch_long();
auto flags = parser.fetch_int();
auth_flag_ = (flags & AUTH_FLAG) != 0;
auth_key_ = parser.template fetch_string<string>();
if ((flags & HAS_CREATED_AT) != 0) {
created_at_ = parser.fetch_double();
}
if ((flags & HAS_EXPIRES_AT) != 0) {
double time_left = parser.fetch_double();
double old_server_time = parser.fetch_double();
double passed_server_time = max(Clocks::system() - old_server_time, 0.0);
time_left = max(time_left - passed_server_time, 0.0);
expires_at_ = Time::now() + time_left;
}
// just in case
have_header_ = true;
}
private:
uint64 auth_key_id_{0};
string auth_key_;
bool auth_flag_{false};
bool have_header_{true};
double header_expires_at_{0};
double expires_at_{0};
double created_at_{0};
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,70 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/actor/actor.h"
#include "td/utils/common.h"
namespace td {
namespace mtproto {
class ConnectionManager : public Actor {
public:
class ConnectionToken {
public:
ConnectionToken() = default;
explicit ConnectionToken(ActorShared<ConnectionManager> connection_manager)
: connection_manager_(std::move(connection_manager)) {
}
ConnectionToken(const ConnectionToken &) = delete;
ConnectionToken &operator=(const ConnectionToken &) = delete;
ConnectionToken(ConnectionToken &&) = default;
ConnectionToken &operator=(ConnectionToken &&other) noexcept {
reset();
connection_manager_ = std::move(other.connection_manager_);
return *this;
}
~ConnectionToken() {
reset();
}
void reset() {
if (!connection_manager_.empty()) {
send_closure(connection_manager_, &ConnectionManager::dec_connect);
connection_manager_.reset();
}
}
bool empty() const {
return connection_manager_.empty();
}
private:
ActorShared<ConnectionManager> connection_manager_;
};
static ConnectionToken connection(ActorId<ConnectionManager> connection_manager) {
return connection_impl(connection_manager, 1);
}
static ConnectionToken connection_proxy(ActorId<ConnectionManager> connection_manager) {
return connection_impl(connection_manager, 2);
}
protected:
uint32 connect_cnt_ = 0;
uint32 connect_proxy_cnt_ = 0;
private:
void inc_connect();
void dec_connect();
static ConnectionToken connection_impl(ActorId<ConnectionManager> connection_manager, int mode);
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,371 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthData.h"
#include "td/mtproto/MessageId.h"
#include "td/mtproto/MtprotoQuery.h"
#include "td/mtproto/PacketStorer.h"
#include "td/mtproto/utils.h"
#include "td/mtproto/mtproto_api.h"
#include "td/utils/common.h"
#include "td/utils/misc.h"
#include "td/utils/Slice.h"
#include "td/utils/Span.h"
#include "td/utils/StorerBase.h"
#include "td/utils/Time.h"
namespace td {
namespace mtproto_api {
class msg_container {
public:
static const int32 ID = 0x73f1f8dc;
};
} // namespace mtproto_api
namespace mtproto {
template <class Object, class ObjectStorer>
class ObjectImpl {
public:
ObjectImpl(bool not_empty, Object &&object, AuthData *auth_data)
: not_empty_(not_empty), object_(std::move(object)), object_storer_(object_) {
if (empty()) {
return;
}
message_id_ = auth_data->next_message_id(Time::now_cached());
seq_no_ = auth_data->next_seq_no(false);
}
template <class StorerT>
void do_store(StorerT &storer) const {
if (empty()) {
return;
}
storer.store_binary(message_id_);
storer.store_binary(seq_no_);
storer.store_binary(static_cast<int32>(object_storer_.size()));
storer.store_storer(object_storer_);
}
bool not_empty() const {
return not_empty_;
}
bool empty() const {
return !not_empty_;
}
MessageId get_message_id() const {
return message_id_;
}
private:
bool not_empty_;
Object object_;
ObjectStorer object_storer_;
MessageId message_id_;
int32 seq_no_;
};
using AckImpl = ObjectImpl<mtproto_api::msgs_ack, TLObjectStorer<mtproto_api::msgs_ack>>;
using PingImpl = ObjectImpl<mtproto_api::ping_delay_disconnect, TLStorer<mtproto_api::ping_delay_disconnect>>;
using HttpWaitImpl = ObjectImpl<mtproto_api::http_wait, TLStorer<mtproto_api::http_wait>>;
using GetFutureSaltsImpl = ObjectImpl<mtproto_api::get_future_salts, TLStorer<mtproto_api::get_future_salts>>;
using ResendImpl = ObjectImpl<mtproto_api::msg_resend_req, TLObjectStorer<mtproto_api::msg_resend_req>>;
using CancelImpl = ObjectImpl<mtproto_api::rpc_drop_answer, TLStorer<mtproto_api::rpc_drop_answer>>;
using GetInfoImpl = ObjectImpl<mtproto_api::msgs_state_req, TLObjectStorer<mtproto_api::msgs_state_req>>;
using DestroyAuthKeyImpl = ObjectImpl<mtproto_api::destroy_auth_key, TLStorer<mtproto_api::destroy_auth_key>>;
class CancelVectorImpl {
public:
CancelVectorImpl(bool not_empty, const vector<int64> &to_cancel, AuthData *auth_data) {
storers_.reserve(to_cancel.size());
for (auto &request_id : to_cancel) {
storers_.emplace_back(true, mtproto_api::rpc_drop_answer(request_id), auth_data);
}
}
template <class StorerT>
void do_store(StorerT &storer) const {
for (auto &s : storers_) {
storer.store_storer(s);
}
}
bool not_empty() const {
return !storers_.empty();
}
MessageId get_message_id() const {
CHECK(storers_.size() == 1);
return storers_[0].get_message_id();
}
private:
vector<PacketStorer<CancelImpl>> storers_;
};
class InvokeAfter {
public:
explicit InvokeAfter(Span<MessageId> message_ids) : message_ids_(message_ids) {
}
template <class StorerT>
void store(StorerT &storer) const {
if (message_ids_.empty()) {
return;
}
if (message_ids_.size() == 1) {
storer.store_int(static_cast<int32>(0xcb9f372d));
storer.store_binary(message_ids_[0].get());
return;
}
// invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
storer.store_int(static_cast<int32>(0x3dc4b4f0));
storer.store_int(static_cast<int32>(0x1cb5c415));
storer.store_int(narrow_cast<int32>(message_ids_.size()));
for (auto message_id : message_ids_) {
storer.store_binary(message_id.get());
}
}
private:
Span<MessageId> message_ids_;
};
class QueryImpl {
public:
QueryImpl(const MtprotoQuery &query, Slice header) : query_(query), header_(header) {
}
template <class StorerT>
void do_store(StorerT &storer) const {
storer.store_binary(query_.message_id);
storer.store_binary(query_.seq_no);
InvokeAfter invoke_after(query_.invoke_after_message_ids);
auto invoke_after_storer = create_default_storer(invoke_after);
Slice data = query_.packet.as_slice();
mtproto_api::gzip_packed packed(data);
auto plain_storer = create_storer(data);
auto gzip_storer = TLObjectStorer<mtproto_api::gzip_packed>(packed);
const Storer &data_storer =
query_.gzip_flag ? static_cast<const Storer &>(gzip_storer) : static_cast<const Storer &>(plain_storer);
auto header_storer = create_storer(header_);
auto suff_storer = create_storer(invoke_after_storer, data_storer);
auto all_storer = create_storer(header_storer, suff_storer);
storer.store_binary(static_cast<uint32>(all_storer.size()));
storer.store_storer(all_storer);
}
private:
const MtprotoQuery &query_;
Slice header_;
};
class QueryVectorImpl {
public:
QueryVectorImpl(const vector<MtprotoQuery> &to_send, Slice header) : to_send_(to_send), header_(header) {
}
template <class StorerT>
void do_store(StorerT &storer) const {
if (to_send_.empty()) {
return;
}
for (auto &query : to_send_) {
storer.store_storer(PacketStorer<QueryImpl>(query, header_));
}
}
private:
const vector<MtprotoQuery> &to_send_;
Slice header_;
};
class ContainerImpl {
public:
ContainerImpl(int32 cnt, Storer &storer) : cnt_(cnt), storer_(storer) {
}
template <class StorerT>
void do_store(StorerT &storer) const {
storer.store_binary(mtproto_api::msg_container::ID);
storer.store_binary(cnt_);
storer.store_storer(storer_);
}
private:
int32 cnt_;
Storer &storer_;
};
class CryptoImpl {
public:
CryptoImpl(const vector<MtprotoQuery> &to_send, Slice header, vector<int64> &&to_ack, int64 ping_id, int ping_timeout,
int max_delay, int max_after, int max_wait, int future_salt_n, vector<int64> get_info,
vector<int64> resend, const vector<int64> &cancel, bool destroy_key, AuthData *auth_data,
MessageId *container_message_id, MessageId *get_info_message_id, MessageId *resend_message_id,
MessageId *ping_message_id, MessageId *parent_message_id)
: query_storer_(to_send, header)
, ack_empty_(to_ack.empty())
, ack_storer_(!ack_empty_, mtproto_api::msgs_ack(std::move(to_ack)), auth_data)
, http_wait_storer_(max_delay >= 0, mtproto_api::http_wait(max_delay, max_after, max_wait), auth_data)
, get_future_salts_storer_(future_salt_n > 0, mtproto_api::get_future_salts(future_salt_n), auth_data)
, get_info_not_empty_(!get_info.empty())
, get_info_storer_(get_info_not_empty_, mtproto_api::msgs_state_req(std::move(get_info)), auth_data)
, resend_not_empty_(!resend.empty())
, resend_storer_(resend_not_empty_, mtproto_api::msg_resend_req(std::move(resend)), auth_data)
, cancel_not_empty_(!cancel.empty())
, cancel_cnt_(static_cast<int32>(cancel.size()))
, cancel_storer_(cancel_not_empty_, cancel, auth_data)
, destroy_key_storer_(destroy_key, mtproto_api::destroy_auth_key(), auth_data)
, ping_storer_(ping_id != 0, mtproto_api::ping_delay_disconnect(ping_id, ping_timeout), auth_data)
, tmp_storer_(query_storer_, ack_storer_)
, tmp2_storer_(tmp_storer_, http_wait_storer_)
, tmp3_storer_(tmp2_storer_, get_future_salts_storer_)
, tmp4_storer_(tmp3_storer_, get_info_storer_)
, tmp5_storer_(tmp4_storer_, resend_storer_)
, tmp6_storer_(tmp5_storer_, cancel_storer_)
, tmp7_storer_(tmp6_storer_, destroy_key_storer_)
, concat_storer_(tmp7_storer_, ping_storer_)
, cnt_(static_cast<int32>(to_send.size()) + ack_storer_.not_empty() + ping_storer_.not_empty() +
http_wait_storer_.not_empty() + get_future_salts_storer_.not_empty() + get_info_storer_.not_empty() +
resend_storer_.not_empty() + cancel_cnt_ + destroy_key_storer_.not_empty())
, container_storer_(cnt_, concat_storer_) {
CHECK(cnt_ != 0);
if (get_info_storer_.not_empty() && get_info_message_id) {
*get_info_message_id = get_info_storer_.get_message_id();
}
if (resend_storer_.not_empty() && resend_message_id) {
*resend_message_id = resend_storer_.get_message_id();
}
if (ping_storer_.not_empty() && ping_message_id) {
*ping_message_id = ping_storer_.get_message_id();
}
if (cnt_ > 1 ||
(!to_send.empty() && !auth_data->is_valid_outbound_msg_id(to_send[0].message_id, Time::now_cached()))) {
type_ = Mixed;
message_id_ = auth_data->next_message_id(Time::now_cached());
seq_no_ = auth_data->next_seq_no(false);
*container_message_id = message_id_;
*parent_message_id = message_id_;
} else if (!to_send.empty()) {
CHECK(to_send.size() == 1u);
type_ = OnlyQuery;
*parent_message_id = to_send[0].message_id;
} else if (ack_storer_.not_empty()) {
type_ = OnlyAck;
*parent_message_id = ack_storer_.get_message_id();
} else if (ping_storer_.not_empty()) {
type_ = OnlyPing;
*parent_message_id = ping_storer_.get_message_id();
} else if (http_wait_storer_.not_empty()) {
type_ = OnlyHttpWait;
*parent_message_id = http_wait_storer_.get_message_id();
} else if (get_future_salts_storer_.not_empty()) {
type_ = OnlyGetFutureSalts;
*parent_message_id = get_future_salts_storer_.get_message_id();
} else if (get_info_storer_.not_empty()) {
type_ = OnlyGetInfo;
*parent_message_id = get_info_storer_.get_message_id();
} else if (resend_storer_.not_empty()) {
type_ = OnlyResend;
*parent_message_id = resend_storer_.get_message_id();
} else if (cancel_storer_.not_empty()) {
type_ = OnlyCancel;
*parent_message_id = cancel_storer_.get_message_id();
} else if (destroy_key_storer_.not_empty()) {
type_ = OnlyDestroyKey;
*parent_message_id = destroy_key_storer_.get_message_id();
} else {
UNREACHABLE();
}
}
template <class StorerT>
void do_store(StorerT &storer) const {
switch (type_) {
case OnlyAck:
return storer.store_storer(ack_storer_);
case OnlyQuery:
return storer.store_storer(query_storer_);
case OnlyPing:
return storer.store_storer(ping_storer_);
case OnlyHttpWait:
return storer.store_storer(http_wait_storer_);
case OnlyGetFutureSalts:
return storer.store_storer(get_future_salts_storer_);
case OnlyResend:
return storer.store_storer(resend_storer_);
case OnlyCancel:
return storer.store_storer(cancel_storer_);
case OnlyGetInfo:
return storer.store_storer(get_info_storer_);
case OnlyDestroyKey:
return storer.store_storer(destroy_key_storer_);
default:
storer.store_binary(message_id_);
storer.store_binary(seq_no_);
storer.store_binary(static_cast<int32>(container_storer_.size()));
storer.store_storer(container_storer_);
}
}
private:
PacketStorer<QueryVectorImpl> query_storer_;
bool ack_empty_;
PacketStorer<AckImpl> ack_storer_;
PacketStorer<HttpWaitImpl> http_wait_storer_;
PacketStorer<GetFutureSaltsImpl> get_future_salts_storer_;
bool get_info_not_empty_;
PacketStorer<GetInfoImpl> get_info_storer_;
bool resend_not_empty_;
PacketStorer<ResendImpl> resend_storer_;
bool cancel_not_empty_;
int32 cancel_cnt_;
PacketStorer<CancelVectorImpl> cancel_storer_;
PacketStorer<DestroyAuthKeyImpl> destroy_key_storer_;
PacketStorer<PingImpl> ping_storer_;
ConcatStorer tmp_storer_;
ConcatStorer tmp2_storer_;
ConcatStorer tmp3_storer_;
ConcatStorer tmp4_storer_;
ConcatStorer tmp5_storer_;
ConcatStorer tmp6_storer_;
ConcatStorer tmp7_storer_;
ConcatStorer concat_storer_;
int32 cnt_;
PacketStorer<ContainerImpl> container_storer_;
enum Type {
OnlyQuery,
OnlyAck,
OnlyPing,
OnlyHttpWait,
OnlyGetFutureSalts,
OnlyResend,
OnlyCancel,
OnlyGetInfo,
OnlyDestroyKey,
Mixed
};
Type type_;
MessageId message_id_;
int32 seq_no_;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,29 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/Slice.h"
namespace td {
namespace mtproto {
class DhCallback {
public:
DhCallback() = default;
DhCallback(const DhCallback &) = delete;
DhCallback &operator=(const DhCallback &) = delete;
DhCallback(DhCallback &&) = delete;
DhCallback &operator=(DhCallback &&) = delete;
virtual ~DhCallback() = default;
virtual int is_good_prime(Slice prime_str) const = 0;
virtual void add_good_prime(Slice prime_str) const = 0;
virtual void add_bad_prime(Slice prime_str) const = 0;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,124 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/BigNum.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include <utility>
namespace td {
namespace mtproto {
class DhCallback;
class DhHandshake {
public:
void set_config(int32 g_int, Slice prime_str);
static Status check_config(int32 g_int, Slice prime_str, DhCallback *callback);
bool has_config() const {
return has_config_;
}
void set_g_a_hash(Slice g_a_hash);
void set_g_a(Slice g_a_str);
bool has_g_a() const {
return has_g_a_;
}
string get_g_a() const;
string get_g_b() const;
string get_g_b_hash() const;
Status run_checks(bool skip_config_check, DhCallback *callback) TD_WARN_UNUSED_RESULT;
BigNum get_g() const;
BigNum get_p() const;
BigNum get_b() const;
BigNum get_g_ab();
std::pair<int64, string> gen_key();
static int64 calc_key_id(Slice auth_key);
enum Flags { HasConfig = 1, HasGA = 2 };
template <class StorerT>
void store(StorerT &storer) const {
auto flags = 0;
if (has_config_) {
flags |= HasConfig;
}
if (has_g_a_) {
flags |= HasGA;
}
storer.store_int(flags);
if (has_config_) {
// prime_, prime_str_, b_, g_, g_int_, g_b_
storer.store_string(prime_str_);
storer.store_string(b_.to_binary());
storer.store_int(g_int_);
storer.store_string(g_b_.to_binary());
}
if (has_g_a_) {
storer.store_string(g_a_.to_binary());
}
}
template <class ParserT>
void parse(ParserT &parser) {
auto flags = parser.fetch_int();
if (flags & HasConfig) {
has_config_ = true;
}
if (flags & HasGA) {
has_g_a_ = true;
}
if (has_config_) {
// prime_, prime_str_, b_, g_, g_int_, g_b_
prime_str_ = parser.template fetch_string<std::string>();
prime_ = BigNum::from_binary(prime_str_);
b_ = BigNum::from_binary(parser.template fetch_string<string>());
g_int_ = parser.fetch_int();
g_.set_value(g_int_);
g_b_ = BigNum::from_binary(parser.template fetch_string<string>());
}
if (has_g_a_) {
g_a_ = BigNum::from_binary(parser.template fetch_string<string>());
}
}
private:
static Status check_config(Slice prime_str, const BigNum &prime, int32 g_int, BigNumContext &ctx,
DhCallback *callback) TD_WARN_UNUSED_RESULT;
static Status dh_check(const BigNum &prime, const BigNum &g_a, const BigNum &g_b) TD_WARN_UNUSED_RESULT;
string prime_str_;
BigNum prime_;
BigNum g_;
int32 g_int_ = 0;
BigNum b_;
BigNum g_b_;
BigNum g_a_;
string g_a_hash_;
bool has_g_a_hash_{false};
bool ok_g_a_hash_{false};
bool has_config_ = false;
bool has_g_a_ = false;
BigNumContext ctx_;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,109 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthKey.h"
#include "td/mtproto/RSA.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/UInt.h"
namespace td {
namespace mtproto {
class DhCallback;
class AuthKeyHandshakeContext {
public:
virtual ~AuthKeyHandshakeContext() = default;
virtual DhCallback *get_dh_callback() = 0;
virtual PublicRsaKeyInterface *get_public_rsa_key_interface() = 0;
};
class AuthKeyHandshake {
public:
class Callback {
public:
Callback() = default;
Callback(const Callback &) = delete;
Callback &operator=(const Callback &) = delete;
virtual ~Callback() = default;
virtual void send_no_crypto(const Storer &storer) = 0;
};
AuthKeyHandshake(int32 dc_id, int32 expires_in);
void set_timeout_in(double timeout_in);
bool is_ready_for_finish() const;
void on_finish();
void resume(Callback *connection);
Status on_message(Slice message, Callback *connection, AuthKeyHandshakeContext *context) TD_WARN_UNUSED_RESULT;
void clear();
const AuthKey &get_auth_key() const {
return auth_key_;
}
AuthKey release_auth_key() {
return std::move(auth_key_);
}
double get_server_time_diff() const {
return server_time_diff_;
}
uint64 get_server_salt() const {
return server_salt_;
}
private:
enum class State : int32 { Start, ResPQ, ServerDHParams, DHGenResponse, Finish };
State state_ = State::Start;
enum class Mode : int32 { Main, Temp };
Mode mode_ = Mode::Main;
int32 dc_id_ = 0;
int32 expires_in_ = 0;
double expires_at_ = 0;
double start_time_ = 0;
double timeout_in_ = 0;
AuthKey auth_key_;
double server_time_diff_ = 0;
uint64 server_salt_ = 0;
UInt128 nonce_;
UInt128 server_nonce_;
UInt256 new_nonce_;
string last_query_;
template <class T>
static string store_object(const T &object);
void send(Callback *connection, const Storer &storer);
static void do_send(Callback *connection, const Storer &storer);
Status on_start(Callback *connection) TD_WARN_UNUSED_RESULT;
Status on_res_pq(Slice message, Callback *connection, PublicRsaKeyInterface *public_rsa_key) TD_WARN_UNUSED_RESULT;
Status on_server_dh_params(Slice message, Callback *connection, DhCallback *dh_callback) TD_WARN_UNUSED_RESULT;
Status on_dh_gen_response(Slice message, Callback *connection) TD_WARN_UNUSED_RESULT;
friend StringBuilder &operator<<(StringBuilder &string_builder, const State &state);
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,56 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/Handshake.h"
#include "td/mtproto/HandshakeConnection.h"
#include "td/mtproto/RawConnection.h"
#include "td/actor/actor.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
// Owns RawConnection. Generates new auth key. And returns it and RawConnection. Or error...
class HandshakeActor final : public Actor {
public:
HandshakeActor(unique_ptr<AuthKeyHandshake> handshake, unique_ptr<RawConnection> raw_connection,
unique_ptr<AuthKeyHandshakeContext> context, double timeout,
Promise<unique_ptr<RawConnection>> raw_connection_promise,
Promise<unique_ptr<AuthKeyHandshake>> handshake_promise);
void close();
private:
unique_ptr<AuthKeyHandshake> handshake_;
unique_ptr<HandshakeConnection> connection_;
double timeout_;
Promise<unique_ptr<RawConnection>> raw_connection_promise_;
Promise<unique_ptr<AuthKeyHandshake>> handshake_promise_;
void start_up() final;
void tear_down() final;
void hangup() final;
void timeout_expired() final;
void loop() final;
void finish(Status status);
void return_connection(Status status);
void return_handshake();
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,86 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthKey.h"
#include "td/mtproto/Handshake.h"
#include "td/mtproto/MessageId.h"
#include "td/mtproto/NoCryptoStorer.h"
#include "td/mtproto/PacketInfo.h"
#include "td/mtproto/PacketStorer.h"
#include "td/mtproto/RawConnection.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/format.h"
#include "td/utils/logging.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
namespace td {
namespace mtproto {
class HandshakeConnection final
: private RawConnection::Callback
, private AuthKeyHandshake::Callback {
public:
HandshakeConnection(unique_ptr<RawConnection> raw_connection, AuthKeyHandshake *handshake,
unique_ptr<AuthKeyHandshakeContext> context)
: raw_connection_(std::move(raw_connection)), handshake_(handshake), context_(std::move(context)) {
handshake_->resume(this);
}
PollableFdInfo &get_poll_info() {
return raw_connection_->get_poll_info();
}
unique_ptr<RawConnection> move_as_raw_connection() {
return std::move(raw_connection_);
}
void close() {
raw_connection_->close();
}
Status flush() {
auto status = raw_connection_->flush(AuthKey(), *this);
if (status.code() == -404) {
LOG(WARNING) << "Clear handshake " << tag("error", status);
handshake_->clear();
}
return status;
}
private:
unique_ptr<RawConnection> raw_connection_;
AuthKeyHandshake *handshake_;
unique_ptr<AuthKeyHandshakeContext> context_;
void send_no_crypto(const Storer &storer) final {
raw_connection_->send_no_crypto(PacketStorer<NoCryptoImpl>(MessageId(), storer));
}
Status on_raw_packet(const PacketInfo &packet_info, BufferSlice packet) final {
if (!packet_info.no_crypto_flag) {
return Status::Error("Expected not encrypted packet");
}
// skip header
if (packet.size() < 12) {
return Status::Error("Result is too small");
}
packet.confirm_read(12);
auto fixed_packet_size = packet.size() & ~3; // remove some padded data
TRY_STATUS(handshake_->on_message(packet.as_slice().truncate(fixed_packet_size), this, context_.get()));
return Status::OK();
}
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,59 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TransportType.h"
#include "td/net/HttpQuery.h"
#include "td/net/HttpReader.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
namespace http {
class Transport final : public IStreamTransport {
public:
explicit Transport(string secret) : secret_(std::move(secret)) {
}
Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) final TD_WARN_UNUSED_RESULT;
bool support_quick_ack() const final {
return false;
}
void write(BufferWriter &&message, bool quick_ack) final;
bool can_read() const final;
bool can_write() const final;
void init(ChainBufferReader *input, ChainBufferWriter *output) final {
reader_.init(input);
output_ = output;
}
size_t max_prepend_size() const final;
size_t max_append_size() const final;
TransportType get_type() const final {
return {TransportType::Http, 0, ProxySecret::from_raw(secret_)};
}
bool use_random_padding() const final;
private:
string secret_;
HttpReader reader_;
HttpQuery http_query_;
ChainBufferWriter *output_ = nullptr;
enum { Write, Read } turn_ = Write;
};
} // namespace http
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,40 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/TransportType.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class IStreamTransport {
public:
IStreamTransport() = default;
IStreamTransport(const IStreamTransport &) = delete;
IStreamTransport &operator=(const IStreamTransport &) = delete;
virtual ~IStreamTransport() = default;
virtual Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) = 0;
virtual bool support_quick_ack() const = 0;
virtual void write(BufferWriter &&message, bool quick_ack) = 0;
virtual bool can_read() const = 0;
virtual bool can_write() const = 0;
virtual void init(ChainBufferReader *input, ChainBufferWriter *output) = 0;
virtual size_t max_prepend_size() const = 0;
virtual size_t max_append_size() const = 0;
virtual TransportType get_type() const = 0;
virtual bool use_random_padding() const = 0;
};
unique_ptr<IStreamTransport> create_transport(TransportType type);
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,22 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/Slice.h"
#include "td/utils/UInt.h"
namespace td {
namespace mtproto {
void KDF(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt256 *aes_iv);
void tmp_KDF(const UInt128 &server_nonce, const UInt256 &new_nonce, UInt256 *tmp_aes_key, UInt256 *tmp_aes_iv);
void KDF2(Slice auth_key, const UInt128 &msg_key, int X, UInt256 *aes_key, UInt256 *aes_iv);
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,70 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/format.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h"
#include <type_traits>
namespace td {
namespace mtproto {
class MessageId {
uint64 message_id_ = 0;
public:
MessageId() = default;
explicit constexpr MessageId(uint64 message_id) : message_id_(message_id) {
}
template <class T, typename = std::enable_if_t<std::is_convertible<T, int64>::value>>
MessageId(T message_id) = delete;
uint64 get() const {
return message_id_;
}
bool operator==(const MessageId &other) const {
return message_id_ == other.message_id_;
}
bool operator!=(const MessageId &other) const {
return message_id_ != other.message_id_;
}
friend bool operator<(const MessageId &lhs, const MessageId &rhs) {
return lhs.get() < rhs.get();
}
friend bool operator>(const MessageId &lhs, const MessageId &rhs) {
return lhs.get() > rhs.get();
}
friend bool operator<=(const MessageId &lhs, const MessageId &rhs) {
return lhs.get() <= rhs.get();
}
friend bool operator>=(const MessageId &lhs, const MessageId &rhs) {
return lhs.get() >= rhs.get();
}
};
struct MessageIdHash {
uint32 operator()(MessageId message_id) const {
return Hash<uint64>()(message_id.get());
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, MessageId message_id) {
return string_builder << "message " << format::as_hex(message_id.get());
}
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,27 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/MessageId.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
namespace td {
namespace mtproto {
struct MtprotoQuery {
MessageId message_id;
int32 seq_no;
BufferSlice packet;
bool gzip_flag;
vector<MessageId> invoke_after_message_ids;
bool use_quick_ack;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,43 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/MessageId.h"
#include "td/utils/Random.h"
#include "td/utils/StorerBase.h"
namespace td {
namespace mtproto {
class NoCryptoImpl {
public:
NoCryptoImpl(MessageId message_id, const Storer &data, bool need_pad = true) : message_id_(message_id), data_(data) {
if (need_pad) {
size_t pad_size = -static_cast<int>(data_.size()) & 15;
pad_size += 16 * (static_cast<size_t>(Random::secure_int32()) % 16);
pad_.resize(pad_size);
Random::secure_bytes(pad_);
}
}
template <class StorerT>
void do_store(StorerT &storer) const {
storer.store_binary(message_id_.get());
storer.store_binary(static_cast<int32>(data_.size() + pad_.size()));
storer.store_storer(data_);
storer.store_slice(pad_);
}
private:
MessageId message_id_;
const Storer &data_;
std::string pad_;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,33 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/MessageId.h"
#include "td/utils/common.h"
namespace td {
namespace mtproto {
struct PacketInfo {
enum { Common, EndToEnd } type = Common;
uint32 message_ack{0};
uint64 salt{0};
uint64 session_id{0};
MessageId message_id;
int32 seq_no{0};
int32 version{1};
bool no_crypto_flag{false};
bool is_creator{false};
bool check_mod4{true};
bool use_random_padding{false};
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,44 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/StorerBase.h"
#include "td/utils/tl_storers.h"
#include <limits>
namespace td {
namespace mtproto {
template <class Impl>
class PacketStorer final
: public Storer
, public Impl {
public:
size_t size() const final {
if (size_ != std::numeric_limits<size_t>::max()) {
return size_;
}
TlStorerCalcLength storer;
this->do_store(storer);
return size_ = storer.get_length();
}
size_t store(uint8 *ptr) const final {
TlStorerUnsafe storer(ptr);
this->do_store(storer);
return static_cast<size_t>(storer.get_buf() - ptr);
}
using Impl::Impl;
private:
mutable size_t size_ = std::numeric_limits<size_t>::max();
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,25 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthData.h"
#include "td/mtproto/RawConnection.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
#include "td/utils/Slice.h"
namespace td {
namespace mtproto {
ActorOwn<> create_ping_actor(Slice actor_name, unique_ptr<RawConnection> raw_connection, unique_ptr<AuthData> auth_data,
Promise<unique_ptr<RawConnection>> promise, ActorShared<> parent);
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,34 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/AuthData.h"
#include "td/mtproto/RawConnection.h"
#include "td/utils/common.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class PingConnection {
public:
virtual ~PingConnection() = default;
virtual PollableFdInfo &get_poll_info() = 0;
virtual unique_ptr<RawConnection> move_as_raw_connection() = 0;
virtual Status flush() = 0;
virtual bool was_pong() const = 0;
virtual double rtt() const = 0;
static unique_ptr<PingConnection> create_req_pq(unique_ptr<RawConnection> raw_connection, size_t ping_count);
static unique_ptr<PingConnection> create_ping_pong(unique_ptr<RawConnection> raw_connection,
unique_ptr<AuthData> auth_data);
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,69 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class ProxySecret {
public:
static constexpr size_t MAX_DOMAIN_LENGTH = 182; // must be small enough to not overflow TLS-hello length
static Result<ProxySecret> from_link(Slice encoded_secret, bool truncate_if_needed = false);
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret, bool truncate_if_needed = false);
static ProxySecret from_raw(Slice raw_secret) {
ProxySecret result;
result.secret_ = raw_secret.str();
return result;
}
Slice get_raw_secret() const {
return secret_;
}
Slice get_proxy_secret() const {
Slice proxy_secret(secret_);
if (proxy_secret.size() >= 17) {
return proxy_secret.substr(1, 16);
}
return proxy_secret;
}
string get_encoded_secret() const;
bool use_random_padding() const {
return secret_.size() >= 17;
}
bool emulate_tls() const {
return secret_.size() >= 17 && static_cast<unsigned char>(secret_[0]) == 0xee;
}
string get_domain() const {
CHECK(emulate_tls());
return secret_.substr(17);
}
private:
friend bool operator==(const ProxySecret &lhs, const ProxySecret &rhs) {
return lhs.secret_ == rhs.secret_;
}
string secret_;
};
inline bool operator!=(const ProxySecret &lhs, const ProxySecret &rhs) {
return !(lhs == rhs);
}
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,49 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/BigNum.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class RSA {
public:
RSA clone() const;
int64 get_fingerprint() const;
size_t size() const;
bool encrypt(Slice from, MutableSlice to) const;
void decrypt_signature(Slice from, MutableSlice to) const;
static Result<RSA> from_pem_public_key(Slice pem);
private:
RSA(BigNum n, BigNum e);
BigNum n_;
BigNum e_;
};
class PublicRsaKeyInterface {
public:
virtual ~PublicRsaKeyInterface() = default;
struct RsaKey {
RSA rsa;
int64 fingerprint;
};
virtual Result<RsaKey> get_rsa_key(const vector<int64> &fingerprints) = 0;
virtual void drop_keys() = 0;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,92 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/ConnectionManager.h"
#include "td/mtproto/PacketInfo.h"
#include "td/mtproto/TransportType.h"
#include "td/utils/buffer.h"
#include "td/utils/BufferedFd.h"
#include "td/utils/common.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/port/IPAddress.h"
#include "td/utils/port/SocketFd.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
namespace td {
namespace mtproto {
class AuthKey;
class RawConnection {
public:
class StatsCallback {
public:
virtual ~StatsCallback() = default;
virtual void on_read(uint64 bytes) = 0;
virtual void on_write(uint64 bytes) = 0;
virtual void on_pong() = 0; // called when we know that connection is alive
virtual void on_error() = 0; // called on RawConnection error. Such error should be very rare on good connections.
virtual void on_mtproto_error() = 0;
};
RawConnection() = default;
RawConnection(const RawConnection &) = delete;
RawConnection &operator=(const RawConnection &) = delete;
virtual ~RawConnection();
static unique_ptr<RawConnection> create(IPAddress ip_address, BufferedFd<SocketFd> buffered_socket_fd,
TransportType transport_type, unique_ptr<StatsCallback> stats_callback);
virtual void set_connection_token(ConnectionManager::ConnectionToken connection_token) = 0;
virtual bool can_send() const = 0;
virtual TransportType get_transport_type() const = 0;
virtual size_t send_crypto(const Storer &storer, uint64 session_id, int64 salt, const AuthKey &auth_key,
uint64 quick_ack_token) = 0;
virtual void send_no_crypto(const Storer &storer) = 0;
virtual PollableFdInfo &get_poll_info() = 0;
virtual StatsCallback *stats_callback() = 0;
class Callback {
public:
Callback() = default;
Callback(const Callback &) = delete;
Callback &operator=(const Callback &) = delete;
virtual ~Callback() = default;
virtual Status on_raw_packet(const PacketInfo &packet_info, BufferSlice packet) = 0;
virtual Status on_quick_ack(uint64 quick_ack_token) {
return Status::Error("Quick acknowledgements aren't supported by the callback");
}
virtual Status before_write() {
return Status::OK();
}
virtual void on_read(size_t size) {
}
};
// NB: After first returned error, all subsequent calls will return error too.
virtual Status flush(const AuthKey &auth_key, Callback &callback) TD_WARN_UNUSED_RESULT = 0;
virtual bool has_error() const = 0;
virtual void close() = 0;
struct PublicFields {
uint32 extra{0};
string debug_str;
double rtt{0};
};
virtual PublicFields &extra() = 0;
virtual const PublicFields &extra() const = 0;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,288 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/MessageId.h"
#include "td/mtproto/MtprotoQuery.h"
#include "td/mtproto/PacketInfo.h"
#include "td/mtproto/RawConnection.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/logging.h"
#include "td/utils/Named.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/ScopeGuard.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_parsers.h"
#include <utility>
namespace td {
extern int VERBOSITY_NAME(mtproto);
namespace mtproto_api {
class new_session_created;
class bad_msg_notification;
class bad_server_salt;
class msgs_ack;
class gzip_packed;
class pong;
class future_salts;
class msgs_state_info;
class msgs_all_info;
class msg_detailed_info;
class msg_new_detailed_info;
class DestroyAuthKeyRes;
class destroy_auth_key_ok;
class destroy_auth_key_fail;
class destroy_auth_key_none;
} // namespace mtproto_api
namespace mtproto {
class AuthData;
class SessionConnection final
: public Named
, private RawConnection::Callback {
public:
enum class Mode : int32 { Tcp, Http, HttpLongPoll };
SessionConnection(Mode mode, unique_ptr<RawConnection> raw_connection, AuthData *auth_data);
SessionConnection(const SessionConnection &) = delete;
SessionConnection &operator=(const SessionConnection &) = delete;
SessionConnection(SessionConnection &&) = delete;
SessionConnection &operator=(SessionConnection &&) = delete;
~SessionConnection() = default;
PollableFdInfo &get_poll_info();
unique_ptr<RawConnection> move_as_raw_connection();
// Interface
MessageId send_query(BufferSlice buffer, bool gzip_flag, MessageId message_id,
vector<MessageId> invoke_after_message_ids, bool use_quick_ack);
std::pair<MessageId, BufferSlice> encrypted_bind(int64 perm_key, int64 nonce, int32 expires_at);
void get_state_info(MessageId message_id);
void resend_answer(MessageId message_id);
void cancel_answer(MessageId message_id);
void destroy_key();
void set_online(bool online_flag, bool is_main);
void force_ack();
Slice get_debug_str() const {
return raw_connection_ == nullptr ? Slice() : raw_connection_->extra().debug_str;
}
class Callback {
public:
Callback() = default;
Callback(const Callback &) = delete;
Callback &operator=(const Callback &) = delete;
virtual ~Callback() = default;
virtual void on_connected() = 0;
virtual void on_closed(Status status) = 0;
virtual void on_server_salt_updated() = 0;
virtual void on_server_time_difference_updated(bool force) = 0;
virtual void on_new_session_created(uint64 unique_id, MessageId first_message_id) = 0;
virtual void on_session_failed(Status status) = 0;
virtual void on_container_sent(MessageId container_message_id, vector<MessageId> message_ids) = 0;
virtual Status on_pong(double ping_time, double pong_time, double current_time) = 0;
virtual Status on_update(BufferSlice packet) = 0;
virtual void on_message_ack(MessageId message_id) = 0;
virtual Status on_message_result_ok(MessageId message_id, BufferSlice packet, size_t original_size) = 0;
virtual void on_message_result_error(MessageId message_id, int code, string message) = 0;
virtual void on_message_failed(MessageId message_id, Status status) = 0;
virtual void on_message_info(MessageId message_id, int32 state, MessageId answer_message_id, int32 answer_size,
int32 source) = 0;
virtual Status on_destroy_auth_key() = 0;
};
double flush(SessionConnection::Callback *callback);
// NB: Do not call force_close after on_closed callback
void force_close(SessionConnection::Callback *callback);
private:
static constexpr int ACK_DELAY = 30; // 30s
static constexpr double QUERY_DELAY = 0.001; // 0.001s
static constexpr double RESEND_ANSWER_DELAY = 0.001; // 0.001s
struct MsgInfo {
MessageId message_id;
int32 seq_no;
size_t size;
};
friend StringBuilder &operator<<(StringBuilder &string_builder, const MsgInfo &info);
bool online_flag_ = false;
bool is_main_ = false;
bool was_moved_ = false;
double rtt() const {
return max(2.0, raw_connection_->extra().rtt * 1.5 + 1);
}
double read_disconnect_delay() const {
return online_flag_ ? rtt() * 3.5 : 135 + random_delay_;
}
double ping_disconnect_delay() const {
return online_flag_ && is_main_ ? rtt() * 2.5 : 135 + random_delay_;
}
double ping_may_delay() const {
return online_flag_ ? rtt() * 0.5 : 30 + random_delay_;
}
double ping_must_delay() const {
return online_flag_ ? rtt() : 60 + random_delay_;
}
double http_max_wait() const {
return 25.0; // 25s. Longer could be closed by proxy
}
static constexpr int HTTP_MAX_AFTER = 10; // 0.01s
static constexpr int HTTP_MAX_DELAY = 30; // 0.03s
vector<MtprotoQuery> to_send_;
vector<MessageId> to_ack_message_ids_;
double force_send_at_ = 0;
struct ServiceQuery {
enum Type { GetStateInfo, ResendAnswer } type_;
MessageId container_message_id_;
vector<int64> msg_ids_;
};
vector<MessageId> to_resend_answer_message_ids_;
vector<MessageId> to_cancel_answer_message_ids_;
vector<MessageId> to_get_state_info_message_ids_;
FlatHashMap<MessageId, ServiceQuery, MessageIdHash> service_queries_;
// nobody cleans up this map. But it should be really small.
FlatHashMap<MessageId, vector<MessageId>, MessageIdHash> container_to_service_message_id_;
double random_delay_ = 0;
double last_read_at_ = 0;
double last_ping_at_ = 0;
double last_pong_at_ = 0;
double real_last_read_at_ = 0;
double real_last_pong_at_ = 0;
MessageId last_ping_message_id_;
MessageId last_ping_container_message_id_;
uint64 last_read_size_ = 0;
uint64 last_write_size_ = 0;
bool need_destroy_auth_key_ = false;
bool sent_destroy_auth_key_ = false;
double destroy_auth_key_send_time_ = 0.0;
double flush_packet_at_ = 0;
double last_get_future_salt_at_ = 0;
enum { Init, Run, Fail, Closed } state_;
Mode mode_;
bool connected_flag_ = false;
MessageId container_message_id_;
MessageId main_message_id_;
double created_at_ = 0;
unique_ptr<RawConnection> raw_connection_;
AuthData *const auth_data_;
SessionConnection::Callback *callback_ = nullptr;
BufferSlice *current_buffer_slice_ = nullptr;
BufferSlice as_buffer_slice(Slice packet);
auto set_buffer_slice(BufferSlice *buffer_slice) TD_WARN_UNUSED_RESULT {
auto old_buffer_slice = current_buffer_slice_;
current_buffer_slice_ = buffer_slice;
return ScopeExit() + [&to = current_buffer_slice_, from = old_buffer_slice] {
to = from;
};
}
void reset_server_time_difference(MessageId message_id);
static Status parse_message(TlParser &parser, MsgInfo *info, Slice *packet,
bool crypto_flag = true) TD_WARN_UNUSED_RESULT;
Status parse_packet(TlParser &parser) TD_WARN_UNUSED_RESULT;
Status on_packet_container(const MsgInfo &info, Slice packet) TD_WARN_UNUSED_RESULT;
Status on_packet_rpc_result(const MsgInfo &info, Slice packet) TD_WARN_UNUSED_RESULT;
template <class T>
Status on_packet(const MsgInfo &info, const T &packet) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info,
const mtproto_api::new_session_created &new_session_created) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info,
const mtproto_api::bad_msg_notification &bad_msg_notification) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::bad_server_salt &bad_server_salt) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::msgs_ack &msgs_ack) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::gzip_packed &gzip_packed) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::pong &pong) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::future_salts &salts) TD_WARN_UNUSED_RESULT;
Status on_msgs_state_info(const vector<int64> &msg_ids, Slice info) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::msgs_state_info &msgs_state_info) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::msgs_all_info &msgs_all_info) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::msg_detailed_info &msg_detailed_info) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info,
const mtproto_api::msg_new_detailed_info &msg_new_detailed_info) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info, const mtproto_api::destroy_auth_key_ok &destroy_auth_key) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info,
const mtproto_api::destroy_auth_key_none &destroy_auth_key) TD_WARN_UNUSED_RESULT;
Status on_packet(const MsgInfo &info,
const mtproto_api::destroy_auth_key_fail &destroy_auth_key) TD_WARN_UNUSED_RESULT;
Status on_destroy_auth_key(const mtproto_api::DestroyAuthKeyRes &destroy_auth_key);
Status on_slice_packet(const MsgInfo &info, Slice packet) TD_WARN_UNUSED_RESULT;
Status on_main_packet(const PacketInfo &packet_info, Slice packet) TD_WARN_UNUSED_RESULT;
void on_message_failed(MessageId message_id, Status status);
void on_message_failed_inner(MessageId message_id);
void do_close(Status status);
void send_ack(MessageId message_id);
void send_crypto(const Storer &storer, uint64 quick_ack_token);
void send_before(double tm);
bool may_ping() const;
bool must_ping() const;
bool must_flush_packet();
void flush_packet();
Status init() TD_WARN_UNUSED_RESULT;
Status do_flush() TD_WARN_UNUSED_RESULT;
Status before_write() final TD_WARN_UNUSED_RESULT;
Status on_raw_packet(const PacketInfo &packet_info, BufferSlice packet) final;
Status on_quick_ack(uint64 quick_ack_token) final;
void on_read(size_t size) final;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,181 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TlsReaderByteFlow.h"
#include "td/mtproto/TransportType.h"
#include "td/utils/AesCtrByteFlow.h"
#include "td/utils/buffer.h"
#include "td/utils/ByteFlow.h"
#include "td/utils/common.h"
#include "td/utils/crypto.h"
#include "td/utils/port/detail/PollableFd.h"
#include "td/utils/Status.h"
#include "td/utils/UInt.h"
namespace td {
namespace mtproto {
namespace tcp {
class IntermediateTransport {
public:
explicit IntermediateTransport(bool with_padding) : with_padding_(with_padding) {
}
// Writes a packet into message.
// Returns 0 if everything is ok, and [expected_size] otherwise.
// There is no sense to call this function when [stream->size > expected_size]
//
// (TCP is a stream-oriented protocol, so the input message is a stream, not a slice)
size_t read_from_stream(ChainBufferReader *stream, BufferSlice *message, uint32 *quick_ack);
// Writes header inplace.
void write_prepare_inplace(BufferWriter *message, bool quick_ack);
// Writes first several bytes into output stream.
void init_output_stream(ChainBufferWriter *stream);
bool with_padding() const {
return with_padding_;
}
private:
bool with_padding_;
};
class OldTransport final : public IStreamTransport {
public:
OldTransport() = default;
Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) final TD_WARN_UNUSED_RESULT {
return impl_.read_from_stream(input_, message, quick_ack);
}
bool support_quick_ack() const final {
return true;
}
void write(BufferWriter &&message, bool quick_ack) final {
impl_.write_prepare_inplace(&message, quick_ack);
output_->append(message.as_buffer_slice());
}
void init(ChainBufferReader *input, ChainBufferWriter *output) final {
input_ = input;
output_ = output;
impl_.init_output_stream(output_);
}
bool can_read() const final {
return true;
}
bool can_write() const final {
return true;
}
size_t max_prepend_size() const final {
return 4;
}
size_t max_append_size() const final {
return 15;
}
TransportType get_type() const final {
return TransportType{TransportType::Tcp, 0, ProxySecret()};
}
bool use_random_padding() const final {
return false;
}
private:
IntermediateTransport impl_{false};
ChainBufferReader *input_{nullptr};
ChainBufferWriter *output_{nullptr};
};
class ObfuscatedTransport final : public IStreamTransport {
public:
ObfuscatedTransport(int16 dc_id, ProxySecret secret)
: dc_id_(dc_id), secret_(std::move(secret)), impl_(secret_.use_random_padding()) {
}
Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) final TD_WARN_UNUSED_RESULT;
bool support_quick_ack() const final {
return true;
}
void write(BufferWriter &&message, bool quick_ack) final;
void init(ChainBufferReader *input, ChainBufferWriter *output) final;
bool can_read() const final {
return true;
}
bool can_write() const final {
return true;
}
size_t max_prepend_size() const final {
size_t res = 4;
if (secret_.emulate_tls()) {
res += 5;
if (is_first_tls_packet_) {
res += 6;
}
}
res += header_.size();
if (res & 3) {
res += 4 - (res & 3);
}
return res;
}
size_t max_append_size() const final {
return 15;
}
TransportType get_type() const final {
return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_};
}
bool use_random_padding() const final {
return secret_.use_random_padding();
}
private:
int16 dc_id_;
bool is_first_tls_packet_{true};
ProxySecret secret_;
std::string header_;
IntermediateTransport impl_;
TlsReaderByteFlow tls_reader_byte_flow_;
AesCtrByteFlow aes_ctr_byte_flow_;
ByteFlowSink byte_flow_sink_;
ChainBufferReader *input_ = nullptr;
static constexpr int32 MAX_TLS_PACKET_LENGTH = 2878;
// TODO: use ByteFlow?
// One problem is that BufferedFd owns output_buffer_
// The other problem is that first 56 bytes must be sent unencrypted.
UInt256 output_key_;
AesCtrState output_state_;
ChainBufferWriter *output_ = nullptr;
void do_write_tls(BufferWriter &&message);
void do_write_tls(BufferBuilder &&builder);
void do_write_main(BufferWriter &&message);
void do_write(BufferSlice &&message);
};
using Transport = ObfuscatedTransport;
} // namespace tcp
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,51 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/net/TransparentProxy.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/port/IPAddress.h"
#include "td/utils/port/SocketFd.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class Grease {
public:
static void init(MutableSlice res);
};
class TlsInit final : public TransparentProxy {
public:
TlsInit(SocketFd socket_fd, string domain, string secret, unique_ptr<Callback> callback, ActorShared<> parent,
double server_time_difference)
: TransparentProxy(std::move(socket_fd), IPAddress(), std::move(domain), std::move(secret), std::move(callback),
std::move(parent))
, server_time_difference_(server_time_difference) {
}
private:
double server_time_difference_{0};
enum class State {
SendHello,
WaitHelloResponse,
} state_ = State::SendHello;
std::string hello_rand_;
void send_hello();
Status wait_hello_response();
Status loop_impl() final;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,20 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/ByteFlow.h"
namespace td {
namespace mtproto {
class TlsReaderByteFlow final : public ByteFlowBase {
public:
bool loop() final;
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,139 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/PacketInfo.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/logging.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StorerBase.h"
#include "td/utils/UInt.h"
#include <utility>
namespace td {
extern int VERBOSITY_NAME(raw_mtproto);
namespace mtproto {
class AuthKey;
class Transport {
public:
class ReadResult {
public:
enum Type { Packet, Nop, Error, Quickack };
static ReadResult make_nop() {
return {};
}
static ReadResult make_error(int32 error_code) {
ReadResult res;
res.type_ = Error;
res.error_code_ = error_code;
return res;
}
static ReadResult make_packet(MutableSlice packet) {
CHECK(!packet.empty());
ReadResult res;
res.type_ = Packet;
res.packet_ = packet;
return res;
}
static ReadResult make_quick_ack(uint32 quick_ack) {
ReadResult res;
res.type_ = Quickack;
res.quick_ack_ = quick_ack;
return res;
}
Type type() const {
return type_;
}
MutableSlice packet() const {
CHECK(type_ == Packet);
return packet_;
}
uint32 quick_ack() const {
CHECK(type_ == Quickack);
return quick_ack_;
}
int32 error() const {
CHECK(type_ == Error);
return error_code_;
}
private:
Type type_ = Nop;
MutableSlice packet_;
int32 error_code_ = 0;
uint32 quick_ack_ = 0;
};
static Result<uint64> read_auth_key_id(Slice message);
// Reads MTProto packet from [message] and saves it into [data].
// If message is encrypted, [auth_key] is used.
// Decryption and unpacking is made inplace, so [data] will be subslice of [message].
// Returns size of MTProto packet.
// If dest.size() >= size, the packet is also written into [dest].
// If auth_key is nonempty, encryption will be used.
static Result<ReadResult> read(MutableSlice message, const AuthKey &auth_key,
PacketInfo *packet_info) TD_WARN_UNUSED_RESULT;
static BufferWriter write(const Storer &storer, const AuthKey &auth_key, PacketInfo *packet_info,
size_t prepend_size = 0, size_t append_size = 0);
// public for testing purposes
static std::pair<uint32, UInt128> calc_message_key2(const AuthKey &auth_key, int X, Slice to_encrypt);
private:
template <class HeaderT>
static std::pair<uint32, UInt128> calc_message_ack_and_key(const HeaderT &head, size_t data_size);
template <class HeaderT>
static size_t calc_crypto_size(size_t data_size);
template <class HeaderT>
static size_t calc_crypto_size2(size_t data_size, PacketInfo *packet_info);
static size_t calc_no_crypto_size(size_t data_size);
static Status read_no_crypto(MutableSlice message, PacketInfo *packet_info, MutableSlice *data) TD_WARN_UNUSED_RESULT;
static Status read_crypto(MutableSlice message, const AuthKey &auth_key, PacketInfo *packet_info,
MutableSlice *data) TD_WARN_UNUSED_RESULT;
static Status read_e2e_crypto(MutableSlice message, const AuthKey &auth_key, PacketInfo *packet_info,
MutableSlice *data) TD_WARN_UNUSED_RESULT;
template <class HeaderT, class PrefixT>
static Status read_crypto_impl(int X, MutableSlice message, const AuthKey &auth_key, HeaderT **header_ptr,
PrefixT **prefix_ptr, MutableSlice *data,
PacketInfo *packet_info) TD_WARN_UNUSED_RESULT;
static BufferWriter write_no_crypto(const Storer &storer, PacketInfo *packet_info, size_t prepend_size,
size_t append_size);
static BufferWriter write_crypto(const Storer &storer, const AuthKey &auth_key, PacketInfo *packet_info,
size_t prepend_size, size_t append_size);
static BufferWriter write_e2e_crypto(const Storer &storer, const AuthKey &auth_key, PacketInfo *packet_info,
size_t prepend_size, size_t append_size);
template <class HeaderT>
static void write_crypto_impl(int X, const Storer &storer, const AuthKey &auth_key, PacketInfo *packet_info,
HeaderT *header, size_t data_size, size_t padded_size);
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,27 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/mtproto/ProxySecret.h"
#include "td/utils/common.h"
namespace td {
namespace mtproto {
struct TransportType {
enum Type { Tcp, ObfuscatedTcp, Http } type = Tcp;
int16 dc_id{0};
ProxySecret secret;
TransportType() = default;
TransportType(Type type, int16 dc_id, ProxySecret secret) : type(type), dc_id(dc_id), secret(std::move(secret)) {
}
};
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,55 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/Storer.h"
#include "td/utils/StorerBase.h"
#include "td/utils/tl_storers.h"
#include <limits>
namespace td {
template <class T>
using TLStorer = DefaultStorer<T>;
template <class T>
class TLObjectStorer final : public Storer {
mutable size_t size_ = std::numeric_limits<size_t>::max();
const T &object_;
public:
explicit TLObjectStorer(const T &object) : object_(object) {
}
size_t size() const final {
if (size_ == std::numeric_limits<size_t>::max()) {
TlStorerCalcLength storer;
storer.store_binary(T::ID);
object_.store(storer);
size_ = storer.get_length();
}
return size_;
}
size_t store(uint8 *ptr) const final {
TlStorerUnsafe storer(ptr);
storer.store_binary(T::ID);
object_.store(storer);
return static_cast<size_t>(storer.get_buf() - ptr);
}
};
namespace mtproto_api {
class Function;
} // namespace mtproto_api
namespace mtproto {
TLStorer<mtproto_api::Function> create_function_storer(const mtproto_api::Function &function);
} // namespace mtproto
} // namespace td

View File

@ -0,0 +1,82 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/ChannelId.h"
#include "td/telegram/ChatId.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h"
#include <type_traits>
namespace td {
class AccentColorId {
int32 id = -1;
public:
AccentColorId() = default;
explicit constexpr AccentColorId(int32 accent_color_id) : id(accent_color_id) {
}
template <class T, typename = std::enable_if_t<std::is_convertible<T, int32>::value>>
AccentColorId(T accent_color_id) = delete;
explicit AccentColorId(UserId user_id) : id(static_cast<int32>(user_id.get() % 7)) {
}
explicit AccentColorId(ChatId chat_id) : id(static_cast<int32>(chat_id.get() % 7)) {
}
explicit AccentColorId(ChannelId channel_id) : id(static_cast<int32>(channel_id.get() % 7)) {
}
bool is_valid() const {
return id >= 0;
}
bool is_built_in() const {
return 0 <= id && id < 7;
}
int32 get() const {
return id;
}
bool operator==(const AccentColorId &other) const {
return id == other.id;
}
bool operator!=(const AccentColorId &other) const {
return id != other.id;
}
template <class StorerT>
void store(StorerT &storer) const {
storer.store_int(id);
}
template <class ParserT>
void parse(ParserT &parser) {
id = parser.fetch_int();
}
};
struct AccentColorIdHash {
uint32 operator()(AccentColorId accent_color_id) const {
return Hash<int32>()(accent_color_id.get());
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, AccentColorId accent_color_id) {
return string_builder << "accent color #" << accent_color_id.get();
}
} // namespace td

View File

@ -0,0 +1,15 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
namespace td {
enum class AccessRights : int32 { Know, Read, Edit, Write };
} // namespace td

View File

@ -0,0 +1,136 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
namespace td {
struct BinlogEvent;
class Td;
class AccountManager final : public Actor {
public:
AccountManager(Td *td, ActorShared<> parent);
AccountManager(const AccountManager &) = delete;
AccountManager &operator=(const AccountManager &) = delete;
AccountManager(AccountManager &&) = delete;
AccountManager &operator=(AccountManager &&) = delete;
~AccountManager() final;
void set_default_message_ttl(int32 message_ttl, Promise<Unit> &&promise);
void get_default_message_ttl(Promise<int32> &&promise);
void set_account_ttl(int32 account_ttl, Promise<Unit> &&promise);
void get_account_ttl(Promise<int32> &&promise);
void confirm_qr_code_authentication(const string &link, Promise<td_api::object_ptr<td_api::session>> &&promise);
void get_active_sessions(Promise<td_api::object_ptr<td_api::sessions>> &&promise);
void terminate_session(int64 session_id, Promise<Unit> &&promise);
void terminate_all_other_sessions(Promise<Unit> &&promise);
void confirm_session(int64 session_id, Promise<Unit> &&promise);
void toggle_session_can_accept_calls(int64 session_id, bool can_accept_calls, Promise<Unit> &&promise);
void toggle_session_can_accept_secret_chats(int64 session_id, bool can_accept_secret_chats, Promise<Unit> &&promise);
void set_inactive_session_ttl_days(int32 authorization_ttl_days, Promise<Unit> &&promise);
void get_connected_websites(Promise<td_api::object_ptr<td_api::connectedWebsites>> &&promise);
void disconnect_website(int64 website_id, Promise<Unit> &&promise);
void disconnect_all_websites(Promise<Unit> &&promise);
void get_user_link(Promise<td_api::object_ptr<td_api::userLink>> &&promise);
void import_contact_token(const string &token, Promise<td_api::object_ptr<td_api::user>> &&promise);
void invalidate_authentication_codes(vector<string> &&authentication_codes);
void update_unconfirmed_authorization_timeout(bool is_external);
void on_new_unconfirmed_authorization(int64 hash, int32 date, string &&device, string &&location);
bool on_confirm_authorization(int64 hash);
void on_binlog_events(vector<BinlogEvent> &&events);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
class UnconfirmedAuthorization;
class UnconfirmedAuthorizations;
class ChangeAuthorizationSettingsOnServerLogEvent;
class InvalidateSignInCodesOnServerLogEvent;
class ResetAuthorizationOnServerLogEvent;
class ResetAuthorizationsOnServerLogEvent;
class ResetWebAuthorizationOnServerLogEvent;
class ResetWebAuthorizationsOnServerLogEvent;
class SetAccountTtlOnServerLogEvent;
class SetAuthorizationTtlOnServerLogEvent;
class SetDefaultHistoryTtlOnServerLogEvent;
void start_up() final;
void timeout_expired() final;
void tear_down() final;
void get_user_link_impl(Promise<td_api::object_ptr<td_api::userLink>> &&promise);
static string get_unconfirmed_authorizations_key();
void save_unconfirmed_authorizations() const;
bool delete_expired_unconfirmed_authorizations();
td_api::object_ptr<td_api::updateUnconfirmedSession> get_update_unconfirmed_session() const;
void send_update_unconfirmed_session() const;
void change_authorization_settings_on_server(int64 hash, bool set_encrypted_requests_disabled,
bool encrypted_requests_disabled, bool set_call_requests_disabled,
bool call_requests_disabled, bool confirm, uint64 log_event_id,
Promise<Unit> &&promise);
void invalidate_sign_in_codes_on_server(vector<string> authentication_codes, uint64 log_event_id);
void reset_authorization_on_server(int64 hash, uint64 log_event_id, Promise<Unit> &&promise);
void reset_authorizations_on_server(uint64 log_event_id, Promise<Unit> &&promise);
void reset_web_authorization_on_server(int64 hash, uint64 log_event_id, Promise<Unit> &&promise);
void reset_web_authorizations_on_server(uint64 log_event_id, Promise<Unit> &&promise);
void set_account_ttl_on_server(int32 account_ttl, uint64 log_event_id, Promise<Unit> &&promise);
void set_authorization_ttl_on_server(int32 authorization_ttl_days, uint64 log_event_id, Promise<Unit> &&promise);
void set_default_history_ttl_on_server(int32 message_ttl, uint64 log_event_id, Promise<Unit> &&promise);
Td *td_;
ActorShared<> parent_;
unique_ptr<UnconfirmedAuthorizations> unconfirmed_authorizations_;
};
} // namespace td

View File

@ -0,0 +1,33 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
namespace td {
struct AffectedHistory {
int32 pts_;
int32 pts_count_;
bool is_final_;
explicit AffectedHistory(tl_object_ptr<telegram_api::messages_affectedHistory> &&affected_history)
: pts_(affected_history->pts_)
, pts_count_(affected_history->pts_count_)
, is_final_(affected_history->offset_ <= 0) {
}
explicit AffectedHistory(tl_object_ptr<telegram_api::messages_affectedFoundMessages> &&affected_history)
: pts_(affected_history->pts_)
, pts_count_(affected_history->pts_count_)
, is_final_(affected_history->offset_ <= 0) {
}
};
} // namespace td

View File

@ -0,0 +1,43 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class AffiliateType {
DialogId dialog_id_;
explicit AffiliateType(DialogId dialog_id) : dialog_id_(dialog_id) {
}
public:
AffiliateType() = default;
static Result<AffiliateType> get_affiliate_type(Td *td, const td_api::object_ptr<td_api::AffiliateType> &type);
DialogId get_dialog_id() const {
return dialog_id_;
}
telegram_api::object_ptr<telegram_api::InputPeer> get_input_peer(Td *td) const;
td_api::object_ptr<td_api::AffiliateType> get_affiliate_type_object(Td *td) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const AffiliateType &affiliate_type);
} // namespace td

View File

@ -0,0 +1,38 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/actor/actor.h"
#include "td/actor/MultiTimeout.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Promise.h"
namespace td {
class AlarmManager final : public Actor {
public:
explicit AlarmManager(ActorShared<> parent);
void set_alarm(double seconds, Promise<Unit> &&promise);
private:
void tear_down() final;
static void on_alarm_timeout_callback(void *alarm_manager_ptr, int64 alarm_id);
void on_alarm_timeout(int64 alarm_id);
ActorShared<> parent_;
int64 alarm_id_ = 1;
FlatHashMap<int64, Promise<Unit>> pending_alarms_;
MultiTimeout alarm_timeout_{"AlarmTimeout"};
};
} // namespace td

View File

@ -0,0 +1,166 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/Dimensions.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/PhotoSize.h"
#include "td/telegram/SecretInputMedia.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
#include "td/utils/WaitFreeHashMap.h"
namespace td {
class Td;
class AnimationsManager final : public Actor {
public:
AnimationsManager(Td *td, ActorShared<> parent);
AnimationsManager(const AnimationsManager &) = delete;
AnimationsManager &operator=(const AnimationsManager &) = delete;
AnimationsManager(AnimationsManager &&) = delete;
AnimationsManager &operator=(AnimationsManager &&) = delete;
~AnimationsManager() final;
int32 get_animation_duration(FileId file_id) const;
tl_object_ptr<td_api::animation> get_animation_object(FileId file_id) const;
void create_animation(FileId file_id, string minithumbnail, PhotoSize thumbnail, AnimationSize animated_thumbnail,
bool has_stickers, vector<FileId> &&sticker_file_ids, string file_name, string mime_type,
int32 duration, Dimensions dimensions, bool replace);
tl_object_ptr<telegram_api::InputMedia> get_input_media(
FileId file_id, telegram_api::object_ptr<telegram_api::InputFile> input_file,
telegram_api::object_ptr<telegram_api::InputFile> input_thumbnail, bool has_spoiler) const;
SecretInputMedia get_secret_input_media(FileId animation_file_id,
telegram_api::object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail, int32 layer) const;
FileId get_animation_thumbnail_file_id(FileId file_id) const;
FileId get_animation_animated_thumbnail_file_id(FileId file_id) const;
void delete_animation_thumbnail(FileId file_id);
FileId dup_animation(FileId new_id, FileId old_id);
void merge_animations(FileId new_id, FileId old_id);
void on_update_animation_search_emojis();
void on_update_animation_search_provider();
void on_update_saved_animations_limit();
void reload_saved_animations(bool force);
void repair_saved_animations(Promise<Unit> &&promise);
void on_get_saved_animations(bool is_repair, tl_object_ptr<telegram_api::messages_SavedGifs> &&saved_animations_ptr);
void on_get_saved_animations_failed(bool is_repair, Status error);
vector<FileId> get_saved_animations(Promise<Unit> &&promise);
FileSourceId get_saved_animations_file_source_id();
void send_save_gif_query(FileId animation_id, bool unsave, Promise<Unit> &&promise);
void add_saved_animation(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
void add_saved_animation_by_id(FileId animation_id);
void remove_saved_animation(const tl_object_ptr<td_api::InputFile> &input_file, Promise<Unit> &&promise);
template <class StorerT>
void store_animation(FileId file_id, StorerT &storer) const;
template <class ParserT>
FileId parse_animation(ParserT &parser);
string get_animation_search_text(FileId file_id) const;
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
class Animation {
public:
string file_name;
string mime_type;
int32 duration = 0;
Dimensions dimensions;
string minithumbnail;
PhotoSize thumbnail;
AnimationSize animated_thumbnail;
bool has_stickers = false;
vector<FileId> sticker_file_ids;
FileId file_id;
};
const Animation *get_animation(FileId file_id) const;
FileId on_get_animation(unique_ptr<Animation> new_animation, bool replace);
int64 get_saved_animations_hash(const char *source) const;
void add_saved_animation_impl(FileId animation_id, bool add_on_server, Promise<Unit> &&promise);
void load_saved_animations(Promise<Unit> &&promise);
void on_load_saved_animations_from_database(const string &value);
void on_load_saved_animations_finished(vector<FileId> &&saved_animation_ids, bool from_database = false);
void try_send_update_animation_search_parameters() const;
td_api::object_ptr<td_api::updateAnimationSearchParameters> get_update_animation_search_parameters_object() const;
td_api::object_ptr<td_api::updateSavedAnimations> get_update_saved_animations_object() const;
void send_update_saved_animations(bool from_database = false);
void save_saved_animations_to_database();
void tear_down() final;
class AnimationListLogEvent;
Td *td_;
ActorShared<> parent_;
WaitFreeHashMap<FileId, unique_ptr<Animation>, FileIdHash> animations_;
int32 saved_animations_limit_ = 200;
vector<FileId> saved_animation_ids_;
vector<FileId> saved_animation_file_ids_;
double next_saved_animations_load_time_ = 0;
bool are_saved_animations_being_loaded_ = false;
bool are_saved_animations_loaded_ = false;
vector<Promise<Unit>> load_saved_animations_queries_;
vector<Promise<Unit>> repair_saved_animations_queries_;
FileSourceId saved_animations_file_source_id_;
string animation_search_emojis_;
string animation_search_provider_;
bool is_animation_search_emojis_inited_ = false;
bool is_animation_search_provider_inited_ = false;
};
} // namespace td

View File

@ -0,0 +1,28 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
namespace td {
struct BinlogEvent;
class Td;
void get_invite_text(Td *td, Promise<string> &&promise);
void save_app_log(Td *td, const string &type, DialogId dialog_id, tl_object_ptr<telegram_api::JSONValue> &&data,
Promise<Unit> &&promise);
void on_save_app_log_binlog_event(Td *td, BinlogEvent &&event);
} // namespace td

View File

@ -0,0 +1,140 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
namespace td {
class Td;
class AttachMenuManager final : public Actor {
public:
AttachMenuManager(Td *td, ActorShared<> parent);
void init();
void reload_attach_menu_bots(Promise<Unit> &&promise);
void get_attach_menu_bot(UserId user_id, Promise<td_api::object_ptr<td_api::attachmentMenuBot>> &&promise);
void reload_attach_menu_bot(UserId user_id, Promise<Unit> &&promise);
FileSourceId get_attach_menu_bot_file_source_id(UserId user_id);
void toggle_bot_is_added_to_attach_menu(UserId user_id, bool is_added, bool allow_write_access,
Promise<Unit> &&promise);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
static string get_attach_menu_bots_database_key();
private:
void start_up() final;
void timeout_expired() final;
void tear_down() final;
struct AttachMenuBotColor {
int32 light_color_ = -1;
int32 dark_color_ = -1;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
friend bool operator==(const AttachMenuBotColor &lhs, const AttachMenuBotColor &rhs);
friend bool operator!=(const AttachMenuBotColor &lhs, const AttachMenuBotColor &rhs);
struct AttachMenuBot {
bool is_added_ = false;
UserId user_id_;
bool supports_self_dialog_ = false;
bool supports_user_dialogs_ = false;
bool supports_bot_dialogs_ = false;
bool supports_group_dialogs_ = false;
bool supports_broadcast_dialogs_ = false;
bool request_write_access_ = false;
bool show_in_attach_menu_ = false;
bool show_in_side_menu_ = false;
bool side_menu_disclaimer_needed_ = false;
string name_;
AttachMenuBotColor name_color_;
FileId default_icon_file_id_;
FileId ios_static_icon_file_id_;
FileId ios_animated_icon_file_id_;
FileId android_icon_file_id_;
FileId macos_icon_file_id_;
FileId android_side_menu_icon_file_id_;
FileId ios_side_menu_icon_file_id_;
FileId macos_side_menu_icon_file_id_;
AttachMenuBotColor icon_color_;
FileId placeholder_file_id_;
static constexpr uint32 CACHE_VERSION = 3;
uint32 cache_version_ = 0;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
class AttachMenuBotsLogEvent;
friend bool operator==(const AttachMenuBot &lhs, const AttachMenuBot &rhs);
friend bool operator!=(const AttachMenuBot &lhs, const AttachMenuBot &rhs);
bool is_active() const;
Result<AttachMenuBot> get_attach_menu_bot(tl_object_ptr<telegram_api::attachMenuBot> &&bot);
td_api::object_ptr<td_api::attachmentMenuBot> get_attachment_menu_bot_object(const AttachMenuBot &bot) const;
td_api::object_ptr<td_api::updateAttachmentMenuBots> get_update_attachment_menu_bots_object() const;
void remove_bot_from_attach_menu(UserId user_id);
void send_update_attach_menu_bots() const;
void save_attach_menu_bots();
void on_reload_attach_menu_bots(Result<telegram_api::object_ptr<telegram_api::AttachMenuBots>> &&result);
void on_get_attach_menu_bot(UserId user_id,
Result<telegram_api::object_ptr<telegram_api::attachMenuBotsBot>> &&result,
Promise<td_api::object_ptr<td_api::attachmentMenuBot>> &&promise);
Td *td_;
ActorShared<> parent_;
bool is_inited_ = false;
int64 hash_ = 0;
vector<AttachMenuBot> attach_menu_bots_;
FlatHashMap<UserId, FileSourceId, UserIdHash> attach_menu_bot_file_source_ids_;
vector<Promise<Unit>> reload_attach_menu_bots_queries_;
};
} // namespace td

View File

@ -0,0 +1,90 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/files/FileId.h"
#include "td/telegram/PhotoSize.h"
#include "td/telegram/SecretInputMedia.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/buffer.h"
#include "td/utils/common.h"
#include "td/utils/WaitFreeHashMap.h"
namespace td {
class Td;
class AudiosManager {
public:
explicit AudiosManager(Td *td);
AudiosManager(const AudiosManager &) = delete;
AudiosManager &operator=(const AudiosManager &) = delete;
AudiosManager(AudiosManager &&) = delete;
AudiosManager &operator=(AudiosManager &&) = delete;
~AudiosManager();
int32 get_audio_duration(FileId file_id) const;
tl_object_ptr<td_api::audio> get_audio_object(FileId file_id) const;
td_api::object_ptr<td_api::notificationSound> get_notification_sound_object(FileId file_id) const;
void create_audio(FileId file_id, string minithumbnail, PhotoSize thumbnail, string file_name, string mime_type,
int32 duration, string title, string performer, int32 date, bool replace);
tl_object_ptr<telegram_api::InputMedia> get_input_media(
FileId file_id, telegram_api::object_ptr<telegram_api::InputFile> input_file,
telegram_api::object_ptr<telegram_api::InputFile> input_thumbnail) const;
SecretInputMedia get_secret_input_media(FileId audio_file_id,
telegram_api::object_ptr<telegram_api::InputEncryptedFile> input_file,
const string &caption, BufferSlice thumbnail, int32 layer) const;
FileId get_audio_thumbnail_file_id(FileId file_id) const;
void append_audio_album_cover_file_ids(FileId file_id, vector<FileId> &file_ids) const;
void delete_audio_thumbnail(FileId file_id);
FileId dup_audio(FileId new_id, FileId old_id);
void merge_audios(FileId new_id, FileId old_id);
template <class StorerT>
void store_audio(FileId file_id, StorerT &storer) const;
template <class ParserT>
FileId parse_audio(ParserT &parser);
string get_audio_search_text(FileId file_id) const;
private:
class Audio {
public:
string file_name;
string mime_type;
int32 duration = 0;
int32 date = 0;
string title;
string performer;
string minithumbnail;
PhotoSize thumbnail;
FileId file_id;
};
const Audio *get_audio(FileId file_id) const;
FileId on_get_audio(unique_ptr<Audio> new_audio, bool replace);
Td *td_;
WaitFreeHashMap<FileId, unique_ptr<Audio>, FileIdHash> audios_;
};
} // namespace td

View File

@ -0,0 +1,233 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/EmailVerification.h"
#include "td/telegram/net/NetActor.h"
#include "td/telegram/net/NetQuery.h"
#include "td/telegram/SendCodeHelper.h"
#include "td/telegram/SentEmailCode.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/TermsOfService.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/actor/Timeout.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
namespace td {
class AuthManager final : public NetActor {
public:
AuthManager(int32 api_id, const string &api_hash, ActorShared<> parent);
bool is_bot() const {
return is_bot_ || net_query_type_ == NetQueryType::BotAuthentication;
}
bool is_authorized() const;
bool was_authorized() const;
void get_state(uint64 query_id);
void set_phone_number(uint64 query_id, string phone_number,
td_api::object_ptr<td_api::phoneNumberAuthenticationSettings> settings);
void set_firebase_token(uint64 query_id, string token);
void report_missing_code(uint64 query_id, string mobile_network_code);
void set_email_address(uint64 query_id, string email_address);
void resend_authentication_code(uint64 query_id, td_api::object_ptr<td_api::ResendCodeReason> &&reason);
void check_email_code(uint64 query_id, EmailVerification &&code);
void reset_email_address(uint64 query_id);
void check_code(uint64 query_id, string code);
void register_user(uint64 query_id, string first_name, string last_name, bool disable_notification);
void request_qr_code_authentication(uint64 query_id, vector<UserId> other_user_ids);
void check_bot_token(uint64 query_id, string bot_token);
void check_password(uint64 query_id, string password);
void request_password_recovery(uint64 query_id);
void check_password_recovery_code(uint64 query_id, string code);
void recover_password(uint64 query_id, string code, string new_password, string new_hint);
void log_out(uint64 query_id);
void delete_account(uint64 query_id, string reason, string password);
void on_update_login_token();
void on_authorization_lost(string source);
void on_closing(bool destroy_flag);
// can return nullptr if state isn't initialized yet
tl_object_ptr<td_api::AuthorizationState> get_current_authorization_state_object() const;
private:
static constexpr size_t MAX_NAME_LENGTH = 64; // server side limit
enum class State : int32 {
None,
WaitPhoneNumber,
WaitCode,
WaitQrCodeConfirmation,
WaitPassword,
WaitRegistration,
WaitEmailAddress,
WaitEmailCode,
Ok,
LoggingOut,
DestroyingKeys,
Closing
} state_ = State::None;
enum class NetQueryType : int32 {
None,
SignIn,
SignUp,
SendCode,
SendEmailCode,
VerifyEmailAddress,
ResetEmailAddress,
RequestQrCode,
ImportQrCode,
GetPassword,
CheckPassword,
RequestPasswordRecovery,
CheckPasswordRecoveryCode,
RecoverPassword,
RequestFirebaseSms,
BotAuthentication,
Authentication,
LogOut,
DeleteAccount
};
struct WaitPasswordState {
string current_client_salt_;
string current_server_salt_;
int32 srp_g_ = 0;
string srp_p_;
string srp_B_;
int64 srp_id_ = 0;
string hint_;
bool has_recovery_ = false;
bool has_secure_values_ = false;
string email_address_pattern_;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
struct DbState;
bool load_state();
void save_state();
ActorShared<> parent_;
// STATE
// from constructor
int32 api_id_;
string api_hash_;
// State::WaitEmailAddress
bool allow_apple_id_ = false;
bool allow_google_id_ = false;
// State::WaitEmailCode
string email_address_;
SentEmailCode email_code_info_;
int32 reset_available_period_ = -1;
int32 reset_pending_date_ = -1;
EmailVerification email_code_;
// State::WaitCode
SendCodeHelper send_code_helper_;
string code_;
// State::WaitQrCodeConfirmation
vector<UserId> other_user_ids_;
string login_token_;
double login_token_expires_at_ = 0.0;
int32 imported_dc_id_ = -1;
// State::WaitPassword
string password_;
// State::WaitRegistration
TermsOfService terms_of_service_;
// for bots
string bot_token_;
uint64 query_id_ = 0;
WaitPasswordState wait_password_state_;
string recovery_code_;
string new_password_;
string new_hint_;
int32 login_code_retry_delay_ = 0;
Timeout poll_export_login_code_timeout_;
bool checking_password_ = false;
bool was_qr_code_request_ = false;
bool was_check_bot_token_ = false;
bool is_bot_ = false;
uint64 net_query_id_ = 0;
NetQueryType net_query_type_ = NetQueryType::None;
vector<uint64> pending_get_authorization_state_requests_;
void on_new_query(uint64 query_id);
void on_current_query_error(Status status);
void on_current_query_ok();
void start_net_query(NetQueryType net_query_type, NetQueryPtr net_query);
static void on_update_login_token_static(void *td);
void send_export_login_token_query();
void set_login_token_expires_at(double login_token_expires_at);
void do_delete_account(uint64 query_id, string reason,
Result<tl_object_ptr<telegram_api::InputCheckPasswordSRP>> r_input_password);
void send_auth_sign_in_query();
void send_log_out_query();
void destroy_auth_keys();
void on_account_banned() const;
void on_sent_code(telegram_api::object_ptr<telegram_api::auth_SentCode> &&sent_code_ptr);
void on_send_code_result(NetQueryPtr &&net_query);
void on_send_email_code_result(NetQueryPtr &&net_query);
void on_verify_email_address_result(NetQueryPtr &&net_query);
void on_reset_email_address_result(NetQueryPtr &&net_query);
void on_request_qr_code_result(NetQueryPtr &&net_query, bool is_import);
void on_get_password_result(NetQueryPtr &&net_query);
void on_request_password_recovery_result(NetQueryPtr &&net_query);
void on_check_password_recovery_code_result(NetQueryPtr &&net_query);
void on_request_firebase_sms_result(NetQueryPtr &&net_query);
void on_authentication_result(NetQueryPtr &&net_query, bool is_from_current_query);
void on_log_out_result(NetQueryPtr &&net_query);
void on_delete_account_result(NetQueryPtr &&net_query);
void on_get_login_token(tl_object_ptr<telegram_api::auth_LoginToken> login_token);
void on_get_authorization(tl_object_ptr<telegram_api::auth_Authorization> auth_ptr);
void on_result(NetQueryPtr net_query) final;
void update_state(State new_state, bool should_save_state = true);
tl_object_ptr<td_api::AuthorizationState> get_authorization_state_object(State authorization_state) const;
static void send_ok(uint64 query_id);
static void on_query_error(uint64 query_id, Status status);
void start_up() final;
void tear_down() final;
};
} // namespace td

View File

@ -0,0 +1,39 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/net/NetType.h"
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
namespace td {
class Td;
class AutoDownloadSettings {
public:
int32 max_photo_file_size = 0;
int64 max_video_file_size = 0;
int64 max_other_file_size = 0;
int32 video_upload_bitrate = 0;
bool is_enabled = false;
bool preload_large_videos = false;
bool preload_next_audio = false;
bool preload_stories = false;
bool use_less_data_for_calls = false;
};
AutoDownloadSettings get_auto_download_settings(const td_api::object_ptr<td_api::autoDownloadSettings> &settings);
void get_auto_download_settings_presets(Td *td,
Promise<td_api::object_ptr<td_api::autoDownloadSettingsPresets>> &&promise);
void set_auto_download_settings(Td *td, NetType type, AutoDownloadSettings settings, Promise<Unit> &&promise);
} // namespace td

View File

@ -0,0 +1,117 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
namespace td {
class Td;
class AutosaveManager final : public Actor {
public:
AutosaveManager(Td *td, ActorShared<> parent);
void reload_autosave_settings();
void get_autosave_settings(Promise<td_api::object_ptr<td_api::autosaveSettings>> &&promise);
void set_autosave_settings(td_api::object_ptr<td_api::AutosaveSettingsScope> &&scope,
td_api::object_ptr<td_api::scopeAutosaveSettings> &&settings, Promise<Unit> &&promise);
void clear_autosave_settings_exceptions(Promise<Unit> &&promise);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
struct DialogAutosaveSettings {
bool are_inited_ = false;
bool autosave_photos_ = false;
bool autosave_videos_ = false;
int64 max_video_file_size_ = 0;
static constexpr int64 MIN_MAX_VIDEO_FILE_SIZE = 512 * 1024;
static constexpr int64 DEFAULT_MAX_VIDEO_FILE_SIZE = 100 * 1024 * 1024;
static constexpr int64 MAX_MAX_VIDEO_FILE_SIZE = static_cast<int64>(4000) * 1024 * 1024;
DialogAutosaveSettings() = default;
explicit DialogAutosaveSettings(const telegram_api::autoSaveSettings *settings);
explicit DialogAutosaveSettings(const td_api::scopeAutosaveSettings *settings);
telegram_api::object_ptr<telegram_api::autoSaveSettings> get_input_auto_save_settings() const;
td_api::object_ptr<td_api::scopeAutosaveSettings> get_scope_autosave_settings_object() const;
td_api::object_ptr<td_api::autosaveSettingsException> get_autosave_settings_exception_object(
const Td *td, DialogId dialog_id) const;
bool operator==(const DialogAutosaveSettings &other) const;
bool operator!=(const DialogAutosaveSettings &other) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
struct AutosaveSettings {
bool are_inited_ = false;
bool are_being_reloaded_ = false;
bool need_reload_ = false;
DialogAutosaveSettings user_settings_;
DialogAutosaveSettings chat_settings_;
DialogAutosaveSettings broadcast_settings_;
FlatHashMap<DialogId, DialogAutosaveSettings, DialogIdHash> exceptions_;
td_api::object_ptr<td_api::autosaveSettings> get_autosave_settings_object(const Td *td) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
void tear_down() final;
string get_autosave_settings_database_key();
void load_autosave_settings(Promise<td_api::object_ptr<td_api::autosaveSettings>> &&promise);
void on_load_autosave_settings_from_database(string value);
void on_get_autosave_settings(Result<telegram_api::object_ptr<telegram_api::account_autoSaveSettings>> r_settings);
void save_autosave_settings();
static td_api::object_ptr<td_api::updateAutosaveSettings> get_update_autosave_settings(
td_api::object_ptr<td_api::AutosaveSettingsScope> &&scope, const DialogAutosaveSettings &settings);
void send_update_autosave_settings(td_api::object_ptr<td_api::AutosaveSettingsScope> &&scope,
const DialogAutosaveSettings &settings);
Td *td_;
ActorShared<> parent_;
AutosaveSettings settings_;
vector<Promise<td_api::object_ptr<td_api::autosaveSettings>>> load_settings_queries_;
};
} // namespace td

View File

@ -0,0 +1,70 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h"
#include "td/utils/tl_helpers.h"
#include <type_traits>
namespace td {
class BackgroundId {
int64 id = 0;
public:
BackgroundId() = default;
explicit constexpr BackgroundId(int64 background_id) : id(background_id) {
}
template <class T, typename = std::enable_if_t<std::is_convertible<T, int64>::value>>
BackgroundId(T background_id) = delete;
int64 get() const {
return id;
}
bool operator==(const BackgroundId &other) const {
return id == other.id;
}
bool operator!=(const BackgroundId &other) const {
return id != other.id;
}
bool is_valid() const {
return id != 0;
}
bool is_local() const {
return 0 < id && id <= 0x7FFFFFFF;
}
template <class StorerT>
void store(StorerT &storer) const {
td::store(id, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(id, parser);
}
};
struct BackgroundIdHash {
uint32 operator()(BackgroundId background_id) const {
return Hash<int64>()(background_id.get());
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, BackgroundId background_id) {
return string_builder << "background " << background_id.get();
}
} // namespace td

View File

@ -0,0 +1,61 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BackgroundId.h"
#include "td/telegram/BackgroundType.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class BackgroundInfo {
BackgroundId background_id_;
BackgroundType background_type_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundInfo &background_info);
public:
BackgroundInfo() : background_id_(), background_type_() {
}
BackgroundInfo(Td *td, telegram_api::object_ptr<telegram_api::WallPaper> &&wallpaper_ptr, bool allow_empty);
td_api::object_ptr<td_api::background> get_background_object(const Td *td) const;
td_api::object_ptr<td_api::chatBackground> get_chat_background_object(const Td *td) const;
bool is_valid() const {
return background_id_.is_valid();
}
bool operator==(const BackgroundInfo &other) const {
return background_type_ == other.background_type_ &&
(background_id_ == other.background_id_ || (background_id_.is_local() && other.background_id_.is_local()));
}
bool operator!=(const BackgroundInfo &other) const {
return !(*this == other);
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
inline StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundInfo &background_info) {
return string_builder << background_info.background_id_ << " with " << background_info.background_type_;
}
} // namespace td

View File

@ -0,0 +1,243 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BackgroundId.h"
#include "td/telegram/BackgroundType.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/files/FileUploadId.h"
#include "td/telegram/logevent/LogEvent.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/FlatHashSet.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
#include <memory>
#include <utility>
namespace td {
class Td;
class BackgroundManager final : public Actor {
public:
BackgroundManager(Td *td, ActorShared<> parent);
void get_backgrounds(bool for_dark_theme, Promise<td_api::object_ptr<td_api::backgrounds>> &&promise);
void reload_background(BackgroundId background_id, int64 access_hash, Promise<Unit> &&promise);
std::pair<BackgroundId, BackgroundType> search_background(const string &name, Promise<Unit> &&promise);
void set_background(const td_api::InputBackground *input_background, const td_api::BackgroundType *background_type,
bool for_dark_theme, Promise<td_api::object_ptr<td_api::background>> &&promise);
void delete_background(bool for_dark_theme, Promise<Unit> &&promise);
void remove_background(BackgroundId background_id, Promise<Unit> &&promise);
void reset_backgrounds(Promise<Unit> &&promise);
void set_dialog_background(DialogId dialog_id, const td_api::InputBackground *input_background,
const td_api::BackgroundType *background_type, int32 dark_theme_dimming, bool for_both,
Promise<Unit> &&promise);
void delete_dialog_background(DialogId dialog_id, bool restore_previous, Promise<Unit> &&promise);
td_api::object_ptr<td_api::background> get_background_object(BackgroundId background_id, bool for_dark_theme,
const BackgroundType *type) const;
std::pair<BackgroundId, BackgroundType> on_get_background(
BackgroundId expected_background_id, const string &expected_background_name,
telegram_api::object_ptr<telegram_api::WallPaper> wallpaper_ptr, bool replace_type, bool allow_empty);
FileSourceId get_background_file_source_id(BackgroundId background_id, int64 access_hash);
void on_uploaded_background_file(FileUploadId file_upload_id, const BackgroundType &type, DialogId dialog_id,
bool for_dark_theme, telegram_api::object_ptr<telegram_api::WallPaper> wallpaper,
Promise<td_api::object_ptr<td_api::background>> &&promise);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
void store_background(BackgroundId background_id, LogEventStorerCalcLength &storer);
void store_background(BackgroundId background_id, LogEventStorerUnsafe &storer);
void parse_background(BackgroundId &background_id, LogEventParser &parser);
private:
struct Background {
BackgroundId id;
int64 access_hash = 0;
string name;
FileId file_id;
bool is_creator = false;
bool is_default = false;
bool is_dark = false;
bool has_new_local_id = true;
BackgroundType type;
FileSourceId file_source_id;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
struct LocalBackgroundHash {
uint32 operator()(const Background &background) const {
return Hash<string>()(background.name);
}
};
struct LocalBackgroundEquals {
bool operator()(const Background &lhs, const Background &rhs) const {
return lhs.name == rhs.name && lhs.type == rhs.type && lhs.is_creator == rhs.is_creator &&
lhs.is_default == rhs.is_default && lhs.is_dark == rhs.is_dark;
}
};
class BackgroundLogEvent;
class BackgroundsLogEvent;
class UploadBackgroundFileCallback;
void start_up() final;
void tear_down() final;
static string get_background_database_key(bool for_dark_theme);
static string get_local_backgrounds_database_key(bool for_dark_theme);
void save_background_id(bool for_dark_theme);
void save_local_backgrounds(bool for_dark_theme);
void reload_background_from_server(BackgroundId background_id, const string &background_name,
telegram_api::object_ptr<telegram_api::InputWallPaper> &&input_wallpaper,
Promise<Unit> &&promise) const;
td_api::object_ptr<td_api::updateDefaultBackground> get_update_default_background_object(bool for_dark_theme) const;
td_api::object_ptr<td_api::backgrounds> get_backgrounds_object(bool for_dark_theme) const;
void send_update_default_background(bool for_dark_theme) const;
void set_max_local_background_id(BackgroundId background_id);
BackgroundId get_next_local_background_id();
void set_local_background_id(Background &background);
void add_local_background_to_cache(const Background &background);
BackgroundId add_local_background(const BackgroundType &type);
void add_background(const Background &background, bool replace_type);
Background *get_background_ref(BackgroundId background_id);
const Background *get_background(BackgroundId background_id) const;
static string get_background_name_database_key(const string &name);
void on_load_background_from_database(string name, string value);
void on_get_backgrounds(Result<telegram_api::object_ptr<telegram_api::account_WallPapers>> result);
Result<FileId> prepare_input_file(const tl_object_ptr<td_api::InputFile> &input_file);
Result<DialogId> get_background_dialog(DialogId dialog_id);
void do_set_dialog_background(DialogId dialog_id, BackgroundId background_id, BackgroundType type, bool for_both,
Promise<Unit> &&promise);
void send_set_dialog_background_query(DialogId dialog_id,
telegram_api::object_ptr<telegram_api::InputWallPaper> input_wallpaper,
telegram_api::object_ptr<telegram_api::wallPaperSettings> settings,
MessageId old_message_id, bool for_both, Promise<Unit> &&promise);
void set_background(BackgroundId background_id, BackgroundType type, bool for_dark_theme,
Promise<td_api::object_ptr<td_api::background>> &&promise);
void on_installed_background(BackgroundId background_id, BackgroundType type, bool for_dark_theme,
Result<Unit> &&result, Promise<td_api::object_ptr<td_api::background>> &&promise);
void set_background_id(BackgroundId background_id, const BackgroundType &type, bool for_dark_theme);
void on_removed_background(BackgroundId background_id, Result<Unit> &&result, Promise<Unit> &&promise);
void on_reset_background(Result<Unit> &&result, Promise<Unit> &&promise);
void upload_background_file(FileId file_id, const BackgroundType &type, DialogId dialog_id, bool for_dark_theme,
Promise<td_api::object_ptr<td_api::background>> &&promise);
void on_upload_background_file(FileUploadId file_upload_id,
telegram_api::object_ptr<telegram_api::InputFile> input_file);
void on_upload_background_file_error(FileUploadId file_upload_id, Status status);
void do_upload_background_file(FileUploadId file_upload_id, const BackgroundType &type, DialogId dialog_id,
bool for_dark_theme, telegram_api::object_ptr<telegram_api::InputFile> &&input_file,
Promise<td_api::object_ptr<td_api::background>> &&promise);
FlatHashMap<BackgroundId, unique_ptr<Background>, BackgroundIdHash> backgrounds_;
FlatHashMap<BackgroundId, std::pair<int64, FileSourceId>, BackgroundIdHash>
background_id_to_file_source_id_; // background_id -> [access_hash, file_source_id]
FlatHashMap<string, BackgroundId> name_to_background_id_;
FlatHashMap<FileId, BackgroundId, FileIdHash> file_id_to_background_id_;
FlatHashSet<string> loaded_from_database_backgrounds_;
FlatHashMap<string, vector<Promise<Unit>>> being_loaded_from_database_backgrounds_;
BackgroundId set_background_id_[2];
BackgroundType set_background_type_[2];
vector<std::pair<BackgroundId, BackgroundType>> installed_backgrounds_;
vector<std::pair<bool, Promise<td_api::object_ptr<td_api::backgrounds>>>> pending_get_backgrounds_queries_;
std::shared_ptr<UploadBackgroundFileCallback> upload_background_file_callback_;
struct UploadedFileInfo {
BackgroundType type_;
DialogId dialog_id_;
bool for_dark_theme_;
Promise<td_api::object_ptr<td_api::background>> promise_;
UploadedFileInfo(BackgroundType type, DialogId dialog_id, bool for_dark_theme,
Promise<td_api::object_ptr<td_api::background>> &&promise)
: type_(type), dialog_id_(dialog_id), for_dark_theme_(for_dark_theme), promise_(std::move(promise)) {
}
};
FlatHashMap<FileUploadId, UploadedFileInfo, FileUploadIdHash> being_uploaded_files_;
FlatHashMap<Background, BackgroundId, LocalBackgroundHash, LocalBackgroundEquals> local_backgrounds_;
BackgroundId max_local_background_id_;
vector<BackgroundId> local_background_ids_[2];
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -0,0 +1,159 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include "td/utils/StringBuilder.h"
namespace td {
class BackgroundFill {
int32 top_color_ = 0;
int32 bottom_color_ = 0;
int32 rotation_angle_ = 0;
int32 third_color_ = -1;
int32 fourth_color_ = -1;
BackgroundFill() = default;
explicit BackgroundFill(int32 solid_color) : top_color_(solid_color), bottom_color_(solid_color) {
}
BackgroundFill(int32 top_color, int32 bottom_color, int32 rotation_angle)
: top_color_(top_color), bottom_color_(bottom_color), rotation_angle_(rotation_angle) {
if (get_type() != Type::Gradient) {
rotation_angle_ = 0;
}
}
BackgroundFill(int32 first_color, int32 second_color, int32 third_color, int32 fourth_color)
: top_color_(first_color), bottom_color_(second_color), third_color_(third_color), fourth_color_(fourth_color) {
}
explicit BackgroundFill(const telegram_api::wallPaperSettings *settings);
static Result<BackgroundFill> get_background_fill(const td_api::BackgroundFill *fill);
string get_link(bool is_first) const;
td_api::object_ptr<td_api::BackgroundFill> get_background_fill_object() const;
enum class Type : int32 { Solid, Gradient, FreeformGradient };
Type get_type() const {
if (third_color_ != -1) {
return Type::FreeformGradient;
}
if (top_color_ == bottom_color_) {
return Type::Solid;
}
return Type::Gradient;
}
friend bool operator==(const BackgroundFill &lhs, const BackgroundFill &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundFill &fill);
friend class BackgroundType;
static Result<BackgroundFill> get_background_fill(Slice name);
bool is_dark() const;
};
bool operator==(const BackgroundFill &lhs, const BackgroundFill &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundFill &fill);
class BackgroundType {
enum class Type : int32 { Wallpaper, Pattern, Fill, ChatTheme };
Type type_ = Type::Fill;
bool is_blurred_ = false;
bool is_moving_ = false;
int32 intensity_ = 0;
BackgroundFill fill_;
string theme_name_;
friend bool operator==(const BackgroundType &lhs, const BackgroundType &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundType &type);
BackgroundType(bool is_blurred, bool is_moving, int32 dark_theme_dimming)
: type_(Type::Wallpaper), is_blurred_(is_blurred), is_moving_(is_moving), intensity_(dark_theme_dimming) {
}
BackgroundType(bool is_moving, BackgroundFill &&fill, int32 intensity)
: type_(Type::Pattern), is_moving_(is_moving), intensity_(intensity), fill_(std::move(fill)) {
}
BackgroundType(BackgroundFill &&fill, int32 dark_theme_dimming)
: type_(Type::Fill), intensity_(dark_theme_dimming), fill_(std::move(fill)) {
}
explicit BackgroundType(string theme_name) : type_(Type::ChatTheme), theme_name_(std::move(theme_name)) {
}
public:
BackgroundType() = default;
BackgroundType(bool has_no_file, bool is_pattern, telegram_api::object_ptr<telegram_api::wallPaperSettings> settings);
static Result<BackgroundType> get_background_type(const td_api::BackgroundType *background_type,
int32 dark_theme_dimming);
static Result<BackgroundType> get_local_background_type(Slice name);
static bool is_background_name_local(Slice name);
bool has_file() const {
return type_ == Type::Wallpaper || type_ == Type::Pattern;
}
bool has_gradient_fill() const {
return type_ == Type::Fill && fill_.get_type() != BackgroundFill::Type::Solid;
}
string get_mime_type() const;
void apply_parameters_from_link(Slice name);
string get_link(bool is_first = true) const;
bool has_equal_type(const BackgroundType &other) const {
return type_ == other.type_;
}
td_api::object_ptr<td_api::BackgroundType> get_background_type_object() const;
telegram_api::object_ptr<telegram_api::wallPaperSettings> get_input_wallpaper_settings() const;
bool is_dark() const {
CHECK(type_ == Type::Fill);
return fill_.is_dark();
}
int32 get_dark_theme_dimming() const {
if (type_ == Type::Pattern) {
return 0;
}
return intensity_;
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
bool operator==(const BackgroundType &lhs, const BackgroundType &rhs);
inline bool operator!=(const BackgroundType &lhs, const BackgroundType &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BackgroundType &type);
} // namespace td

View File

@ -0,0 +1,22 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
namespace td {
// append-only
enum class BaseTheme : int32 { Classic, Day, Night, Tinted, Arctic };
bool is_dark_base_theme(BaseTheme base_theme);
BaseTheme get_base_theme(const telegram_api::object_ptr<telegram_api::BaseTheme> &base_theme);
} // namespace td

View File

@ -0,0 +1,69 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Birthdate {
public:
Birthdate() = default;
explicit Birthdate(telegram_api::object_ptr<telegram_api::birthday> birthday);
explicit Birthdate(td_api::object_ptr<td_api::birthdate> birthdate);
td_api::object_ptr<td_api::birthdate> get_birthdate_object() const;
telegram_api::object_ptr<telegram_api::birthday> get_input_birthday() const;
bool is_empty() const {
return birthdate_ == 0;
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
int32 birthdate_ = 0;
int32 get_day() const {
return birthdate_ & 31;
}
int32 get_month() const {
return (birthdate_ >> 5) & 15;
}
int32 get_year() const {
return birthdate_ >> 9;
}
void init(int32 day, int32 month, int32 year);
friend bool operator==(const Birthdate &lhs, const Birthdate &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const Birthdate &birthdate);
};
bool operator==(const Birthdate &lhs, const Birthdate &rhs);
inline bool operator!=(const Birthdate &lhs, const Birthdate &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const Birthdate &birthdate);
} // namespace td

View File

@ -0,0 +1,99 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h"
namespace td {
class BlockListId {
enum class Type : int32 { None = -1, Main, Stories };
Type type_ = Type::None;
friend struct BlockListIdHash;
explicit BlockListId(Type type) : type_(type) {
}
public:
BlockListId() = default;
BlockListId(bool is_blocked, bool is_blocked_for_stories)
: type_(is_blocked ? Type::Main : (is_blocked_for_stories ? Type::Stories : Type::None)) {
}
explicit BlockListId(const td_api::object_ptr<td_api::BlockList> &block_list) {
if (block_list == nullptr) {
return;
}
switch (block_list->get_id()) {
case td_api::blockListMain::ID:
type_ = Type::Main;
break;
case td_api::blockListStories::ID:
type_ = Type::Stories;
break;
default:
UNREACHABLE();
}
}
static BlockListId main() {
return BlockListId(Type::Main);
}
static BlockListId stories() {
return BlockListId(Type::Stories);
}
td_api::object_ptr<td_api::BlockList> get_block_list_object() const {
switch (type_) {
case Type::None:
return nullptr;
case Type::Main:
return td_api::make_object<td_api::blockListMain>();
case Type::Stories:
return td_api::make_object<td_api::blockListStories>();
default:
UNREACHABLE();
}
}
bool is_valid() const {
return type_ == Type::Main || type_ == Type::Stories;
}
bool operator==(const BlockListId &other) const {
return type_ == other.type_;
}
bool operator!=(const BlockListId &other) const {
return type_ != other.type_;
}
};
struct BlockListIdHash {
uint32 operator()(BlockListId block_list_id) const {
return Hash<int32>()(static_cast<int32>(block_list_id.type_));
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, BlockListId block_list_id) {
if (block_list_id == BlockListId::main()) {
return string_builder << "MainBlockList";
}
if (block_list_id == BlockListId::stories()) {
return string_builder << "StoriesBlockList";
}
return string_builder << "InvalidBlockList";
}
} // namespace td

View File

@ -0,0 +1,65 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogBoostLinkInfo.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
#include <utility>
namespace td {
class Td;
class BoostManager final : public Actor {
public:
BoostManager(Td *td, ActorShared<> parent);
td_api::object_ptr<td_api::chatBoostLevelFeatures> get_chat_boost_level_features_object(bool for_megagroup,
int32 level) const;
td_api::object_ptr<td_api::chatBoostFeatures> get_chat_boost_features_object(bool for_megagroup) const;
void get_boost_slots(Promise<td_api::object_ptr<td_api::chatBoostSlots>> &&promise);
void get_dialog_boost_status(DialogId dialog_id, Promise<td_api::object_ptr<td_api::chatBoostStatus>> &&promise);
void boost_dialog(DialogId dialog_id, vector<int32> slot_ids,
Promise<td_api::object_ptr<td_api::chatBoostSlots>> &&promise);
Result<std::pair<string, bool>> get_dialog_boost_link(DialogId dialog_id);
void get_dialog_boost_link_info(Slice url, Promise<DialogBoostLinkInfo> &&promise);
td_api::object_ptr<td_api::chatBoostLinkInfo> get_chat_boost_link_info_object(const DialogBoostLinkInfo &info) const;
void get_dialog_boosts(DialogId dialog_id, bool only_gift_codes, const string &offset, int32 limit,
Promise<td_api::object_ptr<td_api::foundChatBoosts>> &&promise);
void get_user_dialog_boosts(DialogId dialog_id, UserId user_id,
Promise<td_api::object_ptr<td_api::foundChatBoosts>> &&promise);
void on_update_dialog_boost(DialogId dialog_id, telegram_api::object_ptr<telegram_api::boost> &&boost);
private:
void tear_down() final;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -0,0 +1,103 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
#include "td/utils/tl_helpers.h"
namespace td {
class Td;
class BotCommand {
string command_;
string description_;
friend bool operator==(const BotCommand &lhs, const BotCommand &rhs);
public:
BotCommand() = default;
BotCommand(string command, string description) : command_(std::move(command)), description_(std::move(description)) {
}
explicit BotCommand(telegram_api::object_ptr<telegram_api::botCommand> &&bot_command);
td_api::object_ptr<td_api::botCommand> get_bot_command_object() const;
telegram_api::object_ptr<telegram_api::botCommand> get_input_bot_command() const;
template <class StorerT>
void store(StorerT &storer) const {
td::store(command_, storer);
td::store(description_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(command_, parser);
td::parse(description_, parser);
}
};
bool operator==(const BotCommand &lhs, const BotCommand &rhs);
inline bool operator!=(const BotCommand &lhs, const BotCommand &rhs) {
return !(lhs == rhs);
}
class BotCommands {
UserId bot_user_id_;
vector<BotCommand> commands_;
friend bool operator==(const BotCommands &lhs, const BotCommands &rhs);
public:
BotCommands() = default;
BotCommands(UserId bot_user_id, vector<telegram_api::object_ptr<telegram_api::botCommand>> &&bot_commands);
td_api::object_ptr<td_api::botCommands> get_bot_commands_object(Td *td) const;
static bool update_all_bot_commands(vector<BotCommands> &all_bot_commands, BotCommands &&bot_commands);
UserId get_bot_user_id() const {
return bot_user_id_;
}
template <class StorerT>
void store(StorerT &storer) const {
td::store(bot_user_id_, storer);
td::store(commands_, storer);
}
template <class ParserT>
void parse(ParserT &parser) {
td::parse(bot_user_id_, parser);
td::parse(commands_, parser);
}
};
bool operator==(const BotCommands &lhs, const BotCommands &rhs);
inline bool operator!=(const BotCommands &lhs, const BotCommands &rhs) {
return !(lhs == rhs);
}
void set_commands(Td *td, td_api::object_ptr<td_api::BotCommandScope> &&scope_ptr, string &&language_code,
vector<td_api::object_ptr<td_api::botCommand>> &&commands, Promise<Unit> &&promise);
void delete_commands(Td *td, td_api::object_ptr<td_api::BotCommandScope> &&scope_ptr, string &&language_code,
Promise<Unit> &&promise);
void get_commands(Td *td, td_api::object_ptr<td_api::BotCommandScope> &&scope_ptr, string &&language_code,
Promise<td_api::object_ptr<td_api::botCommands>> &&promise);
} // namespace td

View File

@ -0,0 +1,43 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/Status.h"
namespace td {
class Td;
class BotCommandScope {
enum class Type : int32 {
Default,
AllUsers,
AllChats,
AllChatAdministrators,
Dialog,
DialogAdministrators,
DialogParticipant
};
Type type_ = Type::Default;
DialogId dialog_id_;
UserId user_id_;
explicit BotCommandScope(Type type, DialogId dialog_id = DialogId(), UserId user_id = UserId());
public:
static Result<BotCommandScope> get_bot_command_scope(Td *td, td_api::object_ptr<td_api::BotCommandScope> scope_ptr);
telegram_api::object_ptr<telegram_api::BotCommandScope> get_input_bot_command_scope(const Td *td) const;
};
} // namespace td

View File

@ -0,0 +1,207 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/DialogParticipant.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/files/FileSourceId.h"
#include "td/telegram/files/FileUploadId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
#include <memory>
namespace td {
class StoryContent;
class Td;
class BotInfoManager final : public Actor {
public:
BotInfoManager(Td *td, ActorShared<> parent);
BotInfoManager(const BotInfoManager &) = delete;
BotInfoManager &operator=(const BotInfoManager &) = delete;
BotInfoManager(BotInfoManager &&) = delete;
BotInfoManager &operator=(BotInfoManager &&) = delete;
~BotInfoManager() final;
void get_owned_bots(Promise<td_api::object_ptr<td_api::users>> &&promise);
void set_default_group_administrator_rights(AdministratorRights administrator_rights, Promise<Unit> &&promise);
void set_default_channel_administrator_rights(AdministratorRights administrator_rights, Promise<Unit> &&promise);
void can_bot_send_messages(UserId bot_user_id, Promise<Unit> &&promise);
void allow_bot_to_send_messages(UserId bot_user_id, Promise<Unit> &&promise);
FileSourceId get_bot_media_preview_file_source_id(UserId bot_user_id);
FileSourceId get_bot_media_preview_info_file_source_id(UserId bot_user_id, const string &language_code);
void get_bot_media_previews(UserId bot_user_id, Promise<td_api::object_ptr<td_api::botMediaPreviews>> &&promise);
void get_bot_media_preview_info(UserId bot_user_id, const string &language_code,
Promise<td_api::object_ptr<td_api::botMediaPreviewInfo>> &&promise);
void reload_bot_media_previews(UserId bot_user_id, Promise<Unit> &&promise);
void reload_bot_media_preview_info(UserId bot_user_id, const string &language_code, Promise<Unit> &&promise);
void add_bot_media_preview(UserId bot_user_id, const string &language_code,
td_api::object_ptr<td_api::InputStoryContent> &&input_content,
Promise<td_api::object_ptr<td_api::botMediaPreview>> &&promise);
void edit_bot_media_preview(UserId bot_user_id, const string &language_code, FileId file_id,
td_api::object_ptr<td_api::InputStoryContent> &&input_content,
Promise<td_api::object_ptr<td_api::botMediaPreview>> &&promise);
void reorder_bot_media_previews(UserId bot_user_id, const string &language_code, const vector<int32> &file_ids,
Promise<Unit> &&promise);
void delete_bot_media_previews(UserId bot_user_id, const string &language_code, const vector<int32> &file_ids,
Promise<Unit> &&promise);
void set_bot_name(UserId bot_user_id, const string &language_code, const string &name, Promise<Unit> &&promise);
void get_bot_name(UserId bot_user_id, const string &language_code, Promise<string> &&promise);
void set_bot_info_description(UserId bot_user_id, const string &language_code, const string &description,
Promise<Unit> &&promise);
void get_bot_info_description(UserId bot_user_id, const string &language_code, Promise<string> &&promise);
void set_bot_info_about(UserId bot_user_id, const string &language_code, const string &about,
Promise<Unit> &&promise);
void get_bot_info_about(UserId bot_user_id, const string &language_code, Promise<string> &&promise);
void set_custom_bot_verification(UserId bot_user_id, DialogId dialog_id, bool is_verified,
const string &custom_description, Promise<Unit> &&promise);
private:
static constexpr double MAX_QUERY_DELAY = 0.01;
class UploadMediaCallback;
class AddPreviewMediaQuery;
struct PendingBotMediaPreview {
FileId edited_file_id_;
UserId bot_user_id_;
string language_code_;
unique_ptr<StoryContent> content_;
FileUploadId file_upload_id_;
uint32 upload_order_ = 0;
bool was_reuploaded_ = false;
Promise<td_api::object_ptr<td_api::botMediaPreview>> promise_;
};
struct PendingSetBotInfoQuery {
UserId bot_user_id_;
string language_code_;
int type_ = 0;
string value_;
Promise<Unit> promise_;
PendingSetBotInfoQuery(UserId bot_user_id, const string &language_code, int type, const string &value,
Promise<Unit> &&promise)
: bot_user_id_(bot_user_id)
, language_code_(language_code)
, type_(type)
, value_(value)
, promise_(std::move(promise)) {
}
};
struct PendingGetBotInfoQuery {
UserId bot_user_id_;
string language_code_;
int type_ = 0;
Promise<string> promise_;
PendingGetBotInfoQuery(UserId bot_user_id, const string &language_code, int type, Promise<string> &&promise)
: bot_user_id_(bot_user_id), language_code_(language_code), type_(type), promise_(std::move(promise)) {
}
};
void tear_down() final;
void hangup() final;
void timeout_expired() final;
Result<telegram_api::object_ptr<telegram_api::InputUser>> get_media_preview_bot_input_user(
UserId user_id, bool can_be_edited = false);
static Status validate_bot_media_preview_language_code(const string &language_code);
void do_add_bot_media_preview(unique_ptr<PendingBotMediaPreview> &&pending_preview, vector<int> bad_parts);
void on_add_bot_media_preview_file_parts_missing(unique_ptr<PendingBotMediaPreview> &&pending_preview,
vector<int> &&bad_parts);
void on_upload_bot_media_preview(FileUploadId file_upload_id,
telegram_api::object_ptr<telegram_api::InputFile> input_file);
void on_upload_bot_media_preview_error(FileUploadId file_upload_id, Status status);
telegram_api::object_ptr<telegram_api::InputMedia> get_fake_input_media(FileId file_id) const;
void add_pending_set_query(UserId bot_user_id, const string &language_code, int type, const string &value,
Promise<Unit> &&promise);
void add_pending_get_query(UserId bot_user_id, const string &language_code, int type, Promise<string> &&promise);
vector<PendingSetBotInfoQuery> pending_set_bot_info_queries_;
vector<PendingGetBotInfoQuery> pending_get_bot_info_queries_;
FlatHashMap<UserId, FileSourceId, UserIdHash> bot_media_preview_file_source_ids_;
struct MediaPreviewSource {
UserId bot_user_id_;
string language_code_;
MediaPreviewSource() = default;
MediaPreviewSource(UserId bot_user_id, string language_code)
: bot_user_id_(bot_user_id), language_code_(std::move(language_code)) {
}
friend bool operator==(const MediaPreviewSource &lhs, const MediaPreviewSource &rhs) {
return lhs.bot_user_id_ == rhs.bot_user_id_ && lhs.language_code_ == rhs.language_code_;
}
};
struct MediaPreviewSourceHash {
uint32 operator()(MediaPreviewSource source) const {
return combine_hashes(UserIdHash()(source.bot_user_id_), Hash<string>()(source.language_code_));
}
};
FlatHashMap<MediaPreviewSource, FileSourceId, MediaPreviewSourceHash> bot_media_preview_info_file_source_ids_;
FlatHashMap<FileUploadId, unique_ptr<PendingBotMediaPreview>, FileUploadIdHash> being_uploaded_files_;
std::shared_ptr<UploadMediaCallback> upload_media_callback_;
uint32 bot_media_preview_upload_order_ = 0;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -0,0 +1,83 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
#include "td/utils/tl_helpers.h"
namespace td {
class Td;
class BotMenuButton {
string text_;
string url_;
friend bool operator==(const BotMenuButton &lhs, const BotMenuButton &rhs);
public:
BotMenuButton() = default;
BotMenuButton(string &&text, string &&url) : text_(std::move(text)), url_(std::move(url)) {
}
td_api::object_ptr<td_api::botMenuButton> get_bot_menu_button_object(Td *td) const;
template <class StorerT>
void store(StorerT &storer) const {
bool has_text = !text_.empty();
bool has_url = !url_.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(has_text);
STORE_FLAG(has_url);
END_STORE_FLAGS();
if (has_text) {
td::store(text_, storer);
}
if (has_url) {
td::store(url_, storer);
}
}
template <class ParserT>
void parse(ParserT &parser) {
bool has_text;
bool has_url;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(has_text);
PARSE_FLAG(has_url);
END_PARSE_FLAGS();
if (has_text) {
td::parse(text_, parser);
}
if (has_url) {
td::parse(url_, parser);
}
}
};
bool operator==(const BotMenuButton &lhs, const BotMenuButton &rhs);
inline bool operator!=(const BotMenuButton &lhs, const BotMenuButton &rhs) {
return !(lhs == rhs);
}
unique_ptr<BotMenuButton> get_bot_menu_button(telegram_api::object_ptr<telegram_api::BotMenuButton> &&bot_menu_button);
td_api::object_ptr<td_api::botMenuButton> get_bot_menu_button_object(Td *td, const BotMenuButton *bot_menu_button);
void set_menu_button(Td *td, UserId user_id, td_api::object_ptr<td_api::botMenuButton> &&menu_button,
Promise<Unit> &&promise);
void get_menu_button(Td *td, UserId user_id, Promise<td_api::object_ptr<td_api::botMenuButton>> &&promise);
} // namespace td

View File

@ -0,0 +1,25 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
namespace td {
class Td;
void send_bot_custom_query(Td *td, const string &method, const string &parameters,
Promise<td_api::object_ptr<td_api::customRequestResult>> &&promise);
void answer_bot_custom_query(Td *td, int64 custom_query_id, const string &data, Promise<Unit> &&promise);
void set_bot_updates_status(Td *td, int32 pending_update_count, const string &error_message, Promise<Unit> &&promise);
} // namespace td

View File

@ -0,0 +1,81 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
namespace td {
class Td;
class BotRecommendationManager final : public Actor {
public:
BotRecommendationManager(Td *td, ActorShared<> parent);
void get_bot_recommendations(UserId bot_user_id, bool return_local,
Promise<td_api::object_ptr<td_api::users>> &&users_promise,
Promise<td_api::object_ptr<td_api::count>> &&count_promise);
void open_bot_recommended_bot(UserId bot_user_id, UserId opened_bot_user_id, Promise<Unit> &&promise);
private:
static constexpr int32 BOT_RECOMMENDATIONS_CACHE_TIME = 86400; // some reasonable limit
struct RecommendedBots {
int32 total_count_ = 0;
vector<UserId> bot_user_ids_;
double next_reload_time_ = 0.0;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
void tear_down() final;
bool is_suitable_recommended_bot(UserId bot_user_id) const;
bool are_suitable_recommended_bots(const RecommendedBots &recommended_bots) const;
string get_bot_recommendations_database_key(UserId bot_user_id);
void load_bot_recommendations(UserId bot_user_id, bool use_database, bool return_local,
Promise<td_api::object_ptr<td_api::users>> &&users_promise,
Promise<td_api::object_ptr<td_api::count>> &&count_promise);
void fail_load_bot_recommendations_queries(UserId bot_user_id, Status &&error);
void finish_load_bot_recommendations_queries(UserId bot_user_id, int32 total_count, vector<UserId> bot_user_ids);
void on_load_bot_recommendations_from_database(UserId bot_user_id, string value);
void reload_bot_recommendations(UserId bot_user_id);
void on_get_bot_recommendations(UserId bot_user_id,
Result<telegram_api::object_ptr<telegram_api::users_Users>> &&r_users);
Td *td_;
ActorShared<> parent_;
FlatHashMap<UserId, RecommendedBots, UserIdHash> bot_recommended_bots_;
FlatHashMap<UserId, vector<Promise<td_api::object_ptr<td_api::users>>>, UserIdHash> get_bot_recommendations_queries_;
FlatHashMap<UserId, vector<Promise<td_api::object_ptr<td_api::count>>>, UserIdHash>
get_bot_recommendation_count_queries_[2];
};
} // namespace td

View File

@ -0,0 +1,59 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/CustomEmojiId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Dependencies;
class Td;
class BotVerification {
public:
BotVerification() = default;
explicit BotVerification(telegram_api::object_ptr<telegram_api::botVerification> &&bot_verification);
static unique_ptr<BotVerification> get_bot_verification(
telegram_api::object_ptr<telegram_api::botVerification> &&bot_verification);
td_api::object_ptr<td_api::botVerification> get_bot_verification_object(Td *td) const;
bool is_valid() const {
return bot_user_id_.is_valid() && icon_.is_valid();
}
void add_dependencies(Dependencies &dependencies) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
UserId bot_user_id_;
CustomEmojiId icon_;
string description_;
friend bool operator==(const BotVerification &lhs, const BotVerification &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BotVerification &bot_verification);
};
bool operator==(const BotVerification &lhs, const BotVerification &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const BotVerification &bot_verification);
} // namespace td

View File

@ -0,0 +1,56 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/CustomEmojiId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class BotVerifierSettings {
public:
BotVerifierSettings() = default;
explicit BotVerifierSettings(telegram_api::object_ptr<telegram_api::botVerifierSettings> &&bot_verifier_settings);
static unique_ptr<BotVerifierSettings> get_bot_verifier_settings(
telegram_api::object_ptr<telegram_api::botVerifierSettings> &&bot_verifier_settings);
td_api::object_ptr<td_api::botVerificationParameters> get_bot_verification_parameters_object(Td *td) const;
bool is_valid() const {
return icon_.is_valid();
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
CustomEmojiId icon_;
string company_;
string description_;
bool can_modify_custom_description_ = false;
friend bool operator==(const BotVerifierSettings &lhs, const BotVerifierSettings &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BotVerifierSettings &bot_verifier_settings);
};
bool operator==(const BotVerifierSettings &lhs, const BotVerifierSettings &rhs);
StringBuilder &operator<<(StringBuilder &string_builder, const BotVerifierSettings &bot_verifier_settings);
} // namespace td

View File

@ -0,0 +1,70 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BusinessAwayMessageSchedule.h"
#include "td/telegram/BusinessRecipients.h"
#include "td/telegram/QuickReplyShortcutId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Dependencies;
class Td;
class BusinessAwayMessage {
public:
BusinessAwayMessage() = default;
explicit BusinessAwayMessage(telegram_api::object_ptr<telegram_api::businessAwayMessage> away_message);
explicit BusinessAwayMessage(td_api::object_ptr<td_api::businessAwayMessageSettings> away_message);
td_api::object_ptr<td_api::businessAwayMessageSettings> get_business_away_message_settings_object(Td *td) const;
telegram_api::object_ptr<telegram_api::inputBusinessAwayMessage> get_input_business_away_message(Td *td) const;
bool is_empty() const {
return !is_valid();
}
bool is_valid() const {
return shortcut_id_.is_server();
}
void add_dependencies(Dependencies &dependencies) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
QuickReplyShortcutId shortcut_id_;
BusinessRecipients recipients_;
BusinessAwayMessageSchedule schedule_;
bool offline_only_ = false;
friend bool operator==(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessage &away_message);
};
bool operator==(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs);
inline bool operator!=(const BusinessAwayMessage &lhs, const BusinessAwayMessage &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessage &away_message);
} // namespace td

View File

@ -0,0 +1,54 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class BusinessAwayMessageSchedule {
public:
BusinessAwayMessageSchedule() = default;
explicit BusinessAwayMessageSchedule(telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule> schedule);
explicit BusinessAwayMessageSchedule(td_api::object_ptr<td_api::BusinessAwayMessageSchedule> schedule);
td_api::object_ptr<td_api::BusinessAwayMessageSchedule> get_business_away_message_schedule_object() const;
telegram_api::object_ptr<telegram_api::BusinessAwayMessageSchedule> get_input_business_away_message_schedule() const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
enum class Type : int32 { Always, OutsideOfWorkHours, Custom };
Type type_ = Type::Always;
int32 start_date_ = 0;
int32 end_date_ = 0;
friend bool operator==(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessageSchedule &schedule);
};
bool operator==(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs);
inline bool operator!=(const BusinessAwayMessageSchedule &lhs, const BusinessAwayMessageSchedule &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessAwayMessageSchedule &schedule);
} // namespace td

View File

@ -0,0 +1,86 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/tl_helpers.h"
namespace td {
class Dependencies;
class Td;
class BusinessBotManageBar {
UserId business_bot_user_id_;
string business_bot_manage_url_;
bool is_business_bot_paused_ = false;
bool can_business_bot_reply_ = false;
friend bool operator==(const BusinessBotManageBar &lhs, const BusinessBotManageBar &rhs);
public:
static unique_ptr<BusinessBotManageBar> create(bool is_business_bot_paused, bool can_business_bot_reply,
UserId business_bot_user_id, string business_bot_manage_url);
bool is_empty() const;
void fix(DialogId dialog_id);
td_api::object_ptr<td_api::businessBotManageBar> get_business_bot_manage_bar_object(Td *td) const;
bool on_user_deleted();
bool set_business_bot_is_paused(bool is_paused);
void add_dependencies(Dependencies &dependencies) const;
template <class StorerT>
void store(StorerT &storer) const {
bool has_business_bot_user_id = business_bot_user_id_.is_valid();
bool has_business_bot_manage_url = !business_bot_manage_url_.empty();
BEGIN_STORE_FLAGS();
STORE_FLAG(is_business_bot_paused_);
STORE_FLAG(can_business_bot_reply_);
STORE_FLAG(has_business_bot_user_id);
STORE_FLAG(has_business_bot_manage_url);
END_STORE_FLAGS();
if (has_business_bot_user_id) {
td::store(business_bot_user_id_, storer);
}
if (has_business_bot_manage_url) {
td::store(business_bot_manage_url_, storer);
}
}
template <class ParserT>
void parse(ParserT &parser) {
bool has_business_bot_user_id;
bool has_business_bot_manage_url;
BEGIN_PARSE_FLAGS();
PARSE_FLAG(is_business_bot_paused_);
PARSE_FLAG(can_business_bot_reply_);
PARSE_FLAG(has_business_bot_user_id);
PARSE_FLAG(has_business_bot_manage_url);
END_PARSE_FLAGS();
if (has_business_bot_user_id) {
td::parse(business_bot_user_id_, parser);
}
if (has_business_bot_manage_url) {
td::parse(business_bot_manage_url_, parser);
}
}
};
bool operator==(const BusinessBotManageBar &lhs, const BusinessBotManageBar &rhs);
bool operator!=(const BusinessBotManageBar &lhs, const BusinessBotManageBar &rhs);
} // namespace td

View File

@ -0,0 +1,54 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/MessageEntity.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class UserManager;
class BusinessChatLink {
string link_;
FormattedText text_;
string title_;
int32 view_count_ = 0;
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessChatLink &link);
public:
BusinessChatLink(const UserManager *user_manager, telegram_api::object_ptr<telegram_api::businessChatLink> &&link);
bool is_valid() const {
return !link_.empty();
}
td_api::object_ptr<td_api::businessChatLink> get_business_chat_link_object(const UserManager *user_manager) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessChatLink &link);
class BusinessChatLinks {
vector<BusinessChatLink> business_chat_links_;
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessChatLinks &links);
public:
BusinessChatLinks(const UserManager *user_manager,
vector<telegram_api::object_ptr<telegram_api::businessChatLink>> &&links);
td_api::object_ptr<td_api::businessChatLinks> get_business_chat_links_object(const UserManager *user_manager) const;
};
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessChatLinks &links);
} // namespace td

View File

@ -0,0 +1,71 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BusinessRecipients.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/telegram/UserId.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class BusinessConnectedBot {
public:
BusinessConnectedBot() = default;
explicit BusinessConnectedBot(telegram_api::object_ptr<telegram_api::connectedBot> connected_bot);
explicit BusinessConnectedBot(td_api::object_ptr<td_api::businessConnectedBot> connected_bot);
td_api::object_ptr<td_api::businessConnectedBot> get_business_connected_bot_object(Td *td) const;
bool is_valid() const {
return user_id_.is_valid();
}
UserId get_user_id() const {
return user_id_;
}
const BusinessRecipients &get_recipients() const {
return recipients_;
}
bool get_can_reply() const {
return can_reply_;
}
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
UserId user_id_;
BusinessRecipients recipients_;
bool can_reply_ = false;
friend bool operator==(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessConnectedBot &connected_bot);
};
bool operator==(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs);
inline bool operator!=(const BusinessConnectedBot &lhs, const BusinessConnectedBot &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessConnectedBot &connected_bot);
} // namespace td

View File

@ -0,0 +1,79 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/HashTableUtils.h"
#include "td/utils/StringBuilder.h"
namespace td {
class BusinessConnectionId {
string business_connection_id_;
public:
BusinessConnectionId() = default;
explicit BusinessConnectionId(string &&business_connection_id)
: business_connection_id_(std::move(business_connection_id)) {
}
explicit BusinessConnectionId(const string &business_connection_id)
: business_connection_id_(business_connection_id) {
}
bool is_empty() const {
return business_connection_id_.empty();
}
bool is_valid() const {
return !business_connection_id_.empty();
}
const string &get() const {
return business_connection_id_;
}
bool operator==(const BusinessConnectionId &other) const {
return business_connection_id_ == other.business_connection_id_;
}
bool operator!=(const BusinessConnectionId &other) const {
return business_connection_id_ != other.business_connection_id_;
}
telegram_api::object_ptr<telegram_api::Function> get_invoke_prefix() const {
if (is_empty()) {
return nullptr;
}
return telegram_api::make_object<telegram_api::invokeWithBusinessConnectionPrefix>(business_connection_id_);
}
template <class StorerT>
void store(StorerT &storer) const {
storer.store_string(business_connection_id_);
}
template <class ParserT>
void parse(ParserT &parser) {
business_connection_id_ = parser.template fetch_string<string>();
}
};
struct BusinessConnectionIdHash {
uint32 operator()(BusinessConnectionId business_connection_id) const {
return Hash<string>()(business_connection_id.get());
}
};
inline StringBuilder &operator<<(StringBuilder &string_builder, BusinessConnectionId business_connection_id) {
return string_builder << "business connection " << business_connection_id.get();
}
} // namespace td

View File

@ -0,0 +1,230 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BusinessConnectionId.h"
#include "td/telegram/DialogId.h"
#include "td/telegram/files/FileUploadId.h"
#include "td/telegram/MessageEffectId.h"
#include "td/telegram/MessageId.h"
#include "td/telegram/MessageInputReplyTo.h"
#include "td/telegram/net/DcId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/FlatHashMap.h"
#include "td/utils/Promise.h"
#include "td/utils/Status.h"
#include "td/utils/WaitFreeHashMap.h"
#include <memory>
namespace td {
struct InputMessageContent;
struct ReplyMarkup;
class Td;
class BusinessConnectionManager final : public Actor {
public:
BusinessConnectionManager(Td *td, ActorShared<> parent);
BusinessConnectionManager(const BusinessConnectionManager &) = delete;
BusinessConnectionManager &operator=(const BusinessConnectionManager &) = delete;
BusinessConnectionManager(BusinessConnectionManager &&) = delete;
BusinessConnectionManager &operator=(BusinessConnectionManager &&) = delete;
~BusinessConnectionManager() final;
Status check_business_connection(const BusinessConnectionId &connection_id, DialogId dialog_id) const;
DcId get_business_connection_dc_id(const BusinessConnectionId &connection_id) const;
void on_update_bot_business_connect(telegram_api::object_ptr<telegram_api::botBusinessConnection> &&connection);
void on_update_bot_new_business_message(const BusinessConnectionId &connection_id,
telegram_api::object_ptr<telegram_api::Message> &&message,
telegram_api::object_ptr<telegram_api::Message> &&reply_to_message);
void on_update_bot_edit_business_message(const BusinessConnectionId &connection_id,
telegram_api::object_ptr<telegram_api::Message> &&message,
telegram_api::object_ptr<telegram_api::Message> &&reply_to_message);
void on_update_bot_delete_business_messages(const BusinessConnectionId &connection_id, DialogId dialog_id,
vector<int32> &&messages);
void get_business_connection(const BusinessConnectionId &connection_id,
Promise<td_api::object_ptr<td_api::businessConnection>> &&promise);
void send_message(BusinessConnectionId business_connection_id, DialogId dialog_id,
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to, bool disable_notification,
bool protect_content, MessageEffectId effect_id,
td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void send_message_album(BusinessConnectionId business_connection_id, DialogId dialog_id,
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to, bool disable_notification,
bool protect_content, MessageEffectId effect_id,
vector<td_api::object_ptr<td_api::InputMessageContent>> &&input_message_contents,
Promise<td_api::object_ptr<td_api::businessMessages>> &&promise);
void edit_business_message_text(BusinessConnectionId business_connection_id, DialogId dialog_id, MessageId message_id,
td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void edit_business_message_live_location(BusinessConnectionId business_connection_id, DialogId dialog_id,
MessageId message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
td_api::object_ptr<td_api::location> &&input_location, int32 live_period,
int32 heading, int32 proximity_alert_radius,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void edit_business_message_media(BusinessConnectionId business_connection_id, DialogId dialog_id,
MessageId message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void edit_business_message_caption(BusinessConnectionId business_connection_id, DialogId dialog_id,
MessageId message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
td_api::object_ptr<td_api::formattedText> &&input_caption, bool invert_media,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void edit_business_message_reply_markup(BusinessConnectionId business_connection_id, DialogId dialog_id,
MessageId message_id, td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void stop_poll(BusinessConnectionId business_connection_id, DialogId dialog_id, MessageId message_id,
td_api::object_ptr<td_api::ReplyMarkup> &&reply_markup,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
struct BusinessConnection;
struct PendingMessage;
class SendBusinessMessageQuery;
class SendBusinessMediaQuery;
class SendBusinessMultiMediaQuery;
class UploadBusinessMediaQuery;
class UploadMediaCallback;
class UploadThumbnailCallback;
class EditBusinessMessageQuery;
class StopBusinessPollQuery;
struct UploadMediaResult {
unique_ptr<PendingMessage> message_;
telegram_api::object_ptr<telegram_api::InputMedia> input_media_;
};
struct BeingUploadedMedia {
unique_ptr<PendingMessage> message_;
telegram_api::object_ptr<telegram_api::InputFile> input_file_;
Promise<UploadMediaResult> promise_;
};
struct MediaGroupSendRequest {
size_t finished_count_ = 0;
vector<Result<UploadMediaResult>> upload_results_;
Promise<td_api::object_ptr<td_api::businessMessages>> promise_;
unique_ptr<PendingMessage> paid_media_message_;
Promise<td_api::object_ptr<td_api::businessMessage>> paid_media_promise_;
};
void tear_down() final;
Status check_business_message_id(MessageId message_id) const;
void on_get_business_connection(const BusinessConnectionId &connection_id,
Result<telegram_api::object_ptr<telegram_api::Updates>> r_updates);
MessageInputReplyTo create_business_message_input_reply_to(
td_api::object_ptr<td_api::InputMessageReplyTo> &&reply_to);
Result<InputMessageContent> process_input_message_content(
td_api::object_ptr<td_api::InputMessageContent> &&input_message_content);
unique_ptr<PendingMessage> create_business_message_to_send(BusinessConnectionId business_connection_id,
DialogId dialog_id, MessageInputReplyTo &&input_reply_to,
bool disable_notification, bool protect_content,
MessageEffectId effect_id,
unique_ptr<ReplyMarkup> &&reply_markup,
InputMessageContent &&input_content) const;
void do_send_message(unique_ptr<PendingMessage> &&message,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void process_sent_business_message(telegram_api::object_ptr<telegram_api::Updates> &&updates_ptr,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void upload_media(unique_ptr<PendingMessage> &&message, Promise<UploadMediaResult> &&promise,
vector<int> bad_parts = {});
void complete_send_media(unique_ptr<PendingMessage> &&message,
telegram_api::object_ptr<telegram_api::InputMedia> &&input_media,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void on_upload_media(FileUploadId file_upload_id, telegram_api::object_ptr<telegram_api::InputFile> input_file);
void on_upload_media_error(FileUploadId file_upload_id, Status status);
void on_upload_thumbnail(FileUploadId thumbnail_file_upload_id,
telegram_api::object_ptr<telegram_api::InputFile> thumbnail_input_file);
void do_upload_media(BeingUploadedMedia &&being_uploaded_media,
telegram_api::object_ptr<telegram_api::InputFile> input_thumbnail);
void complete_upload_media(unique_ptr<PendingMessage> &&message,
telegram_api::object_ptr<telegram_api::MessageMedia> &&media,
Promise<UploadMediaResult> &&promise);
int64 generate_new_media_album_id();
void do_send_message_album(int64 request_id, BusinessConnectionId business_connection_id, DialogId dialog_id,
MessageInputReplyTo &&input_reply_to, bool disable_notification, bool protect_content,
MessageEffectId effect_id, vector<InputMessageContent> &&message_contents,
Promise<td_api::object_ptr<td_api::businessMessages>> &&promise);
void on_upload_message_album_media(int64 request_id, size_t media_pos, Result<UploadMediaResult> &&result);
void process_sent_business_message_album(telegram_api::object_ptr<telegram_api::Updates> &&updates_ptr,
Promise<td_api::object_ptr<td_api::businessMessages>> &&promise);
void on_upload_message_paid_media(int64 request_id, size_t media_pos, Result<UploadMediaResult> &&result);
void on_fail_send_message(unique_ptr<PendingMessage> &&message, const Status &error);
void do_edit_message_media(unique_ptr<PendingMessage> &&message,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
void do_edit_business_message_media(Result<UploadMediaResult> &&result,
Promise<td_api::object_ptr<td_api::businessMessage>> &&promise);
td_api::object_ptr<td_api::updateBusinessConnection> get_update_business_connection(
const BusinessConnection *connection) const;
WaitFreeHashMap<BusinessConnectionId, unique_ptr<BusinessConnection>, BusinessConnectionIdHash> business_connections_;
FlatHashMap<BusinessConnectionId, vector<Promise<td_api::object_ptr<td_api::businessConnection>>>,
BusinessConnectionIdHash>
get_business_connection_queries_;
int64 current_media_group_send_request_id_ = 0;
FlatHashMap<int64, MediaGroupSendRequest> media_group_send_requests_;
std::shared_ptr<UploadMediaCallback> upload_media_callback_;
std::shared_ptr<UploadThumbnailCallback> upload_thumbnail_callback_;
FlatHashMap<FileUploadId, BeingUploadedMedia, FileUploadIdHash> being_uploaded_files_;
FlatHashMap<FileUploadId, BeingUploadedMedia, FileUploadIdHash> being_uploaded_thumbnails_;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

View File

@ -0,0 +1,70 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BusinessRecipients.h"
#include "td/telegram/QuickReplyShortcutId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Dependencies;
class Td;
class BusinessGreetingMessage {
public:
BusinessGreetingMessage() = default;
explicit BusinessGreetingMessage(telegram_api::object_ptr<telegram_api::businessGreetingMessage> greeting_message);
explicit BusinessGreetingMessage(td_api::object_ptr<td_api::businessGreetingMessageSettings> greeting_message);
td_api::object_ptr<td_api::businessGreetingMessageSettings> get_business_greeting_message_settings_object(
Td *td) const;
telegram_api::object_ptr<telegram_api::inputBusinessGreetingMessage> get_input_business_greeting_message(
Td *td) const;
bool is_empty() const {
return !is_valid();
}
bool is_valid() const {
return shortcut_id_.is_server();
}
void add_dependencies(Dependencies &dependencies) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
QuickReplyShortcutId shortcut_id_;
BusinessRecipients recipients_;
int32 inactivity_days_ = 0;
friend bool operator==(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessGreetingMessage &greeting_message);
};
bool operator==(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs);
inline bool operator!=(const BusinessGreetingMessage &lhs, const BusinessGreetingMessage &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessGreetingMessage &greeting_message);
} // namespace td

View File

@ -0,0 +1,60 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/BusinessAwayMessage.h"
#include "td/telegram/BusinessGreetingMessage.h"
#include "td/telegram/BusinessIntro.h"
#include "td/telegram/BusinessWorkHours.h"
#include "td/telegram/DialogLocation.h"
#include "td/telegram/files/FileId.h"
#include "td/telegram/td_api.h"
#include "td/utils/common.h"
namespace td {
class Dependencies;
class Td;
class BusinessInfo {
public:
td_api::object_ptr<td_api::businessInfo> get_business_info_object(Td *td) const;
bool is_empty() const;
static bool set_location(unique_ptr<BusinessInfo> &business_info, DialogLocation &&location);
static bool set_work_hours(unique_ptr<BusinessInfo> &business_info, BusinessWorkHours &&work_hours);
static bool set_away_message(unique_ptr<BusinessInfo> &business_info, BusinessAwayMessage &&away_message);
static bool set_greeting_message(unique_ptr<BusinessInfo> &business_info, BusinessGreetingMessage &&greeting_message);
static bool set_intro(unique_ptr<BusinessInfo> &business_info, BusinessIntro &&intro);
void add_dependencies(Dependencies &dependencies) const;
vector<FileId> get_file_ids(const Td *td) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
static bool is_empty_location(const DialogLocation &location);
DialogLocation location_;
BusinessWorkHours work_hours_;
BusinessAwayMessage away_message_;
BusinessGreetingMessage greeting_message_;
BusinessIntro intro_;
};
} // namespace td

View File

@ -0,0 +1,62 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/files/FileId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h"
#include "td/utils/StringBuilder.h"
namespace td {
class Td;
class BusinessIntro {
public:
BusinessIntro() = default;
BusinessIntro(Td *td, telegram_api::object_ptr<telegram_api::businessIntro> intro);
BusinessIntro(Td *td, td_api::object_ptr<td_api::inputBusinessStartPage> intro);
td_api::object_ptr<td_api::businessStartPage> get_business_start_page_object(Td *td) const;
telegram_api::object_ptr<telegram_api::inputBusinessIntro> get_input_business_intro(Td *td) const;
bool is_empty() const {
return title_.empty() && description_.empty() && !sticker_file_id_.is_valid();
}
vector<FileId> get_file_ids(const Td *td) const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
private:
string title_;
string description_;
FileId sticker_file_id_;
friend bool operator==(const BusinessIntro &lhs, const BusinessIntro &rhs);
friend StringBuilder &operator<<(StringBuilder &string_builder, const BusinessIntro &intro);
};
bool operator==(const BusinessIntro &lhs, const BusinessIntro &rhs);
inline bool operator!=(const BusinessIntro &lhs, const BusinessIntro &rhs) {
return !(lhs == rhs);
}
StringBuilder &operator<<(StringBuilder &string_builder, const BusinessIntro &intro);
} // namespace td

View File

@ -0,0 +1,71 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2025
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#pragma once
#include "td/telegram/DialogId.h"
#include "td/telegram/td_api.h"
#include "td/telegram/UserId.h"
#include "td/actor/actor.h"
#include "td/utils/common.h"
#include "td/utils/Promise.h"
namespace td {
class BusinessAwayMessage;
class BusinessGreetingMessage;
class BusinessIntro;
class BusinessWorkHours;
class DialogLocation;
class Td;
class BusinessManager final : public Actor {
public:
BusinessManager(Td *td, ActorShared<> parent);
void get_business_connected_bot(Promise<td_api::object_ptr<td_api::businessConnectedBot>> &&promise);
void set_business_connected_bot(td_api::object_ptr<td_api::businessConnectedBot> &&bot, Promise<Unit> &&promise);
void delete_business_connected_bot(UserId bot_user_id, Promise<Unit> &&promise);
void toggle_business_connected_bot_dialog_is_paused(DialogId dialog_id, bool is_paused, Promise<Unit> &&promise);
void remove_business_connected_bot_from_dialog(DialogId dialog_id, Promise<Unit> &&promise);
void get_business_chat_links(Promise<td_api::object_ptr<td_api::businessChatLinks>> &&promise);
void create_business_chat_link(td_api::object_ptr<td_api::inputBusinessChatLink> &&link_info,
Promise<td_api::object_ptr<td_api::businessChatLink>> &&promise);
void edit_business_chat_link(const string &link, td_api::object_ptr<td_api::inputBusinessChatLink> &&link_info,
Promise<td_api::object_ptr<td_api::businessChatLink>> &&promise);
void delete_business_chat_link(const string &link, Promise<Unit> &&promise);
void get_business_chat_link_info(const string &link,
Promise<td_api::object_ptr<td_api::businessChatLinkInfo>> &&promise);
void set_business_location(DialogLocation &&location, Promise<Unit> &&promise);
void set_business_work_hours(BusinessWorkHours &&work_hours, Promise<Unit> &&promise);
void set_business_greeting_message(BusinessGreetingMessage &&greeting_message, Promise<Unit> &&promise);
void set_business_away_message(BusinessAwayMessage &&away_message, Promise<Unit> &&promise);
void set_business_intro(BusinessIntro &&intro, Promise<Unit> &&promise);
private:
void tear_down() final;
Td *td_;
ActorShared<> parent_;
};
} // namespace td

Some files were not shown because too many files have changed in this diff Show More