Public Access
A streaming JSON scanner (a 33 KB list of releases costs a few hundred bytes), the release reader built on it, HTTP response heads and chunked bodies, URLs, and the decisions: which release is an update, whether to announce it, and which download URLs the device takes. Tested against the real answers of git.twis.la. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
53 lines
1.8 KiB
C++
53 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "json_scan.h"
|
|
|
|
namespace roro::release {
|
|
|
|
// What the device needs to know about one Gitea release (docs/milestones/R1.md, #6).
|
|
struct Release {
|
|
std::string tag; // "v0.10.0"
|
|
std::string published; // "2026-10-06T08:11:31Z"
|
|
std::string notes; // the first paragraph of the text: the tag's message
|
|
std::string otaUrl; // where the signed Update File is
|
|
uint32_t otaSize = 0;
|
|
bool draft = false, prerelease = false;
|
|
|
|
// Something that can be installed and that the project meant to publish (drafts and
|
|
// pre-releases are left out for now: a release channel is #53).
|
|
bool usable() const { return !draft && !prerelease && !tag.empty() && !otaUrl.empty(); }
|
|
std::string date() const { return published.substr(0, 10); } // "2026-10-06"
|
|
};
|
|
|
|
// Reads Gitea's answer as it arrives: `releases/latest` (one object) or `releases?limit=N` (a list).
|
|
class ReleaseReader {
|
|
public:
|
|
explicit ReleaseReader(size_t maxReleases = 10);
|
|
|
|
void feed(const char* data, size_t len) { scanner_.feed(data, len); }
|
|
void end(); // after the last chunk
|
|
bool ok() const { return !scanner_.failed(); }
|
|
bool complete() const { return scanner_.done(); }
|
|
const std::vector<Release>& releases() const { return releases_; }
|
|
|
|
private:
|
|
void value(const std::string& path, const std::string& text, bool isString, bool truncated);
|
|
void flushAsset();
|
|
|
|
JsonScanner scanner_;
|
|
size_t max_;
|
|
std::vector<Release> releases_;
|
|
int assetRelease_ = -1, assetIndex_ = -1;
|
|
std::string assetName_, assetUrl_;
|
|
uint32_t assetSize_ = 0;
|
|
};
|
|
|
|
// The first paragraph of a release's text, trimmed; "..." if the text was cut before it ended.
|
|
std::string firstParagraph(const std::string& text, bool truncated);
|
|
|
|
} // namespace roro::release
|