Compare commits
12 Commits
57243489c8
...
forge-ci
| Author | SHA1 | Date | |
|---|---|---|---|
| 677ea89517 | |||
| 06ba0029b2 | |||
| ddddaaac8d | |||
| 241ead5cd0 | |||
| 8b57f3c096 | |||
| 6ff17e27f5 | |||
| 2a42e2e2a3 | |||
| a6f05525e3 | |||
| c8b813084b | |||
| 428dcb8727 | |||
| 517ceacf79 | |||
| 83a0754e46 |
60
.forgejo/workflows/deploy.yml
Normal file
60
.forgejo/workflows/deploy.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
name: Deploy Hugo Site
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- forge-ci
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-deploy:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Install Hugo - latest version
|
||||||
|
run: |
|
||||||
|
apt-get update -y
|
||||||
|
apt-get install -y wget tar jq # Install necessary components
|
||||||
|
ldd --version
|
||||||
|
|
||||||
|
# If a Hugo version is provided in the secrets, use this
|
||||||
|
# else latest will be used
|
||||||
|
if [ -n "${{ secrets.HUGO_VERSION }}" ]; then
|
||||||
|
HUGO_VERSION="${{ secrets.HUGO_VERSION }}"
|
||||||
|
echo "Using Hugo version from secret: $HUGO_VERSION"
|
||||||
|
else
|
||||||
|
# Use the GitHub API to get information about the latest release, then use jq to find out the tag name
|
||||||
|
HUGO_VERSION=$(wget -qO- https://api.github.com/repos/gohugoio/hugo/releases/latest | jq -r '.tag_name')
|
||||||
|
echo "Using latest Hugo version: $HUGO_VERSION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use ${HUGO_VERSION#v} to strip the v from v1.0.0
|
||||||
|
# See "Substring Removal" in https://tldp.org/LDP/abs/html/string-manipulation.html
|
||||||
|
wget -O hugo.tar.gz "https://github.com/gohugoio/hugo/releases/download/${HUGO_VERSION}/hugo_extended_${HUGO_VERSION#v}_Linux-64bit.tar.gz"
|
||||||
|
tar -xzf hugo.tar.gz hugo
|
||||||
|
mv hugo /usr/local/bin/hugo
|
||||||
|
chmod +x /usr/local/bin/hugo
|
||||||
|
ldd /usr/local/bin/hugo
|
||||||
|
hugo version
|
||||||
|
|
||||||
|
- name: Build site
|
||||||
|
run: hugo --minify
|
||||||
|
|
||||||
|
- name: Deploy to server via rsync
|
||||||
|
env:
|
||||||
|
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
||||||
|
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
||||||
|
DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
|
||||||
|
run: |
|
||||||
|
apt-get install -y rsync openssh-client
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
|
||||||
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
|
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
|
||||||
|
rsync -avz --delete public/ "$DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH"
|
||||||
@@ -7,7 +7,6 @@ disqusShortname = ""
|
|||||||
# Enable Google Analytics by entering your tracking code
|
# Enable Google Analytics by entering your tracking code
|
||||||
googleAnalytics = ""
|
googleAnalytics = ""
|
||||||
preserveTaxonomyNames = true
|
preserveTaxonomyNames = true
|
||||||
paginate = 5 #frontpage pagination
|
|
||||||
|
|
||||||
[privacy]
|
[privacy]
|
||||||
# Google Analytics privacy settings - https://gohugo.io/about/hugo-and-gdpr/index.html#googleanalytics
|
# Google Analytics privacy settings - https://gohugo.io/about/hugo-and-gdpr/index.html#googleanalytics
|
||||||
|
|||||||
11
content/post/checking-shelters/animal-discovery.drawio.html
Normal file
11
content/post/checking-shelters/animal-discovery.drawio.html
Normal file
File diff suppressed because one or more lines are too long
122
content/post/checking-shelters/index.md
Normal file
122
content/post/checking-shelters/index.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
---
|
||||||
|
title: "How to manually check hundreds of animal shelters - every 14 days"
|
||||||
|
date: 2025-11-08T12:05:10+02:00
|
||||||
|
lastmod: 2025-11-08T21:05:10+02:00
|
||||||
|
draft: false
|
||||||
|
image: "uploads/checking-shelters.png"
|
||||||
|
categories: [ 'English' ]
|
||||||
|
tags: [ 'notfellchen', 'animal shelter', 'animal welfare', 'django' ]
|
||||||
|
---
|
||||||
|
|
||||||
|
I run a website called [Notfellchen](https://notfellchen.org) that list animals that are waiting for adoption. It's
|
||||||
|
currently restricted to fancy rats in Germany and that for good reason: Running this website involves **checking every
|
||||||
|
shelter every two weeks manually**. You need to visit the website, check if there are new animals, contact the shelter
|
||||||
|
and add them to notfellchen if they allow it. This takes time. A lot.
|
||||||
|
|
||||||
|
This blog post will outline some of the things I did in order to streamline this and make it possible to **check every
|
||||||
|
german shelter in 2.5 hours**.
|
||||||
|
|
||||||
|
## General process
|
||||||
|
|
||||||
|
When you establish a process. want others to help you or if you want to find inefficiencies, it's a good idea to
|
||||||
|
formalize it. So here is a rough BPMN diagram of the whole process.
|
||||||
|
|
||||||
|
{{< html animal-discovery.drawio.html >}}
|
||||||
|
|
||||||
|
## List of animal shelters
|
||||||
|
|
||||||
|
Focusing on the first step: We want to check the website of an animal shelter - but where do we get a list of animal
|
||||||
|
shelters from? Luckily there is an easy answer: [OpenStreetMap](https://openstreetmap.org) and I wrote a
|
||||||
|
whole [other blog post on how I imported and improved this data](https://hyteck.de/post/improve-osm-by-using-it/).
|
||||||
|
|
||||||
|
## Species-specific link
|
||||||
|
|
||||||
|
Importing this data provides us (most of the time) with a link to the shelter's website. However, rats are usually not
|
||||||
|
listed on the home page but on a subsite.
|
||||||
|
In order to save time, I introduced the concept of a species-specific link per organization and species.
|
||||||
|
|
||||||
|
So for the Tierheim Entenhausen this might look like this
|
||||||
|
|
||||||
|
| Species | Species specific link |
|
||||||
|
|---------|--------------------------------------------------------|
|
||||||
|
| Cat | https://tierheim-entenhausen.de/adoption/cats |
|
||||||
|
| Rats | https://tierheim-entenhausen.de/adoption/small-mammals |
|
||||||
|
|
||||||
|
As animal shelter pages look very different from each other, clicking this link provides an enormous time benefit
|
||||||
|
compared to clicking through a homepage manually.
|
||||||
|
|
||||||
|
# Org check page
|
||||||
|
|
||||||
|
I set up a special page to make it most efficient to check shelters. It's structured in four parts:
|
||||||
|
|
||||||
|
* **Stats**: The stats show how many animal shelters are checked in the last two weeks and how many to go.
|
||||||
|
* **Not checked for the longest period**: Shows the animal shelters to check next, it's therefore sorted by the date
|
||||||
|
they were last checked
|
||||||
|
* **In active communication**: A overview of the organizations where there is communication (or an attempt thereof).
|
||||||
|
This can take multiple das or even weeks so the internal comment field is very useful to keep track.
|
||||||
|
* **Last checked** It sometimes happens that I accidentally set a organization to "Checked" by accident. I added this
|
||||||
|
section to make it easier to revert that.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Shortcuts
|
||||||
|
|
||||||
|
To make it even faster to work through the organizations I added some shortcuts for the most common functionality and
|
||||||
|
documented the browser own shortcut to close a tab.
|
||||||
|
|
||||||
|
* `O`: Open website of the first organization
|
||||||
|
* `CTRL+W`: Close tab (Firefox, Chrome)
|
||||||
|
* `C`: Mark first organization as checked
|
||||||
|
|
||||||
|
## Results
|
||||||
|
|
||||||
|
After implementing all this, how long does it take now to check all organizations? Here are the numbers
|
||||||
|
|
||||||
|
| Measurement | |
|
||||||
|
|-----------------------------------------------------------|--------------|
|
||||||
|
| Time to check one organization (avg.) | 12.1s |
|
||||||
|
| Organization checked per minute | 4.96 org/min |
|
||||||
|
| Time to check all (eligible) german animal shelters (429) | 1 h 16 min |
|
||||||
|
|
||||||
|
This excludes the time, it takes to add animals or contact rescue organizations. One of these actions must be taken
|
||||||
|
whenever an eligible animal is found on a website. Here you can see how this interrupts the process:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
And here is the breakdown of time per activity. A big caveat here is, that I did not follow up on previous conversations
|
||||||
|
here, therefore the contacting number is likely an underestimation.
|
||||||
|
|
||||||
|
| Activity | Time spent | Percentage |
|
||||||
|
|------------|------------|------------|
|
||||||
|
| Checking | 54 min 44s | 72.3% |
|
||||||
|
| Adding | 11 min 15s | 14.9% |
|
||||||
|
| Contacting | 9min 41s | 12.8% |
|
||||||
|
|
||||||
|
To me, this looks like a pretty good result. I can't say which optimizations brought how much improvement, but I'd argue
|
||||||
|
they all play a role in reaching the 12s per rescue organizations that is checked.
|
||||||
|
|
||||||
|
In order to check all german animal shelters, one needs to put in about 2 and a half hours every two weeks. That seems
|
||||||
|
reasonable to me. Further improvements of the likely do not lie in the organization check page but the contact process
|
||||||
|
and adoption notice form.
|
||||||
|
|
||||||
|
For now, I'm happy with the results.
|
||||||
|
|
||||||
|
# Addendum: Common annoyances
|
||||||
|
|
||||||
|
When doing this over the last few months I encountered some recurring issues that not only were annoying but also take
|
||||||
|
up a majority of the time. Here are some that stood out
|
||||||
|
|
||||||
|
* **Broken SSL encryption** So many animal shelters do not have a functioning SSL certificate. It takes time to work
|
||||||
|
around the warnings.
|
||||||
|
* **No results not indicated** More often than not, animal shelters do not have rats. However, when you visit a page
|
||||||
|
like [this](https://tierschutzliga.de/tierheime/tierparadies-oberdinger-moos/tiervermittlung/#?THM=TOM&Tierart=Kleintiere)
|
||||||
|
it's hard to know if there is a technical issue or if there are no animals for your search.
|
||||||
|
* **No static links** Sites where you have to click through a menu to get to the right page, but you can not link
|
||||||
|
directly to it.
|
||||||
|
* **No website** Seriously, there are some animal shelters that only use Instagram or Facebook to tell people about the
|
||||||
|
animals they have. This is not only a privacy nightmare, it's also incredibly hard to find out which information is
|
||||||
|
up-to-date. Furthermore, there exists no data structure, so posts about animals often miss crucial information like
|
||||||
|
the sex.
|
||||||
|
|
||||||
|
While I obviously have some grievances here, I know the organizations never have enough resources, and they'd
|
||||||
|
usually love to have a nicer website. Just keep that in mind too.
|
||||||
BIN
content/post/checking-shelters/progress.png
Normal file
BIN
content/post/checking-shelters/progress.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
BIN
content/post/checking-shelters/screenshot-checking-site.png
Normal file
BIN
content/post/checking-shelters/screenshot-checking-site.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 273 KiB |
14
layouts/shortcodes/html.html
Normal file
14
layouts/shortcodes/html.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{{ $source := index .Params 0 }}
|
||||||
|
<div class="embedded-html">
|
||||||
|
{{ with .Page.Resources.GetMatch $source | readFile }}
|
||||||
|
{{ replace . "https://viewer.diagrams.net/js/viewer-static.min.js" "/js/viewer-static.min.js"|safeHTML }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
/* Reset the image width that is set in the theme for
|
||||||
|
If wired styling issues appear, check if the theme is responsible and eventually unset this here
|
||||||
|
*/
|
||||||
|
.geAdaptiveAsset {
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
7625
static/js/viewer-static.min.js
vendored
Normal file
7625
static/js/viewer-static.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
static/uploads/checking-shelters.png
Normal file
BIN
static/uploads/checking-shelters.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 146 KiB |
Reference in New Issue
Block a user