void print_groupchatpeers(Tox *m, int groupnumber) { int num = tox_group_number_peers(m, groupnumber); if (num < 0) return; if (!num) { new_lines("[g]+ no peers left in group."); return; } uint8_t names[num][TOX_MAX_NAME_LENGTH]; uint16_t lengths[num]; tox_group_get_names(m, groupnumber, names, lengths, num); int i; char numstr[16]; char header[] = "[g]+ "; size_t header_len = strlen(header); char msg[STRING_LENGTH]; strcpy(msg, header); size_t len_total = header_len; for (i = 0; i < num; ++i) { size_t len_name = lengths[i]; size_t len_num = sprintf(numstr, "%i: ", i); if (len_num + len_name + len_total + 3 >= STRING_LENGTH) { new_lines_mark(msg, 1); strcpy(msg, header); len_total = header_len; } strcpy(msg + len_total, numstr); len_total += len_num; memcpy(msg + len_total, (char *)names[i], len_name); len_total += len_name; if (i < num - 1) { strcpy(msg + len_total, "|"); len_total++; } } new_lines_mark(msg, 1); }
static void purge_empty_groups(Tox *m) { uint32_t i; for (i = 0; i < Tox_Bot.chats_idx; ++i) { if (!Tox_Bot.g_chats[i].active) continue; int num_peers = tox_group_number_peers(m, Tox_Bot.g_chats[i].num); if (num_peers <= 1) { fprintf(stderr, "Deleting empty group %i\n", Tox_Bot.g_chats[i].num); tox_del_groupchat(m, i); group_leave(i); } } }
void print_groupnamelistchange(Tox *m, int groupnumber, int peernumber, uint8_t change, void *userdata) { char msg[256]; if (change == TOX_CHAT_CHANGE_PEER_ADD) { sprintf(msg, "[g] #%i: New peer %i.", groupnumber, peernumber); new_lines(msg); } else if (change == TOX_CHAT_CHANGE_PEER_DEL) { /* if peer was the last in list, it simply dropped, * otherwise it was overwritten by the last peer * * adjust output */ int peers_total = tox_group_number_peers(m, groupnumber); if (peers_total == peernumber) { sprintf(msg, "[g] #%i: Peer %i left.", groupnumber, peernumber); new_lines(msg); } else { uint8_t peername[TOX_MAX_NAME_LENGTH] = {0}; int len = tox_group_peername(m, groupnumber, peernumber, peername); if (len <= 0) peername[0] = 0; sprintf(msg, "[g] #%i: Peer %i left. Former peer [%i: <%s>] is now peer %i.", groupnumber, peernumber, peers_total, peername, peernumber); new_lines(msg); } } else if (change == TOX_CHAT_CHANGE_PEER_NAME) { uint8_t peername[TOX_MAX_NAME_LENGTH] = {0}; int len = tox_group_peername(m, groupnumber, peernumber, peername); if (len <= 0) peername[0] = 0; sprintf(msg, "[g] #%i: Peer %i's name changed: %s", groupnumber, peernumber, peername); new_lines(msg); } else { sprintf(msg, "[g] #%i: Name list changed (peer %i, change %i?):", groupnumber, peernumber, change); new_lines(msg); print_groupchatpeers(m, groupnumber); } }
static void groupchat_onGroupNamelistChange(ToxWindow *self, Tox *m, int groupnum, int peernum, uint8_t change) { if (self->num != groupnum) return; if (groupnum > max_groupchat_index) return; groupchats[groupnum].num_peers = tox_group_number_peers(m, groupnum); int num_peers = groupchats[groupnum].num_peers; if (peernum > num_peers) return; /* get old peer name before updating name list */ uint8_t oldpeername[TOX_MAX_NAME_LENGTH]; if (change != TOX_CHAT_CHANGE_PEER_ADD) { memcpy(oldpeername, &groupchats[groupnum].oldpeer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(oldpeername)); uint16_t old_n_len = groupchats[groupnum].oldpeer_name_lengths[peernum]; oldpeername[old_n_len] = '\0'; } /* Update name/len lists */ uint8_t tmp_peerlist[num_peers][TOX_MAX_NAME_LENGTH]; uint16_t tmp_peerlens[num_peers]; if (tox_group_get_names(m, groupnum, tmp_peerlist, tmp_peerlens, num_peers) == -1) { memset(tmp_peerlist, 0, sizeof(tmp_peerlist)); memset(tmp_peerlens, 0, sizeof(tmp_peerlens)); } copy_peernames(groupnum, tmp_peerlist, tmp_peerlens, num_peers); /* get current peername then sort namelist */ uint8_t peername[TOX_MAX_NAME_LENGTH]; if (change != TOX_CHAT_CHANGE_PEER_DEL) { uint16_t n_len = groupchats[groupnum].peer_name_lengths[peernum]; memcpy(peername, &groupchats[groupnum].peer_names[peernum * TOX_MAX_NAME_LENGTH], sizeof(peername)); peername[n_len] = '\0'; } qsort(groupchats[groupnum].peer_names, groupchats[groupnum].num_peers, TOX_MAX_NAME_LENGTH, qsort_strcasecmp_hlpr); ChatContext *ctx = self->chatwin; const char *event; char timefrmt[TIME_STR_SIZE]; get_time_str(timefrmt, sizeof(timefrmt)); switch (change) { case TOX_CHAT_CHANGE_PEER_ADD: if (!timed_out(groupchats[groupnum].start_time, GROUP_EVENT_WAIT)) break; struct group_add_thrd *thrd = malloc(sizeof(struct group_add_thrd)); thrd->m = m; thrd->peernum = peernum; thrd->groupnum = groupnum; thrd->self = self; thrd->timestamp = get_unix_time(); if (pthread_attr_init(&thrd->attr) != 0) { free(thrd); return; } if (pthread_attr_setdetachstate(&thrd->attr, PTHREAD_CREATE_DETACHED) != 0) { pthread_attr_destroy(&thrd->attr); free(thrd); return; } if (pthread_create(&thrd->tid, &thrd->attr, group_add_wait, (void *) thrd) != 0) { pthread_attr_destroy(&thrd->attr); free(thrd); return; } break; case TOX_CHAT_CHANGE_PEER_DEL: event = "has left the room"; line_info_add(self, timefrmt, (char *) oldpeername, NULL, DISCONNECTION, 0, RED, event); if (groupchats[self->num].side_pos > 0) --groupchats[self->num].side_pos; write_to_log(event, (char *) oldpeername, ctx->log, true); break; case TOX_CHAT_CHANGE_PEER_NAME: if (!timed_out(groupchats[self->num].start_time, GROUP_EVENT_WAIT)) return; /* ignore initial name change (TODO: this is a bad way to do this) */ if (strcmp((char *) oldpeername, DEFAULT_TOX_NAME) == 0) return; event = " is now known as "; line_info_add(self, timefrmt, (char *) oldpeername, (char *) peername, NAME_CHANGE, 0, 0, event); char tmp_event[TOXIC_MAX_NAME_LENGTH * 2 + 32]; snprintf(tmp_event, sizeof(tmp_event), "is now known as %s", (char *) peername); write_to_log(tmp_event, (char *) oldpeername, ctx->log, true); break; } sound_notify(self, silent, NT_WNDALERT_2, NULL); }
/** * @brief Return the number of peers in the group chat on success, or -1 on failure */ int Core::getGroupNumberPeers(int groupId) const { return tox_group_number_peers(tox, groupId); }
void line_eval(Tox *m, char *line) { if (line[0] == '/') { char inpt_command = line[1]; char prompt[STRING_LENGTH + 2] = "> "; int prompt_offset = 3; strcat(prompt, line); new_lines(prompt); if (inpt_command == 'f') { // add friend command: /f ID int i, delta = 0; char temp_id[128]; for (i = 0; i < 128; i++) { temp_id[i - delta] = line[i + prompt_offset]; if ((temp_id[i - delta] == ' ') || (temp_id[i - delta] == '+')) delta++; } unsigned char *bin_string = hex_string_to_bin(temp_id); int num = tox_add_friend(m, bin_string, (uint8_t *)"Install Gentoo", sizeof("Install Gentoo")); free(bin_string); char numstring[100]; switch (num) { case TOX_FAERR_TOOLONG: sprintf(numstring, "[i] Message is too long."); break; case TOX_FAERR_NOMESSAGE: sprintf(numstring, "[i] Please add a message to your request."); break; case TOX_FAERR_OWNKEY: sprintf(numstring, "[i] That appears to be your own ID."); break; case TOX_FAERR_ALREADYSENT: sprintf(numstring, "[i] Friend request already sent."); break; case TOX_FAERR_UNKNOWN: sprintf(numstring, "[i] Undefined error when adding friend."); break; default: if (num >= 0) { sprintf(numstring, "[i] Added friend as %d.", num); save_data(m); } else sprintf(numstring, "[i] Unknown error %i.", num); break; } new_lines(numstring); } else if (inpt_command == 'd') { tox_do(m); } else if (inpt_command == 'm') { //message command: /m friendnumber messsage char *posi[1]; int num = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { if (tox_send_message(m, num, (uint8_t *) *posi + 1, strlen(*posi + 1)) < 1) { char sss[256]; sprintf(sss, "[i] could not send message to friend num %u", num); new_lines(sss); } else { print_formatted_message(m, *posi + 1, num, 1); } } else new_lines("Error, bad input."); } else if (inpt_command == 'n') { uint8_t name[TOX_MAX_NAME_LENGTH]; size_t i, len = strlen(line); for (i = 3; i < len; i++) { if (line[i] == 0 || line[i] == '\n') break; name[i - 3] = line[i]; } name[i - 3] = 0; tox_set_name(m, name, i - 2); char numstring[100]; sprintf(numstring, "[i] changed nick to %s", (char *)name); new_lines(numstring); } else if (inpt_command == 'l') { print_friendlist(m); } else if (inpt_command == 's') { uint8_t status[TOX_MAX_STATUSMESSAGE_LENGTH]; size_t i, len = strlen(line); for (i = 3; i < len; i++) { if (line[i] == 0 || line[i] == '\n') break; status[i - 3] = line[i]; } status[i - 3] = 0; tox_set_status_message(m, status, strlen((char *)status)); char numstring[100]; sprintf(numstring, "[i] changed status to %s", (char *)status); new_lines(numstring); } else if (inpt_command == 'a') { // /a #: accept uint8_t numf = atoi(line + 3); char numchar[100]; if (numf >= num_requests || pending_requests[numf].accepted) { sprintf(numchar, "[i] you either didn't receive that request or you already accepted it"); new_lines(numchar); } else { int num = tox_add_friend_norequest(m, pending_requests[numf].id); if (num != -1) { pending_requests[numf].accepted = 1; sprintf(numchar, "[i] friend request %u accepted as friend no. %d", numf, num); new_lines(numchar); save_data(m); } else { sprintf(numchar, "[i] failed to add friend"); new_lines(numchar); } } } else if (inpt_command == 'r') { // /r #: remove friend uint8_t numf = atoi(line + 3); if (!tox_friend_exists(m, numf)) { char err[64]; sprintf(err, "You don't have a friend %i.", numf); new_lines(err); return; } char msg[128 + TOX_MAX_NAME_LENGTH]; char fname[TOX_MAX_NAME_LENGTH ]; getfriendname_terminated(m, numf, fname); sprintf(msg, "Are you sure you want to delete friend %i: %s? (y/n)", numf, fname); input_line[0] = 0; new_lines(msg); int c; do { c = getchar(); } while ((c != 'y') && (c != 'n') && (c != EOF)); if (c == 'y') { int res = tox_del_friend(m, numf); if (res == 0) sprintf(msg, "[i] [%i: %s] is no longer your friend", numf, fname); else sprintf(msg, "[i] failed to remove friend"); new_lines(msg); } } else if (inpt_command == 'h') { //help if (line[2] == ' ') { if (line[3] == 'f') { new_lines_mark(help_friend1, 1); new_lines_mark(help_friend2, 1); return; } else if (line[3] == 'g') { new_lines_mark(help_group, 1); return; } } new_lines_mark(help_main, 1); } else if (inpt_command == 'x') { //info char idstring[200]; get_id(m, idstring); new_lines(idstring); } else if (inpt_command == 'g') { //create new group chat char msg[256]; sprintf(msg, "[g] Created new group chat with number: %u", tox_add_groupchat(m)); new_lines(msg); } else if (inpt_command == 'i') { //invite friendnum to groupnum char *posi[1]; int friendnumber = strtoul(line + prompt_offset, posi, 0); int groupnumber = strtoul(*posi + 1, NULL, 0); char msg[256]; sprintf(msg, "[g] Invited friend number %u to group number %u, returned: %u (0 means success)", friendnumber, groupnumber, tox_invite_friend(m, friendnumber, groupnumber)); new_lines(msg); } else if (inpt_command == 'z') { //send message to groupnum char *posi[1]; int groupnumber = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { int res = tox_group_message_send(m, groupnumber, (uint8_t *)*posi + 1, strlen(*posi + 1)); if (res == 0) { char msg[32 + STRING_LENGTH]; sprintf(msg, "[g] #%u: YOU: %s", groupnumber, *posi + 1); new_lines(msg); } else { char msg[128]; sprintf(msg, "[i] could not send message to group no. %u: %i", groupnumber, res); new_lines(msg); } } } else if (inpt_command == 't') { char *posi[1]; int friendnum = strtoul(line + prompt_offset, posi, 0); if (**posi != 0) { char msg[512]; sprintf(msg, "[t] Sending file %s to friendnum %u filenumber is %i (-1 means failure)", *posi + 1, friendnum, add_filesender(m, friendnum, *posi + 1)); new_lines(msg); } } else if (inpt_command == 'q') { //exit save_data(m); endwin(); tox_kill(m); exit(EXIT_SUCCESS); } else if (inpt_command == 'c') { //set conversation partner if (line[2] == 'r') { if (conversation_default != 0) { conversation_default = 0; new_lines("[i] default conversation reset"); } else new_lines("[i] default conversation wasn't set, nothing to do"); } else if (line[3] != ' ') { new_lines("[i] invalid command"); } else { int num = atoi(line + 4); /* zero is also returned for not-a-number */ if (!num && strcmp(line + 4, "0")) num = -1; if (num < 0) new_lines("[i] invalid command parameter"); else if (line[2] == 'f') { conversation_default = num + 1; char buffer[128]; sprintf(buffer, "[i] default conversation is now to friend %i", num); new_lines(buffer); } else if (line[2] == 'g') { char buffer[128]; conversation_default = - (num + 1); sprintf(buffer, "[i] default conversation is now to group %i", num); new_lines(buffer); } else new_lines("[i] invalid command"); } } else if (inpt_command == 'p') { //list peers char *posi = NULL; int group_number = strtoul(line + prompt_offset, &posi, 0); if (posi != NULL) { char msg[64]; int peer_cnt = tox_group_number_peers(m, group_number); if (peer_cnt < 0) { new_lines("[g] Invalid group number."); } else if (peer_cnt == 0) { sprintf(msg, "[g] #%i: No peers in group.", group_number); new_lines(msg); } else { sprintf(msg, "[g] #%i: Group has %i peers. Names:", group_number, peer_cnt); new_lines(msg); print_groupchatpeers(m, group_number); } } } else { new_lines("[i] invalid command"); } } else { if (conversation_default != 0) { if (conversation_default > 0) { int friendnumber = conversation_default - 1; uint32_t res = tox_send_message(m, friendnumber, (uint8_t *)line, strlen(line)); if (res == 0) { char sss[128]; sprintf(sss, "[i] could not send message to friend no. %u", friendnumber); new_lines(sss); } else print_formatted_message(m, line, friendnumber, 1); } else { int groupnumber = - conversation_default - 1; int res = tox_group_message_send(m, groupnumber, (uint8_t *)line, strlen(line)); if (res == 0) { char msg[32 + STRING_LENGTH]; sprintf(msg, "[g] #%u: YOU: %s", groupnumber, line); new_lines(msg); } else { char msg[128]; sprintf(msg, "[i] could not send message to group no. %u: %i", groupnumber, res); new_lines(msg); } } } else new_lines("[i] invalid input: neither command nor in conversation"); } }