commit
410499e5bf
@ -0,0 +1,30 @@ |
|||||||
|
# use the official gcc image, based on debian |
||||||
|
# can use verions as well, like gcc:5.2 |
||||||
|
# see https://hub.docker.com/_/gcc/ |
||||||
|
image: gcc |
||||||
|
|
||||||
|
stages: |
||||||
|
- build |
||||||
|
|
||||||
|
build: |
||||||
|
stage: build |
||||||
|
# instead of calling g++ directly you can also use some build toolkit like make |
||||||
|
# install the necessary build tools when needed |
||||||
|
before_script: |
||||||
|
- apt update && apt -y install make autoconf gcc libtoxcore-dev libconfig-dev |
||||||
|
script: |
||||||
|
- cd src/ |
||||||
|
- gcc -o echo_bot misc.c tox_bot.c commands.c -std=gnu99 -lsodium -I /usr/local/include/ -ltoxcore -lconfig |
||||||
|
artifacts: |
||||||
|
paths: |
||||||
|
- src/echo_bot |
||||||
|
# depending on your build setup it's most likely a good idea to cache outputs to reduce the build time |
||||||
|
# cache: |
||||||
|
# paths: |
||||||
|
# - "*.o" |
||||||
|
|
||||||
|
# run tests using the binary built before |
||||||
|
#test: |
||||||
|
# stage: test |
||||||
|
# script: |
||||||
|
# - ./runmytests.sh |
@ -0,0 +1,2 @@ |
|||||||
|
76367760E8BDF485BE5FE616A9B445A5EE4F74DB180353591AADAEC800D307315DDBEF1679B2 |
||||||
|
3AABCAD5409C24BEEF0B789BF8357A6D7C83C41BF575D53EA87E967A16DDBD017B1C26D4D157 |
@ -0,0 +1,245 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <string.h> |
||||||
|
#include <strings.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <time.h> |
||||||
|
#include <inttypes.h> |
||||||
|
|
||||||
|
#include <tox/tox.h> |
||||||
|
|
||||||
|
#include "tox_bot.h" |
||||||
|
#include "misc.h" |
||||||
|
|
||||||
|
#define MAX_COMMAND_LENGTH TOX_MAX_MESSAGE_LENGTH |
||||||
|
#define MAX_NUM_ARGS 4 |
||||||
|
|
||||||
|
/* Commands */ |
||||||
|
/* */ |
||||||
|
static void cmd_help(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], bool user) |
||||||
|
{ |
||||||
|
char com_res[TOX_MAX_MESSAGE_LENGTH]; |
||||||
|
char str1[100] = "\n\n\t\t### Command list ### \n"; |
||||||
|
char str2[100] = "ping\t\t\t\t\t - Print pong answer\n"; |
||||||
|
char str3[100] = "echo \"<message>\"\t\t\t - Echoing your message\n"; |
||||||
|
char str4[100] = "changename \"<new bot name>\"\t\t - Set a new bot name\n"; |
||||||
|
char str5[100] = "changestatus \"<new bot statusname>\"\t - Set a new bot status message\n"; |
||||||
|
snprintf(com_res, sizeof com_res, "%s%s%s%s%s", str1, str2, str3, str4, str5); |
||||||
|
|
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) com_res, strlen(com_res), NULL); |
||||||
|
log_msg(tox, com_res, friendnum, user); |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static void cmd_ping(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], bool user) |
||||||
|
{ |
||||||
|
const char *outmsg = NULL; |
||||||
|
|
||||||
|
outmsg = "pong"; |
||||||
|
|
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); |
||||||
|
log_msg(tox, outmsg, friendnum, user); |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static void cmd_echo(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], bool user) |
||||||
|
{ |
||||||
|
const char *inmsg = NULL; |
||||||
|
|
||||||
|
if (argc < 1) { |
||||||
|
inmsg = "Error: Message required"; |
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) inmsg, strlen(inmsg), NULL); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
char outmsg[TOX_MAX_MESSAGE_LENGTH]; |
||||||
|
int len = 0; |
||||||
|
|
||||||
|
if (argv[1][0] == '\"') { /* remove opening and closing quotes */ |
||||||
|
snprintf(outmsg, sizeof(outmsg), "%s", &argv[1][1]); |
||||||
|
len = strlen(outmsg) - 1; |
||||||
|
} else { |
||||||
|
snprintf(outmsg, sizeof(outmsg), "%s", argv[1]); |
||||||
|
len = strlen(outmsg); |
||||||
|
} |
||||||
|
|
||||||
|
outmsg[len] = '\0'; |
||||||
|
|
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); |
||||||
|
log_msg(tox, outmsg, friendnum, user); |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static void bot_changename(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], bool user) |
||||||
|
{ |
||||||
|
const char *outmsg = NULL; |
||||||
|
|
||||||
|
if (argc < 1) { |
||||||
|
outmsg = "Error: Name required"; |
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
char name[TOX_MAX_NAME_LENGTH]; |
||||||
|
int len = 0; |
||||||
|
|
||||||
|
if (argv[1][0] == '\"') { /* remove opening and closing quotes */ |
||||||
|
snprintf(name, sizeof(name), "%s", &argv[1][1]); |
||||||
|
len = strlen(name) - 1; |
||||||
|
} else { |
||||||
|
snprintf(name, sizeof(name), "%s", argv[1]); |
||||||
|
len = strlen(name); |
||||||
|
} |
||||||
|
|
||||||
|
name[len] = '\0'; |
||||||
|
tox_self_set_name(tox, (uint8_t *) name, (uint16_t) len, NULL); |
||||||
|
|
||||||
|
char com_res[TOX_MAX_MESSAGE_LENGTH]; |
||||||
|
snprintf(com_res, sizeof com_res, "%s%s%s", "*** Name changed to \"", name, "\" ***"); |
||||||
|
|
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) com_res, |
||||||
|
strlen(com_res), NULL); |
||||||
|
write_conf(tox, name, NULL); |
||||||
|
log_msg(tox, com_res, friendnum, user); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static void bot_changestatus(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], bool user) |
||||||
|
{ |
||||||
|
const char *outmsg = NULL; |
||||||
|
|
||||||
|
if (argc < 1) { |
||||||
|
outmsg = "Error: Status required"; |
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
char status[TOX_MAX_STATUS_MESSAGE_LENGTH]; |
||||||
|
int len = 0; |
||||||
|
|
||||||
|
if (argv[1][0] == '\"') { /* remove opening and closing quotes */ |
||||||
|
snprintf(status, sizeof(status), "%s", &argv[1][1]); |
||||||
|
len = strlen(status) - 1; |
||||||
|
} else { |
||||||
|
snprintf(status, sizeof(status), "%s", argv[1]); |
||||||
|
len = strlen(status); |
||||||
|
} |
||||||
|
|
||||||
|
status[len] = '\0'; |
||||||
|
|
||||||
|
tox_self_set_status_message(tox, (uint8_t *) status, (uint16_t) len, NULL); |
||||||
|
|
||||||
|
char com_res[TOX_MAX_MESSAGE_LENGTH]; |
||||||
|
snprintf(com_res, sizeof com_res, "%s%s%s", "*** Status changed to \"", status, "\" ***"); |
||||||
|
|
||||||
|
tox_friend_send_message(tox, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) com_res, |
||||||
|
strlen(com_res), NULL); |
||||||
|
write_conf(tox, NULL, status); |
||||||
|
log_msg(tox, com_res, friendnum, user); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/* */ |
||||||
|
/* Commands end */ |
||||||
|
|
||||||
|
|
||||||
|
/* Parses input command and puts args into arg array.
|
||||||
|
Returns number of arguments on success, -1 on failure. */ |
||||||
|
static int parse_command(const char *input, char (*args)[MAX_COMMAND_LENGTH]) |
||||||
|
{ |
||||||
|
char *cmd = strdup(input); |
||||||
|
|
||||||
|
if (cmd == NULL) { |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
int num_args = 0; |
||||||
|
int i = 0; /* index of last char in an argument */ |
||||||
|
|
||||||
|
/* characters wrapped in double quotes count as one arg */ |
||||||
|
while (num_args < MAX_NUM_ARGS) { |
||||||
|
int qt_ofst = 0; /* set to 1 to offset index for quote char at end of arg */ |
||||||
|
|
||||||
|
if (*cmd == '\"') { |
||||||
|
qt_ofst = 1; |
||||||
|
i = char_find(1, cmd, '\"'); |
||||||
|
|
||||||
|
if (cmd[i] == '\0') { |
||||||
|
free(cmd); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} else { |
||||||
|
i = char_find(0, cmd, ' '); |
||||||
|
} |
||||||
|
|
||||||
|
memcpy(args[num_args], cmd, i + qt_ofst); |
||||||
|
args[num_args++][i + qt_ofst] = '\0'; |
||||||
|
|
||||||
|
if (cmd[i] == '\0') { /* no more args */ |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
char tmp[MAX_COMMAND_LENGTH]; |
||||||
|
snprintf(tmp, sizeof(tmp), "%s", &cmd[i + 1]); |
||||||
|
strcpy(cmd, tmp); /* tmp will always fit inside cmd */ |
||||||
|
} |
||||||
|
|
||||||
|
free(cmd); |
||||||
|
return num_args; |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static struct { |
||||||
|
const char *name; |
||||||
|
void (*func)(Tox *tox, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH], |
||||||
|
bool user); |
||||||
|
} commands[] = { |
||||||
|
{ "help", cmd_help }, |
||||||
|
{ "ping", cmd_ping }, |
||||||
|
{ "echo", cmd_echo }, |
||||||
|
{ "changename", bot_changename }, |
||||||
|
{ "changestatus", bot_changestatus }, |
||||||
|
{ NULL, NULL }, |
||||||
|
}; |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
static int do_command(Tox *tox, uint32_t friendnum, int num_args, char (*args)[MAX_COMMAND_LENGTH], |
||||||
|
bool user) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
|
||||||
|
for (i = 0; commands[i].name; ++i) { |
||||||
|
if (strcmp(args[0], commands[i].name) == 0) { |
||||||
|
(commands[i].func)(tox, friendnum, num_args - 1, args, user); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
int execute(Tox *tox, uint32_t friendnum, const char *input, int length, bool user) |
||||||
|
{ |
||||||
|
if (length >= MAX_COMMAND_LENGTH) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
char args[MAX_NUM_ARGS][MAX_COMMAND_LENGTH]; |
||||||
|
int num_args = parse_command(input, args); |
||||||
|
|
||||||
|
if (num_args == -1) { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
return do_command(tox, friendnum, num_args, args, user); |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
#ifndef COMMANDS_H |
||||||
|
#define COMMANDS_H |
||||||
|
|
||||||
|
int execute(Tox *m, int friendnumber, const char *input, int length, bool user); |
||||||
|
|
||||||
|
#endif /* COMMANDS_H */ |
@ -0,0 +1,128 @@ |
|||||||
|
#include <sys/types.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <string.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <unistd.h> |
||||||
|
#include <time.h> |
||||||
|
|
||||||
|
#include <tox/tox.h> |
||||||
|
|
||||||
|
#include "misc.h" |
||||||
|
|
||||||
|
char *hex_string_to_bin(const char *hex_string) |
||||||
|
{ |
||||||
|
size_t len = strlen(hex_string); |
||||||
|
char *val = malloc(len); |
||||||
|
|
||||||
|
if (val == NULL) { |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
size_t i; |
||||||
|
|
||||||
|
for (i = 0; i < len; ++i, hex_string += 2) { |
||||||
|
sscanf(hex_string, "%2hhx", &val[i]); |
||||||
|
} |
||||||
|
|
||||||
|
return val; |
||||||
|
} |
||||||
|
|
||||||
|
uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length) |
||||||
|
{ |
||||||
|
int len = MIN(length, size - 1); |
||||||
|
memcpy(msg, data, len); |
||||||
|
msg[len] = '\0'; |
||||||
|
return len; |
||||||
|
} |
||||||
|
|
||||||
|
int char_find(int idx, const char *s, char ch) |
||||||
|
{ |
||||||
|
int i = idx; |
||||||
|
|
||||||
|
for (i = idx; s[i]; ++i) { |
||||||
|
if (s[i] == ch) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return i; |
||||||
|
} |
||||||
|
|
||||||
|
void log_msg(Tox *tox, const uint8_t *inmsg, uint32_t friend_number, bool user) |
||||||
|
{ |
||||||
|
char name[TOX_MAX_NAME_LENGTH]; |
||||||
|
|
||||||
|
if (user == true) { |
||||||
|
tox_friend_get_name(tox, friend_number, (uint8_t *) name, NULL); |
||||||
|
size_t len = tox_friend_get_name_size(tox, friend_number, NULL); |
||||||
|
name[len] = '\0'; |
||||||
|
} else { |
||||||
|
tox_self_get_name(tox, (uint8_t *) name); |
||||||
|
size_t len = tox_self_get_name_size(tox); |
||||||
|
name[len] = '\0'; |
||||||
|
} |
||||||
|
|
||||||
|
char cur_time[128]; |
||||||
|
time_t t; |
||||||
|
struct tm* ptm; |
||||||
|
|
||||||
|
t = time(NULL); |
||||||
|
ptm = localtime(&t); |
||||||
|
|
||||||
|
strftime(cur_time, 128, "%d-%b-%Y %H:%M:%S", ptm); |
||||||
|
|
||||||
|
printf("%s (%s): %s\n", cur_time, name, inmsg); |
||||||
|
} |
||||||
|
|
||||||
|
int file_contains_key(const char *public_key, const char *path) |
||||||
|
{ |
||||||
|
FILE *fp = NULL; |
||||||
|
|
||||||
|
struct stat s; |
||||||
|
|
||||||
|
if (stat(path, &s) != 0) { |
||||||
|
FILE *fp = fopen(path, "w"); |
||||||
|
|
||||||
|
if (fp == NULL) { |
||||||
|
fprintf(stderr, "Warning: failed to create '%s' file\n", path); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
fprintf(stderr, "Warning: creating new '%s' file. Did you lose the old one?\n", path); |
||||||
|
fclose(fp); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
fp = fopen(path, "r"); |
||||||
|
|
||||||
|
if (fp == NULL) { |
||||||
|
fprintf(stderr, "Warning: failed to read '%s' file\n", path); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
char id[256]; |
||||||
|
|
||||||
|
while (fgets(id, sizeof(id), fp)) { |
||||||
|
int len = strlen(id); |
||||||
|
|
||||||
|
if (--len < TOX_PUBLIC_KEY_SIZE) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
char *key_bin = hex_string_to_bin(id); |
||||||
|
|
||||||
|
if (memcmp(key_bin, public_key, TOX_PUBLIC_KEY_SIZE) == 0) { |
||||||
|
free(key_bin); |
||||||
|
fclose(fp); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
free(key_bin); |
||||||
|
} |
||||||
|
|
||||||
|
fclose(fp); |
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
#ifndef MISC_H |
||||||
|
#define MISC_H |
||||||
|
|
||||||
|
#ifndef MIN |
||||||
|
#define MIN(x, y) (((x) < (y)) ? (x) : (y)) |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef MAX |
||||||
|
#define MAX(x, y) (((x) > (y)) ? (x) : (y)) |
||||||
|
#endif |
||||||
|
|
||||||
|
/* converts hexidecimal string to binary */ |
||||||
|
char *hex_string_to_bin(const char *hex_string); |
||||||
|
|
||||||
|
/* copies data to msg buffer.
|
||||||
|
returns length of msg, which will be no larger than size-1 */ |
||||||
|
uint16_t copy_tox_str(char *msg, size_t size, const char *data, uint16_t length); |
||||||
|
|
||||||
|
/* returns index of the first instance of ch in s starting at idx.
|
||||||
|
returns length of s if char not found */ |
||||||
|
int char_find(int idx, const char *s, char ch); |
||||||
|
|
||||||
|
/* add msg time */ |
||||||
|
void log_msg(Tox *tox, const uint8_t *msg, uint32_t friend_number, bool user); |
||||||
|
|
||||||
|
/*
|
||||||
|
* Searches plain text file pointed to by path for lines that match public_key. |
||||||
|
* |
||||||
|
* Returns 1 if a match is found. |
||||||
|
* Returns 0 if a match is not found. |
||||||
|
* Returns -1 on file operation failure. |
||||||
|
* |
||||||
|
* public_key must be a binary representation of a Tox public key. |
||||||
|
*/ |
||||||
|
int file_contains_key(const char *public_key, const char *path); |
||||||
|
|
||||||
|
#endif /* MISC_H */ |
@ -0,0 +1,298 @@ |
|||||||
|
#include <ctype.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <string.h> |
||||||
|
|
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#include <libconfig.h> |
||||||
|
#include <sodium/utils.h> |
||||||
|
#include <tox/tox.h> |
||||||
|
|
||||||
|
#include "misc.h" |
||||||
|
#include "commands.h" |
||||||
|
|
||||||
|
typedef struct DHT_node { |
||||||
|
const char *ip; |
||||||
|
uint16_t port; |
||||||
|
const char key_hex[TOX_PUBLIC_KEY_SIZE*2 + 1]; |
||||||
|
} DHT_node; |
||||||
|
|
||||||
|
const char *SAVEDATA_FILENAME = "savedata.tox"; |
||||||
|
const char *SAVEDATA_TMP_FILENAME = "savedata.tox.tmp"; |
||||||
|
const char *MASTERLIST_FILE = "masterkeys.txt"; |
||||||
|
const char *CFG_FILE = "bot.cfg"; |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
Tox *create_tox() |
||||||
|
{ |
||||||
|
Tox *tox; |
||||||
|
|
||||||
|
struct Tox_Options options; |
||||||
|
|
||||||
|
tox_options_default(&options); |
||||||
|
|
||||||
|
FILE *f = fopen(SAVEDATA_FILENAME, "rb"); |
||||||
|
if (f) { |
||||||
|
fseek(f, 0, SEEK_END); |
||||||
|
long fsize = ftell(f); |
||||||
|
fseek(f, 0, SEEK_SET); |
||||||
|
|
||||||
|
uint8_t *savedata = malloc(fsize); |
||||||
|
|
||||||
|
fread(savedata, fsize, 1, f); |
||||||
|
fclose(f); |
||||||
|
|
||||||
|
options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE; |
||||||
|
options.savedata_data = savedata; |
||||||
|
options.savedata_length = fsize; |
||||||
|
|
||||||
|
tox = tox_new(&options, NULL); |
||||||
|
|
||||||
|
free(savedata); |
||||||
|
} else { |
||||||
|
tox = tox_new(&options, NULL); |
||||||
|
} |
||||||
|
|
||||||
|
return tox; |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
int config_tox(Tox *tox) |
||||||
|
{ |
||||||
|
config_t cfg; |
||||||
|
config_setting_t *setting; |
||||||
|
const char *str; |
||||||
|
|
||||||
|
config_init(&cfg); |
||||||
|
|
||||||
|
if (!config_read_file(&cfg, CFG_FILE)) { |
||||||
|
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), |
||||||
|
config_error_line(&cfg), config_error_text(&cfg)); |
||||||
|
config_destroy(&cfg); |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
const char *name; |
||||||
|
|
||||||
|
if (config_lookup_string(&cfg, "Tox_Bot_Name", &str)) { |
||||||
|
printf("Tox bot name: %s\n", str); |
||||||
|
name = str; |
||||||
|
} |
||||||
|
else { |
||||||
|
name = "Tox Bot test"; |
||||||
|
fprintf(stderr, "No 'Tox_Bot_Name' setting in configuration file. "); |
||||||
|
printf("The default name is used\n"); |
||||||
|
} |
||||||
|
|
||||||
|
const char *status_message; |
||||||
|
|
||||||
|
if (config_lookup_string(&cfg, "Tox_Bot_Status", &str)) { |
||||||
|
printf("Tox bot status: %s\n", str); |
||||||
|
status_message = str; |
||||||
|
} |
||||||
|
else { |
||||||
|
status_message = "Hello, World!"; |
||||||
|
fprintf(stderr, "No 'Tox_Bot_Status' setting in configuration file. "); |
||||||
|
printf("The default status is used\n"); |
||||||
|
} |
||||||
|
|
||||||
|
tox_self_set_name(tox, name, strlen(name), NULL); |
||||||
|
|
||||||
|
tox_self_set_status_message(tox, status_message, strlen(status_message), NULL); |
||||||
|
|
||||||
|
config_destroy(&cfg); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
int write_conf(Tox *tox, uint8_t *name, uint8_t *status_message) |
||||||
|
{ |
||||||
|
config_t cfg; |
||||||
|
config_setting_t *setting; |
||||||
|
const char *str; |
||||||
|
|
||||||
|
config_init(&cfg); |
||||||
|
|
||||||
|
if (!config_read_file(&cfg, CFG_FILE)) { |
||||||
|
fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), |
||||||
|
config_error_line(&cfg), config_error_text(&cfg)); |
||||||
|
config_destroy(&cfg); |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
if (name != NULL) { |
||||||
|
setting = config_lookup(&cfg, "Tox_Bot_Name"); |
||||||
|
config_setting_set_string(setting, name); |
||||||
|
} |
||||||
|
|
||||||
|
if (status_message != NULL) { |
||||||
|
setting = config_lookup(&cfg, "Tox_Bot_Status"); |
||||||
|
config_setting_set_string(setting, status_message); |
||||||
|
} |
||||||
|
|
||||||
|
if(! config_write_file(&cfg, CFG_FILE)) |
||||||
|
{ |
||||||
|
fprintf(stderr, "Error while writing file.\n"); |
||||||
|
config_destroy(&cfg); |
||||||
|
exit(EXIT_FAILURE); |
||||||
|
} |
||||||
|
|
||||||
|
config_destroy(&cfg); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
void update_savedata_file(const Tox *tox) |
||||||
|
{ |
||||||
|
size_t size = tox_get_savedata_size(tox); |
||||||
|
uint8_t *savedata = malloc(size); |
||||||
|
tox_get_savedata(tox, savedata); |
||||||
|
|
||||||
|
FILE *f = fopen(SAVEDATA_TMP_FILENAME, "wb"); |
||||||
|
fwrite(savedata, size, 1, f); |
||||||
|
fclose(f); |
||||||
|
|
||||||
|
rename(SAVEDATA_TMP_FILENAME, SAVEDATA_FILENAME); |
||||||
|
|
||||||
|
free(savedata); |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
void bootstrap(Tox *tox) |
||||||
|
{ |
||||||
|
DHT_node nodes[] = |
||||||
|
{ |
||||||
|
{"85.143.221.42", 33445, "DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43"}, |
||||||
|
{"2a04:ac00:1:9f00:5054:ff:fe01:becd", 33445, "DA4E4ED4B697F2E9B000EEFE3A34B554ACD3F45F5C96EAEA2516DD7FF9AF7B43"}, |
||||||
|
{"78.46.73.141", 33445, "02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46"}, |
||||||
|
{"2a01:4f8:120:4091::3", 33445, "02807CF4F8BB8FB390CC3794BDF1E8449E9A8392C5D3F2200019DA9F1E812E46"}, |
||||||
|
{"tox.initramfs.io", 33445, "3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25"}, |
||||||
|
{"tox2.abilinski.com", 33445, "7A6098B590BDC73F9723FC59F82B3F9085A64D1B213AAF8E610FD351930D052D"}, |
||||||
|
{"205.185.115.131", 53, "3091C6BEB2A993F1C6300C16549FABA67098FF3D62C6D253828B531470B53D68"}, |
||||||
|
{"tox.kurnevsky.net", 33445, "82EF82BA33445A1F91A7DB27189ECFC0C013E06E3DA71F588ED692BED625EC23"} |
||||||
|
}; |
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(nodes)/sizeof(DHT_node); i ++) { |
||||||
|
unsigned char key_bin[TOX_PUBLIC_KEY_SIZE]; |
||||||
|
sodium_hex2bin(key_bin, sizeof(key_bin), nodes[i].key_hex, sizeof(nodes[i].key_hex)-1, |
||||||
|
NULL, NULL, NULL); |
||||||
|
tox_bootstrap(tox, nodes[i].ip, nodes[i].port, key_bin, NULL); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
void print_tox_id(Tox *tox) |
||||||
|
{ |
||||||
|
uint8_t tox_id_bin[TOX_ADDRESS_SIZE]; |
||||||
|
tox_self_get_address(tox, tox_id_bin); |
||||||
|
|
||||||
|
char tox_id_hex[TOX_ADDRESS_SIZE*2 + 1]; |
||||||
|
sodium_bin2hex(tox_id_hex, sizeof(tox_id_hex), tox_id_bin, sizeof(tox_id_bin)); |
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(tox_id_hex)-1; i ++) { |
||||||
|
tox_id_hex[i] = toupper(tox_id_hex[i]); |
||||||
|
} |
||||||
|
|
||||||
|
printf("Tox ID: %s\n", tox_id_hex); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** CallBacks **/ |
||||||
|
/** **/ |
||||||
|
static void friend_request_cb(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, |
||||||
|
void *user_data) |
||||||
|
{ |
||||||
|
|
||||||
|
char tox_id_hex[TOX_ADDRESS_SIZE*2 + 1]; |
||||||
|
uint8_t tox_id_bin[TOX_ADDRESS_SIZE]; |
||||||
|
|
||||||
|
sodium_bin2hex(tox_id_hex, sizeof(tox_id_hex), public_key, sizeof(tox_id_bin)); |
||||||
|
|
||||||
|
for (size_t i = 0; i < sizeof(tox_id_hex)-1; i ++) { |
||||||
|
tox_id_hex[i] = toupper(tox_id_hex[i]); |
||||||
|
} |
||||||
|
|
||||||
|
if (file_contains_key(public_key, MASTERLIST_FILE) == 1) { |
||||||
|
printf("New friend is Master: %s\n", tox_id_hex); |
||||||
|
tox_friend_add_norequest(tox, public_key, NULL); |
||||||
|
update_savedata_file(tox); |
||||||
|
} |
||||||
|
else { |
||||||
|
printf("New friend not on the list: %s\n", tox_id_hex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
void friend_message_cb(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *inmsg, |
||||||
|
size_t length, void *user_data) |
||||||
|
{ |
||||||
|
bool user = true; |
||||||
|
log_msg(tox, inmsg, friend_number, user); |
||||||
|
|
||||||
|
const char *outmsg; |
||||||
|
char message[TOX_MAX_MESSAGE_LENGTH]; |
||||||
|
length = copy_tox_str(message, sizeof(message), (const char *) inmsg, length); |
||||||
|
message[length] = '\0'; |
||||||
|
|
||||||
|
user = false; |
||||||
|
|
||||||
|
if (length && execute(tox, friend_number, message, length, user) == -1) { |
||||||
|
outmsg = "Invalid command. Type 'help' for a list of commands"; |
||||||
|
tox_friend_send_message(tox, friend_number, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL); |
||||||
|
log_msg(tox, outmsg, friend_number, user); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */ |
||||||
|
|
||||||
|
void self_connection_status_cb(Tox *tox, TOX_CONNECTION connection_status, void *user_data) |
||||||
|
{ |
||||||
|
switch (connection_status) { |
||||||
|
case TOX_CONNECTION_NONE: |
||||||
|
printf("Offline\n"); |
||||||
|
break; |
||||||
|
case TOX_CONNECTION_TCP: |
||||||
|
printf("Online, using TCP\n"); |
||||||
|
break; |
||||||
|
case TOX_CONNECTION_UDP: |
||||||
|
printf("Online, using UDP\n"); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
/** **/ |
||||||
|
/** CallBacks END**/ |
||||||
|
|
||||||
|
|
||||||
|
int main() |
||||||
|
{ |
||||||
|
Tox *tox = create_tox(); |
||||||
|
|
||||||
|
config_tox(tox); |
||||||
|
bootstrap(tox); |
||||||
|
print_tox_id(tox); |
||||||
|
|
||||||
|
tox_callback_friend_request(tox, friend_request_cb); |
||||||
|
tox_callback_friend_message(tox, friend_message_cb); |
||||||
|
|
||||||
|
tox_callback_self_connection_status(tox, self_connection_status_cb); |
||||||
|
|
||||||
|
update_savedata_file(tox); |
||||||
|
|
||||||
|
printf("Connecting...\n"); |
||||||
|
|
||||||
|
while (1) { |
||||||
|
tox_iterate(tox, NULL); |
||||||
|
usleep(tox_iteration_interval(tox) * 1000); |
||||||
|
} |
||||||
|
|
||||||
|
tox_kill(tox); |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
#ifndef TOXBOT_H |
||||||
|
#define TOXBOT_H |
||||||
|
|
||||||
|
#include <tox/tox.h> |
||||||
|
|
||||||
|
int write_conf(Tox *tox, uint8_t *name, uint8_t *status_message); |
||||||
|
|
||||||
|
#endif /* TOXBOT_H */ |
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in new issue