Ein Shellscript zur automatisierten Post-Erstellung in einem WordPress-Fotoblog Fotografie Shellscript Tools Wordpress 

Ein Shellscript zur automatisierten Post-Erstellung in einem WordPress-Fotoblog

Bisher war das Posten neuer Bilder in meinem Fotoblog für mich immer mit einem relativ hohen Arbeitsaufwand verbunden. Bis zur Veröffentlichung auf dem WordPress-Blog durchlaufen meine Fotos folgende Schritte

  1. Die Fotos werden skaliert, d.h. verkleinert (voll aufgelöste Bilder gibt es nur gegen Bezahlung 😉 ). Dafür habe ich z.B. die Programme “Fotosizer” oder “FastStone Photo Resizer” genutzt, da sie in der Lage sind, mehrere Bilder auf einmal zu verarbeiten. Dabei benötige ich von jedem Foto eine große Variante (für die Detailansicht) und eine kleine Variante (Breite 300px für die Vorschau in der Fotogallerie). Die skalierten Fotos (große Variante) erhalten anschließend ein Wasserzeichen. Dazu habe ich bisher immer die kostenlose Version von “uMark” genutzt.
  2. Anschließend müssen die Fotos per FTP auf den Server übertragen werden. Dazu nutze ich das Programm FileZilla.
  3. Zum Schluss lege ich einen neuen WordPress-Post an. Dort füge ich HTML-Code ein, um eine Fotogallerie zu erzeugen. Außerdem gebe ich noch Bestellnummer und Preis für die Fotos an und füge einen “Kaufen”-Button hinzu, der den Nutzer zu dem Bestellformular weiterleitet.

 
Erst danach kommt für mich der kreative Teil, nämlich die inhaltliche Beschreibung der Fotos und die Beantwortung der Fragen: Welche Pflanzen sind abgebildet? Welche gestalterischen Absichten verfolge ich?

Um den Aufwand für das Vorverarbeiten der Fotos und das Anlegen des Post-Grundgerüstes zu reduzieren, habe ich ein Shell-Skript entwickelt, welches die Schritte 1 bis 3 automatisch durchführt. Dadurch erspare ich mir das mühsame Herumgeklicke in vielen verschiedenen Hilfsprogrammen. Das Shell-Skript basiert auf folgenden Komponenten:

  • ImageMagick – ein leistungsfähiges Bildbearbeitungsprogramm für die Kommandozeile
  • WP REST API – ein WordPress-Plugin zur Remote-Blogverwaltung via GET- und POST-Anfragen
  • cURL – ein Werkzeug zum Erstellen von GET- und POST-Requests auf der Kommandozeile
  • jq – ein Hilfsprogramm zur Verarbeitung von JSON-Daten auf der Kommandozeile
  • WP OAuth Server – ein WordPress-Plugin zur Authentifizierung des WordPress-Nutzers bei passwordgeschützten POST-Anfragen wie z.B. Anlegen oder Aktualisieren von WordPress-Posts
  • Postman – ein Chrome-Plugin, welches ich benutze, um ein Authentifizierungstoken vom OAuth Server zu bekommen.

 
Ich nutze die Bash Shell, die für Windows durch die Installation von Cygwin verfügbar gemacht werden kann.
 

Aufbau des Shell-Skriptes – Teil 1

Ich lege eine neue Datei mit der Endung .sh an – meine Datei heißt “wpauto.sh”. Zur besseren Orientierung füge ich am Anfang der Datei eine Legende mit den Parametern ein, die mein Skript entgegen nehmen soll.

#Parameter:
#$1 Quellordner
#$2 Zielordner
#$3 Dateiname des Titelbildes (wird in diesem Beitrag nicht berücksichtigt)
#$4 OAuth-token
#$5 Posttitel
#$6 Abschnittstitel 
#$7 Abschnitts-ID
#$8 Bestellnummer
#$9 Preis
#$10 Fotos als Gallerie (ja oder nein) (wird in diesem Beitrag nicht berücksichtigt)
#$11 ID des Posts, der aktualisiert werden soll (optional)

Die Legende besteht aus Kommentaren, erkennbar an dem vorangestellten #-Zeichen. Als nächstes definiere ich Variablen, die ich später benötigen werde:

MM=$(date +%m)

HOST='blaustern.bplaced.net'
USER='xxx'
PASSWD='xxx'

