38 lines
2.2 KiB
C++
38 lines
2.2 KiB
C++
/* Снимок каталога CHAT_EVT_STREAM_SOURCES для шапки чата и отдельного окна просмотра.
|
|
* parse применяет данные целиком; valid=false означает недоступность, а не пустой каталог. */
|
|
#pragma once
|
|
#include <QJsonDocument>
|
|
#include <QJsonArray>
|
|
#include <QJsonObject>
|
|
#include <QSet>
|
|
#include <QtEndian>
|
|
#include "../../../lib/debug_config.h"
|
|
|
|
struct LiveStreamSource { quint64 id, epoch; QString name; bool self = false; };
|
|
struct StreamSourceSnapshot { quint64 group = 0; bool valid = false; QList<LiveStreamSource> sources; };
|
|
|
|
inline bool parseStreamSources(const uint8_t* data, int length, StreamSourceSnapshot& out) {
|
|
if (!data || length < 11 || data[8] > 1) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source event invalid bytes=%d", length); return false;
|
|
}
|
|
StreamSourceSnapshot next; next.group = qFromBigEndian<quint64>(data); next.valid = data[8];
|
|
QJsonParseError error;
|
|
auto document = QJsonDocument::fromJson(QByteArray(reinterpret_cast<const char*>(data + 9), length - 9), &error);
|
|
if (!next.group || error.error != QJsonParseError::NoError || !document.isArray()) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source JSON invalid group=%llx error=%s",
|
|
(unsigned long long)next.group, qPrintable(error.errorString())); return false;
|
|
}
|
|
QSet<quint64> seen;
|
|
for (const auto& value : document.array()) {
|
|
auto member = value.toObject(); bool idOk = false, epochOk = false;
|
|
quint64 id = member.value("id").toString().toULongLong(&idOk);
|
|
quint64 epoch = member.value("epoch").toString().toULongLong(&epochOk, 16);
|
|
if (!idOk || !epochOk || !id || !epoch || seen.contains(id) || !member.value("name").isString()) {
|
|
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "desktop source identity invalid group=%llx", (unsigned long long)next.group); return false;
|
|
}
|
|
QString name = member.value("name").toString(); if (name.isEmpty()) name = QString::number(id);
|
|
next.sources.append({id, epoch, name, member.value("self").toInt() != 0}); seen.insert(id);
|
|
}
|
|
out = std::move(next); return true;
|
|
}
|