citadel

My dotfiles, scripts and nix configs
git clone git://jb55.com/citadel
Log | Files | Refs | README | LICENSE

pdf2remarkable (5238B)


      1 #!/usr/bin/env bash
      2 # Transfer PDF file(s) to a reMarkable
      3 # Adrian Daerr 2017/2018 - public domain
      4 #
      5 # - The files will appear in reMarkable's top-level "My Files" directory,
      6 # - After finishing all transfers, you have to restart the xochitl
      7 #   service on the tablet in order to force a scan of its document
      8 #   directory ${xochitldir} (so that you see the newly transferred
      9 #   files), e.g. by sending the tablet the following command:
     10 #     ssh remarkable systemctl restart xochitl
     11 #
     12 # Disclaimer and liability limitation:
     13 # [see also all-caps text borrowed from GPL below]
     14 # - This is a dirty hack based on superficial reverse-engineering.
     15 # - Expect this script to break at any time, especially upon a
     16 #   reMarkable system upgrade
     17 # - I am not responsible for any damage caused by this script,
     18 #   including (but not limited to) bricking your reMarkable, erasing
     19 #   your documents etc. YOU ARE USING THIS SOFTWARE ON YOUR OWN RISK.
     20 #
     21 # Disclaimer of Warranty.
     22 #
     23 # THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
     24 # APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
     25 # COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
     26 # “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
     27 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     28 # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE
     29 # RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
     30 # SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
     31 # NECESSARY SERVICING, REPAIR OR CORRECTION.
     32 #
     33 # Limitation of Liability.
     34 #
     35 # IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
     36 # WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
     37 # MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE
     38 # LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
     39 # INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
     40 # INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
     41 # DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
     42 # YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE
     43 # WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS
     44 # BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
     45 #
     46 # Prerequisites:
     47 #
     48 # * The ssh access has to be configured under the host alias 'remarkable',
     49 # e.g. by putting the following in .ssh/config :
     50 # | host remarkable
     51 # |        Hostname 10.11.99.1
     52 # |        User root
     53 # |        ForwardX11 no
     54 # |        ForwardAgent no
     55 # See also the variable "xochitldir" below
     56 #
     57 # * Beyond core utilities (date, basename,...), the following software
     58 #   has to be installed on the host computer:
     59 # - uuidgen
     60 # - imagemagick (or graphicsmagick)
     61 
     62 set -e
     63 
     64 # This is where ssh will try to copy the files associated with the document
     65 xochitldir=remarkable:.local/share/remarkable/xochitl/
     66 
     67 # Check if we have something to do
     68 if [ $# -lt 1 ]; then
     69     echo "Transfer PDF document to a reMarkable tablet"
     70     echo "usage: $(basename $0) path-to-pdf-file [path-to-pdf-file]..."
     71     exit 1
     72 fi
     73 
     74 # Create directory where we prepare the files as the reMarkable expects them
     75 tmpdir=$(mktemp -d)
     76 
     77 # Loop over the command line arguments,
     78 # which we expect are paths to the PDF files to be transfered
     79 for pdfname in "$@" ; do
     80 
     81 # reMarkable documents appear to be identified by universally unique IDs (UUID),
     82 # so we generate one for the document at hand
     83 uuid=$(uuidgen)
     84 
     85 # Copy the PDF file itself
     86 cp "$pdfname" "${tmpdir}/${uuid}.pdf"
     87 
     88 # Add metadata
     89 # The lastModified item appears to contain the date in milliseconds since Epoch
     90 cat <<EOF >>"${tmpdir}/${uuid}.metadata"
     91 {
     92     "deleted": false,
     93     "lastModified": "$(date +%s)000",
     94     "metadatamodified": false,
     95     "modified": false,
     96     "parent": "",
     97     "pinned": false,
     98     "synced": false,
     99     "type": "DocumentType",
    100     "version": 1,
    101     "visibleName": "$(basename "$pdfname" .pdf)"
    102 }
    103 EOF
    104 
    105 # Add content information
    106 cat <<EOF >"${tmpdir}/${uuid}.content"
    107 {
    108     "extraMetadata": {
    109     },
    110     "fileType": "pdf",
    111     "fontName": "",
    112     "lastOpenedPage": 0,
    113     "lineHeight": -1,
    114     "margins": 100,
    115     "pageCount": 1,
    116     "textScale": 1,
    117     "transform": {
    118         "m11": 1,
    119         "m12": 1,
    120         "m13": 1,
    121         "m21": 1,
    122         "m22": 1,
    123         "m23": 1,
    124         "m31": 1,
    125         "m32": 1,
    126         "m33": 1
    127     }
    128 }
    129 EOF
    130 
    131 # Add cache directory
    132 mkdir "${tmpdir}/${uuid}.cache"
    133 
    134 # Add highlights directory
    135 mkdir "${tmpdir}/${uuid}.highlights"
    136 
    137 # Add thumbnails directory
    138 mkdir "${tmpdir}/${uuid}.thumbnails"
    139 
    140 # Generate preview thumbnail for the first page
    141 # Different sizes were found (possibly depending on whether created by
    142 # the reMarkable itself or some synchronization app?): 280x374 or
    143 # 362x512 pixels. In any case the thumbnails appear to be baseline
    144 # jpeg images - JFIF standard 1.01, resolution (DPI), density 228x228
    145 # or 72x72, segment length 16, precision 8, frames 3
    146 #
    147 # The following will look nice only for PDFs that are higher than about 32mm.
    148 convert -limit thread 1 -density 300 "$pdfname"'[0]' -colorspace Gray -separate -average -shave 5%x5% -resize 280x374 "${tmpdir}/${uuid}.thumbnails/0.jpg"
    149 
    150 # Transfer files
    151 echo "Transferring $pdfname$ as $uuid$"
    152 scp -r "${tmpdir}"/* ${xochitldir}
    153 rm -rf "${tmpdir:?}"/*
    154 done
    155 
    156 rm -rf "${tmpdir}"