Handle multiple identities in a bcmr

This commit is contained in:
2025-04-10 16:25:43 +02:00
parent cf07797350
commit 831589ef2a
2 changed files with 69 additions and 37 deletions
+59 -34
View File
@@ -52,33 +52,36 @@ bool Processor::run()
for (auto *source : m_sources) { for (auto *source : m_sources) {
assert(source); assert(source);
assert(source->identities.size() > 0);
QString outPath = m_outDir + source->hash + ".json"; QString outPath = m_outDir + source->hash + ".json";
if (!QFile::exists(outPath)) { if (!QFile::exists(outPath)) {
logCritical() << "Placing BCMR " << source->name << "as" << source->hash; logCritical() << "Placing BCMR " << source->identities.at(0)->name << "as" << source->hash;
QFile::copy(source->origFilename, outPath); QFile::copy(source->origFilename, outPath);
} }
for (const auto &resource : std::as_const(source->resources)) { for (auto *id : source->identities) {
QUrl url(resource); for (const auto &resource : std::as_const(id->resources)) {
if (!url.isValid()) QUrl url(resource);
continue; if (!url.isValid())
QString path = m_outDir + source->hash + "/" + url.host() + url.path(); continue;
if (QFile::exists(path)) QString path = m_outDir + source->hash + "/" + url.host() + url.path();
continue; if (QFile::exists(path))
if (url.scheme() == "ipfs") { continue;
// use the main gateway for download if (url.scheme() == "ipfs") {
url = QUrl(QString("https://ipfs.io/ipfs/%1").arg(resource.mid(7))); // use the main gateway for download
} url = QUrl(QString("https://ipfs.io/ipfs/%1").arg(resource.mid(7)));
if (url.scheme() == "http" || url.scheme() == "https") { }
// schedule for download. if (url.scheme() == "http" || url.scheme() == "https") {
DownloadJob *job = new DownloadJob(&m_network); // schedule for download.
job->setTargetFilePath(path); DownloadJob *job = new DownloadJob(&m_network);
job->setSourceUrl(url); job->setTargetFilePath(path);
connect (job, &DownloadJob::finished, this, [=]() { job->setSourceUrl(url);
m_downloadJobs.removeAll(job); connect (job, &DownloadJob::finished, this, [=]() {
QTimer::singleShot(1, this, SLOT(runDownloadQueue())); m_downloadJobs.removeAll(job);
}); QTimer::singleShot(1, this, SLOT(runDownloadQueue()));
m_downloadJobs.append(job); });
m_downloadJobs.append(job);
}
} }
} }
} }
@@ -88,15 +91,22 @@ bool Processor::run()
MetaCategory *mc = i->second; MetaCategory *mc = i->second;
QJsonArray sources; QJsonArray sources;
auto owners = std::vector<MetaBCMR*>(mc->owners.begin(), mc->owners.end()); auto owners = std::vector<MetaBCMR*>(mc->owners.begin(), mc->owners.end());
std::sort(owners.begin(), owners.end(), [](MetaBCMR *a, MetaBCMR *b) { std::sort(owners.begin(), owners.end(), [mc](MetaBCMR *a, MetaBCMR *b) {
return a->timestamp > b->timestamp; // we're sorting the bcmr itself, but we only really care about a
// single identity inside each of them. THAT is what we'll compare.
MetaIdentity *ai = a->idForCategory(mc->category);
assert(ai);
MetaIdentity *bi = b->idForCategory(mc->category);
assert(bi);
return ai->timestamp > bi->timestamp;
}); });
for (auto owner : owners) { for (auto owner : owners) {
QJsonObject o; QJsonObject o;
o.insert("bcmr", owner->hash); o.insert("bcmr", owner->hash);
o.insert("name", owner->name); MetaIdentity *id = owner->idForCategory(mc->category);
o.insert("timestamp", owner->timestampStr); o.insert("name", id->name);
o.insert("timestamp", id->timestampStr);
sources.append(o); sources.append(o);
} }
QJsonObject root; QJsonObject root;
@@ -212,9 +222,6 @@ void Processor::parseBCMR(const QString &path)
if (me == nullptr) { if (me == nullptr) {
me = new MetaBCMR(); me = new MetaBCMR();
me->origFilename = path; me->origFilename = path;
me->name = revision["name"].toString();
me->timestampStr = revisionDates.back();
me->timestamp = QDateTime::fromString(me->timestampStr, Qt::ISODate);
// calc hash // calc hash
CSHA256 hasher; CSHA256 hasher;
hasher.write(data.constData(), data.size()); hasher.write(data.constData(), data.size());
@@ -224,13 +231,20 @@ void Processor::parseBCMR(const QString &path)
m_sources.push_back(me); m_sources.push_back(me);
} }
logInfo() << "Found BCMR" << me->name << identity.key(); MetaIdentity *id = new MetaIdentity();
id->name = revision["name"].toString();
id->timestampStr = revisionDates.back();
id->timestamp = QDateTime::fromString(id->timestampStr, Qt::ISODate);
id->identity = identity.key();
me->identities.push_back(id);
logInfo() << "Found BCMR" << id->name << identity.key();
const auto uris_ = revision["uris"]; const auto uris_ = revision["uris"];
if (uris_.isObject()) { if (uris_.isObject()) {
const auto uris = uris_.toObject(); const auto uris = uris_.toObject();
auto icon = uris["icon"]; auto icon = uris["icon"];
if (icon.isString()) if (icon.isString())
me->resources.insert(icon.toString()); id->resources.insert(icon.toString());
} }
const auto token_ = revision["token"]; const auto token_ = revision["token"];
@@ -240,8 +254,9 @@ void Processor::parseBCMR(const QString &path)
if (cat.size() != 64) { if (cat.size() != 64) {
logCritical() << "found token, but category is invalid length" << cat.size(); logCritical() << "found token, but category is invalid length" << cat.size();
} else { } else {
id->category = cat;
MetaCategory *mc = fetchOrCreate(cat); MetaCategory *mc = fetchOrCreate(cat);
me->tokens.push_back(mc); id->tokens.push_back(mc);
mc->owners.insert(me); mc->owners.insert(me);
// walk all nfts and extract image and icon resource urls // walk all nfts and extract image and icon resource urls
auto types = token; auto types = token;
@@ -255,10 +270,10 @@ void Processor::parseBCMR(const QString &path)
continue; continue;
auto image = uris["image"]; auto image = uris["image"];
if (image.isString()) if (image.isString())
me->resources.insert(image.toString()); id->resources.insert(image.toString());
auto icon = uris["icon"]; auto icon = uris["icon"];
if (icon.isString()) if (icon.isString())
me->resources.insert(icon.toString()); id->resources.insert(icon.toString());
} }
} }
@@ -295,3 +310,13 @@ Processor::MetaCategory *Processor::fetchOrCreate(const QString &catId)
return mc; return mc;
} }
Processor::MetaIdentity *Processor::MetaBCMR::idForCategory(const QString &category) const
{
for (auto *i : identities) {
if (i->category == category) {
return i;
}
}
return nullptr;
}
+10 -3
View File
@@ -30,15 +30,22 @@ private:
struct MetaCategory; struct MetaCategory;
MetaCategory *fetchOrCreate(const QString &catId); MetaCategory *fetchOrCreate(const QString &catId);
struct MetaBCMR { struct MetaIdentity {
QString hash;
QString origFilename;
QString name; QString name;
QString timestampStr; QString timestampStr;
QString category; // the sha256 of the token category
QString identity; // the 'key' of the identity (typically an auth-base)
QDateTime timestamp; QDateTime timestamp;
std::vector<struct MetaCategory*> tokens; std::vector<struct MetaCategory*> tokens;
QSet<QString> resources; QSet<QString> resources;
}; };
struct MetaBCMR {
QString hash;
QString origFilename;
std::vector<MetaIdentity*> identities;
MetaIdentity* idForCategory(const QString &category) const;
};
struct MetaCategory { struct MetaCategory {
QString category; QString category;