In der Variable “MM” speichere ich die Nummer des aktuellen Monats, denn in meiner WordPress-Installation müssen die Fotos stets unter einem Pfad mit dem Muster “wp-content/uploads/<Jahreszahl>/<Monatszahl>” abgespeichert werden. Die Variablen “HOST”, “USER” und “PASSWD” benötige ich für den FTP-Upload.
 

Aufbau des Shell-Skriptes – Teil 2 ImageMagick

Folgender Code-Abschnitt zeigt die Bash-Befehle zum Einsatz von ImageMagick.

cd $1 

mkdir $2

for filename in *.JPG
do 
  na=$(basename $filename .JPG)
  echo konvertiere $na ...
	
  magick composite -dissolve 30% -gravity center 'C:/watermark_gross.png' $filename ${na}_watermark.jpg
  magick convert ${na}_watermark.jpg -strip -quality 85% -interlace Plane -gaussian-blur 0.05 -resize 40% ${na}_resize.jpg
  magick convert $filename -strip -resize 300 ${na}-300x200.jpg
	
  mv ${na}_resize.jpg $2
  mv ${na}-300x200.jpg $2
  rm ${na}_watermark.jpg
done
...
cd $2

 

Mit dem Befehl “magick composite -dissolve …” wird das gerade betrachtete Foto mit einem Wasserzeichen überlagert. Es erhält eine Transparenz von 30% und wird durch die Angabe “-gravity center” zentriert (in der Mitte) angeordnet.

Der nächste Befehl “magick convert …” entfernt alle Metadaten (-strip) und reduziert die Qualität ( -quality, -interlace, -gaussian-blur) sowie die Größe (-resize). Heraus kommt ein Bild, dessen Größe nur noch 40% von der Größe des Ausgangsbildes beträgt. Dadurch -und aufgrund der Qualitätsreduzierung- hat es eine wesentlich geringere Dateigröße (ca. 400 – 500 KB bei einem Ausgangsbild von ca. 6MB).

Die Vorschau-Variante des Bildes mit einer Breite von 300 Pixeln erzeuge ich mit dem zweiten “magick convert …”-Befehl. Die beiden vorverarbeiteten Bilder verschiebe ich in den Ordner $2.

Bitte beachten:  Durch die Schleife “for filename in *.JPG do .. done” werden innerhalb des Ordners $1 alle Dateien mit der Endung “JPG” betrachtet. Bilder mit anderen Endungen (z.B. “jpg” oder “png”) werden ignoriert.

Hinweis: In der Variable $filename wird die komplette Pfadangabe des Bildes gespeichert. Die Anweisungbasename $filename .JPG” extrahiert daraus den Dateinamen und schneidet zusätzlich noch die Dateiendung ab. Um das Ergebnis dieser Anweisung (und nicht die Anweisung selbst) der Variable “na” zuzuweisen, muss die Anweisung in Klammern gesetzt werden und es muss ein $-Zeichen vorangestellt werden.
 

Aufbau des Shell-Skriptes – Teil 3 FTP

Folgender Code-Abschnitt zeigt, wie die Bilder mittels FTP auf den Server in das passende WordPress-Uploadverzeichnis übertragen werden.

echo übertrage Fotos zum Server ...

ftp -n $HOST <<END_SCRIPT > /dev/null
user $USER $PASSWD
cd /fotos/wp-content/uploads/2016/$MM
quote TYPE I
prompt
mput *.jpg
quit
END_SCRIPT

Hier greife ich auf die Monatszahl in der Variable “MM” zu, um die Bilder in das richtige Verzeichnis einzuordnen. Außerdem werden jetzt die Variablen “HOST”, “USER”, und “PASSWD” verwendet. Beachten Sie, dass bei dem Zugriff auf eine Shell-Variable ein $-Zeichen vor den Variablennamen gestellt werden muss. Die Deklaration erfolgt hingegen ohne $-Zeichen.

Eine Übersicht über die verwendeten FTP-Kommandos und -Parameter finden Sie bei ComputerHope.com. An dieser Stelle nur ein paar Hinweise: Mit “> /dev/null” leite ich eventuell auftretende Meldungen ins Nirvana um. Diese Angabe kann also weggelassen werden. Für den Upload von Bilddateien ist der Befehl “quote TYPE I” wichtig, damit die Bilder im Binärformat und nicht im ASCII-Format zum Server übertragen werden. Der Befehl “prompt” ist notwendig, um laut StackOverflow “die Nutzerinteraktion zu beenden” bevor der Befehl “mput” ausgeführt wird. Ohne dem funktioniert es jedenfalls nicht.
 

