mirror of
https://github.com/bellingcat/auto-archiver-setup-tool.git
synced 2026-06-11 13:08:37 +03:00
Merge pull request #2 from bellingcat/feat/add-existing-sheet
This commit is contained in:
11
package-lock.json
generated
11
package-lock.json
generated
@@ -8,6 +8,7 @@
|
||||
"name": "firebase-archiver-2",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"@mdi/font": "^7.2.96",
|
||||
"core-js": "^3.8.3",
|
||||
"firebase": "^9.22.0",
|
||||
"firebaseui": "^6.0.2",
|
||||
@@ -2783,6 +2784,11 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@mdi/font": {
|
||||
"version": "7.3.67",
|
||||
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.3.67.tgz",
|
||||
"integrity": "sha512-SWxvzRbUQRfewlIV+OF4/YF4DkeTjMWoT8Hh9yeU/5UBVdJZj9Uf4a9+cXjknSIhIaMxZ/4N1O/s7ojApOOGjg=="
|
||||
},
|
||||
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||
"version": "5.1.1-v1",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||
@@ -14324,6 +14330,11 @@
|
||||
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
|
||||
"dev": true
|
||||
},
|
||||
"@mdi/font": {
|
||||
"version": "7.3.67",
|
||||
"resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.3.67.tgz",
|
||||
"integrity": "sha512-SWxvzRbUQRfewlIV+OF4/YF4DkeTjMWoT8Hh9yeU/5UBVdJZj9Uf4a9+cXjknSIhIaMxZ/4N1O/s7ojApOOGjg=="
|
||||
},
|
||||
"@nicolo-ribaudo/eslint-scope-5-internals": {
|
||||
"version": "5.1.1-v1",
|
||||
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"serve": "vue-cli-service serve --port 8081",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 614 B |
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 1em">
|
||||
<div class="text-h5 mt-5 mb-3" v-if="docs.length > 0">
|
||||
Your auto-archiver documents
|
||||
Your auto-archiver sheets
|
||||
</div>
|
||||
<v-row v-for="doc in docs" :key="doc.sheetId">
|
||||
<v-col>
|
||||
|
||||
@@ -3,12 +3,12 @@ import { getAuth } from "firebase/auth";
|
||||
import { getFirestore } from "firebase/firestore";
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: "AIzaSyBN5oJ8c_VGhcfesAxXPVmuVnJ_V5MM8JM",
|
||||
authDomain: "osm-search-364115.firebaseapp.com",
|
||||
projectId: "osm-search-364115",
|
||||
storageBucket: "osm-search-364115.appspot.com",
|
||||
messagingSenderId: "919009657823",
|
||||
appId: "1:919009657823:web:f3be7f8470a6c36665ba6a"
|
||||
apiKey: "AIzaSyBEawXAq9pajlVKQtLopWyd_ELDwoUlbDo",
|
||||
authDomain: "bellingcat-auto-archiver-b85db.firebaseapp.com",
|
||||
projectId: "bellingcat-auto-archiver-b85db",
|
||||
storageBucket: "bellingcat-auto-archiver-b85db.appspot.com",
|
||||
messagingSenderId: "406209235111",
|
||||
appId: "1:406209235111:web:f27327bed2db7295a43382",
|
||||
};
|
||||
|
||||
const firebaseApp = initializeApp(firebaseConfig);
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
addDoc,
|
||||
query,
|
||||
where,
|
||||
limit,
|
||||
getDocs,
|
||||
doc,
|
||||
deleteDoc,
|
||||
@@ -29,6 +30,7 @@ export default new Vuex.Store({
|
||||
access_token: null,
|
||||
docs: [],
|
||||
loading: false,
|
||||
errorMessage: "",
|
||||
},
|
||||
mutations: {
|
||||
setUser(state, user) {
|
||||
@@ -43,6 +45,9 @@ export default new Vuex.Store({
|
||||
setAccessToken(state, access_token) {
|
||||
state.access_token = access_token;
|
||||
},
|
||||
setErrorMessage(state, errorMessage) {
|
||||
state.errorMessage = errorMessage;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async signin({ commit, dispatch }) {
|
||||
@@ -282,7 +287,7 @@ export default new Vuex.Store({
|
||||
endColumnIndex: 11,
|
||||
},
|
||||
description:
|
||||
"Protecting header row (needed for auto-archiver)",
|
||||
"Protecting header row (needed for auto-archiver), do not modify archiving column names, you can add and move columns around when no 'Archive in Progress' is present in the 'Archive status' column.",
|
||||
warningOnly: true,
|
||||
},
|
||||
},
|
||||
@@ -317,5 +322,45 @@ export default new Vuex.Store({
|
||||
console.error("add (firebase.js): ", error);
|
||||
}
|
||||
},
|
||||
|
||||
async enable({ state, dispatch, commit }, { spreadsheetId }) {
|
||||
commit("setLoading", true);
|
||||
commit("setErrorMessage", "");
|
||||
|
||||
try {
|
||||
// fetch existing sheet
|
||||
const sheetToEnable = await gapi.client.sheets.spreadsheets.get({
|
||||
spreadsheetId: spreadsheetId,
|
||||
});
|
||||
|
||||
const q = query(
|
||||
collection(firebaseFirestore, "sheets"),
|
||||
where("uid", "==", state.user.uid),
|
||||
where("sheetId", "==", spreadsheetId),
|
||||
limit(1)
|
||||
);
|
||||
|
||||
const response = await getDocs(q);
|
||||
if(response.docs.length > 0) {
|
||||
throw "Sheet already enabled";
|
||||
}
|
||||
|
||||
const col = await collection(firebaseFirestore, "sheets");
|
||||
await addDoc(col, {
|
||||
sheetId: spreadsheetId,
|
||||
url: sheetToEnable.result.spreadsheetUrl,
|
||||
timestamp: Date.now(),
|
||||
uid: state.user.uid,
|
||||
lastArchived: null,
|
||||
name: sheetToEnable.result.properties.title,
|
||||
});
|
||||
|
||||
dispatch("getDocs");
|
||||
} catch (error) {
|
||||
commit("setErrorMessage", `Unable to add sheet: ${JSON.stringify(error)}`);
|
||||
commit("setLoading", false);
|
||||
console.error("add (firebase.js): ", error);
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -25,27 +25,38 @@
|
||||
>associated article</a
|
||||
>.
|
||||
</p>
|
||||
<h4>How archiving a Google Spreadsheet works</h4>
|
||||
<ul>
|
||||
<li>Add links to the <code>Link</code> column</li>
|
||||
<li>
|
||||
Links be archived
|
||||
<b>every 15 minutes</b>, or you can trigger a manual archive
|
||||
below
|
||||
</li>
|
||||
<li>
|
||||
You can modify and share the Google Sheet subsequently, but do
|
||||
not edit the auto archiver column names in the header row or
|
||||
remove the service account from the shared users
|
||||
</li>
|
||||
</ul>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<DocList v-if="user" />
|
||||
|
||||
<div class="text-h5 mt-5 mb-3">Manage new auto-archiver sheets</div>
|
||||
|
||||
<v-card style="margin-bottom: 1em">
|
||||
<v-card-title>Create a new auto-archiver sheet</v-card-title>
|
||||
<v-card-text>
|
||||
<ol style="margin-bottom: 1em">
|
||||
<li>Press "create" to create a new archiving Google Sheet</li>
|
||||
<li>
|
||||
Add links to the "Link" column. They will be archived every 15
|
||||
minutes, or you can trigger a manual archive below
|
||||
</li>
|
||||
<li>
|
||||
This sheet will be shared with the service account necessary for
|
||||
Bellingcat's archiving server
|
||||
</li>
|
||||
<li>
|
||||
You can modify and share the Google Sheet subsequently, but do
|
||||
not edit the column names in the header row or remove the
|
||||
service account from the shared users
|
||||
</li>
|
||||
<li>The sheet will appear in your list</li>
|
||||
</ol>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
<v-card>
|
||||
<v-card-title>Create a new auto archiver sheet</v-card-title>
|
||||
<v-card-text>
|
||||
<v-text-field
|
||||
label="Document name"
|
||||
v-model="docName"
|
||||
@@ -58,7 +69,93 @@
|
||||
>Create</v-btn
|
||||
>
|
||||
<v-alert v-if="!user" color="#f2d97c" light icon="mdi-alert"
|
||||
><a href="#" @click="$store.dispatch('signin')"
|
||||
><a href="#!" @click="$store.dispatch('signin')"
|
||||
>Sign in with a Google account</a
|
||||
>
|
||||
to continue</v-alert
|
||||
>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-card>
|
||||
<v-card-title
|
||||
>Enable the auto-archiver in an existing sheet</v-card-title
|
||||
>
|
||||
<v-card-text>
|
||||
<ol style="margin-bottom: 1em">
|
||||
<li>
|
||||
Invite
|
||||
<code
|
||||
>bellingcat-auto-archiver-api@bellingcat-auto-archiver-b85db.iam.gserviceaccount.com</code
|
||||
>
|
||||
into your spreadsheet
|
||||
</li>
|
||||
<!-- Link Archive status Destination folder Archive location Archive date Thumbnail Upload timestamp Upload title Textual content Screenshot Hash -->
|
||||
<li>
|
||||
Make sure you have the following <b>mandatory</b> column names:
|
||||
<ul>
|
||||
<li><code>Link</code> where you will put the URLs.</li>
|
||||
<li>
|
||||
<code>Archive Status</code> to monitor progress and success
|
||||
of archiver
|
||||
</li>
|
||||
<li>
|
||||
<code>Archive location</code> where the link to the archived
|
||||
content is added
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
Add any of the following <b>optional</b> column names:
|
||||
<ul>
|
||||
<li>
|
||||
<code>Archive date</code> info on when archiving occurred
|
||||
</li>
|
||||
<li>
|
||||
<code>Thumbnail</code> an image preview from archived media
|
||||
</li>
|
||||
<li>
|
||||
<code>Upload timestamp</code> online content creation date
|
||||
</li>
|
||||
<li><code>Upload title</code> title</li>
|
||||
<li><code>Textual content</code> text content</li>
|
||||
<li><code>Screenshot</code> link to page screenshot</li>
|
||||
<li>
|
||||
<code>Hash</code> content hash (for integrity purposes)
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Paste the Google Sheet URL</li>
|
||||
<li>Press "enable" to add the Google Sheet to your list</li>
|
||||
<li>
|
||||
Manually check archiving is working and re-check the steps above
|
||||
if it is not
|
||||
</li>
|
||||
</ol>
|
||||
<v-alert
|
||||
v-if="$store.state.errorMessage"
|
||||
title="Error"
|
||||
text
|
||||
type="error"
|
||||
variant="outlined"
|
||||
closable
|
||||
>{{ $store.state.errorMessage }}</v-alert
|
||||
>
|
||||
<v-text-field
|
||||
label="Google Sheet URL"
|
||||
v-model="spreadsheetUrl"
|
||||
:hint="spreadsheetId ? 'Detected id: ' + spreadsheetId : ''"
|
||||
persistent-hint
|
||||
v-if="user"
|
||||
></v-text-field>
|
||||
<v-btn
|
||||
@click="$store.dispatch('enable', { spreadsheetId })"
|
||||
:loading="$store.state.loading"
|
||||
v-if="user"
|
||||
>Enable</v-btn
|
||||
>
|
||||
<v-alert v-if="!user" color="#f2d97c" light icon="mdi-alert"
|
||||
><a href="#!" @click="$store.dispatch('signin')"
|
||||
>Sign in with a Google account</a
|
||||
>
|
||||
to continue</v-alert
|
||||
@@ -67,8 +164,6 @@
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<DocList v-if="user" />
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
@@ -83,12 +178,23 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
docName: "Auto archiver sheet",
|
||||
spreadsheetUrl: "",
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
user() {
|
||||
return this.$store.state.user;
|
||||
},
|
||||
spreadsheetId() {
|
||||
if (
|
||||
this.spreadsheetUrl.startsWith("http") &&
|
||||
this.spreadsheetUrl.split("/").length >= 6
|
||||
) {
|
||||
return this.spreadsheetUrl.split("/")[5];
|
||||
}
|
||||
return this.spreadsheetUrl;
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
12
yarn.lock
12
yarn.lock
@@ -1473,9 +1473,9 @@
|
||||
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
|
||||
|
||||
"@mdi/font@^7.2.96":
|
||||
version "7.2.96"
|
||||
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.2.96.tgz#af800d9fe3b424f85ad45e9baa755bd003ab4986"
|
||||
integrity sha512-e//lmkmpFUMZKhmCY9zdjRe4zNXfbOIJnn6xveHbaV2kSw5aJ5dLXUxcRt1Gxfi7ZYpFLUWlkG2MGSFAiqAu7w==
|
||||
version "7.3.67"
|
||||
resolved "https://registry.npmjs.org/@mdi/font/-/font-7.3.67.tgz"
|
||||
integrity sha512-SWxvzRbUQRfewlIV+OF4/YF4DkeTjMWoT8Hh9yeU/5UBVdJZj9Uf4a9+cXjknSIhIaMxZ/4N1O/s7ojApOOGjg==
|
||||
|
||||
"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
|
||||
version "5.1.1-v1"
|
||||
@@ -3801,9 +3801,9 @@ fs.realpath@^1.0.0:
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
|
||||
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
|
||||
function-bind@^1.1.1:
|
||||
version "1.1.1"
|
||||
|
||||
Reference in New Issue
Block a user