|
|
|
|
@ -337,6 +337,53 @@ static void bridge_get_node_name(sqlite3* db, uint64_t node_id, const char* chan
|
|
|
|
|
sqlite3_finalize(st); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Формирует человекочитаемое тело превью последнего сообщения по content_type и "d"-полю. */ |
|
|
|
|
static void bridge_format_preview_body(const char* ct, const char* d, char* out, size_t out_sz) { |
|
|
|
|
int is_text = (!ct || !ct[0] || strcmp(ct, "text/plain") == 0 || strcmp(ct, "voice_transcription") == 0); |
|
|
|
|
if (is_text) { |
|
|
|
|
size_t tl = strlen(d); |
|
|
|
|
if (tl > 60) tl = 60; |
|
|
|
|
if (tl >= out_sz) tl = out_sz - 1; |
|
|
|
|
memcpy(out, d, tl); out[tl] = '\0'; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (strcmp(ct, "audio/opus") == 0) { |
|
|
|
|
int dur_ms = 0; |
|
|
|
|
if (d[0] == '*') { |
|
|
|
|
const char* pipe = strchr(d, '|'); |
|
|
|
|
size_t b64len = pipe ? (size_t)(pipe - d - 1) : strlen(d) - 1; |
|
|
|
|
uint8_t dec[256]; size_t declen = b64_decode(d + 1, b64len, dec, sizeof(dec)); |
|
|
|
|
if (declen > 0) { |
|
|
|
|
char raw[256]; if (declen >= sizeof(raw)) declen = sizeof(raw) - 1; |
|
|
|
|
memcpy(raw, dec, declen); raw[declen] = '\0'; |
|
|
|
|
const char* dur = strstr(raw, ";dur="); |
|
|
|
|
if (dur) dur_ms = atoi(dur + 5); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (dur_ms > 0) { |
|
|
|
|
int s = dur_ms / 1000; |
|
|
|
|
snprintf(out, out_sz, "Voice message (%d:%02d)", s / 60, s % 60); |
|
|
|
|
} else { |
|
|
|
|
snprintf(out, out_sz, "Voice message"); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (strncmp(ct, "video/", 6) == 0) { snprintf(out, out_sz, "Video"); return; } |
|
|
|
|
if (strncmp(ct, "image/", 6) == 0) { snprintf(out, out_sz, "Photo"); return; } |
|
|
|
|
/* файл и прочие нетекстовые: декодируем base64-префикс в имя файла */ |
|
|
|
|
if (d[0] == '*') { |
|
|
|
|
const char* pipe = strchr(d, '|'); |
|
|
|
|
size_t b64len = pipe ? (size_t)(pipe - d - 1) : strlen(d) - 1; |
|
|
|
|
uint8_t dec[512]; size_t declen = b64_decode(d + 1, b64len, dec, sizeof(dec)); |
|
|
|
|
if (declen > 0) { |
|
|
|
|
if (declen >= out_sz) declen = out_sz - 1; |
|
|
|
|
memcpy(out, dec, declen); out[declen] = '\0'; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
snprintf(out, out_sz, "File"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
char* utun_bridge_get_channels_json(void) { |
|
|
|
|
sqlite3* db = chat_core_get_db(); |
|
|
|
|
if (!chat_core_is_initialized() || !db) { |
|
|
|
|
@ -360,7 +407,7 @@ char* utun_bridge_get_channels_json(void) {
|
|
|
|
|
int64_t last_msg_at = sqlite3_column_int64(st, 2); |
|
|
|
|
if (!ch_id) continue; |
|
|
|
|
|
|
|
|
|
char tbl_msg[80], tbl_peers[80], last_msg[128]; |
|
|
|
|
char tbl_msg[80], tbl_peers[80], last_msg[160]; |
|
|
|
|
msg_table_name(ch_id, tbl_msg, sizeof(tbl_msg)); |
|
|
|
|
peers_table_name(ch_id, tbl_peers, sizeof(tbl_peers)); |
|
|
|
|
last_msg[0] = '\0'; |
|
|
|
|
@ -373,17 +420,20 @@ char* utun_bridge_get_channels_json(void) {
|
|
|
|
|
int64_t author = sqlite3_column_int64(lm, 0); |
|
|
|
|
const uint8_t* dptr = sqlite3_column_blob(lm, 1); |
|
|
|
|
int dlen = sqlite3_column_bytes(lm, 1); |
|
|
|
|
char txt[128] = ""; |
|
|
|
|
char body[160] = ""; |
|
|
|
|
if (dptr && dlen > 0) { |
|
|
|
|
const char* dp = (const char*)dptr; |
|
|
|
|
char ct[32] = "text/plain"; |
|
|
|
|
const char* cts = strstr(dp, "\"ct\":\""); |
|
|
|
|
if (cts) { cts += 6; char* cte = strchr((char*)cts, '"'); if (cte) { size_t tlc = (size_t)(cte - cts); if (tlc < sizeof(ct)) { memcpy(ct, cts, tlc); ct[tlc] = '\0'; } } } |
|
|
|
|
const char* ds = strstr(dp, "\"d\":\""); |
|
|
|
|
if (ds) { ds += 5; char* de = strchr((char*)ds, '"'); if (de) { size_t tl = (size_t)(de - ds); if (tl > 120) tl = 120; memcpy(txt, ds, tl); txt[tl] = '\0'; } } |
|
|
|
|
if (ds) { ds += 5; char* de = strchr((char*)ds, '"'); if (de) { size_t tl = (size_t)(de - ds); if (tl > 511) tl = 511; char d[512]; memcpy(d, ds, tl); d[tl] = '\0'; bridge_format_preview_body(ct, d, body, sizeof(body)); } } |
|
|
|
|
} |
|
|
|
|
char author_name[128]; |
|
|
|
|
bridge_get_node_name(db, (uint64_t)author, ch_id, author_name, sizeof(author_name)); |
|
|
|
|
if (!author_name[0]) |
|
|
|
|
snprintf(author_name, sizeof(author_name), "0x%016llx", (unsigned long long)author); |
|
|
|
|
snprintf(last_msg, sizeof(last_msg), "%s: %s", author_name, txt); |
|
|
|
|
snprintf(last_msg, sizeof(last_msg), "%s: %s", author_name, body); |
|
|
|
|
} |
|
|
|
|
sqlite3_finalize(lm); |
|
|
|
|
} |
|
|
|
|
|