Aufbau des Shell-Skriptes – Teil 4 WP REST API

Im folgenden Code-Abschnitt wird zunächst der (für meinen Blog spezifische) HTML-Code erstellt, mit dem die Bilder im WordPress-Post angezeigt werden sollen. Der HTML-Code wird in der Variable “content” gespeichert.

content="<h4 id='$7'><strong>$6</strong></h4>"
content=$content"<p><strong>Bestellnummer für die Fotoserie: $8 ($9 €)</strong><br/>"
content=$content"Größe der Originalbilder: 6000 x 4000</p>"
content=$content"<p><a class='myButton' href='http://fotos.blaustern.bplaced.net/?page_id=42&ids=$8'>Bilder kaufen</a></p>"

content=$content"<div class='my_images'>"
	
for filename in *_resize.jpg
do
   name=$(basename $filename _resize.jpg)
   content=$content"<p><img class='alignnone size-full' id='$name' src='http://fotos.blaustern.bplaced.net/wp-content/uploads/2016/${MM}/$filename' width='2400' height='1600'/></p>"	
done
	
content=$content"</div>"

Im nächsten Schritt wird überprüft, ob der Post neu erstellt oder aktualisiert werden soll. Dies wird anhand der Anzahl der an das Skript übergebenen Parameter ermittelt, die über “$#” abgerufen werden kann. Wenn die Anzahl gleich 10 ist, muss der Post neu erstellt werden. Wenn die Anzahl gleich 11 ist, wurde eine Post-ID als 11ter Parameter übergeben, was bedeutet, dass der Post mit dieser ID erweitert werden soll.

Fall 1: Post neu erstellen.

