mirror of
https://github.com/danog/pif-tdpony.git
synced 2024-11-30 04:19:41 +01:00
Fix bugs and finish implementation
This commit is contained in:
parent
4b45f97535
commit
3a1b156bae
5
.gitignore
vendored
5
.gitignore
vendored
@ -7,3 +7,8 @@ compile_commands.json
|
||||
*sqlite
|
||||
documents
|
||||
libpif.*
|
||||
build
|
||||
depend.*
|
||||
.ninja*
|
||||
*.swp
|
||||
examples/madelinex
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
||||
[submodule "td"]
|
||||
path = td
|
||||
url = https://github.com/danog/td
|
@ -1,12 +1,26 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
||||
|
||||
project(PifTDPony VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(td)
|
||||
include_directories(td/td/generate/auto)
|
||||
include_directories(td/tdutils)
|
||||
set(CMAKE_BUILD_TYPE RelWithDebInfo)
|
||||
|
||||
find_package(Td 1.1.1 REQUIRED)
|
||||
|
||||
add_library(pif SHARED main.cpp)
|
||||
target_link_libraries(pif PRIVATE Td::TdJsonStatic phpcpp)
|
||||
target_link_libraries(pif PRIVATE Td::TdJson phpcpp)
|
||||
set_property(TARGET pif PROPERTY CXX_STANDARD 14)
|
||||
|
||||
add_custom_command(TARGET pif POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/pif.ini
|
||||
$<TARGET_FILE_DIR:pif>
|
||||
)
|
||||
|
||||
execute_process(COMMAND bash "-c" "php --ini | sed '/Scan for additional .ini files in: /!d;s/Scan for additional .ini files in: //'" OUTPUT_VARIABLE INI_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
execute_process(COMMAND php-config --extension-dir OUTPUT_VARIABLE EXTENSION_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
|
||||
install(TARGETS pif DESTINATION ${EXTENSION_DIR})
|
||||
install(FILES pif.ini DESTINATION ${INI_DIR})
|
||||
|
||||
|
42
README.md
42
README.md
@ -1,3 +1,45 @@
|
||||
# PIF-TDPony
|
||||
|
||||
This is a PHP interface for [tdlib](https://core.telegram.org).
|
||||
|
||||
# Installation
|
||||
|
||||
|
||||
```
|
||||
# Installing PHP
|
||||
sudo apt-get install python-software-properties software-properties-common
|
||||
sudo LC_ALL=C.UTF-8 add-apt-repository ppa:ondrej/php
|
||||
sudo apt-get update
|
||||
sudo apt-get install php7.2 php7.2-dev php7.2-fpm php7.2-curl php7.2-xml php7.2-gmp php7.1-zip -y
|
||||
|
||||
# Installing tdlib
|
||||
sudo apt-get install gperf cmake clang ninja-build libssl-dev
|
||||
git clone https://github.com/tdlib/td
|
||||
cd td
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=/usr ..
|
||||
sudo cmake --build . --target install
|
||||
cd ../..
|
||||
|
||||
# Installing PHP-CPP
|
||||
git clone https://github.com/CopernicaMarketingSoftware/PHP-CPP
|
||||
cd PHP-CPP
|
||||
make -j$(nproc)
|
||||
sudo make install
|
||||
cd ..
|
||||
|
||||
# Installing PIF-TDPony
|
||||
git clone https://github.com/danog/pif-tdpony
|
||||
cd pif-tdpony
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
sudo cmake --build . --target install
|
||||
cd ../../
|
||||
```
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
|
||||
|
31
examples/example.php
Normal file
31
examples/example.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
|
||||
if (file_exists('session.madelinex')) {
|
||||
$a = new \danog\MadelineProto\X\API('session.madelinex');
|
||||
} else {
|
||||
$params = [
|
||||
"use_message_database" => true,
|
||||
"api_id" => 6,
|
||||
"api_hash" => "eb06d4abfb49dc3eeb1aeb98ae0f581e",
|
||||
"system_language_code" => "en",
|
||||
"device_model" => "MadelineProto X",
|
||||
"system_version" => "unk",
|
||||
"application_version" => "1.1",
|
||||
"enable_storage_optimizer" => true,
|
||||
"use_pfs" => true,
|
||||
"database_directory" => "./madelinex"
|
||||
];
|
||||
$a = new \danog\MadelineProto\X\API($params);
|
||||
}
|
||||
\danog\Madelineproto\X\Logger::set_verbosity_level(5);
|
||||
|
||||
$a->serialize('session.madelinex');
|
||||
$a->setDatabaseEncryptionKey(); // no password for tdlib database
|
||||
|
||||
|
||||
while (true) {
|
||||
readline();
|
||||
$res = $a->receive(1);
|
||||
var_dumP($res);
|
||||
}
|
190
main.cpp
190
main.cpp
@ -10,11 +10,12 @@ If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <td/telegram/td_json_client.h>
|
||||
#include <td/telegram/Log.h>
|
||||
#include <td/telegram/td_log.h>
|
||||
|
||||
#include <phpcpp.h>
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
|
||||
class API : public Php::Base {
|
||||
public:
|
||||
@ -22,58 +23,187 @@ class API : public Php::Base {
|
||||
virtual ~API() = default;
|
||||
|
||||
void __construct(Php::Parameters ¶ms) {
|
||||
Php::Value self(this);
|
||||
self = Php::Value(this);
|
||||
if (params.size() != 1) {
|
||||
throw Php::Exception("Invalid parameter count");
|
||||
}
|
||||
if (params[0].isString()) {
|
||||
if (!Php::call("file_exists", params[0])) {
|
||||
throw Php::Exception("Provided file does not exist!");
|
||||
}
|
||||
Php::Value unserialized = Php::call("unserialize", Php::call("file_get_contents", params[0]));
|
||||
if (!unserialized.instanceOf("\\danog\\MadelineProto\\X\\TD")) {
|
||||
throw Php::Exception("An error occurred during deserialization!");
|
||||
}
|
||||
self["API"] = unserialized;
|
||||
self["session"] = params[0];
|
||||
} else {
|
||||
self["API"] = Php::Object("\\danog\\MadelineProto\\X\\TD", params[0]);
|
||||
}
|
||||
}
|
||||
void serialize(Php::Parameters ¶ms) {
|
||||
Php::Value path;
|
||||
if (params.size() == 1 && params[0].isString()) {
|
||||
path = params[0];
|
||||
} else if (self.contains("session") && self.get("session").isString()) {
|
||||
path = self.get("session");
|
||||
} else {
|
||||
throw Php::Exception("No valid path was provided");
|
||||
}
|
||||
last_serialized = Php::call("time");
|
||||
Php::call("file_put_contents", path, Php::call("serialize", self.get("API")));
|
||||
}
|
||||
void __destruct() {
|
||||
if (self.contains("session") && self.get("session").isString()) {
|
||||
last_serialized = Php::call("time");
|
||||
Php::call("file_put_contents", self.get("session"), Php::call("serialize", self.get("API")));
|
||||
}
|
||||
}
|
||||
Php::Value __actualcall(Php::Parameters ¶ms) {
|
||||
if (last_serialized < Php::call("time") - 30 && self.contains("session") && self.get("session").isString()) {
|
||||
last_serialized = Php::call("time");
|
||||
Php::call("file_put_contents", self.get("session"), Php::call("serialize", self.get("API")));
|
||||
}
|
||||
if (params[1].size() == 1) {
|
||||
return self.get("API").call(params[0], params[1].get(0));
|
||||
}
|
||||
return self.get("API").call(params[0]);
|
||||
}
|
||||
|
||||
private:
|
||||
Php::Value self;
|
||||
Php::Value last_serialized = 0;
|
||||
};
|
||||
|
||||
class TD : public Php::Base {
|
||||
public:
|
||||
TD() = default;
|
||||
virtual ~TD() = default;
|
||||
|
||||
void __construct(Php::Parameters ¶ms) {
|
||||
self = Php::Value(this);
|
||||
self["tdlibParameters"]["@type"] = "setTdlibParameters";
|
||||
self["tdlibParameters"]["parameters"] = params[0];
|
||||
|
||||
initTdlib();
|
||||
}
|
||||
void __wakeup() {
|
||||
self = Php::Value(this);
|
||||
initTdlib();
|
||||
}
|
||||
void __destruct() {
|
||||
deinitTdlib();
|
||||
}
|
||||
|
||||
Php::Value __sleep() {
|
||||
Php::Array buffer;
|
||||
while (updates.size()) {
|
||||
buffer[buffer.size()] = updates.front();
|
||||
updates.pop();
|
||||
}
|
||||
for (auto &item : buffer) {
|
||||
updates.push(item.second);
|
||||
}
|
||||
self["updatesBuffer"] = buffer;
|
||||
Php::Array result({"updatesBuffer", "tdlibParameters"});
|
||||
return result;
|
||||
}
|
||||
|
||||
void initTdlib() {
|
||||
client = td_json_client_create();
|
||||
Php::Value self(this);
|
||||
td_json_client_execute(client, json_encode(self["tdlibParameters"]));
|
||||
if (self["updatesBuffer"]) {
|
||||
Php::Value buffer = self["updatesBuffer"];
|
||||
for (auto &item : buffer) {
|
||||
updates.push(item.second);
|
||||
}
|
||||
Php::Array empty;
|
||||
self["updatesBuffer"] = empty;
|
||||
}
|
||||
|
||||
Php::Value update;
|
||||
while (true) {
|
||||
update = json_decode(td_json_client_receive(client, 0));
|
||||
if (update) {
|
||||
if (update.get("@type") == "updateAuthorizationState" && update.get("authorization_state").get("@type") == "authorizationStateWaitTdlibParameters") {
|
||||
execute(self["tdlibParameters"]);
|
||||
break;
|
||||
}
|
||||
updates.push(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
void deinitTdlib() {
|
||||
td_json_client_destroy(client);
|
||||
}
|
||||
|
||||
|
||||
void send(Php::Parameters ¶ms) {
|
||||
Php::Value value = params[0];
|
||||
if (value.get("@type") == "setTdlibParameters") {
|
||||
Php::Value self(this);
|
||||
self["tdlibParameters"] = value;
|
||||
}
|
||||
td_json_client_send(client, json_encode(value));
|
||||
}
|
||||
|
||||
Php::Value receive(Php::Parameters ¶ms) {
|
||||
if (updates.size()) {
|
||||
Php::Value res = updates.front();
|
||||
updates.pop();
|
||||
return res;
|
||||
}
|
||||
return json_decode(td_json_client_receive(client, params[0]));
|
||||
}
|
||||
|
||||
Php::Value execute(Php::Parameters ¶ms) {
|
||||
Php::Value value = params[0];
|
||||
if (value.get("@type") == "setTdlibParameters") {
|
||||
Php::Value self(this);
|
||||
return execute(params[0]);
|
||||
}
|
||||
|
||||
Php::Value execute(Php::Value value) {
|
||||
if (value["@type"] && value.get("@type") == "setTdlibParameters") {
|
||||
self["tdlibParameters"] = value;
|
||||
}
|
||||
return json_decode(td_json_client_execute(client, json_encode(value)));
|
||||
std::int64_t query_id = next_query_id();
|
||||
value["@extra"] = query_id;
|
||||
|
||||
td_json_client_send(client, json_encode(value));
|
||||
|
||||
Php::Value update;
|
||||
while (true) {
|
||||
update = json_decode(td_json_client_receive(client, 0));
|
||||
if (update) {
|
||||
if (update["@extra"] == query_id) {
|
||||
return update;
|
||||
}
|
||||
|
||||
|
||||
|
||||
updates.push(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
Php::Value __call(const char *name, Php::Parameters ¶ms) {
|
||||
Php::Array value;
|
||||
if (params.size() == 1) {
|
||||
value = params[0];
|
||||
}
|
||||
value["@type"] = name;
|
||||
return execute(value);
|
||||
}
|
||||
private:
|
||||
void *client;
|
||||
std::queue<Php::Value> updates;
|
||||
Php::Value self;
|
||||
|
||||
std::int64_t query_id = 0;
|
||||
std::int64_t next_query_id() {
|
||||
return ++query_id;
|
||||
}
|
||||
const char *json_encode(Php::Value value) {
|
||||
return strdup(Php::call("json_encode", value));
|
||||
}
|
||||
Php::Value json_decode(std::string value) {
|
||||
return Php::call("json_decode", value, true);
|
||||
Php::Value json_decode(const char *value) {
|
||||
Php::Value result;
|
||||
if (value) {
|
||||
result = Php::call("json_decode", value, true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@ -85,13 +215,14 @@ class Logger : public Php::Base
|
||||
virtual ~Logger() = default;
|
||||
|
||||
static Php::Value set_file_path(Php::Parameters ¶ms) {
|
||||
return td::Log::set_file_path(params[0]);
|
||||
return td_set_log_file_path(params[0]);
|
||||
}
|
||||
static void set_max_file_size(Php::Parameters ¶ms) {
|
||||
td::Log::set_max_file_size(params[0]);
|
||||
std::int64_t size = params[0];
|
||||
td_set_log_max_file_size(size);
|
||||
}
|
||||
static void set_verbosity_level(Php::Parameters ¶ms) {
|
||||
td::Log::set_verbosity_level(params[0]);
|
||||
td_set_log_verbosity_level(params[0]);
|
||||
}
|
||||
};
|
||||
|
||||
@ -114,17 +245,27 @@ extern "C" {
|
||||
// description of the class so that PHP knows which methods are accessible
|
||||
Php::Class<API> api("API");
|
||||
|
||||
api.method<&API::__construct>("__construct", Php::Public | Php::Final, {Php::ByVal("tdlibParameters", Php::Type::Array)});
|
||||
api.method<&API::__wakeup>("__wakeup", Php::Public | Php::Final, {});
|
||||
api.method<&API::__construct>("__construct", Php::Public | Php::Final);
|
||||
api.method<&API::__destruct>("__destruct", Php::Public | Php::Final, {});
|
||||
api.method<&API::send>("send", Php::Public | Php::Final);
|
||||
api.method<&API::receive>("receive", Php::Public | Php::Final, {Php::ByVal("timeout", Php::Type::Float)});
|
||||
api.method<&API::execute>("execute", Php::Public | Php::Final);
|
||||
|
||||
api.property("tdlibParameters", nullptr, Php::Private);
|
||||
api.method<&API::__actualcall>("__call", Php::Public | Php::Final, {Php::ByVal("method", Php::Type::String), Php::ByVal("args", Php::Type::Array)});
|
||||
api.method<&API::serialize>("serialize", Php::Public | Php::Final, {Php::ByVal("path", Php::Type::String)});
|
||||
|
||||
api.constant("PIF_TDPONY_VERSION", "1.0");
|
||||
|
||||
|
||||
Php::Class<TD> td("TD");
|
||||
td.method<&TD::__construct>("__construct", Php::Public | Php::Final);
|
||||
td.method<&TD::__destruct>("__destruct", Php::Public | Php::Final);
|
||||
td.method<&TD::__wakeup>("__wakeup", Php::Public | Php::Final);
|
||||
td.method<&TD::__sleep>("__sleep", Php::Public | Php::Final);
|
||||
td.method<&TD::send>("send", Php::Public | Php::Final);
|
||||
td.method<&TD::receive>("receive", Php::Public | Php::Final, {Php::ByVal("timeout", Php::Type::Float)});
|
||||
td.method<&TD::execute>("execute", Php::Public | Php::Final);
|
||||
|
||||
td.property("tdlibParameters", nullptr, Php::Private);
|
||||
td.property("updatesBuffer", nullptr, Php::Private);
|
||||
|
||||
|
||||
Php::Namespace danog("danog");
|
||||
Php::Namespace MadelineProto("MadelineProto");
|
||||
Php::Namespace X("X");
|
||||
@ -136,6 +277,7 @@ extern "C" {
|
||||
logger.method<&Logger::set_verbosity_level>("set_verbosity_level", Php::Public, {Php::ByVal("verbosity_level", Php::Type::Numeric)});
|
||||
|
||||
X.add(std::move(api));
|
||||
X.add(std::move(td));
|
||||
X.add(std::move(logger));
|
||||
MadelineProto.add(std::move(X));
|
||||
danog.add(std::move(MadelineProto));
|
||||
|
1
td
1
td
@ -1 +0,0 @@
|
||||
Subproject commit b84ed67dfbc7797ffce54490594cc8e3fb4df7ba
|
Loading…
Reference in New Issue
Block a user