aboutsummaryrefslogtreecommitdiffstats
path: root/src/archive_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/archive_parser.cpp')
-rw-r--r--src/archive_parser.cpp176
1 files changed, 81 insertions, 95 deletions
diff --git a/src/archive_parser.cpp b/src/archive_parser.cpp
index 63acf60..f8b9179 100644
--- a/src/archive_parser.cpp
+++ b/src/archive_parser.cpp
@@ -1,6 +1,11 @@
#include "archive_parser.h"
#include "src/list_item.h"
#include "src/types.h"
+#include "activitypub/apactivity.h"
+#include "activitypub/apattachment.h"
+#include "activitypub/apobject.h"
+#include "activitypub/apreblog.h"
+#include "activitypub/appost.h"
#include <QFile>
#include <QJsonParseError>
@@ -9,6 +14,7 @@
#include <QDateTime>
#include <QDirIterator>
#include <QHash>
+#include <QDebug>
Archive::Archive(QString outbox_filename, ArchiveType archive_type) :
outbox_filename(outbox_filename), archive_type(archive_type) {}
@@ -64,6 +70,7 @@ bool is_status_type_allowed(StatusType status_type, ViewStatusTypes allowed_type
}
}
+// specific to Mastodon ActivityStreams archives
StatusType get_status_type(QJsonObject obj) {
/*
* public:
@@ -117,6 +124,7 @@ StatusType get_status_type(QJsonObject obj) {
return status_type;
}
+// Note: No need to create an AP… class for that (unless we want to precache the Activities but that would be very slow and use a lot of memory)
void Archive::update_status_list(ViewStatusTypes allowed_types, QListWidget *parent) {
int i = 0;
for (auto&& item : *outbox_items) {
@@ -131,6 +139,7 @@ void Archive::update_status_list(ViewStatusTypes allowed_types, QListWidget *par
goto next_item;
// Determine the status' type
+ // NOTE: keep
StatusType status_type;
if (activity_type == "Announce") status_type = REBLOG;
else status_type = get_status_type(obj);
@@ -164,159 +173,136 @@ void Archive::update_status_list(ViewStatusTypes allowed_types, QListWidget *par
}
}
-QString get_html_template(const QString& template_name) {
- static QHash<QString, QString>* templates = new QHash<QString, QString>;
-
- if (not templates->contains(template_name)) {
- QFile file("src/templates/"+ template_name +".html");
- if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
- templates->insert(template_name, "<i>Error loading status_info template.</i>");
- return templates->value(template_name);
- }
-
- qDebug() << "Loaded HTML template:" << template_name;
- templates->insert(template_name, file.readAll());
- }
-
- return templates->value(template_name);
-}
-
-QString get_html_status_object_as_list(QJsonObject obj, QString element_name) {
- QString text;
+QStringList get_status_object_list(QJsonObject obj, QString element_name) {
+ QStringList list;
if (obj.contains(element_name)) {
- QJsonArray to = obj.value(element_name).toArray();
+ QJsonArray elem = obj.value(element_name).toArray();
- for (auto collection : to)
- text.append(collection.toString() + ", ");
+ for (auto collection : elem)
+ list.append(collection.toString());
}
- if (text.isEmpty())
- text = "<em>(empty)</em>";
- else
- text.chop(2); // remove leftover ", "
-
- return text;
+ return list;
}
-QString get_html_status_object_languages(QJsonObject obj, QString element_name = "contentMap") {
- QString text;
+QStringList get_status_object_language_list(QJsonObject obj, QString element_name = "contentMap") {
+ QStringList list;
if (obj.contains(element_name) and obj.value(element_name).isObject()) {
QJsonObject content_map = obj.value(element_name).toObject();
QStringList languages = content_map.keys();
for (auto lang : languages)
- text.append(lang + ", ");
+ list.append(lang);
}
- if (text.isEmpty())
- text = "<em>(unknown)</em>";
- else
- text.chop(2); // remove leftover ", "
-
- return text;
+ return list;
}
-QString Archive::get_html_status_attachments(QJsonValueRef attachments_ref, int text_zone_width) {
- QString text;
+std::vector<APAttachmentFields> Archive::get_status_attachments_list(QJsonValueRef attachments_ref) {
+ std::vector<APAttachmentFields> list;
QJsonArray attachments = attachments_ref.toArray();
- int i = 1;
for (auto attachment_ref : attachments) {
- QString att_html(get_html_template("attachment"));
- QJsonObject attachment = attachment_ref.toObject();
+ APAttachmentFields element;
- att_html.replace("{{id}}", QString::number(i));
+ QJsonObject attachment = attachment_ref.toObject();
if (attachment.contains("url")) {
QString url = attachment["url"].toString();
+ // NOTE: This will continue to be done by the archive parser when building the APAttachmentFields object!! SO DO NOT MOVE
// Initialize attachment_dir if it hasn't been done
if (attachment_dir_have_to_find) find_attachment_dir(url);
// Also add a "/", after the attachment dir path, to make sure that the url starts with one as sometimes the ones in the json do not. We could make this prettier (but a bit slower) by only adding it conditionally. This might be worth it as the path can be copied and opened in the browser.
url.prepend(attachment_dir.absolutePath() + "/");
- att_html.replace("{{path}}", url);
- att_html.replace("{{filename}}", QFileInfo(url).fileName()); // FIXME: this is ugly
- }
- if (attachment.contains("mediaType") and attachment["mediaType"].toString().startsWith("image/"))
- // dynamically resize image based on the display widget size to avoid horizontal scrolling
- att_html.replace("{{img-width}}", QString::number((float)text_zone_width - (float)text_zone_width*0.15));
- else
- att_html.replace("{{img-width}}", "0");
+ element.path = url;
+ element.filename = QFileInfo(url).fileName();
+ }
- if (attachment.contains("name"))
- att_html.replace("{{alt-text}}", attachment["name"].toString());
+ element.media_type = attachment["mediaType"].toString();
+ element.name = attachment["name"].toString();
- text.append(att_html);
- ++i;
+ list.push_back(element);
}
- return text;
+ return list;
}
// status_index is assumed to be a valid index
QString Archive::get_html_status_info(int status_index, int text_zone_width, StatusType status_type, QLocale* locale) {
- QString info_text(get_html_template("status_info"));
+ // the JSON AP Activity (TODO: fix misleading name)
QJsonObject obj = outbox_items->at(status_index).toObject();
- if (obj.contains("type") and obj["type"].isString())
- info_text.replace("{{type}}", obj["type"].toString());
+ APActivityFields act_fields = {
+ .visibility = status_type
+ };
+
+ QString obj_url;
- if (obj.contains("published") and obj["published"].isString()) {
- // TODO: add a UI setting for configuring the display of local time or UTC time.
- QDateTime date = QDateTime::fromString(obj["published"].toString(), Qt::ISODate).toLocalTime();
- // Using QLocale::toString() is forward compatible with Qt 6 as QDateTime::toString() will not return anymore a string in the system locale.
- info_text.replace("{{published}}", locale->toString(date));
+ // The post
+ APObjectFields obj_fields;
+
+ if (obj.contains("type") and obj["type"].isString()) {
+ QString type = obj["type"].toString();
+ if (type == "Create") act_fields.type = APActivityType::CREATE;
+ else if (type == "Announce") act_fields.type = APActivityType::ANNOUNCE;
+ else act_fields.type = APActivityType::UNKNOWN;
}
+ if (obj.contains("published") and obj["published"].isString())
+ act_fields.published = obj["published"].toString();
+
if (obj.contains("id") and obj["id"].isString())
- info_text.replace("{{url-id}}", obj["id"].toString());
+ act_fields.object_url = obj["id"].toString();
- info_text.replace("{{to}}", get_html_status_object_as_list(obj, "to"));
- info_text.replace("{{cc}}", get_html_status_object_as_list(obj, "cc"));
+ if (obj.contains("actor"))
+ act_fields.by_actor = obj["actor"].toString(); // returns Null string if actor is not a string
+
+ act_fields.to_actors = get_status_object_list(obj, "to");
+ act_fields.cc_actors = get_status_object_list(obj, "cc");
if (obj["object"].isObject()) {
+ // the JSON AP Object (TODO: fix misleading name)
QJsonObject activity = obj["object"].toObject();
- if (activity.contains("summary")) {
- QString summary_text = activity["summary"].toString();
- if (summary_text.isEmpty())
- summary_text = "<em>(empty)</em>";
- info_text.replace("{{summary}}", summary_text);
- }
+ obj_fields.visibility = get_status_type(activity);
- info_text.replace("{{attachment-div}}", get_html_status_attachments(activity["attachment"], text_zone_width));
+ if (activity.contains("summary"))
+ obj_fields.summary = activity["summary"].toString();
- if (activity.contains("url") and activity["url"].isString())
- info_text.replace("{{url-status}}", activity["url"].toString());
+ obj_fields.attachments = get_status_attachments_list(activity["attachment"]);
+
+ obj_fields.web_url = activity["url"].toString();
+ obj_fields.object_url = activity["atomUri"].toString(); // atomUri?
+ obj_fields.reply_to_url = activity["inReplyTo"].toString();
if (activity["content"].isString()) {
- info_text.replace("{{content}}", activity["content"].toString());
- info_text.replace("{{lang}}", get_html_status_object_languages(activity));
+ obj_fields.content = activity["content"].toString();
+ obj_fields.languages = get_status_object_language_list(activity);
}
- } else if (obj["object"].isString()) {
- QString text = obj["object"].toString();
- QString content_text;
-
- if (status_type == REBLOG) {
- content_text = "Reblog of this object: <a href=\"{{url}}\">{{url}}</a>";
- content_text.replace("{{url}}", text);
- info_text.replace("{{url-status}}", text);
- } else
- content_text = text;
-
- info_text.replace("{{content}}", content_text);
- info_text.replace("{{summary}}", "<em>(empty)</em>");
- info_text.replace("{{lang}}", "<em>(not applicable)</em>");
- info_text.replace("{{attachment-div}}", "");
- }
- return info_text;
+ obj_fields.to_actors = get_status_object_list(activity, "to");
+ obj_fields.cc_actors = get_status_object_list(activity, "cc");
+ obj_fields.by_actor = activity["attributedTo"].toString();
+ obj_fields.published = activity["published"].toString();
+
+ } else if (obj["object"].isString())
+ obj_url = obj["object"].toString();
+
+ if (obj_url.isNull())
+ act_fields.object = new APPost(obj_fields);
+ else
+ act_fields.object = new APReblog({obj_url, act_fields.visibility});
+
+ // TODO: it is currently a waste to create this APActivity object that will be immediately destroyed but it allows us to extend archive parsing to something that will become abstract (and an abstract base class) and separate from display (the final goal) which will allow us to add other sources that feed us with posts, reblogs and Actor information. furthermore, these objects can be cached for reuse in a session.
+ return APActivity(act_fields).get_html_render({text_zone_width, locale});
}
+// TODO: make this use an APActivity object that will be present as an StatusListItem member.
QString Archive::get_html_status_text(int status_index) {
QString text("");
QJsonObject obj = outbox_items->at(status_index).toObject();