support old archive formats and download JSON data

This commit is contained in:
msramalho
2023-08-18 16:21:56 +01:00
parent ef7496ff60
commit be94f88192
3 changed files with 47 additions and 11 deletions

View File

@@ -1,13 +1,14 @@
{ {
"private": true, "private": true,
"scripts": { "scripts": {
"build": "rm -rf distribution && rm -f distribution.zip && API_ENDPOINT=http://134.122.58.133:8004 parcel build source/manifest.json --no-content-hash --no-source-maps --dist-dir distribution --no-cache --detailed-report 0 && zip -r distribution.zip distribution", "build": "rm -rf distribution && rm -f distribution.zip && API_ENDPOINT=https://auto-archiver-api.bellingcat.com parcel build source/manifest.json --no-content-hash --no-source-maps --dist-dir distribution --no-cache --detailed-report 0 && zip -r distribution.zip distribution",
"lint": "run-p lint:*", "lint": "run-p lint:*",
"lint-fix": "run-p 'lint:* -- --fix'", "lint-fix": "run-p 'lint:* -- --fix'",
"lint:css": "stylelint source/**/*.css", "lint:css": "stylelint source/**/*.css",
"lint:js": "xo", "lint:js": "xo",
"test": "run-p lint:* build", "test": "run-p lint:* build",
"watch": "parcel watch source/manifest.json --dist-dir distribution --no-cache --no-hmr" "watch": "parcel watch source/manifest.json --dist-dir distribution --no-cache --no-hmr",
"watch-prod": "API_ENDPOINT=https://auto-archiver-api.bellingcat.com parcel watch source/manifest.json --dist-dir distribution --no-cache --no-hmr"
}, },
"browserslist": [ "browserslist": [
"last 1 Chrome version", "last 1 Chrome version",

View File

@@ -1,6 +1,6 @@
{ {
"name": "Auto-archiver extension", "name": "Auto-archiver extension",
"version": "0.3.1", "version": "0.3.2",
"description": "A gateway to effective archiving of online content, including behind private platforms. ", "description": "A gateway to effective archiving of online content, including behind private platforms. ",
"homepage_url": "https://github.com/bellingcat/auto-archiver-extension", "homepage_url": "https://github.com/bellingcat/auto-archiver-extension",
"manifest_version": 3, "manifest_version": 3,

View File

@@ -26,24 +26,36 @@
</td> </td>
<td class="col s5"><a :href="task?.url" target="_blank">{{ task.url }}</a></td> <td class="col s5"><a :href="task?.url" target="_blank">{{ task.url }}</a></td>
<td class="col s2"> <td class="col s2">
<a v-if="archiveUrl.length" :href="archiveUrl" target="_blank"> <div v-if="archiveUrls.length > 1">{{ task?.result?.status || "success" }}:</div>
{{ task?.result?.status || "open" }}</a> <div v-for="au in archiveUrls">
<span v-if="!archiveUrl.length">{{ task?.result?.error || 'no result' }}</span> <a :href="au.url" target="_blank" :title="`${au.id}: ${au.url}`">
{{ archiveUrls.length == 1 ? (task?.result?.status || "success") : au.id }}
</a>
</div>
<span v-if="!archiveUrls.length">{{ task?.result?.error || 'no result' }}</span>
</td> </td>
<td class="col s3">{{ readbleDate }}</td> <td class="col s3">{{ readbleDate }}</td>
<td class="col s1" v-if="(taskFailed || taskSucceeded) && taskType == 'local'"> <td class="col s1">
<a class="delete-btn" href="#" v-on:click="deleteTask"><i class="material-icons small">delete</i></a> <a class="delete-btn" v-if="(taskFailed || taskSucceeded) && taskType == 'local'" href="#"
v-on:click="deleteTask"><i class="material-icons small">delete</i></a>
<a class="download-btn" v-if="taskSucceeded" href="#" v-on:click="downloadTask"><i
class="material-icons small" title="Download JSON data">data_object</i></a>
</td> </td>
</tr> </tr>
</template> </template>
<style> <style>
.delete-btn { .delete-btn,
.download-btn {
color: grey; color: grey;
} }
.delete-btn:hover { .delete-btn:hover {
color: darkred; color: darkred;
} }
.download-btn:hover {
color: teal;
}
</style> </style>
<script> <script>
@@ -73,6 +85,23 @@ export default {
deleteTask: function () { deleteTask: function () {
this.$emit('remove', this.task.id); this.$emit('remove', this.task.id);
}, },
downloadTask: function () {
const json = JSON.stringify(this.task);
const blob = new Blob([json], { type: 'application/json' });
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = `task-${this.task?.id}.json`;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
// Clean up
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl);
},
taskFinished: function (task) { taskFinished: function (task) {
return task.status == 'SUCCESS' || task.status == 'FAILURE' || task.status == 'REVOKED'; return task.status == 'SUCCESS' || task.status == 'FAILURE' || task.status == 'REVOKED';
}, },
@@ -93,8 +122,14 @@ export default {
} }
}, },
computed: { computed: {
archiveUrl() { /**
return this.task?.result?.media?.filter(m => m?.properties?.id == "_final_media")?.at(0)?.urls?.at(0) || ''; * Tries to extract the _final_media archive URL, but will return a list of URLs in case that one is not present and others are, this is needed since some older archives don't have an html page but rather a video/screenshot.
*/
archiveUrls() {
let urlsToShow = [this.task?.result?.media?.filter(m => m?.properties?.id == "_final_media")?.at(0)].filter(m => m !== undefined);
urlsToShow = urlsToShow.length ? urlsToShow : this.task?.result?.media || [];
urlsToShow = urlsToShow.map(m => { return { url: m?.urls?.at(0), id: m?.properties?.id } }).filter(m => m.url !== undefined);
return urlsToShow;
}, },
readbleDate() { readbleDate() {
if (this.task?.result?.metadata?._processed_at) { if (this.task?.result?.metadata?._processed_at) {