if [ $# -eq 10 ]
then
   echo lege neuen WordPress-Post an...

   curl -ss -X POST -H "Content-Type: application/json" http://fotos.blaustern.bplaced.net/wp-json/wp/v2/posts?access_token=$4 -d '{"title": "'"$5"'", "content": "'"$content"'" }' > /dev/null
fi

Wenn das Plugin “WP REST API” (siehe Link oben) für WordPress installiert wurde, kann der POST-Request wie oben gezeigt mit dem Werkzeug “curl” durchgeführt werden. Details zum Aufbau des Requests finden Sie in der Dokumentation der REST API. Wichtig ist das “access_token” zur Authentifizierung, welches ich als 4ten Parameter beim Aufruf des Skriptes erwarte. Mehr dazu im letzten Abschnitt. Eventuell auftretende Konsolenmeldungen und Fortschrittsanzeigen lösche ich mittels “-ss” und “> /dev/null”. Wer die Ausgaben sehen möchte, lässt diese Parameter einfach weg.

Fall 2: Post aktualisieren.

if [ $# -eq 11 ]
then	
   echo aktualisiere WordPress-Post...

   old=$(curl -ss -X GET http://fotos.blaustern.bplaced.net/wp-json/wp/v2/posts/${11}?access_token=$4 | jq .content.rendered)
		
   old=$(echo $old | tr -d \")
   old=$(echo $old | tr -d "\r")
   new="$old$content"
	
   curl -ss -X POST -H "Content-Type: application/json" http://fotos.blaustern.bplaced.net/wp-json/wp/v2/posts/${11}?access_token=$4 -d '{"title": "'"$5"'", "content": "'"$new"'" }' > /dev/null
fi

echo Fertig!

Um einen Post mit einer bestimmten ID zu aktualisieren, muss zunächst der bestehende Post-Inhalt mit einer GET-Abfrage ermittelt werden. Per Pipe-Technik wird die Antwort des GET-Requests direkt an das Tool “jq” weitergeleitet. JQ extrahiert aus der im JSON-Format vorliegenden Antwort die Eigenschaft “.content.rendered”. Das Ergebnis ist der HTML-Code des Postinhaltes, welcher in der Variable “old” gespeichert wird.

Anschließend ist es notwendig, den HTML-Code von den umgebenden Anführungszeichen sowie von den enthaltenen “carriage return”-Zeichen (\r) zu befreien. Dies geschieht mit dem Shell-Kommando “translate” (tr). Mit dem Befehl “new=$old$content” wird der neue Post-Inhalt durch Verknüpfung der Variablen “old” und “content” erzeugt. Dieser kann nun mittels POST-Request abgeschickt werden. Die ID des Posts (im Parameter $11 enthalten) wird an die URL angehängt. Auch hier muss das “access_token” mitgeschickt werden.
 

Aufruf des Skriptes

Mein Skript heißt “wpauto.sh”. Auf der Kommandozeile (unter Windows auf der Cygwin-Konsole) kann es durch den Befehl “sh wpauto.sh” aktiviert werden. Ein kompletter Aufruf könnte z.B. wie folgt aussehen:

sh wpauto.sh "C:/users/anna/pictures/fotos28_09_16" ""C:/users/anna/pictures/fotos28_09_16_upload" "Blume1.JPG" 124kdhbi1030dugslsjgls "Neue Blumenfotos" "Fotos Teil 1" "fotos1" 48 19,50 nein

Die Parameter werden in der oben definierten Reihenfolge angegeben.
 

Umgang mit dem WP OAuth Server

Laut Wikipedia ist OAuth

… offenes Protokoll, das eine standardisierte, sichere API-Autorisierung für Desktop-, Web- und mobile-Anwendungen erlaubt. …

Ein Endbenutzer (User oder Resource Owner) kann mit Hilfe dieses Protokolls einer Anwendung (Client) den Zugriff auf seine Daten erlauben (Autorisierung), die von einer anderen Anwendung (Resource Server) verwaltet werden, ohne alle Details seiner Zugangsberechtigung zur anderen Anwendung (Authentifizierung) preiszugeben. Typischerweise wird dabei die Übermittlung von Passwörtern an [die andere Anwendung] vermieden.

Mein Shell-Skript ist also der Client, der Zugriff auf die Daten einer anderen Anwendung (mein WordPress-Blog) nehmen möchte. Die Zugangsdaten, also mein WordPress-Passwort, sollen dabei nicht dem Shell-Skript verraten werden. Stattdessen wird vor jedem Aufruf des Skripts ein Authentifizierungstoken vom OAuth-Server bereitgestellt. Dieses kann das Skript zur Authentifizierung der REST-Anfragen verwenden.

Zunächst muss daher das OAuth-Plugin für WordPress installiert werden (siehe Link oben). In den Plugin-Einstellungen muss anschließend ein neuer Client mit einem bestimmten Client-Namen angelegt werden. Das Plugin generiert für den Client zwei Werte:

  • die Client-ID
  • das Client-Secret

 
Jetzt ist alles vorbereitet, um ein Token zu generieren. Ich nutze dafür die Chrome-App Postman (siehe Link oben) und verwende dabei folgende Einstellungen:

  • URL: http://fotos.blaustern.bplaced.net?oauth=token
  • HTTP Methode: POST
  • Body:
    • x-www-form-urlencoded
    • grant_type:password
    • username:wordpress-username
    • password:wordpress-password
    • client_id:oauth-clientid
    • client_secret:oauth-clientsecret
  • Authorization: Basic Auth, username:oauth-clientid, password:oauth-clientsecret

 
Das Abschicken des Requests geschieht durch Drücken des “Send”-Buttons. Im Antwortfenster kann dann das “access_token” herauskopiert und in die (Cygwin)-Konsole als vierter Parameter des Shell-Skriptes eingefügt werden. Ich habe mir den Request in der Postman-App abgespeichert, sodass ich nur noch auf “Send” drücken muss, wenn ich ein neues Token benötige.
 

Fazit

Auch wenn es ein wenig Arbeit gemacht hat, ein auf meine Bedürfnisse abgestimmtes Skript zu entwickeln, bin ich mit dem Ergebnis sehr zufrieden. Es vereinfacht meinen Foto-Workflow sehr stark. Nachdem ich meine aufgenommenen Fotos digital ein wenig optimiert habe (ich mache das gern mit GIMP), kann ich sie quasi auf Knopfdruck vorverarbeiten und in meinen Fotoblog integrieren lassen. Die manuelle “Strafarbeit” entfällt komplett. Ich kümmere mich danach nur noch um das Ausfeilen des Post-Textes

Related posts