diff --git a/CMakeLists.txt b/CMakeLists.txt index 77a4da3..3bc79d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,12 +14,13 @@ set(INSTALL_PATH "${INSTALL_PATH}" CACHE PATH "Path to install the plugin binary add_library(tox MODULE src/tox-weechat.c - src/tox-weechat-tox.c - src/tox-weechat-utils.c - src/tox-weechat-commands.c - src/tox-weechat-gui.c + src/tox-weechat-identities.c src/tox-weechat-chats.c src/tox-weechat-friend-requests.c + src/tox-weechat-tox-callbacks.c + src/tox-weechat-commands.c + src/tox-weechat-gui.c + src/tox-weechat-utils.c ) add_definitions(-D_GNU_SOURCE) diff --git a/src/tox-weechat-chats.c b/src/tox-weechat-chats.c index a82e98b..c3f4653 100644 --- a/src/tox-weechat-chats.c +++ b/src/tox-weechat-chats.c @@ -5,7 +5,7 @@ #include #include "tox-weechat.h" -#include "tox-weechat-tox.h" +#include "tox-weechat-identities.h" #include "tox-weechat-utils.h" #include "tox-weechat-chats.h" @@ -65,6 +65,22 @@ tox_weechat_chat_refresh(struct t_tox_weechat_chat *chat) free(status_message); } +int +tox_weechat_chat_refresh_timer_callback(void *data, int remaining) +{ + struct t_tox_weechat_chat *chat = data; + tox_weechat_chat_refresh(chat); + + return WEECHAT_RC_OK; +} + +void +tox_weechat_chat_queue_refresh(struct t_tox_weechat_chat *chat) +{ + weechat_hook_timer(0, 0, 1, + tox_weechat_chat_refresh_timer_callback, chat); +} + struct t_tox_weechat_chat * tox_weechat_friend_chat_new(struct t_tox_weechat_identity *identity, int32_t friend_number) diff --git a/src/tox-weechat-chats.h b/src/tox-weechat-chats.h index 31f772b..af62f5e 100644 --- a/src/tox-weechat-chats.h +++ b/src/tox-weechat-chats.h @@ -36,6 +36,10 @@ void tox_weechat_chat_print_action(struct t_tox_weechat_chat *chat, const char *sender, const char *message); -void tox_weechat_chat_refresh(struct t_tox_weechat_chat *chat); +void +tox_weechat_chat_refresh(struct t_tox_weechat_chat *chat); + +void +tox_weechat_chat_queue_refresh(struct t_tox_weechat_chat *chat); #endif // TOX_WEECHAT_CHATS_H diff --git a/src/tox-weechat-commands.c b/src/tox-weechat-commands.c index ac49dfa..a4db067 100644 --- a/src/tox-weechat-commands.c +++ b/src/tox-weechat-commands.c @@ -4,13 +4,17 @@ #include #include "tox-weechat.h" -#include "tox-weechat-tox.h" #include "tox-weechat-utils.h" +#include "tox-weechat-identities.h" #include "tox-weechat-chats.h" #include "tox-weechat-friend-requests.h" #include "tox-weechat-commands.h" +// TODO: something +extern int +tox_weechat_bootstrap_tox(Tox *tox, char *address, uint16_t port, char *public_key); + int tox_weechat_cmd_bootstrap(void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol) diff --git a/src/tox-weechat-config.c b/src/tox-weechat-config.c index 5a0467c..df562c4 100644 --- a/src/tox-weechat-config.c +++ b/src/tox-weechat-config.c @@ -3,7 +3,7 @@ #include "tox-weechat.h" struct t_config_file *tox_weechat_config_file = NULL; -struct t_config_section *tox_weechat_config_section_server = NULL; +struct t_config_section *tox_weechat_config_section_identity = NULL; int tox_weechat_config_reload_callback(void *data, @@ -65,7 +65,7 @@ tox_weechat_config_init() tox_weechat_config_file = weechat_config_new("tox", tox_weechat_config_reload_callback, NULL); - tox_weechat_config_section_server = + tox_weechat_config_section_identity = weechat_config_new_section(tox_weechat_config_file, "identity", 0, 0, tox_weechat_config_identity_read_callback, NULL, @@ -78,17 +78,17 @@ tox_weechat_config_init() } void -tox_weechat_config_init_server(const char *name) +tox_weechat_config_init_identity(const char *name) { struct t_config_option *option = weechat_config_new_option(tox_weechat_config_file, - tox_weechat_config_section_server, + tox_weechat_config_section_identity, "name", "string", "identity name", NULL, 0, 0, name, name, 0, - tox_weechat_config_server_name_check_callback, NULL, - tox_weechat_config_server_name_change_callback, NULL, + tox_weechat_config_identity_name_check_callback, NULL, + tox_weechat_config_identity_name_change_callback, NULL, NULL, NULL); } diff --git a/src/tox-weechat-friend-requests.c b/src/tox-weechat-friend-requests.c index 0fa4871..8e970e2 100644 --- a/src/tox-weechat-friend-requests.c +++ b/src/tox-weechat-friend-requests.c @@ -6,7 +6,7 @@ #include #include "tox-weechat.h" -#include "tox-weechat-tox.h" +#include "tox-weechat-identities.h" #include "tox-weechat-utils.h" #include "tox-weechat-friend-requests.h" diff --git a/src/tox-weechat-gui.c b/src/tox-weechat-gui.c index 624ba62..d595bcd 100644 --- a/src/tox-weechat-gui.c +++ b/src/tox-weechat-gui.c @@ -6,8 +6,8 @@ #include #include "tox-weechat.h" +#include "tox-weechat-identities.h" #include "tox-weechat-utils.h" -#include "tox-weechat-tox.h" #include "tox-weechat-gui.h" diff --git a/src/tox-weechat-identities.c b/src/tox-weechat-identities.c new file mode 100644 index 0000000..df11646 --- /dev/null +++ b/src/tox-weechat-identities.c @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "tox-weechat.h" +#include "tox-weechat-chats.h" +#include "tox-weechat-tox-callbacks.h" +#include "tox-weechat-utils.h" + +#include "tox-weechat-identities.h" + +struct t_tox_weechat_identity *tox_weechat_identities = NULL; +struct t_tox_weechat_identity *tox_weechat_last_identity = NULL; + +/** + * Return the default data file path for an identity name. Must be freed. + */ +char * +tox_weechat_default_data_path(const char *name) +{ + const char *weechat_dir = weechat_info_get("weechat_dir", NULL); + const char *tox_dir = "/tox/"; + + weechat_mkdir_home("tox", 0755); + + int path_length = strlen(weechat_dir) + strlen(tox_dir) + strlen(name) + 1; + char *tox_data_path = malloc(sizeof(*tox_data_path) + path_length); + + strcpy(tox_data_path, weechat_dir); + strcat(tox_data_path, tox_dir); + strcat(tox_data_path, name); + tox_data_path[path_length-1] = 0; + + return tox_data_path; +} + +int +tox_weechat_load_data_file(Tox *tox, char *path) +{ + FILE *file = fopen(path, "r"); + if (file) + { + // get file size + fseek(file, 0, SEEK_END); + size_t size = ftell(file); + rewind(file); + + // allocate a buffer and read file into it + uint8_t *data = malloc(sizeof(*data) * size); + fread(data, sizeof(uint8_t), size, file); + fclose(file); + + // try loading the data + int status = tox_load(tox, data, size); + + free(data); + + return status; + } + + return -1; +} + +int +tox_weechat_save_data_file(Tox *tox, char *path) +{ + // save Tox data to a buffer + uint32_t size = tox_size(tox); + uint8_t *data = malloc(sizeof(*data) * size); + tox_save(tox, data); + + // save buffer to a file + FILE *file = fopen(path, "w"); + if (file) + { + fwrite(data, sizeof(data[0]), size, file); + fclose(file); + + return 0; + } + + return -1; +} + +int +tox_weechat_identity_buffer_close_callback(void *data, + struct t_gui_buffer *buffer) +{ + struct t_tox_weechat_identity *identity = data; + identity->buffer = NULL; + + tox_weechat_identity_free(data); + + return WEECHAT_RC_OK; +} + +#define BOOTSTRAP_ADDRESS "192.254.75.98" +#define BOOTSTRAP_PORT 33445 +#define BOOTSTRAP_KEY "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F" + +int +tox_weechat_bootstrap_tox(Tox *tox, char *address, uint16_t port, char *public_key) +{ + char *binary_key = malloc(TOX_FRIEND_ADDRESS_SIZE); + tox_weechat_hex2bin(public_key, binary_key); + + int result = tox_bootstrap_from_address(tox, + address, + htons(port), + (uint8_t *)binary_key); + free(binary_key); + + return result; +} + + +struct t_tox_weechat_identity * +tox_weechat_identity_new(const char *name) +{ + struct t_tox_weechat_identity *identity = malloc(sizeof(*identity)); + identity->name = strdup(name); + identity->data_file_path = tox_weechat_default_data_path(name); + + // add to identity list + identity->prev_identity= tox_weechat_last_identity; + identity->next_identity = NULL; + + if (tox_weechat_identities == NULL) + tox_weechat_identities = identity; + else + tox_weechat_last_identity->next_identity = identity; + + tox_weechat_last_identity = identity; + + // set up internal vars + identity->chats = identity->last_chat = NULL; + // TODO: load from disk + identity->friend_requests = identity->last_friend_request = NULL; + identity->friend_request_count = 0; + + return identity; +} + +void +tox_weechat_identity_connect(struct t_tox_weechat_identity *identity) +{ + // create main buffer + identity->buffer = weechat_buffer_new(identity->name, + NULL, NULL, + tox_weechat_identity_buffer_close_callback, NULL); + + // create Tox + identity->tox = tox_new(NULL); + + // try loading Tox saved data + if (tox_weechat_load_data_file(identity->tox, identity->data_file_path) == -1) + { + // couldn't load Tox, set a default name + tox_set_name(identity->tox, + (uint8_t *)"WeeChatter", strlen("WeeChatter")); + } + + // bootstrap DHT + tox_weechat_bootstrap_tox(identity->tox, BOOTSTRAP_ADDRESS, + BOOTSTRAP_PORT, + BOOTSTRAP_KEY); + + // start Tox_do loop + tox_weechat_do_timer_cb(identity, 0); + + // register Tox callbacks + tox_callback_friend_message(identity->tox, tox_weechat_friend_message_callback, identity); + tox_callback_friend_action(identity->tox, tox_weechat_friend_action_callback, identity); + tox_callback_connection_status(identity->tox, tox_weechat_connection_status_callback, identity); + tox_callback_name_change(identity->tox, tox_weechat_name_change_callback, identity); + tox_callback_user_status(identity->tox, tox_weechat_user_status_callback, identity); + tox_callback_status_message(identity->tox, tox_weechat_status_message_callback, identity); + tox_callback_friend_request(identity->tox, tox_weechat_callback_friend_request, identity); +} + +struct t_tox_weechat_identity * +tox_weechat_identity_for_buffer(struct t_gui_buffer *buffer) +{ + for (struct t_tox_weechat_identity *identity = tox_weechat_identities; + identity; + identity = identity->next_identity) + { + if (identity->buffer == buffer) + return identity; + + for (struct t_tox_weechat_chat *chat = identity->chats; + chat; + chat = chat->next_chat) + { + if (chat->buffer == buffer) + return identity; + } + } + + return NULL; +} + +void +tox_weechat_identity_free(struct t_tox_weechat_identity *identity) +{ + // remove from list + if (identity == tox_weechat_last_identity) + tox_weechat_last_identity = identity->prev_identity; + + if (identity->prev_identity) + identity->prev_identity->next_identity = identity->next_identity; + else + tox_weechat_identities = identity->next_identity; + + if (identity->next_identity) + identity->next_identity->prev_identity = identity->prev_identity; + + // save and kill tox + int result = tox_weechat_save_data_file(identity->tox, + identity->data_file_path); + tox_kill(identity->tox); + + if (result == -1) + { + weechat_printf(NULL, + "%sCould not save Tox identity %s to file: %s", + weechat_prefix("error"), + identity->name, + identity->data_file_path); + } + + if (identity->buffer) + weechat_buffer_close(identity->buffer); + + // TODO: free config, free friend reqs/chats + + free(identity->name); + free(identity); +} + +void +tox_weechat_identity_free_all() +{ + while (tox_weechat_identities) + tox_weechat_identity_free(tox_weechat_identities); +} diff --git a/src/tox-weechat-tox.h b/src/tox-weechat-identities.h similarity index 50% rename from src/tox-weechat-tox.h rename to src/tox-weechat-identities.h index a97bae3..50cc772 100644 --- a/src/tox-weechat-tox.h +++ b/src/tox-weechat-identities.h @@ -1,14 +1,28 @@ -#ifndef TOX_WEECHAT_TOX_H -#define TOX_WEECHAT_TOX_H +#ifndef TOX_WEECHAT_IDENTITIES_H +#define TOX_WEECHAT_IDENTITIES_H #include +enum t_tox_weechat_identity_option +{ + TOX_WEECHAT_IDENTITY_OPTION_SAVEFILE = 0, + TOX_WEECHAT_IDENTITY_OPTION_AUTOCONNECT, + TOX_WEECHAT_IDENTITY_OPTION_MAX_FRIEND_REQUESTS, + + TOX_WEECHAT_IDENTITY_NUM_OPTIONS, +}; + struct t_tox_weechat_identity { struct Tox *tox; char *name; - char *data_path; + + struct t_config_option *options[TOX_WEECHAT_IDENTITY_NUM_OPTIONS]; + + // TODO: move to option + char *data_file_path; + unsigned int max_friend_requests; struct t_gui_buffer *buffer; @@ -20,7 +34,6 @@ struct t_tox_weechat_identity struct t_tox_weechat_friend_request *friend_requests; struct t_tox_weechat_friend_request *last_friend_request; unsigned int friend_request_count; - unsigned int max_friend_requests; struct t_tox_weechat_identity *next_identity; struct t_tox_weechat_identity *prev_identity; @@ -29,25 +42,19 @@ struct t_tox_weechat_identity extern struct t_tox_weechat_identity *tox_weechat_identities; extern struct t_tox_weechat_identity *tox_weechat_last_identity; -/** - * Initialize the Tox object, bootstrap the DHT and start working. - */ -void tox_weechat_tox_init(); - -struct t_tox_weechat_identity *tox_weechat_identity_for_buffer(struct t_gui_buffer *buffer); - struct t_tox_weechat_identity * tox_weechat_identity_new(const char *name); -/** - * Bootstrap DHT using an inet address, port and a Tox address. - */ -int tox_weechat_bootstrap(char *address, uint16_t port, char *public_key); -int tox_weechat_bootstrap_tox(struct Tox *tox, char *address, uint16_t port, char *public_key); +void +tox_weechat_identity_connect(struct t_tox_weechat_identity *identity); -/** - * Dump Tox to file and de-initialize. - */ -void tox_weechat_tox_free(); +struct t_tox_weechat_identity * +tox_weechat_identity_for_buffer(struct t_gui_buffer *buffer); -#endif // TOX_WEECHAT_TOX_H +void +tox_weechat_identity_free(struct t_tox_weechat_identity *identity); + +void +tox_weechat_identity_free_all(); + +#endif // TOX_WEECHAT_IDENTITIES_H diff --git a/src/tox-weechat-tox-callbacks.c b/src/tox-weechat-tox-callbacks.c new file mode 100644 index 0000000..af1ef42 --- /dev/null +++ b/src/tox-weechat-tox-callbacks.c @@ -0,0 +1,189 @@ +#include + +#include +#include + +#include "tox-weechat.h" +#include "tox-weechat-identities.h" +#include "tox-weechat-chats.h" +#include "tox-weechat-friend-requests.h" +#include "tox-weechat-utils.h" + +#include "tox-weechat-tox-callbacks.h" + +int +tox_weechat_do_timer_cb(void *data, + int remaining_calls) +{ + struct t_tox_weechat_identity *identity = data; + + tox_do(identity->tox); + weechat_hook_timer(tox_do_interval(identity->tox), 0, 1, + tox_weechat_do_timer_cb, identity); + + // check connection status + int connected = tox_isconnected(identity->tox); + if (connected ^ identity->is_connected) + { + identity->is_connected = connected; + } + + return WEECHAT_RC_OK; +} + +void +tox_weechat_friend_message_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + struct t_tox_weechat_chat *chat = tox_weechat_get_friend_chat(identity, + friend_number); + + char *name = tox_weechat_get_name_nt(identity->tox, friend_number); + char *message_nt = tox_weechat_null_terminate(message, length); + + tox_weechat_chat_print_message(chat, name, message_nt); + + free(name); + free(message_nt); +} + +void +tox_weechat_friend_action_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + struct t_tox_weechat_chat *chat = tox_weechat_get_friend_chat(identity, + friend_number); + + char *name = tox_weechat_get_name_nt(identity->tox, friend_number); + char *message_nt = tox_weechat_null_terminate(message, length); + + tox_weechat_chat_print_action(chat, name, message_nt); + + free(name); + free(message_nt); +} + +void +tox_weechat_connection_status_callback(Tox *tox, + int32_t friend_number, + uint8_t status, + void *data) +{ + if (status == 1) + { + struct t_tox_weechat_identity *identity = data; + char *name = tox_weechat_get_name_nt(identity->tox, friend_number); + + weechat_printf(identity->buffer, + "%s%s just went online!", + weechat_prefix("network"), + name); + free(name); + } +} + +void +tox_weechat_name_change_callback(Tox *tox, + int32_t friend_number, + const uint8_t *name, + uint16_t length, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, + friend_number); + + char *old_name = tox_weechat_get_name_nt(identity->tox, friend_number); + char *new_name = tox_weechat_null_terminate(name, length); + + if (chat && strcmp(old_name, new_name) != 0) + { + tox_weechat_chat_queue_refresh(chat); + + weechat_printf(chat->buffer, + "%s%s is now known as %s", + weechat_prefix("network"), + old_name, new_name); + } + + weechat_printf(identity->buffer, + "%s%s is now known as %s", + weechat_prefix("network"), + old_name, new_name); + + free(old_name); + free(new_name); +} + +void +tox_weechat_user_status_callback(Tox *tox, + int32_t friend_number, + uint8_t status, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, + friend_number); + if (chat) + tox_weechat_chat_queue_refresh(chat); +} + +void +tox_weechat_status_message_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, + friend_number); + if (chat) + tox_weechat_chat_queue_refresh(chat); +} + +void +tox_weechat_callback_friend_request(Tox *tox, + const uint8_t *public_key, + const uint8_t *message, + uint16_t length, + void *data) +{ + struct t_tox_weechat_identity *identity = data; + + if (identity->friend_request_count >= identity->max_friend_requests) + { + weechat_printf(identity->buffer, + "%sReceived a friend request, but your friend request list is full!", + weechat_prefix("warning")); + return; + } + + // TODO: move to t-w-f-r.h + struct t_tox_weechat_friend_request *request = malloc(sizeof(*request)); + + memcpy(request->address, public_key, TOX_CLIENT_ID_SIZE); + request->message = tox_weechat_null_terminate(message, length); + + tox_weechat_friend_request_add(identity, request); + + char *hex_address = malloc(TOX_CLIENT_ID_SIZE * 2 + 1); + tox_weechat_bin2hex(request->address, TOX_CLIENT_ID_SIZE, hex_address); + + weechat_printf(identity->buffer, + "%sReceived a friend request from %s: \"%s\"", + weechat_prefix("network"), + hex_address, + request->message); + + free(hex_address); +} + diff --git a/src/tox-weechat-tox-callbacks.h b/src/tox-weechat-tox-callbacks.h new file mode 100644 index 0000000..a9629b4 --- /dev/null +++ b/src/tox-weechat-tox-callbacks.h @@ -0,0 +1,59 @@ +#ifndef TOX_WEECHAT_TOX_CALLBACKS_H +#define TOX_WEECHAT_TOX_CALLBACKS_H + +#include + +#include + +int +tox_weechat_do_timer_cb(void *data, + int remaining_calls); + +void +tox_weechat_friend_message_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data); + +void +tox_weechat_friend_action_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data); + +void +tox_weechat_connection_status_callback(Tox *tox, + int32_t friend_number, + uint8_t status, + void *data); + +void +tox_weechat_name_change_callback(Tox *tox, + int32_t friend_number, + const uint8_t *name, + uint16_t length, + void *data); + +void +tox_weechat_user_status_callback(Tox *tox, + int32_t friend_number, + uint8_t status, + void *data); + +void +tox_weechat_status_message_callback(Tox *tox, + int32_t friend_number, + const uint8_t *message, + uint16_t length, + void *data); + +void +tox_weechat_callback_friend_request(Tox *tox, + const uint8_t *public_key, + const uint8_t *message, + uint16_t length, + void *data); + +#endif // TOX_WEECHAT_TOX_CALLBACKS_H diff --git a/src/tox-weechat-tox.c b/src/tox-weechat-tox.c deleted file mode 100644 index 476e3ff..0000000 --- a/src/tox-weechat-tox.c +++ /dev/null @@ -1,394 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "tox-weechat.h" -#include "tox-weechat-utils.h" -#include "tox-weechat-chats.h" -#include "tox-weechat-friend-requests.h" - -#include "tox-weechat-tox.h" - -#define INITIAL_NAME "WeeChatter" - -#define BOOTSTRAP_ADDRESS "192.254.75.98" -#define BOOTSTRAP_PORT 33445 -#define BOOTSTRAP_KEY "951C88B7E75C867418ACDB5D273821372BB5BD652740BCDF623A4FA293E75D2F" - -struct t_tox_weechat_identity *tox_weechat_identities = NULL; -struct t_tox_weechat_identity *tox_weechat_last_identity = NULL; - -char * -tox_weechat_default_data_path(const char *name) -{ - const char *weechat_dir = weechat_info_get("weechat_dir", NULL); - const char *tox_dir = "/tox/"; - - weechat_mkdir_home("tox", 0755); - - int path_length = strlen(weechat_dir) + strlen(tox_dir) + strlen(name) + 1; - char *tox_data_path = malloc(sizeof(*tox_data_path) + path_length); - - strcpy(tox_data_path, weechat_dir); - strcat(tox_data_path, tox_dir); - strcat(tox_data_path, name); - tox_data_path[path_length-1] = 0; - - return tox_data_path; -} - -/** - * Load Tox data from a file path. - * - * Returns 0 on success, -1 on failure. */ -int -tox_weechat_load_file(Tox *tox, char *path) -{ - FILE *file = fopen(path, "r"); - if (file) - { - // get file size - fseek(file, 0, SEEK_END); - size_t size = ftell(file); - rewind(file); - - // allocate a buffer and read file into it - uint8_t *data = malloc(sizeof(*data) * size); - fread(data, sizeof(uint8_t), size, file); - fclose(file); - - // try loading the data - int status = tox_load(tox, data, size); - free(data); - - return status; - } - - return -1; -} - -int -tox_weechat_do_timer_cb(void *data, - int remaining_calls) -{ - struct t_tox_weechat_identity *identity = data; - - tox_do(identity->tox); - weechat_hook_timer(tox_do_interval(identity->tox), 0, 1, - tox_weechat_do_timer_cb, identity); - - int connected = tox_isconnected(identity->tox); - if (connected ^ identity->is_connected) - { - identity->is_connected = connected; - weechat_bar_item_update("buffer_plugin"); - } - - return WEECHAT_RC_OK; -} - -int -tox_weechat_chat_refresh_timer_callback(void *data, int remaining) -{ - struct t_tox_weechat_chat *chat = data; - tox_weechat_chat_refresh(chat); - - return WEECHAT_RC_OK; -} - -void -tox_weechat_friend_message_callback(Tox *tox, - int32_t friend_number, - const uint8_t *message, - uint16_t length, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - struct t_tox_weechat_chat *chat = tox_weechat_get_friend_chat(identity, - friend_number); - - char *name = tox_weechat_get_name_nt(identity->tox, friend_number); - char *message_nt = tox_weechat_null_terminate(message, length); - - tox_weechat_chat_print_message(chat, name, message_nt); - - free(name); - free(message_nt); -} - -void -tox_weechat_friend_action_callback(Tox *tox, - int32_t friend_number, - const uint8_t *message, - uint16_t length, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - struct t_tox_weechat_chat *chat = tox_weechat_get_friend_chat(identity, - friend_number); - - char *name = tox_weechat_get_name_nt(identity->tox, friend_number); - char *message_nt = tox_weechat_null_terminate(message, length); - - tox_weechat_chat_print_action(chat, name, message_nt); - - free(name); - free(message_nt); -} - -void -tox_weechat_connection_status_callback(Tox *tox, - int32_t friend_number, - uint8_t status, - void *data) -{ - if (status == 1) - { - struct t_tox_weechat_identity *identity = data; - char *name = tox_weechat_get_name_nt(identity->tox, friend_number); - - weechat_printf(identity->buffer, - "%s%s just went online!", - weechat_prefix("network"), - name); - free(name); - } -} - -void -tox_weechat_name_change_callback(Tox *tox, - int32_t friend_number, - const uint8_t *name, - uint16_t length, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, - friend_number); - - char *old_name = tox_weechat_get_name_nt(identity->tox, friend_number); - char *new_name = tox_weechat_null_terminate(name, length); - - if (strcmp(old_name, new_name) != 0) - { - if (chat) - { - weechat_hook_timer(10, 0, 1, - tox_weechat_chat_refresh_timer_callback, chat); - - weechat_printf(chat->buffer, - "%s%s is now known as %s", - weechat_prefix("network"), - old_name, new_name); - } - } - - weechat_printf(identity->buffer, - "%s%s is now known as %s", - weechat_prefix("network"), - old_name, new_name); - - free(old_name); - free(new_name); -} - -void -tox_weechat_user_status_callback(Tox *tox, - int32_t friend_number, - uint8_t status, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, - friend_number); - if (chat) - weechat_hook_timer(10, 0, 1, - tox_weechat_chat_refresh_timer_callback, chat); -} - -void -tox_weechat_status_message_callback(Tox *tox, - int32_t friend_number, - const uint8_t *message, - uint16_t length, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - struct t_tox_weechat_chat *chat = tox_weechat_get_existing_friend_chat(identity, - friend_number); - if (chat) - weechat_hook_timer(10, 0, 1, - tox_weechat_chat_refresh_timer_callback, chat); -} - -void -tox_weechat_callback_friend_request(Tox *tox, - const uint8_t *public_key, - const uint8_t *message, - uint16_t length, - void *data) -{ - struct t_tox_weechat_identity *identity = data; - if (identity->friend_request_count >= identity->max_friend_requests) - { - weechat_printf(identity->buffer, - "%sReceived a friend request, but your friend request " - "list is full!", - weechat_prefix("warning")); - return; - } - struct t_tox_weechat_friend_request *request = malloc(sizeof(*request)); - - memcpy(request->address, public_key, TOX_CLIENT_ID_SIZE); - request->message = tox_weechat_null_terminate(message, length); - - tox_weechat_friend_request_add(identity, request); - - char *hex_address = malloc(TOX_CLIENT_ID_SIZE * 2 + 1); - tox_weechat_bin2hex(request->address, TOX_CLIENT_ID_SIZE, hex_address); - - weechat_printf(identity->buffer, - "%sReceived a friend request from %s: \"%s\"", - weechat_prefix("network"), - hex_address, - request->message); - - free(hex_address); -} - -int -tox_weechat_bootstrap_tox(Tox *tox, char *address, uint16_t port, char *public_key) -{ - char *binary_key = malloc(TOX_FRIEND_ADDRESS_SIZE); - tox_weechat_hex2bin(public_key, binary_key); - - int result = tox_bootstrap_from_address(tox, - address, - htons(port), - (uint8_t *)binary_key); - free(binary_key); - - return result; -} - -int -tox_weechat_bootstrap(char *address, uint16_t port, char *public_key) -{ - return tox_weechat_bootstrap_tox(tox_weechat_identities->tox, address, port, public_key); -} - -void -tox_weechat_tox_init() -{ - tox_weechat_identity_new("tox"); -} - -struct t_tox_weechat_identity * -tox_weechat_identity_new(const char *name) -{ - struct t_tox_weechat_identity *identity = malloc(sizeof(*identity)); - identity->name = strdup(name); - identity->data_path = tox_weechat_default_data_path("tox"); - - // TODO: add close callback - identity->buffer = weechat_buffer_new(identity->name, NULL, NULL, NULL, NULL); - - identity->tox = tox_new(NULL); - - // try loading Tox saved data - if (tox_weechat_load_file(identity->tox, identity->data_path) == -1) - { - // couldn't load Tox, set a default name - tox_set_name(identity->tox, - (uint8_t *)INITIAL_NAME, strlen(INITIAL_NAME)); - } - - identity->prev_identity= tox_weechat_last_identity; - identity->next_identity = NULL; - - if (tox_weechat_identities == NULL) - tox_weechat_identities = identity; - else - tox_weechat_last_identity->next_identity = identity; - - tox_weechat_last_identity = identity; - - // bootstrap DHT - tox_weechat_bootstrap_tox(identity->tox, BOOTSTRAP_ADDRESS, - BOOTSTRAP_PORT, - BOOTSTRAP_KEY); - - // start tox_do loop - tox_weechat_do_timer_cb(identity, 0); - - // register tox callbacks - tox_callback_friend_message(identity->tox, tox_weechat_friend_message_callback, identity); - tox_callback_friend_action(identity->tox, tox_weechat_friend_action_callback, identity); - tox_callback_connection_status(identity->tox, tox_weechat_connection_status_callback, identity); - tox_callback_name_change(identity->tox, tox_weechat_name_change_callback, identity); - tox_callback_user_status(identity->tox, tox_weechat_user_status_callback, identity); - tox_callback_status_message(identity->tox, tox_weechat_status_message_callback, identity); - tox_callback_friend_request(identity->tox, tox_weechat_callback_friend_request, identity); - - return identity; -} - -struct t_tox_weechat_identity * -tox_weechat_identity_for_buffer(struct t_gui_buffer *buffer) -{ - for (struct t_tox_weechat_identity *identity = tox_weechat_identities; - identity; - identity = identity->next_identity) - { - if (identity->buffer == buffer) - return identity; - - for (struct t_tox_weechat_chat *chat = identity->chats; - chat; - chat = chat->next_chat) - { - if (chat->buffer == buffer) - return identity; - } - } - - return NULL; -} - -void -tox_weechat_save_to_file(Tox *tox, char *path) -{ - // save Tox data to a buffer - uint32_t size = tox_size(tox); - uint8_t *data = malloc(sizeof(*data) * size); - tox_save(tox, data); - - // save buffer to a file - FILE *data_file = fopen(path, "w"); - fwrite(data, sizeof(data[0]), size, data_file); - fclose(data_file); -} - -void -tox_weechat_free_identity(struct t_tox_weechat_identity *identity) -{ - tox_weechat_save_to_file(identity->tox, - identity->data_path); - - tox_kill(identity->tox); - free(identity->name); - free(identity->data_path); - free(identity); -} - -void -tox_weechat_tox_free() -{ - tox_weechat_free_identity(tox_weechat_identities); -} - diff --git a/src/tox-weechat.c b/src/tox-weechat.c index c1f87e3..418eeb4 100644 --- a/src/tox-weechat.c +++ b/src/tox-weechat.c @@ -2,7 +2,7 @@ #include -#include "tox-weechat-tox.h" +#include "tox-weechat-identities.h" #include "tox-weechat-commands.h" #include "tox-weechat-gui.h" #include "tox-weechat-friend-requests.h" @@ -24,7 +24,8 @@ weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) { weechat_plugin = plugin; - tox_weechat_tox_init(); + struct t_tox_weechat_identity *identity = tox_weechat_identity_new("tox"); + tox_weechat_identity_connect(identity); tox_weechat_commands_init(); tox_weechat_gui_init(); @@ -34,7 +35,7 @@ weechat_plugin_init(struct t_weechat_plugin *plugin, int argc, char *argv[]) int weechat_plugin_end(struct t_weechat_plugin *plugin) { - tox_weechat_tox_free(); + tox_weechat_identity_free_all(); return WEECHAT_RC_OK; }