mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-03-25 08:45:04 +00:00
Add a firefox add-on
This commit is contained in:
parent
30b5c9d7f8
commit
3eb9916f1a
@ -1,6 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
inkscape -z -e logo-48.png -w 48 -h 48 logo-only.svg
|
||||||
inkscape -z -e logo-96.png -w 96 -h 96 logo-only.svg
|
inkscape -z -e logo-96.png -w 96 -h 96 logo-only.svg
|
||||||
inkscape -z -e logo-400.png -w 400 -h 400 logo-only.svg
|
inkscape -z -e logo-400.png -w 400 -h 400 logo-only.svg
|
||||||
|
|
||||||
inkscape -z -e logo-mc-96.png -w 96 -h 96 logo-only-mc.svg
|
inkscape -z -e logo-mc-96.png -w 96 -h 96 logo-only-mc.svg
|
||||||
inkscape -z -e logo-mc-400.png -w 400 -h 400 logo-only-mc.svg
|
inkscape -z -e logo-mc-400.png -w 400 -h 400 logo-only-mc.svg
|
||||||
|
@ -105,3 +105,83 @@ Example:
|
|||||||
``` bash
|
``` bash
|
||||||
./ds.sh ~/Downloads/*.pdf
|
./ds.sh ~/Downloads/*.pdf
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Webextension for Docspell
|
||||||
|
|
||||||
|
Idea: Inside the browser click on a PDF and send it to docspell. It is
|
||||||
|
downloaded in the context of your current page. Then handed to an
|
||||||
|
application that pushes it to docspell. There is a browser add-on
|
||||||
|
implementing this in `tools/webextension`. This add-on only works with
|
||||||
|
firefox.
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
This is a bit complicated, since you need to install external tools
|
||||||
|
and the web extension. Both work together.
|
||||||
|
|
||||||
|
#### Install `ds.sh`
|
||||||
|
|
||||||
|
First install the `ds.sh` tool somewhere, maybe `/usr/local/bin` as
|
||||||
|
described above.
|
||||||
|
|
||||||
|
|
||||||
|
#### Install the native part
|
||||||
|
|
||||||
|
Then install the "native" part of the web extension:
|
||||||
|
|
||||||
|
Copy or symlink the `native.py` script into some known location. For
|
||||||
|
example:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
ln -s ~/docspell-checkout/tools/webextension/native/native.py /usr/local/share/docspell/native.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Then copy the `app_manifest.json` to
|
||||||
|
`$HOME/.mozilla/native-messaging-hosts/docspell.json`. For example:
|
||||||
|
|
||||||
|
``` bash
|
||||||
|
cp ~/docspell-checkout/tools/webextension/native/app_manifest.json ~/.mozilla/native-messaging-hosts/docspell.json
|
||||||
|
```
|
||||||
|
|
||||||
|
See
|
||||||
|
[here](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#Manifest_location)
|
||||||
|
for details.
|
||||||
|
|
||||||
|
And you might want to modify this json file, so the path to the
|
||||||
|
`native.py` script is correct (it must be absolute).
|
||||||
|
|
||||||
|
If the `ds.sh` script is in your `$PATH`, then this should
|
||||||
|
work. Otherwise, edit the `native.py` script and change the path to
|
||||||
|
the tool. Or create a file `$HOME/.config/docspell/ds.cmd` whose
|
||||||
|
content is the path to the `ds.sh` script.
|
||||||
|
|
||||||
|
|
||||||
|
#### Install the extension
|
||||||
|
|
||||||
|
An extension file can be build using the `make-xpi.sh` script. But
|
||||||
|
installing it in "standard" firefox won't work, because [Mozilla
|
||||||
|
requires extensions to be signed by
|
||||||
|
them](https://wiki.mozilla.org/Add-ons/Extension_Signing). This means
|
||||||
|
creating an account and going through some process…. So here are two
|
||||||
|
alternatives:
|
||||||
|
|
||||||
|
1. Open firefox and type `about:debugging` in the addressbar. Then
|
||||||
|
click on *'Load Temporary Add-on...'* and select the
|
||||||
|
`manifest.json` file. The extension is now installed. The downside
|
||||||
|
is, that the extension will be removed once firefox is closed.
|
||||||
|
2. Use Firefox ESR, which allows to install Add-ons not signed by
|
||||||
|
Mozilla. But it has to be configured: Open firefox and type
|
||||||
|
`about:config` in the address bar. Search for key
|
||||||
|
`xpinstall.signatures.required` and set it to `false`. This is
|
||||||
|
described on the last paragraph on [this
|
||||||
|
page](https://support.mozilla.org/en-US/kb/add-on-signing-in-firefox).
|
||||||
|
|
||||||
|
When you right click on a file link, there should be a context menu
|
||||||
|
entry *'Docspell Upload Helper'*. The add-on will download this file
|
||||||
|
using the browser and then send the file path to the `native.py`
|
||||||
|
script. This script will in turn call `ds.sh` which finally uploads it
|
||||||
|
to your configured URLs.
|
||||||
|
|
||||||
|
Open the Add-ons page (`Ctrl`+`Shift`+`A`), the new add-on should be
|
||||||
|
there.
|
||||||
|
10
tools/webextension/README.md
Normal file
10
tools/webextension/README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
# Webextension for Docspell
|
||||||
|
|
||||||
|
Idea: Inside the browser click on a PDF and send it to docspell. It is
|
||||||
|
downloaded in the context of your current page. Then handed to an
|
||||||
|
application that finally pushes it to docspell.
|
||||||
|
|
||||||
|
Please see the
|
||||||
|
[microsite](https://eikek.github.io/docspell/doc/tools.html) for
|
||||||
|
instructions or navigate to the corresponding [markdown
|
||||||
|
file](../../modules/microsite/src/main/tut/doc/tools.md#webextension-for-docspell).
|
25
tools/webextension/_locales/de/messages.json
Normal file
25
tools/webextension/_locales/de/messages.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extensionName": {
|
||||||
|
"message": "Docspell Upload Helper",
|
||||||
|
"description": "Name of the extension"
|
||||||
|
},
|
||||||
|
|
||||||
|
"extensionDescription": {
|
||||||
|
"message": "Lädt Dateien vom Browser zu Docspell.",
|
||||||
|
"description": "Description of the extension."
|
||||||
|
},
|
||||||
|
|
||||||
|
"notificationTitle": {
|
||||||
|
"message": "Docspell Antwort",
|
||||||
|
"description": "Title of the click notification."
|
||||||
|
},
|
||||||
|
|
||||||
|
"notificationSuccess": {
|
||||||
|
"message": "Die Datei wurde zu Docspell kopiert.",
|
||||||
|
"description": "Tells the user about the success of the upload."
|
||||||
|
},
|
||||||
|
"notificationFailure": {
|
||||||
|
"message": "Die Datei konnte nicht zu Docspell kopiert werden. Ist es evtl. keine PDF Datei?",
|
||||||
|
"description": "Tells the user about the failure of the upload."
|
||||||
|
}
|
||||||
|
}
|
25
tools/webextension/_locales/en/messages.json
Normal file
25
tools/webextension/_locales/en/messages.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"extensionName": {
|
||||||
|
"message": "Docspell Upload Helper",
|
||||||
|
"description": "Name of the extension"
|
||||||
|
},
|
||||||
|
|
||||||
|
"extensionDescription": {
|
||||||
|
"message": "Copies files from the browser to Docspell.",
|
||||||
|
"description": "Description of the extension."
|
||||||
|
},
|
||||||
|
|
||||||
|
"notificationTitle": {
|
||||||
|
"message": "Docspell Response",
|
||||||
|
"description": "Title of the click notification."
|
||||||
|
},
|
||||||
|
|
||||||
|
"notificationSuccess": {
|
||||||
|
"message": "The file has been uploaded to Docspell.",
|
||||||
|
"description": "Tells the user about the success of the upload."
|
||||||
|
},
|
||||||
|
"notificationFailure": {
|
||||||
|
"message": "The file could not be uploaded to Docspell. Maybe it's not a PDF file?",
|
||||||
|
"description": "Tells the user about the failure of the upload."
|
||||||
|
}
|
||||||
|
}
|
87
tools/webextension/docspell.js
Normal file
87
tools/webextension/docspell.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
function onCreated() {
|
||||||
|
if (browser.runtime.lastError) {
|
||||||
|
console.log(`Error: ${browser.runtime.lastError}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onError(error) {
|
||||||
|
console.log(`Error: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResult(response) {
|
||||||
|
console.log(`Response: ${response}`);
|
||||||
|
var title = browser.i18n.getMessage("notificationTitle") || "Docspell Response";
|
||||||
|
var content = "";
|
||||||
|
if (response == 0) {
|
||||||
|
content = browser.i18n.getMessage("notificationSuccess");
|
||||||
|
} else {
|
||||||
|
content = browser.i18n.getMessage("notificationFailure");
|
||||||
|
}
|
||||||
|
browser.notifications.create({
|
||||||
|
"type": "basic",
|
||||||
|
"iconUrl": browser.extension.getURL("icons/logo-48.png"),
|
||||||
|
"title": title,
|
||||||
|
"message": content
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushDocspell(items) {
|
||||||
|
for (let item of items) {
|
||||||
|
console.log(`Pushing to docspell: ${item.filename}`);
|
||||||
|
var sending = browser.runtime.sendNativeMessage("docspell", item.filename);
|
||||||
|
sending.then(showResult, onError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onStartedDownload(id) {
|
||||||
|
console.log(`Started downloading: ${id}`);
|
||||||
|
browser.downloads.onChanged.addListener(function(delta) {
|
||||||
|
if (delta.id == id) {
|
||||||
|
if (delta.state && delta.state.current === "complete") {
|
||||||
|
console.log(`Download ${delta.id} has completed.`);
|
||||||
|
var searching = browser.downloads.search({id});
|
||||||
|
searching.then(pushDocspell, onError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFailed(error) {
|
||||||
|
console.log(`Download failed: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadAsFile(url) {
|
||||||
|
console.log(`Downloading: ${url}`);
|
||||||
|
var downloading = browser.downloads.download({
|
||||||
|
url: url,
|
||||||
|
saveAs: false,
|
||||||
|
conflictAction : 'uniquify'
|
||||||
|
});
|
||||||
|
downloading.then(onStartedDownload, onFailed);
|
||||||
|
}
|
||||||
|
|
||||||
|
browser.contextMenus.create({
|
||||||
|
id: "separator-2",
|
||||||
|
type: "separator",
|
||||||
|
contexts: ["all"]
|
||||||
|
}, onCreated);
|
||||||
|
|
||||||
|
browser.contextMenus.create({
|
||||||
|
id: "docspell-push",
|
||||||
|
title: "Download and push to Docspell",
|
||||||
|
contexts: ["all"]
|
||||||
|
}, onCreated);
|
||||||
|
|
||||||
|
|
||||||
|
browser.contextMenus.onClicked.addListener(function(info, tab) {
|
||||||
|
switch (info.menuItemId) {
|
||||||
|
case "docspell-push":
|
||||||
|
if (info.linkUrl) {
|
||||||
|
downloadAsFile(info.linkUrl);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Docspell Extension loaded");
|
1
tools/webextension/icons/logo-48.png
Symbolic link
1
tools/webextension/icons/logo-48.png
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../artwork/logo-48.png
|
1
tools/webextension/icons/logo-96.png
Symbolic link
1
tools/webextension/icons/logo-96.png
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../artwork/logo-96.png
|
3
tools/webextension/make-xpi.sh
Executable file
3
tools/webextension/make-xpi.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
zip -9r docspell.xpi _locales/ docspell.js icons/ manifest.json
|
36
tools/webextension/manifest.json
Normal file
36
tools/webextension/manifest.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "__MSG_extensionName__",
|
||||||
|
"description": "__MSG_extensionDescription__",
|
||||||
|
"version": "1.0",
|
||||||
|
|
||||||
|
"permissions": [
|
||||||
|
"notifications",
|
||||||
|
"downloads",
|
||||||
|
"contextMenus",
|
||||||
|
"nativeMessaging"
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
"browser_specific_settings": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "docspell@eikek.github.io",
|
||||||
|
"strict_min_version": "50.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"description": "Downloads a file and pushes it to docspell.",
|
||||||
|
|
||||||
|
"icons": {
|
||||||
|
"48": "icons/logo-48.png",
|
||||||
|
"96": "icons/logo-96.png"
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": [
|
||||||
|
"docspell.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"default_locale": "en"
|
||||||
|
}
|
7
tools/webextension/native/app_manifest.json
Normal file
7
tools/webextension/native/app_manifest.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "docspell",
|
||||||
|
"description": "Docspell Uploads",
|
||||||
|
"path": "/usr/local/share/docspell/native.py",
|
||||||
|
"type": "stdio",
|
||||||
|
"allowed_extensions": [ "docspell@eikek.github.io" ]
|
||||||
|
}
|
51
tools/webextension/native/native.py
Executable file
51
tools/webextension/native/native.py
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
import os
|
||||||
|
from os.path import expanduser
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# The path to the ds.sh tool.
|
||||||
|
try:
|
||||||
|
home = expanduser("~")
|
||||||
|
with open(home + '/.config/docspell/ds.cmd', 'r') as file:
|
||||||
|
DS_SH_CMD = file.read().replace('\n', '')
|
||||||
|
except:
|
||||||
|
DS_SH_CMD="ds.sh"
|
||||||
|
|
||||||
|
|
||||||
|
# Read a message from stdin and decode it.
|
||||||
|
def get_message():
|
||||||
|
raw_length = sys.stdin.read(4)
|
||||||
|
if not raw_length:
|
||||||
|
sys.exit(0)
|
||||||
|
message_length = struct.unpack('=I', raw_length)[0]
|
||||||
|
message = sys.stdin.read(message_length)
|
||||||
|
return json.loads(message)
|
||||||
|
|
||||||
|
|
||||||
|
# Encode a message for transmission, given its content.
|
||||||
|
def encode_message(message_content):
|
||||||
|
encoded_content = json.dumps(message_content)
|
||||||
|
encoded_length = struct.pack('=I', len(encoded_content))
|
||||||
|
return {'length': encoded_length, 'content': encoded_content}
|
||||||
|
|
||||||
|
|
||||||
|
# Send an encoded message to stdout.
|
||||||
|
def send_message(encoded_message):
|
||||||
|
sys.stdout.write(encoded_message['length'])
|
||||||
|
sys.stdout.write(encoded_message['content'])
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
filename = get_message()
|
||||||
|
FNULL = open(os.devnull, 'w')
|
||||||
|
rc = subprocess.call(args=[DS_SH_CMD, filename], stdout=FNULL, stderr=FNULL, close_fds=True)
|
||||||
|
os.remove(filename)
|
||||||
|
if rc == 0:
|
||||||
|
send_message(encode_message(rc))
|
||||||
|
else:
|
||||||
|
send_message(encode_message(rc))
|
Loading…
x
Reference in New Issue
Block a user