mirror of
https://github.com/jlengrand/RemarkablePocket.git
synced 2026-03-10 08:41:19 +00:00
Raspberry Pi support
This commit is contained in:
69
README.md
69
README.md
@@ -1,6 +1,8 @@
|
||||

|
||||
|
||||
*Remarkable Pocket* synchronizes articles from [Pocket](https://getpocket.com) to your [Remarkable](https://remarkable.com/) tablet. It can be run on your computer or on a server. Because it does not run on the device itself this approach saves battery life, and is resistant to Remarkable software updates.
|
||||
*Remarkable Pocket* synchronizes articles from [Pocket](https://getpocket.com) to
|
||||
your [Remarkable](https://remarkable.com/) tablet. It can be run on your computer or on a server. Because it does not
|
||||
run on the device itself this approach saves battery life, and is resistant to Remarkable software updates.
|
||||
|
||||
An example run of the program can be found below:
|
||||
|
||||
@@ -32,28 +34,48 @@ An example run of the program can be found below:
|
||||
</details>
|
||||
|
||||
## Features
|
||||
|
||||
- **No installation required.** The application can be run with a single command.
|
||||
- **Works on Remarkable 1 and 2.**
|
||||
- **Full support for images, code blocks, and formulas.**
|
||||
- **Articles are downloaded as epubs.** This allows you to customize the font, font size, margins, etc.
|
||||
- **Automatically archive read articles on Pocket.** When you finish reading an article and close it while on the last page, it will be automatically deleted from the Remarkable and archived on Pocket. A new unread article will be downloaded in its place.
|
||||
- **Download articles from Pocket with a given tag.** If a `tag-filter` (see [Configuration](#configuration)) is supplied then only articles with that tag will be downloaded.
|
||||
- **Automatically archive read articles on Pocket.** When you finish reading an article and close it while on the last
|
||||
page, it will be automatically deleted from the Remarkable and archived on Pocket. A new unread article will be
|
||||
downloaded in its place.
|
||||
- **Download articles from Pocket with a given tag.** If a `tag-filter` (see [Configuration](#configuration)) is
|
||||
supplied then only articles with that tag will be downloaded.
|
||||
|
||||
## Usage
|
||||
The easiest way to run the application is using Docker. First install Docker for your platform from https://docs.docker.com/get-docker/. Then run the following command to start the application on Linux or Mac (I have not tested it on Windows yet):
|
||||
|
||||
The easiest way to run the application is using Docker. First install Docker for your platform
|
||||
from https://docs.docker.com/get-docker/. Then run the following command to start the application on Linux or Mac (I
|
||||
have not tested it on Windows yet):
|
||||
|
||||
```
|
||||
touch ~/.remarkable-pocket ~/.rmapi && mkdir -p ~/.rmapi-cache && docker run -it --env TZ=Europe/Amsterdam -p 65112:65112 -v ~/.remarkable-pocket:/root/.remarkable-pocket -v ~/.rmapi:/root/.rmapi -v ~/.rmapi-cache:/root/.cache/rmapi ghcr.io/nov1n/remarkable-pocket:0.1.0
|
||||
touch ~/.remarkable-pocket ~/.rmapi && mkdir -p ~/.rmapi-cache && docker run -it --env TZ=Europe/Amsterdam -p 65112:65112 -v ~/.remarkable-pocket:/root/.remarkable-pocket -v ~/.rmapi:/root/.rmapi -v ~/.rmapi-cache:/root/.cache/rmapi ghcr.io/nov1n/remarkable-pocket:0.2.0
|
||||
```
|
||||
The first time you run the application, you will be asked to authorize Pocket and Remarkable Cloud. Once you have done this subsequent runs will read the credentials from the `~/.remarkable-pocket` and `~/.rmapi` file. You can also change the timezone in the command to match your location.
|
||||
|
||||
The first time you run the application, you will be asked to authorize Pocket and Remarkable Cloud. Once you have done
|
||||
this subsequent runs will read the credentials from the `~/.remarkable-pocket` and `~/.rmapi` file. You can also change
|
||||
the timezone in the command to match your location.
|
||||
|
||||
By default, articles are synchronized to the `/Pocket/` directory on the Remarkable every 60 minutes.
|
||||
|
||||
*TIP:* If you want to launch the program on startup and keep it running in the background you can use *launchd* (on Mac) or *systemd* (on Linux). On Mac copy [this](nl.carosi.remarkable-pocket.plist) file to `~/Library/LaunchAgents/` followed by: `launchctl load -w nl.carosi.remarkable-pocket.plist`. Logs will be sent to `~/.remarkable-pocket.log`.
|
||||
*TIP:* If you want to launch the program on startup and keep it running in the background you can use *launchd* (on Mac)
|
||||
or *systemd* (on Linux). On Mac copy [this](nl.carosi.remarkable-pocket.plist) file to `~/Library/LaunchAgents/`
|
||||
followed by: `launchctl load -w nl.carosi.remarkable-pocket.plist`. Logs will be sent to `~/.remarkable-pocket.log`.
|
||||
|
||||
## Raspberry Pi
|
||||
|
||||
There is also a Docker image available for the Raspberry Pi, so the command in [Usage](#usage) will work. You do need a
|
||||
browser to complete the authentication flow. If your Pi runs without a screen I recommend using a VNC client when
|
||||
running the program for the first time.
|
||||
|
||||
## Configuration
|
||||
The default configuration can be changed by providing command-line arguments. Simply append these to the `docker run` command. Below is a list of all available options.
|
||||
|
||||
The default configuration can be changed by providing command-line arguments. Simply append these to the `docker run`
|
||||
command. Below is a list of all available options.
|
||||
|
||||
```
|
||||
Usage: remarkable-pocket [-hnorV] [-d=<storageDir>] [-f=<tagFilter>] [-i=<interval>] [-l=<articleLimit>]
|
||||
Synchronizes articles from Pocket to the Remarkable tablet.
|
||||
@@ -76,28 +98,45 @@ Synchronizes articles from Pocket to the Remarkable tablet.
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
- Articles behind a paywall cannot be downloaded.
|
||||
- Articles on websites with sophisticated DDOS protection cannot be downloaded.
|
||||
- Articles on websites with DDOS protection or captcha cannot be downloaded.
|
||||
- Articles that use javascript to load the content cannot be downloaded.
|
||||
|
||||
## Build Instructions
|
||||
The project uses Gradle as a build tool and can be built using the `gradle build` command. This will generate jars in `build/libs/`. To run the jar, use the `java -jar build/libs/remarkable-pocket-x.x.x.jar` command, replacing `x.x.x` with the correct version.
|
||||
|
||||
The project uses Gradle as a build tool and can be built using the `gradle build` command. This will generate jars
|
||||
in `build/libs/`. To run the jar, use the `java -jar build/libs/remarkable-pocket-x.x.x.jar` command, replacing `x.x.x`
|
||||
with the correct version.
|
||||
|
||||
### Building docker
|
||||
To build the docker image run `gradle jib`. This will use a dynamically generated Dockerfile based on the configuration in the `jib` section of the `build.gradle` file. To run the image, see the command in the [Usage](#usage) section.
|
||||
|
||||
To build the docker image run `gradle jib`. This will use a dynamically generated Dockerfile based on the configuration
|
||||
in the `jib` section of the `build.gradle` file. To run the image, see the command in the [Usage](#usage) section.
|
||||
|
||||
### Other package formats
|
||||
If you would like to package the application in another format e.g. `deb`, `nix` or `AUR`, I'm happy to review a Pull Request.
|
||||
|
||||
If you would like to package the application in another format e.g. `deb`, `nix` or `AUR`, I'm happy to review a Pull
|
||||
Request.
|
||||
|
||||
### Disclaimer
|
||||
RemarkablePocket uses rmapi to connect to Remarkable cloud. The newly released sync protocol is not yet tested through and may contain bugs. As [recommended](https://github.com/juruen/rmapi#warning-experimental-support-for-the-new-sync-protocol) by rmapi please make sure you have a backup of your files.
|
||||
|
||||
RemarkablePocket uses rmapi to connect to Remarkable cloud. The newly released sync protocol is not yet tested through
|
||||
and may contain bugs.
|
||||
As [recommended](https://github.com/juruen/rmapi#warning-experimental-support-for-the-new-sync-protocol) by rmapi please
|
||||
make sure you have a backup of your files.
|
||||
|
||||
## Thanks
|
||||
|
||||
- https://epub.press/ for providing a free epub generator API. Consider donating to support this project.
|
||||
- https://github.com/juruen/rmapi for providing a client for the Remarkable Cloud.
|
||||
|
||||
## Support
|
||||
[](https://www.buymeacoffee.com/nov1n) if you want to say thanks. :-)
|
||||
|
||||
[](https://www.buymeacoffee.com/nov1n)
|
||||
if you want to say thanks. :-)
|
||||
|
||||
## Disclaimer
|
||||
The author(s) and contributor(s) are not associated with reMarkable AS, Norway. reMarkable is a registered trademark of reMarkable AS in some countries. Please see https://remarkable.com for their product.
|
||||
|
||||
The author(s) and contributor(s) are not associated with reMarkable AS, Norway. reMarkable is a registered trademark of
|
||||
reMarkable AS in some countries. Please see https://remarkable.com for their product.
|
||||
|
||||
20
build.gradle
20
build.gradle
@@ -1,13 +1,13 @@
|
||||
plugins {
|
||||
id "org.springframework.boot" version "2.5.5"
|
||||
id "io.spring.dependency-management" version "1.0.11.RELEASE"
|
||||
id "com.google.cloud.tools.jib" version "3.1.4"
|
||||
id "com.google.cloud.tools.jib" version "3.3.0"
|
||||
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||
id "java"
|
||||
}
|
||||
|
||||
group = "nl.carosi"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
@@ -17,11 +17,21 @@ java {
|
||||
|
||||
jib {
|
||||
from {
|
||||
image = "azul/zulu-openjdk:17-jre-headless"
|
||||
image = "eclipse-temurin:17-jre"
|
||||
platforms {
|
||||
platform {
|
||||
architecture = 'amd64'
|
||||
os = 'linux'
|
||||
}
|
||||
platform {
|
||||
architecture = 'arm'
|
||||
os = 'linux'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
container {
|
||||
jvmFlags = ["-Xshare:auto", "-XX:TieredStopAtLevel=1", "-XX:CICompilerCount=1", "-XX:+UseSerialGC", "-Xmx512m"]
|
||||
format = "OCI"
|
||||
}
|
||||
to {
|
||||
image = "ghcr.io/nov1n/remarkable-pocket"
|
||||
@@ -30,7 +40,7 @@ jib {
|
||||
extraDirectories {
|
||||
paths = 'src/main/jib'
|
||||
permissions = [
|
||||
'/usr/local/bin/rmapi': '755'
|
||||
'/usr/local/bin/rmapi*': '755'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
12
docker-compose.yml
Normal file
12
docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
remarkable-pocket:
|
||||
image: ghcr.io/nov1n/remarkable-pocket:0.2.0
|
||||
restart: always
|
||||
ports:
|
||||
- 65112:65112
|
||||
volumes:
|
||||
- ~/.remarkable-pocket:/root/.remarkable-pocket
|
||||
- ~/.rmapi:/root/.rmapi
|
||||
- ~/.rmapi-cache:/root/.cache/rmapi
|
||||
@@ -8,7 +8,7 @@
|
||||
<array>
|
||||
<string>/bin/sh</string>
|
||||
<string>-c</string>
|
||||
<string>while ! /usr/local/bin/docker version > /dev/null 2>&1; do sleep 5; done && /usr/local/bin/docker run --env TZ=Europe/Amsterdam -v ~/.remarkable-pocket:/root/.remarkable-pocket -v ~/.rmapi:/root/.rmapi -v ~/.rmapi-cache:/root/.cache/rmapi ghcr.io/nov1n/remarkable-pocket:0.1.0 1>>$HOME/.remarkable-pocket.log 2>&1</string>
|
||||
<string>while ! /usr/local/bin/docker version > /dev/null 2>&1; do sleep 5; done && /usr/local/bin/docker run --env TZ=Europe/Amsterdam -v ~/.remarkable-pocket:/root/.remarkable-pocket -v ~/.rmapi:/root/.rmapi -v ~/.rmapi-cache:/root/.cache/rmapi ghcr.io/nov1n/remarkable-pocket:0.2.0 1>>$HOME/.remarkable-pocket.log 2>&1</string>
|
||||
</array>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
|
||||
@@ -84,13 +84,15 @@ public class PocketAuthenticator {
|
||||
String authUrl = factory.getAuthUrl();
|
||||
LOG.info("Visit {} and authorize this application.\n", authUrl);
|
||||
try {
|
||||
boolean terminated = execService.awaitTermination(1, MINUTES);
|
||||
boolean terminated = execService.awaitTermination(5, MINUTES);
|
||||
if (!terminated) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
LOG.info("Pocket authorization timed out. Please try again.");
|
||||
System.exit(1);
|
||||
// System.exit doesn't work here. I suspect there is a deadlock in the
|
||||
// 'logStream' method where it blocks on stdin.
|
||||
Runtime.getRuntime().halt(1);
|
||||
}
|
||||
|
||||
return factory.create();
|
||||
|
||||
@@ -31,7 +31,11 @@ public class RemarkableApi {
|
||||
"WARNING!!!",
|
||||
" Using the new 1.5 sync",
|
||||
" Make sure you have a backup");
|
||||
private static final String RMAPI_EXECUTABLE = "/usr/local/bin/rmapi";
|
||||
private static final String RMAPI_EXECUTABLE =
|
||||
"/usr/local/bin/rmapi"
|
||||
+ (new File("/.dockerenv").exists()
|
||||
? ("_" + System.getProperty("os.arch"))
|
||||
: "");
|
||||
private final String rmStorageDir;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import picocli.CommandLine.Option;
|
||||
sortOptions = false,
|
||||
usageHelpAutoWidth = true,
|
||||
// TODO: Read from gradle.properties
|
||||
version = "0.1.0",
|
||||
version = "0.2.0",
|
||||
mixinStandardHelpOptions = true)
|
||||
class SyncCommand implements Callable<Integer> {
|
||||
@Option(
|
||||
@@ -97,6 +97,9 @@ class SyncCommand implements Callable<Integer> {
|
||||
public Integer call() {
|
||||
ensureConnected(System.err::println);
|
||||
|
||||
// Handle sigterm (^C)
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(() -> Runtime.getRuntime().halt(1)));
|
||||
|
||||
Map<String, Object> cliProperties =
|
||||
Map.ofEntries(
|
||||
entry("pocket.archive-read", Boolean.toString(!noArchive)),
|
||||
|
||||
BIN
src/main/jib/usr/local/bin/rmapi_arm
Executable file
BIN
src/main/jib/usr/local/bin/rmapi_arm
Executable file
Binary file not shown.
Reference in New Issue
Block a user