Allow visiting/viewing an app message by id.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3635 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
Cory McWilliams 2021-01-09 23:06:33 +00:00
parent d8657866f5
commit 2b5a56abfe
5 changed files with 69 additions and 11 deletions

View File

@ -52,7 +52,7 @@ function socket(request, response, client) {
var packageName;
var blobId;
var match;
if (match = /^\/(&[^\.]*\.\w+)(\/?.*)/.exec(message.path)) {
if (match = /^\/([&%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(message.path)) {
blobId = match[1];
} else if (match = /^\/\~([^\/]+)\/([^\/]+)\/$/.exec(message.path)) {
var user = match[1];

View File

@ -267,16 +267,16 @@ async function getProcessBlob(blobId, key, options) {
}
process.task.setImports(imports);
process.task.activate();
let source = await ssb.blobGet(blobId);
let source = await getBlobOrContent(blobId);
var appSource = utf8Decode(source);
try {
var app = JSON.parse(appSource);
if (app.type == "tildefriends-app") {
var id = app.files["app.js"];
var blob = await ssb.blobGet(id);
var blob = await getBlobOrContent(id);
appSource = utf8Decode(blob);
await Promise.all(Object.keys(app.files).map(async function(f) {
await process.task.loadFile([f, await ssb.blobGet(app.files[f])]);
await process.task.loadFile([f, await getBlobOrContent(app.files[f])]);
}));
}
} catch (e) {
@ -387,6 +387,16 @@ function sendData(response, data) {
}
}
async function getBlobOrContent(id) {
if (!id) {
return;
} else if (id.startsWith('&')) {
return ssb.blobGet(id);
} else if (id.startsWith('%')) {
return ssb.messageContentGet(id);
}
}
async function blobHandler(request, response, blobId, uri) {
var found = false;
if (!found) {
@ -402,7 +412,7 @@ async function blobHandler(request, response, blobId, uri) {
}
if (!uri) {
response.writeHead(301, {"Location": blobId + "/"});
response.writeHead(301, {"Location": "/" + blobId + "/"});
response.end(data);
return;
}
@ -414,14 +424,14 @@ async function blobHandler(request, response, blobId, uri) {
if (match = /^\/\~(\w+)\/(\w+)$/.exec(blobId)) {
var id = await new Database(match[1]).get('path:' + match[2]);
if (id) {
data = await ssb.blobGet(id);
data = await getBlobOrContent(id);
if (match[3]) {
var app = JSON.parse(data);
data = app.files[match[3]];
}
}
} else {
data = await ssb.blobGet(blobId);
data = await getBlobOrContent(blobId);
}
sendData(response, data);
} else if (uri == "/save") {
@ -449,12 +459,16 @@ async function blobHandler(request, response, blobId, uri) {
var db = new Database(match[1]);
var id = await db.get('path:' + match[2]);
if (id) {
data = utf8Decode(await ssb.blobGet(id));
data = utf8Decode(await getBlobOrContent(id));
var app = JSON.parse(data);
print(JSON.stringify(app));
data = app.files[uri.substring(1)];
data = await ssb.blobGet(data);
data = await getBlobOrContent(data);
}
} else {
data = utf8Decode(await getBlobOrContent(blobId));
var app = JSON.parse(data);
data = app.files[uri.substring(1)];
data = await getBlobOrContent(data);
}
sendData(response, data);
}
@ -479,7 +493,7 @@ httpd.all("", function(request, response) {
return response.end();
} else if (match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri)) {
return blobHandler(request, response, match[1], match[2]);
} else if (match = /^\/(&[^\.]*\.\w+)(\/?.*)/.exec(request.uri)) {
} else if (match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri)) {
return blobHandler(request, response, match[1], match[2]);
} else if (match = /^\/static(\/.*)/.exec(request.uri)) {
return staticFileHandler(request, response, null, match[1]);

View File

@ -1902,6 +1902,31 @@ bool tf_ssb_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char* ou
return result;
}
bool tf_ssb_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_t* out_size)
{
bool result = false;
sqlite3_stmt* statement;
const char* query = "SELECT content FROM messages WHERE id = ?";
if (sqlite3_prepare(ssb->db, query, -1, &statement, NULL) == SQLITE_OK) {
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_ROW) {
const uint8_t* blob = sqlite3_column_blob(statement, 0);
int size = sqlite3_column_bytes(statement, 0);
if (out_blob) {
*out_blob = malloc(size + 1);
memcpy(*out_blob, blob, size);
(*out_blob)[size] = '\0';
}
if (out_size) {
*out_size = size;
}
result = true;
}
sqlite3_finalize(statement);
}
return result;
}
static bool _tf_ssb_parse_broadcast(const char* in_broadcast, tf_ssb_broadcast_t* out_broadcast)
{
char public_key_str[45] = { 0 };

View File

@ -70,6 +70,8 @@ bool tf_ssb_get_message_by_author_and_sequence(tf_ssb_t* ssb, const char* author
bool tf_ssb_blob_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_t* out_size);
bool tf_ssb_blob_store(tf_ssb_t* ssb, const uint8_t* blob, size_t size, char* out_id, size_t out_id_size);
bool tf_ssb_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_blob, size_t* out_size);
typedef void (tf_ssb_connections_changed_callback_t)(tf_ssb_t* ssb, tf_ssb_change_t change, tf_ssb_connection_t* connection, void* user_data);
void tf_ssb_add_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_connections_changed_callback_t callback, void* user_data);
const char** tf_ssb_get_connection_ids(tf_ssb_t* ssb);

View File

@ -82,6 +82,22 @@ static JSValue _tf_ssb_blobStore(JSContext* context, JSValueConst this_val, int
return result;
}
static JSValue _tf_ssb_messageContentGet(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue result = JS_NULL;
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
if (ssb) {
const char* id = JS_ToCString(context, argv[0]);
uint8_t* blob = NULL;
size_t size = 0;
if (tf_ssb_message_content_get(ssb, id, &blob, &size)) {
result = JS_NewArrayBufferCopy(context, blob, size);
free(blob);
}
}
return result;
}
static JSValue _tf_ssb_connections(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
JSValue result = JS_NULL;
@ -285,6 +301,7 @@ void tf_ssb_init(JSContext* context, tf_ssb_t* ssb)
JS_SetPropertyStr(context, object, "getMessage", JS_NewCFunction(context, _tf_ssb_getMessage, "getMessage", 2));
JS_SetPropertyStr(context, object, "blobGet", JS_NewCFunction(context, _tf_ssb_blobGet, "blobGet", 1));
JS_SetPropertyStr(context, object, "blobStore", JS_NewCFunction(context, _tf_ssb_blobStore, "blobStore", 2));
JS_SetPropertyStr(context, object, "messageContentGet", JS_NewCFunction(context, _tf_ssb_messageContentGet, "messageContentGet", 1));
JS_SetPropertyStr(context, object, "connections", JS_NewCFunction(context, _tf_ssb_connections, "connections", 0));
JS_SetPropertyStr(context, object, "createHistoryStream", JS_NewCFunction(context, _tf_ssb_createHistoryStream, "createHistoryStream", 1));
JS_SetPropertyStr(context, object, "sqlStream", JS_NewCFunction(context, _tf_ssb_sqlStream, "sqlStream", 3));