diff --git a/.gitignore b/.gitignore index 4b85549..588f0a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ -curl*/ -buildDir/ +.build/ +.cache/ .token # Prerequisites diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index a5500f0..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "clangd.arguments": [ - "--compile-commands-dir=build/" - ], - "clangd.path": "clangd", -} \ No newline at end of file diff --git a/README.md b/README.md index 2c0c921..994f88a 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,50 @@ A minimal C Telegram API Framework ## Requirements +- meson - libcurl - json-c > Note: This project is purely educational. It does not aim to cover the entire Telegram Bot API, but only a selected subset of methods. -### Supported Features -#### Types +## How to build + +
+ +Linux + +```bash +$ meson setup build +$ cd build +$ meson compile +$ meson install +``` + +
+ +
+ +Windows + +Install all the required library with `vcpkg` and then copy the DLL file. + +```powershell +$ meson setup build --native-file meson-vcpkg.txt +$ cd build +$ meson compile +$ meson install +``` + +
+ +## Examples +You can find some examples [here](./examples/). + +### Supported Types - **InlineKeyboardMarkup** - Note: Standard `KeyboardMarkup` is intentionally not supported. -#### Methods +#### Supported Methods - `getMe` - `sendMessage` - `editMessageText` diff --git a/examples/echobot/echobot.c b/examples/echobot/echobot.c new file mode 100644 index 0000000..141c907 --- /dev/null +++ b/examples/echobot/echobot.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include + + +bool run = true; + +void sighandler(int signum) { + run = false; +} + +void callback(tgbot *bot, tgbot_cbquery *query) { + fprintf(stdout, "Callback called!"); +} + +void echo_message(tgbot *bot, tgbot_update *update) { + tgbot_send_message(bot, update->chat_id, update->text, "MARKDOWN", NULL, 0, 0); +} + +int main(void) { + printf("Running...\n"); + /* Retrieve bot's token */ + FILE *fp = fopen(".token", "r"); + if (fp == NULL) { + fprintf(stderr, "Unable to retrieve bot token\n"); + return 1; + } + + char token[256]; + fscanf(fp, "%s", token); + fprintf(stdout, "Token: %s\n", token); + fclose(fp); + + signal(SIGINT, sighandler); + + /* Initialize bot */ + tgbot bot; + tgbot_init(&bot, token); + tgbot_update update; + + while (run) { + tgbot_get_update(&bot, &update, callback); + echo_message(&bot, &update); + } + + fprintf(stdout, "Closing..."); + tgbot_destroy(&bot); + + return 0; +} \ No newline at end of file diff --git a/src/main.c b/examples/inlinekeyboard/inlinekeyboard.c similarity index 91% rename from src/main.c rename to examples/inlinekeyboard/inlinekeyboard.c index 1aaabbf..c779f78 100644 --- a/src/main.c +++ b/examples/inlinekeyboard/inlinekeyboard.c @@ -1,11 +1,18 @@ #include +#include #include #include #include -#include "main.h" -#include "tgbot.h" +#include +#define WELCOME_MSG "Hi there! This bot is coded in C." + +void parse_command(tgbot *bot, tgbot_update *update); +void sighandler(int signum); +void callback_parser(tgbot *bot, tgbot_cbquery *query); + +bool run = true; tgbot bot; size_t rows = 1, columns = 2; tgbot_inlinekeyboardmarkup **keyboard; @@ -33,11 +40,8 @@ void callback_handler(tgbot *bot, tgbot_cbquery *query) { } void sighandler(int signum) { - fprintf(stdout, "Cleaning resources...\n"); - tgbot_destroy(&bot); - tgbot_deallocate_inlinekeyboardmarkup(keyboard, rows); - - exit(0); + fprintf(stdout, "Closing...\n"); + run = false; } void parse_command(tgbot *bot, tgbot_update *update) { @@ -108,7 +112,7 @@ int main(void) { tgbot_update update; /* Main loop */ - for (;;) { + while (run) { ret = tgbot_get_update(&bot, &update, callback_handler); if (ret != TGBOT_OK) { fprintf(stderr, "tgbot_get_updates()\n"); @@ -119,4 +123,9 @@ int main(void) { parse_command(&bot, &update); } } + + tgbot_destroy(&bot); + tgbot_deallocate_inlinekeyboardmarkup(keyboard, rows); + + return 0; } diff --git a/include/main.h b/include/main.h deleted file mode 100644 index 17274aa..0000000 --- a/include/main.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef MAIN_H -#define MAIN_H - -#include "tgbot.h" - -#define WELCOME_MSG "Hi there! This bot is coded in C." - -void parse_command(tgbot *bot, tgbot_update *update); -void sighandler(int signum); -void callback_parser(tgbot *bot, tgbot_cbquery *query); - -#endif // MAIN_H diff --git a/include/tgbot.h b/include/tgbot.h index 981811e..70930a5 100644 --- a/include/tgbot.h +++ b/include/tgbot.h @@ -33,7 +33,6 @@ struct tgbot_me_t { }; typedef struct tgbot_me_t tgbot_me; -/* TODO: implement variable length string */ /** * A structure to represent Update object */ diff --git a/meson-vcpkg.txt b/meson-vcpkg.txt new file mode 100644 index 0000000..d506ab0 --- /dev/null +++ b/meson-vcpkg.txt @@ -0,0 +1,28 @@ +[constants] +vcpkg_base_path = 'C:/vcpkg/' +vcpkg_base_install_dir = 'C:/vcpkg/installed/' + +vcpkg_target_triplet = 'x64-windows' +vcpkg_host_triplet = 'x64-windows' + +vcpkg_installed_dir = vcpkg_base_install_dir + vcpkg_target_triplet + '/' +vcpkg_host_installed_dir = vcpkg_base_install_dir + vcpkg_host_triplet + '/' +vcpkg_toolchain_file = vcpkg_base_path + 'scripts/toolchains/windows.cmake' + +[properties] +cmake_toolchain_file = vcpkg_base_path + 'scripts/buildsystems/vcpkg.cmake' + +[binaries] +vcpkg = [ vcpkg_base_path + 'vcpkg.exe'] +pkgconfig = [ vcpkg_installed_dir + 'tools/pkgconf/pkgconf.exe'] + +[cmake] +VCPKG_TARGET_TRIPLET = vcpkg_target_triplet +VCPKG_HOST_TRIPLET = vcpkg_host_triplet +VCPKG_CHAINLOAD_TOOLCHAIN_FILE = vcpkg_base_path + 'scripts/toolchains/windows.cmake' +_VCPKG_INSTALLED_DIR = vcpkg_installed_dir +VCPKG_CRT_LINKAGE = 'dynamic' + +[built-in options] +pkg_config_path = [ vcpkg_installed_dir + 'lib/pkgconfig;' + vcpkg_installed_dir + 'share/pkgconfig'] +cmake_prefix_path = [ vcpkg_installed_dir ] \ No newline at end of file diff --git a/meson.build b/meson.build index 8b16156..99b6c81 100644 --- a/meson.build +++ b/meson.build @@ -1,18 +1,32 @@ -project('tgbot', 'c') -cc = meson.get_compiler('c') +project('tgbot', 'c', version: '0.1') sources = [] subdir('src') inc_dir = include_directories('include') -deps = [] -include_dirs = [inc_dir] - curl_dep = dependency('libcurl') -deps += curl_dep - json_c_dep = dependency('json-c') -deps += json_c_dep -executable('tgbot', sources, include_directories: [include_dirs], dependencies: deps) +deps = [curl_dep, json_c_dep] + +install_headers('include/tgbot.h') +#install_subdir('.', install_dir: 'C:/tgbot') +lib = library( + 'tgbot', + sources, + dependencies: deps, + include_directories: inc_dir, + install: true, +) + +# Example (windows) +lib_inc_dir = include_directories('C:/include') +executable( + 'example', + 'examples/echobot/echobot.c', + dependencies: deps, + link_with: lib, + include_directories: lib_inc_dir, + win_subsystem: 'console', +) \ No newline at end of file diff --git a/src/meson.build b/src/meson.build index 7841226..a94e50f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,3 @@ sources += files( - 'main.c', 'tgbot.c', ) diff --git a/src/tgbot.c b/src/tgbot.c index 9b786ef..c76db22 100644 --- a/src/tgbot.c +++ b/src/tgbot.c @@ -5,7 +5,6 @@ #include #include -#include "json_object.h" #include "tgbot.h" tgbot_rc tgbot_init(tgbot *bot, char *token) {