Knowledge Base

Preserving for the future: Shell scripts, AoC, and more

Sword module repository

This project isn't a mirror, per se, but it is a small repository. I host for myself a small subset of the available SWORD Project modules.

I wanted a private repository for my mobile devices (only places where I use the modules), in case the upstream sources ever disappear. At least one module has, see the fascinating thread.

I took my archive of the BibleTimeMini (now gone too, from where I got it in the Play Store) /.sword/ directory on my old android device and wrote a script to turn that into the modules, but I've since learned how to read the InstallMgr.conf and visit the ftp sites and retrieve modules directly.

files/2024/listings/make-zips-from-sword-dir.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/sh
# File: generate-zips-from-sword-dir.sh
# Location: server3:/mnt/mirror/sword
# Author: bgstack15
# Startdate: 2024-06-06-5 17:21
# SPDX-License-Identifier: GPL-3.0-only
# Title: Generate Zips from Existing .Sword Dir
# Purpose: convert a .sword dir back into modules for loading into my sword library
# History:
# Usage: Use when I am converting an existing .sword dir to set of modules for the repo.
# Reference:
#    https://serverfault.com/questions/108024/silent-7za-compression/827833#827833
# Improve:
# Dependencies:
#    7za
# Documentation: /mnt/public/Support/Programs/BibleTimeMini/sword-repo-readme.md

SWORD_DIR="${SWORD_DIR:-$( dirname $( readlink -f "${0}" ) )}"
OUTDIR="${OUTDIR:-${SWORD_DIR}}"

cd "${SWORD_DIR}"
{ test ! -d mods.d || test ! -d modules ; } && {
   echo "Error: this is not a sword directory. Aborted." 1>&2
   exit 1
}
for mod in mods.d/*.conf ;
do
   mod_name="$( grep -h -E '^\s*\[' "${mod}" | head -n1 | tr -d '[]\r' )"
   datapath="$( awk -F'=' '$1~/DataPath/{print $2}' "${mod}" | sed -r -e 's@^\.\/@@;' )"
    # OpenHymnal has an incorrect DataPath so drilling up solves that.
   _x=0
   _max=4
   while { ! test -e "${datapath}" && test $_x -lt $_max ; } ; do datapath="$( dirname "${datapath}" )" ; echo "For ${mod}, checking ${datapath}" 1>&2 ; _x=$((_x+1)) ; done ;
   #test $_x -ge $_max && { echo "Cannot build ${mod_name}.zip because datapath is broken. Skipping..." 1>&2 ; continue ;}
   echo "${mod_name}.zip" "${mod}" "${datapath}"
   7za -bsp0 -bso0 a "${OUTDIR%%/}/${mod_name}.zip" "${mod}" "${datapath}"
done

So now that I have the module zip files, I place them in /mnt/mirror/sword/modules/ and run this script.

files/2024/listings/generate-sword-repo.sh (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/sh
# File: generate-sword-repo.sh
# Location: server3:/mnt/mirror/sword
# Author: bgstack15
# Startdate: 2024-06-06-5 14:33
# SPDX-License-Identifier: GPL-3.0-only
# Title: Generate Sword Repo and Web Page
# Purpose: generate mods.tar.gz for sword repo
# History:
#    2024-06-13-5 12:58 count number of modules
# Usage: Manually when I want to update the repo metadata based on modules available.
# Reference:
# Improve:
#    get icons for Bible, book, other?
#    use all headers
# Dependencies:
#    prebuilt manifest.json
#    7za
# Documentation: /mnt/public/Support/Programs/BibleTimeMini/sword-repo-readme.md

REPO_DIR="${REPODIR:-/mnt/mirror/sword}"
MODULES_DIR="${MODULES_DIR:-${REPO_DIR%%/}/modules}"

generate_mods_d_tar_gz() {
   rm -rf "${REPO_DIR:-NOTHINGTODEL}/mods.d/"*
   rmdir "${REPO_DIR:-NOTHINGTODEL}/mods.d"
   cd "${REPO_DIR}"
   for zip in "${MODULES_DIR}"/*zip ;
   do
      7za -bsp0 -bso0 x "${zip}" mods.d
   done
   rm -f "${REPO_DIR:-NOTHINGTODEL}/mods.d.tar.gz"
   tar -zcf mods.d.tar.gz mods.d
}

generate_web() {
   echo "stub"
   {
      echo "<html>"
      echo "<head>"
      echo "<link rel='stylesheet' href='sword.css'>"
      echo '<meta name="viewport" content="width=device-width, initial-scale=1">'
      echo "<title>Example sword library</title>"
      echo "</head>"
      echo "<body>"
      echo "<h1><img src='bgstack15.png' class='headimg'>Example sword library</h1>"
      echo "<h2>Installing this repo</h2>"
      echo "<h3>AndBible</h3>"
      echo 'Paste this link: <a href="https://www.example.com/mirror/sword">https://www.example.com/mirror/sword</a>'
      _used=0
      for mod in "${REPO_DIR%%/}/mods.d/"*.conf ;
      do
         if test "${_used}" = "0" ;
         then
            _count="$( find "${REPO_DIR%%/}/mods.d/"*.conf -print 2>/dev/null | grep -cE . )"
            echo "<h2>Modules (${_count})</h2>"
            _used=1
            echo "<ul>"
         fi
         mod_name="$( grep -h -E '^\s*\[' "${mod}" | head -n1 | tr -d '[]\r' )"
         version="$( <"${mod}" awk -F'=' '$1~/\<Version/{print $2}')"
         license="$( <"${mod}" awk -F'=' '$1~/DistributionLicense/{print $2}')"
         if echo "${license}" | grep -qiE 'Permission to distribute granted to' ;
         then
            # probably not stackrpms, so do not show link.
            echo "<li>${mod_name}</li>"
         else
            echo "<li><a href='modules/${mod_name}.zip'>${mod_name}</a> <span class='smaller'>${version}</span></li>"
         fi
      done
      if test "${_used}" = "1" ;
      then
         echo "</ul>"
      fi
      echo "</body>"
      echo "<footer>"
      printf '%s' "Last generated: " ; TZ=UTC date "+%FT%TZ"
      echo "</footer>"
      echo "</html>"
   } > "${REPO_DIR%%/}/index.html"
}

test -z "${SKIP_TARBALL}" && generate_mods_d_tar_gz
test -z "${SKIP_WEB}" && generate_web

That second one I can run on demand, after placing any new modules in thet module path. It generates the mods.d.tar.gz used by Sword clients and also a small index.html for the web view.

And the css if anyone cares.

files/2024/listings/sword.css (Source)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/* File: fdroid.css
 * Startdate: 2024-06-03-2 14:10
 */

.img {
   max-width: 32px;
   max-height: 32px;
}

.headimg {
   max-width: 64px;
   max-height: 64px;
}

footer {
   font-size: 80%;
}

.smaller {
   font-size: 80%;
}

Comments