|
|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
* chat_member.c — единый код запроса мемберов для GUI |
|
|
|
|
* |
|
|
|
|
* Используется: chatgui (desktop), headless CLI, Android. |
|
|
|
|
* Все три потребителя получают данные через chat_core_get_member_list(). |
|
|
|
|
* Live-состояние участников читается только в uasync-потоке. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include "chat_core_priv.h" |
|
|
|
|
@ -32,6 +32,16 @@ int chat_core_member_online(struct UTUN_INSTANCE* inst, const char* ch_id, uint6
|
|
|
|
|
return topo_node_find_by_id(g, node_id) != NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Рация — живая подписка на конкретную CHAT-группу; у self нет записи в group->nodes. */ |
|
|
|
|
static uint8_t member_radio_flag(struct UTUN_INSTANCE* inst, const char* ch_id, uint64_t node_id) { |
|
|
|
|
if (!inst || !inst->topo_groups || !ch_id || !ch_id[0]) return 0; |
|
|
|
|
struct TOPO_GROUP* group = topo_groups_find(inst->topo_groups, strtoull(ch_id, NULL, 10)); |
|
|
|
|
if (!group || group->group_type != TOPO_GROUP_TYPE_CHAT) return 0; |
|
|
|
|
if (node_id == inst->node_id) return group->radio_active ? CHAT_MEMBER_FLAG_RADIO : 0; |
|
|
|
|
struct TOPO_GROUP_NODE* node = topo_node_find_by_id(group, node_id); |
|
|
|
|
return node && node->radio ? CHAT_MEMBER_FLAG_RADIO : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ─── парсинг adm_tags в flags ─── */ |
|
|
|
|
|
|
|
|
|
static uint8_t parse_adm_tags_flags(const char* adm_tags) { |
|
|
|
|
@ -138,7 +148,7 @@ int chat_core_get_member_list(struct UTUN_INSTANCE* inst, const char* ch_id, uin
|
|
|
|
|
const char* adm_tags = (const char*)sqlite3_column_text(st, 3); |
|
|
|
|
m->storage = (uint8_t)sqlite3_column_int(st, 4); |
|
|
|
|
m->is_self = (uint8_t)(m->node_id == my_id ? 1 : 0); |
|
|
|
|
m->flags = parse_adm_tags_flags(adm_tags); |
|
|
|
|
m->flags = parse_adm_tags_flags(adm_tags) | member_radio_flag(inst, ch_id, m->node_id); |
|
|
|
|
if (sqlite3_column_int(st, 5)) m->flags |= CHAT_MEMBER_FLAG_DELETED; |
|
|
|
|
m->rtt = 0xFFFF; |
|
|
|
|
m->nat_type = 0xFF; |
|
|
|
|
@ -253,7 +263,7 @@ int chat_core_get_single_member(struct UTUN_INSTANCE* inst, const char* ch_id, u
|
|
|
|
|
const char* adm_tags = (const char*)sqlite3_column_text(st, 2); |
|
|
|
|
m.storage = (uint8_t)sqlite3_column_int(st, 3); |
|
|
|
|
m.is_self = (uint8_t)(node_id == my_id ? 1 : 0); |
|
|
|
|
m.flags = parse_adm_tags_flags(adm_tags); |
|
|
|
|
m.flags = parse_adm_tags_flags(adm_tags) | member_radio_flag(inst, ch_id, node_id); |
|
|
|
|
if (sqlite3_column_int(st, 4)) m.flags |= CHAT_MEMBER_FLAG_DELETED; |
|
|
|
|
m.rtt = 0xFFFF; |
|
|
|
|
m.nat_type = 0xFF; |
|
|
|
|
@ -374,8 +384,15 @@ static void on_member_props_changed(uint64_t node_id, const char* adm_tags, cons
|
|
|
|
|
evt[0] = (uint8_t)cl; |
|
|
|
|
memcpy(evt + 1, channel_id, cl); |
|
|
|
|
evt[1 + cl] = 1; |
|
|
|
|
if (chat_core_get_single_member(inst, channel_id, node_id, evt + 1 + cl + 1) == 0) |
|
|
|
|
if (chat_core_get_single_member(inst, channel_id, node_id, evt + 1 + cl + 1) == 0) { |
|
|
|
|
const uint8_t* member = evt + 1 + cl + 1; |
|
|
|
|
DEBUG_DEBUG(DEBUG_CATEGORY_CHAT_SYNC, "chat_member: update ch=%s node=%016llx online=%u self=%u radio=%u", |
|
|
|
|
channel_id, (unsigned long long)node_id, member[8], member[9], !!(member[10] & CHAT_MEMBER_FLAG_RADIO)); |
|
|
|
|
chat_event_post(inst, CHAT_EVT_MEMBER_UPDATED, evt, 1 + (int)cl + 1 + CHAT_MEMBER_DISPLAY_SIZE); |
|
|
|
|
} else { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "chat_member: cannot build update ch=%s node=%016llx", |
|
|
|
|
channel_id, (unsigned long long)node_id); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(st); |
|
|
|
|
|