structure & meta
This commit is contained in:
parent
da6d838193
commit
b25ce65735
284 changed files with 461 additions and 1000 deletions
218
posts/2015/2015-09-14-owncloud-reminder.md
Executable file
218
posts/2015/2015-09-14-owncloud-reminder.md
Executable file
|
|
@ -0,0 +1,218 @@
|
|||
<!-- title: Jouons avec Awk, Bash et Owncloud -->
|
||||
<!-- category: GNU/Linux -->
|
||||
<!-- tag: planet -->
|
||||
|
||||
Un souci de synchronisation du calendrier entre Owncloud et mon téléphone a
|
||||
été le prétexte à bidouiller une fonctionnalité de rappel des événements par
|
||||
e-mail.<!-- more --> Pourquoi des e-mail ? Parce que je suis un fana de ce moyen de
|
||||
communication, la preuve [ici](http://blogduyax.madyanne.fr/du-nouveau-sur-
|
||||
pecosys.html) et [là](http://blogduyax.madyanne.fr/srmail.html).
|
||||
|
||||
Donc ce que je veux c'est un joli e-mail le lundi matin qui résume mes rendez-
|
||||
vous de la semaine (description, date et heure) et puis chaque matin au réveil
|
||||
un e-mail par événement avec le fichier ICS en pièce jointe. [ICS
|
||||
késako](https://fr.wikipedia.org/wiki/ICalendar) ? Un vieux mais très actuel
|
||||
standard de description d'un événement reconnu par la plupart des calendriers.
|
||||
L'intérêt d'avoir le fichier ICS c'est de pouvoir l'ajouter au calendrier
|
||||
local du téléphone en un clic et de paramétrer le rappel en connaissance de
|
||||
cause (le matin on a une petite idée de comment va se profiler sa journée).
|
||||
|
||||
Plutôt que de coder dans un langage évolué, je me suis amusé à réaliser cela
|
||||
avec les outils présent en standard sur GNU/Linux (**Awk** et **Bash**) pour
|
||||
le backend MySQL d'Owncloud. C'est didactique car il est toujours préférable
|
||||
de privilégier l'accès aux données par une API qui sera plus ou moins bien
|
||||
maintenue dans le temps par les développeurs que d'attaquer directement la
|
||||
base de données. D'abord jetons un oeil à structure de la base de donnée
|
||||
Owncloud.
|
||||
|
||||
La table *oc_clndr_calendars* permet de retrouver l'id de calendrier de notre
|
||||
utilisateur.
|
||||
|
||||
mysql> SELECT * FROM oc_clndr_calendars;
|
||||
+----+------------+-------------+-----------+--------+------+---------------+---------------+----------+-----------------------+
|
||||
| id | userid | displayname | uri | active | ctag | calendarorder | calendarcolor | timezone | components |
|
||||
+----+------------+-------------+-----------+--------+------+---------------+---------------+----------+-----------------------+
|
||||
| 1 | yax | Personnel | personnel | 1 | 196 | 0 | NULL | NULL | VEVENT,VTODO,VJOURNAL |
|
||||
+----+------------+-------------+-----------+--------+------+---------------+---------------+----------+-----------------------+
|
||||
|
||||
Et la table *oc_clndr_objects* contient les évènements :
|
||||
|
||||
mysql> DESC oc_clndr_objects;
|
||||
+--------------+------------------+------+-----+---------------------+----------------+
|
||||
| Field | Type | Null | Key | Default | Extra |
|
||||
+--------------+------------------+------+-----+---------------------+----------------+
|
||||
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
|
||||
| calendarid | int(10) unsigned | NO | | 0 | |
|
||||
| objecttype | varchar(40) | NO | | | |
|
||||
| startdate | datetime | YES | | 1970-01-01 00:00:00 | |
|
||||
| enddate | datetime | YES | | 1970-01-01 00:00:00 | |
|
||||
| repeating | int(11) | YES | | 0 | |
|
||||
| summary | varchar(255) | YES | | NULL | |
|
||||
| calendardata | longtext | YES | | NULL | |
|
||||
| uri | varchar(255) | YES | | NULL | |
|
||||
| lastmodified | int(11) | YES | | 0 | |
|
||||
+--------------+------------------+------+-----+---------------------+----------------+
|
||||
|
||||
On peut récupérer les évènements du jour courant avec la requête suivante :
|
||||
|
||||
mysql> SELECT startdate,summary,calendardata FROM oc_clndr_objects WHERE calendarid = 1 AND DATE(startdate) = DATE(NOW()) ORDER by startdate \G;
|
||||
*************************** 1. row ***************************
|
||||
startdate: 2015-09-14 10:30:00
|
||||
summary: Déjeuner avec M.
|
||||
calendardata: BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:ownCloud Calendar
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VEVENT
|
||||
UID:95d9221d97
|
||||
DTSTAMP:20150914T103206Z
|
||||
CREATED:20150913T170426Z
|
||||
LAST-MODIFIED:20150914T103206Z
|
||||
SUMMARY:Déjeuner avec M.
|
||||
DTSTART;TZID=Europe/Paris:20150914T123000
|
||||
DTEND;TZID=Europe/Paris:20150914T140000
|
||||
LOCATION:
|
||||
DESCRIPTION:
|
||||
CATEGORIES:
|
||||
CLASS:PUBLIC
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
*************************** 2. row ***************************
|
||||
startdate: 2015-09-14 16:15:00
|
||||
summary: RV dentiste
|
||||
calendardata: BEGIN:VCALENDAR
|
||||
VERSION:2.0
|
||||
PRODID:ownCloud Calendar
|
||||
CALSCALE:GREGORIAN
|
||||
BEGIN:VEVENT
|
||||
UID:1958bfe4a9
|
||||
DTSTAMP:20150914T103134Z
|
||||
CREATED:20150914T103134Z
|
||||
LAST-MODIFIED:20150914T103134Z
|
||||
SUMMARY:RV dentiste
|
||||
DTSTART;TZID=Europe/Paris:20150914T181500
|
||||
DTEND;TZID=Europe/Paris:20150914T183000
|
||||
LOCATION:
|
||||
DESCRIPTION:
|
||||
CATEGORIES:
|
||||
END:VEVENT
|
||||
END:VCALENDAR
|
||||
|
||||
Les colonnes intéressantes sont :
|
||||
|
||||
- *calendarid* pour filtrer les évènements de notre utilisateur Owncloud
|
||||
- *summary* : le libellé de l'évènement
|
||||
- *startdate* : la date de début de l'évènement
|
||||
- *calendardata* : l'évènement au format iCalendar
|
||||
|
||||
Ce qu'on veut c'est générer un shell script qui récupère les informations du
|
||||
jour et envoie un e-mail par évènement avec le fichier ICS en pièce jointe.
|
||||
L'envoi est réalisé par l'utilitaire **mpack**. Le résultat final espéré pour
|
||||
notre exemple est ce script :
|
||||
|
||||
``` shell
|
||||
#
|
||||
STARTDATE="`date -d '2015-09-14 10:30:00-000' '+%a %e %b %R'`"
|
||||
SUMMARY="Déjeuner avec M."
|
||||
echo "BEGIN:VCALENDAR" >event.ics
|
||||
echo "VERSION:2.0" >> event.ics
|
||||
echo "PRODID:ownCloud Calendar" >> event.ics
|
||||
echo "CALSCALE:GREGORIAN" >> event.ics
|
||||
echo "BEGIN:VEVENT" >> event.ics
|
||||
echo "UID:95d9221d97" >> event.ics
|
||||
echo "DTSTAMP:20150914T103206Z" >> event.ics
|
||||
echo "CREATED:20150913T170426Z" >> event.ics
|
||||
echo "LAST-MODIFIED:20150914T103206Z" >> event.ics
|
||||
echo "SUMMARY:Déjeuner avec M." >> event.ics
|
||||
echo "DTSTART;TZID=Europe/Paris:20150914T123000" >> event.ics
|
||||
echo "DTEND;TZID=Europe/Paris:20150914T140000" >> event.ics
|
||||
echo "LOCATION:" >> event.ics
|
||||
echo "DESCRIPTION:" >> event.ics
|
||||
echo "CATEGORIES:" >> event.ics
|
||||
echo "CLASS:PUBLIC" >> event.ics
|
||||
echo "END:VEVENT" >> event.ics
|
||||
echo "END:VCALENDAR" >>event.ics
|
||||
mpack -s "$SUMMARY - $STARTDATE" event.ics $1
|
||||
#
|
||||
STARTDATE="`date -d '2015-09-14 16:15:00-000' '+%a %e %b %R'`"
|
||||
SUMMARY="RV dentiste"
|
||||
echo "BEGIN:VCALENDAR" >event.ics
|
||||
echo "VERSION:2.0" >> event.ics
|
||||
echo "PRODID:ownCloud Calendar" >> event.ics
|
||||
echo "CALSCALE:GREGORIAN" >> event.ics
|
||||
echo "BEGIN:VEVENT" >> event.ics
|
||||
echo "UID:1958bfe4a9" >> event.ics
|
||||
echo "DTSTAMP:20150914T103134Z" >> event.ics
|
||||
echo "CREATED:20150914T103134Z" >> event.ics
|
||||
echo "LAST-MODIFIED:20150914T103134Z" >> event.ics
|
||||
echo "SUMMARY:RV dentiste" >> event.ics
|
||||
echo "DTSTART;TZID=Europe/Paris:20150914T181500" >> event.ics
|
||||
echo "DTEND;TZID=Europe/Paris:20150914T183000" >> event.ics
|
||||
echo "LOCATION:" >> event.ics
|
||||
echo "DESCRIPTION:" >> event.ics
|
||||
echo "CATEGORIES:" >> event.ics
|
||||
echo "END:VEVENT" >> event.ics
|
||||
echo "END:VCALENDAR" >>event.ics
|
||||
mpack -s "$SUMMARY - $STARTDATE" event.ics $1
|
||||
```
|
||||
|
||||
Comment fait-on ? On exécute la requête SQL et on la donne à manger à un
|
||||
script **awk** qui a pour objectif de générer le shell script ci-dessus. Awk a
|
||||
été inventé pour ce genre de tâche : prendre un fichier en entrée et le
|
||||
modifier pour créer un fichier en sortie. Le script est assez opaque si on n'a
|
||||
jamais pratiqué mais l'idée c'est de décrire la structure du document en
|
||||
entrée (comment distinguer les enregistrements) et de faire correspondre des
|
||||
traitements à certains enregistrements qu'on identifie par une expression
|
||||
régulière.
|
||||
|
||||
Voci le script awk complet :
|
||||
|
||||
``` awk
|
||||
BEGIN {
|
||||
FS="\n"
|
||||
OFS=""
|
||||
ORS="\n"
|
||||
print "#!/bin/sh"
|
||||
print " "
|
||||
}
|
||||
# blank lines
|
||||
/^$/ { next }
|
||||
# record header
|
||||
$1 ~ /^\*\*\*\*/ {
|
||||
next
|
||||
}
|
||||
# summary field
|
||||
$1 ~ /^[ ]*summary\:/ {
|
||||
idx = match($1, /summary\:(.*)/)
|
||||
print "SUMMARY=\"" substr($1, idx + 9) "\""
|
||||
next
|
||||
}
|
||||
# startdate field
|
||||
$1 ~ /^[ ]*startdate\: / {
|
||||
match($1, /startdate\: /)
|
||||
print "STARTDATE=\"`date -d '" substr($1, RSTART + RLENGTH) "-000' '+%a %e %b %R'`\""
|
||||
next
|
||||
}
|
||||
# vcalendar start tag
|
||||
$1 ~ /^[ ]*calendardata\: / {
|
||||
match($1, /calendardata\: /)
|
||||
print "echo \"" substr($1, RSTART + RLENGTH) "\" >event.ics"
|
||||
next
|
||||
}
|
||||
# vcalendar end tag
|
||||
$1 ~ /^END\:VCALENDAR/ {
|
||||
print "echo \"" $1 "\" >>event.ics"
|
||||
print "mpack -s \"$SUMMARY - $STARTDATE\" event.ics $1"
|
||||
print ""
|
||||
next
|
||||
}
|
||||
# vcalendar body
|
||||
{
|
||||
print "echo \"" $0 "\" >> event.ics"
|
||||
}
|
||||
```
|
||||
|
||||
Il ne reste plus qu'à orchestrer tout cela dans un shell script et de
|
||||
l'appeler par une tâche **cron**. Le script complet gère les rappels du jour
|
||||
et les rappels pour la semaine à venir. Il est disponible [sur mon compte
|
||||
GitHub](https://github.com/kianby/owncloud_calremind).
|
||||
Loading…
Add table
Add a link
Reference in a new issue