first commit
This commit is contained in:
		
							
								
								
									
										245
									
								
								src/commands.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/commands.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/commands.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/commands.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										128
									
								
								src/misc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/misc.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								src/misc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/misc.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										298
									
								
								src/tox_bot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								src/tox_bot.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								src/tox_bot.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/tox_bot.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
		Reference in New Issue
	
	Block a user