mirror of
https://github.com/andwati/kget-capture.git
synced 2026-10-18 03:02:56 +00:00
Add a curl/wget one-line installer and popup setup detection
Add install-remote.sh, which fetches the latest release and runs its install.sh so setup no longer needs a git clone. The popup now probes the native host with a "ping" action on open and, if it's not registered yet, shows the one-liner (with copy-to-clipboard) instead of the auto-capture toggle -- so a Web Store install can be completed end-to-end by clicking the extension icon and pasting one command.
This commit is contained in:
@@ -14,6 +14,8 @@ browser's built-in downloader.
|
||||
- Linux with KGet installed and running (or set to autostart)
|
||||
- A Chromium-based browser: Chrome, Chromium, Brave, Vivaldi, or Edge
|
||||
- `python3`, `dbus-send`
|
||||
- `curl` or `wget`, for the one-line remote installer below (skip if you'd
|
||||
rather download and run `install.sh` yourself)
|
||||
- `notify-send`, optional, for the completion notification
|
||||
- `kwriteconfig6` (KDE Frameworks), optional, silences KGet's own duplicate
|
||||
notification
|
||||
@@ -49,22 +51,26 @@ without them.)
|
||||
|
||||
1. Install the extension from the Chrome Web Store: **`<CHROME_WEB_STORE_URL>`**
|
||||
*(placeholder, fill in once the listing is live)*.
|
||||
2. Install the native messaging host that lets the extension talk to KGet.
|
||||
Download and extract `kget-capture-vX.Y.Z.zip` (the source archive, not
|
||||
`kget-capture-extension-vX.Y.Z.zip`) from the
|
||||
[Releases page](https://github.com/andwati/kget-capture/releases), then
|
||||
from inside that folder:
|
||||
2. Click the extension's toolbar icon. The popup detects that the native
|
||||
messaging host isn't set up yet and shows a one-line command; run it in a
|
||||
terminal, then click "I ran it, check again" in the popup:
|
||||
```bash
|
||||
./install.sh
|
||||
curl -fsSL https://raw.githubusercontent.com/andwati/kget-capture/main/install-remote.sh | bash
|
||||
```
|
||||
(or with `wget`: `wget -qO- https://raw.githubusercontent.com/andwati/kget-capture/main/install-remote.sh | bash`)
|
||||
|
||||
This downloads the latest release and runs its `install.sh`, which
|
||||
registers the native host for every supported browser it finds installed
|
||||
and prints any remaining setup warnings. No git clone required. If you'd
|
||||
rather run it yourself: download and extract `kget-capture-vX.Y.Z.zip`
|
||||
(the source archive, not `kget-capture-extension-vX.Y.Z.zip`) from the
|
||||
[Releases page](https://github.com/andwati/kget-capture/releases), then
|
||||
from inside that folder run `./install.sh` directly.
|
||||
3. Open your browser's download settings (`chrome://settings/downloads`,
|
||||
`brave://settings/downloads`, etc.) and turn **off** "Ask where to save
|
||||
each file before downloading". Chrome shows this dialog itself, before the
|
||||
extension gets a chance to intercept the download, so this one-time change
|
||||
is required.
|
||||
|
||||
`install.sh` registers the native host for every supported browser it finds
|
||||
installed and prints any remaining setup warnings.
|
||||
is required (no extension API can do it for you).
|
||||
|
||||
### Building from source
|
||||
|
||||
@@ -131,6 +137,9 @@ Prebuilt releases are published on the
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
- **`install-remote.sh` fails to look up the latest release?** It queries
|
||||
GitHub's API, which rate-limits unauthenticated requests (60/hour per IP);
|
||||
wait a bit, or fall back to the manual `install.sh` steps in Install above.
|
||||
- **Check native host registration:** confirm
|
||||
`~/.config/<browser>/NativeMessagingHosts/com.kget_capture.host.json` exists
|
||||
and its `path` points at an executable file
|
||||
|
||||
+36
-1
@@ -1,5 +1,5 @@
|
||||
body {
|
||||
width: 240px;
|
||||
width: 320px;
|
||||
padding: 12px;
|
||||
font-family: system-ui, sans-serif;
|
||||
font-size: 13px;
|
||||
@@ -36,3 +36,38 @@ h1 {
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cmd-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.cmd-row code {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
background: #f0f0f0;
|
||||
padding: 4px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.cmd-row button {
|
||||
flex: none;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#recheck-setup {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,19 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>KGet Capture</h1>
|
||||
|
||||
<div id="setup-needed" hidden>
|
||||
<p class="hint">One-time setup needed: KGet Capture needs a small local
|
||||
helper installed before it can talk to KGet. Run this in a terminal:</p>
|
||||
<div class="cmd-row">
|
||||
<code id="setup-command"></code>
|
||||
<button id="copy-command" type="button">Copy</button>
|
||||
</div>
|
||||
<p class="status" id="copy-feedback"></p>
|
||||
<button id="recheck-setup" type="button">I ran it, check again</button>
|
||||
</div>
|
||||
|
||||
<div id="ready" hidden>
|
||||
<label class="toggle-row">
|
||||
<input type="checkbox" id="auto-capture-toggle">
|
||||
<span>Auto-capture all downloads</span>
|
||||
@@ -17,6 +30,8 @@
|
||||
dialog itself, before this extension can intercept anything.
|
||||
<button id="open-download-settings" type="button">Turn off Chrome's download prompt</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,14 +1,61 @@
|
||||
const NATIVE_HOST = "com.kget_capture.host";
|
||||
const INSTALL_COMMAND =
|
||||
"curl -fsSL https://raw.githubusercontent.com/andwati/kget-capture/main/install-remote.sh | bash";
|
||||
|
||||
const setupPanel = document.getElementById("setup-needed");
|
||||
const readyPanel = document.getElementById("ready");
|
||||
const checkbox = document.getElementById("auto-capture-toggle");
|
||||
const statusLine = document.getElementById("status-line");
|
||||
const copyFeedback = document.getElementById("copy-feedback");
|
||||
|
||||
function renderStatus(enabled) {
|
||||
statusLine.textContent = `Auto-capture: ${enabled ? "ON" : "OFF"}`;
|
||||
}
|
||||
|
||||
function showReady() {
|
||||
setupPanel.hidden = true;
|
||||
readyPanel.hidden = false;
|
||||
chrome.storage.local.get({ autoCaptureEnabled: true }).then(({ autoCaptureEnabled }) => {
|
||||
checkbox.checked = autoCaptureEnabled;
|
||||
renderStatus(autoCaptureEnabled);
|
||||
});
|
||||
}
|
||||
|
||||
function showSetupNeeded() {
|
||||
document.getElementById("setup-command").textContent = INSTALL_COMMAND;
|
||||
readyPanel.hidden = true;
|
||||
setupPanel.hidden = false;
|
||||
}
|
||||
|
||||
// The native host is only reachable once install.sh (or install-remote.sh)
|
||||
// has registered it -- sendNativeMessage fails with a lastError like
|
||||
// "Specified native messaging host not found" until then, which is exactly
|
||||
// the signal we want to gate the rest of the popup on.
|
||||
function checkNativeHost() {
|
||||
chrome.runtime.sendNativeMessage(NATIVE_HOST, { action: "ping" }, () => {
|
||||
if (chrome.runtime.lastError) {
|
||||
showSetupNeeded();
|
||||
} else {
|
||||
showReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
checkNativeHost();
|
||||
|
||||
document.getElementById("recheck-setup").addEventListener("click", checkNativeHost);
|
||||
|
||||
document.getElementById("copy-command").addEventListener("click", async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(INSTALL_COMMAND);
|
||||
copyFeedback.textContent = "Copied to clipboard.";
|
||||
} catch (e) {
|
||||
copyFeedback.textContent = "Couldn't copy -- select and copy the command manually.";
|
||||
}
|
||||
setTimeout(() => {
|
||||
copyFeedback.textContent = "";
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
checkbox.addEventListener("change", () => {
|
||||
chrome.storage.local.set({ autoCaptureEnabled: checkbox.checked });
|
||||
|
||||
Executable
+60
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
# Fetches the latest release source archive and runs install.sh from it, so
|
||||
# setup doesn't require a git clone:
|
||||
#
|
||||
# curl -fsSL https://raw.githubusercontent.com/andwati/kget-capture/main/install-remote.sh | bash
|
||||
# wget -qO- https://raw.githubusercontent.com/andwati/kget-capture/main/install-remote.sh | bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO="andwati/kget-capture"
|
||||
|
||||
fetch_stdout() {
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL "$1"
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -qO- "$1"
|
||||
else
|
||||
echo "ERROR: this installer needs 'curl' or 'wget' on PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
fetch_to_file() {
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -fsSL "$1" -o "$2"
|
||||
else
|
||||
wget -qO "$2" "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Looking up the latest release..."
|
||||
tag="$(fetch_stdout "https://api.github.com/repos/$REPO/releases/latest" \
|
||||
| grep -m1 '"tag_name"' | sed -E 's/.*"tag_name": *"([^"]+)".*/\1/')"
|
||||
if [ -z "$tag" ]; then
|
||||
echo "ERROR: couldn't determine the latest release tag from GitHub." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Latest release: $tag"
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "ERROR: 'python3' is required but not found on PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tmp_dir="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp_dir"' EXIT
|
||||
|
||||
zip_path="$tmp_dir/kget-capture.zip"
|
||||
zip_url="https://github.com/$REPO/releases/download/$tag/kget-capture-$tag.zip"
|
||||
echo "Downloading $zip_url..."
|
||||
fetch_to_file "$zip_url" "$zip_path"
|
||||
|
||||
echo "Extracting..."
|
||||
src_dir="$tmp_dir/src"
|
||||
python3 -c "
|
||||
import sys, zipfile
|
||||
zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])
|
||||
" "$zip_path" "$src_dir"
|
||||
|
||||
echo "Running install.sh..."
|
||||
bash "$src_dir/install.sh"
|
||||
@@ -154,7 +154,17 @@ def spawn_notifier(transfer_path, dest):
|
||||
|
||||
def main():
|
||||
message = read_message()
|
||||
if not message or message.get("action") != "addTransfer" or "url" not in message:
|
||||
if not message:
|
||||
write_message({"ok": False, "error": "invalid request"})
|
||||
return
|
||||
|
||||
# The extension popup uses this to detect whether the native host is
|
||||
# installed/registered at all, distinct from whether a transfer succeeds.
|
||||
if message.get("action") == "ping":
|
||||
write_message({"ok": True})
|
||||
return
|
||||
|
||||
if message.get("action") != "addTransfer" or "url" not in message:
|
||||
write_message({"ok": False, "error": "invalid request"})
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user