Skip to content
Extraits de code Groupes Projets
adl-submit.py 14,8 ko
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    # Copyright (C) 2005 Thomas Petazzoni <thomas.petazzoni@enix.org>
    #
    # This program is free software; you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation; version 2 of the License.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, write to the Free Software
    # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    
    import xml.dom.minidom
    import getopt
    import sys
    import pycurl
    import StringIO
    import re
    import time
    import locale
    
    locale.setlocale(locale.LC_ALL, ('fr_FR', 'utf-8'))
    
    eventFields = [ "title", "start-date", "end-date", "start-hour",
                    "end-hour", "description", "city", "region",
                    "url", "contact", "submitter", "tags" ]
    
    regions = {
       u'Alsace'               : 1,
       u'Aquitaine'            : 2,
       u'Auvergne'             : 3,
       u'Basse-Normandie'      : 4,
       u'Bourgogne'            : 5,
       u'Bretagne'             : 6,
       u'Centre'               : 7,
       u'Champagne-Ardenne'    : 8,
       u'Corse'                : 9,
       u'Franche-Comté'        : 10,
       u'Haute-Normandie'      : 11,
       u'Île-de-France'        : 12,
       u'Languedoc-Roussillon' : 13,
       u'Limousin'             : 14,
       u'Lorraine'             : 15,
       u'Midi-Pyrénées'        : 16,
       u'Nord-Pas-de-Calais'   : 17,
       u'Pays'                 : 18,
       u'Picardie'             : 19,
       u'Poitou-Charentes'     : 20,
       u'Provence-Alpes-Côte-d\'Azur' : 21,
       u'Rhône-Alpes'          : 22,
       u'Guadeloupe'           : 23,
       u'Guyane'               : 24,
       u'Martinique'           : 25,
       u'Réunion'              : 26,
       u'Autre'                : 27
    }
    
    
    baseUrl = "http://www.agendadulibre.org/"
    
    #baseUrl = "http://localhost:3000/"
    
    def Usage():
        print u"""Soumettre un évènement dans l'Agenda du Libre
    
    Options:
        --file        event.xml   Fichier XML décrivant l'évènement.
        --test-output test.html   Fichier de sortie HTML de test
        --start-date  YYYY-MM-DD  Date de début de l'évènement.
        --end-date    YYYY-MM-DD  Date de fin de l'évènement.
        --start-hour  HH:MM       Heure de début de l'évènement.
        --end-hour    HH:MM       Heure de fin de l'évènement.
        --title       chaine      Titre de l'évènement.
        --description chaine-html Description de l'évènement.
        --city        chaine      Ville de l'évènement.
        --region      entier      Région de l'évènement.
        --url         chaine      URL décrivant l'évènement.
        --contact     chaine      E-mail de contact.
        --tags        chaine      Liste des tags.
    
    Exemple de fichier XML:
        <?xml version="1.0" encoding="UTF-8"?>
        <event>
            <title>Permanence Logiciels Libres</title>
            <start-hour>18:00</start-hour>
            <end-hour>21:00</end-hour>
            <description><![CDATA[
    
             <p><a href="http://www.gulliver.eu.org">Gulliver</a> organise chaque
             semaine une permanence <i>Logiciels Libres</i> ouverte à tous,
             membre de l'association ou non.</p>
    
                <p>Durant cette permanence, vous pourrez trouver des réponses aux
                questions que vous vous posez au sujet du Logiciel Libre, ainsi que
                de l'aide pour résoudre vos problèmes d'installation, de
                configuration et d'utilisation de Logiciels Libres. N'hésitez pas
                à apporter votre ordinateur, afin que les autres participants
                puissent vous aider.</p>
    
                <p>Une connexion Internet est disponible sur place, ainsi que les
                mises à jour pour les distributions GNU/Linux les plus
                courantes.</p>
    
                <p>Cette permanence a lieu à la <a
                href=\"http://www.grand-cordel.com/\">MJC du Grand Cordel</a>, 18
                rue des Plantes à Rennes.</p>
    
            ]]></description>
            <city>Rennes</city>
            <region>Bretagne</region>
            <url>http://www.gulliver.eu.org</url>
            <contact>contact@gulliver.eu.org</contact>
            <tags>gulliver permanence</tags>
        </event>
    
    Valeurs des champs:
        Le fichier XML peut contenir des champs dont le nom est semblable
        à celui des options, à savoir start-date, end-date,
        start-hour, end-hour, title, description, city, region, url et
        contact. Si un champ est défini à la fois dans le fichier XML
        et sur la ligne de commande, alors c'est la valeur donnée sur la
        ligne de commande qui l'emporte. Entre le fichier XML et la ligne de
        commande, tous les champs doivent être définis, sinon l'ajout
        de l'évènement sera refusé. Le seul champ qui peut être
        vide est end-date, auquel cas il sera positionné à la même
        valeur que start-date.
    
    Remplacements:
        Si la chaîne $month est trouvée dans la description, elle sera
        automatiquement remplacée par le nom du mois de la date de début
        de l'évènement.
        Si la chaîne $date est trouvée dans la description, elle sera
        automatiquement remplacée par la date de début de l'évènement
        (numéro du jour dans le mois puis nom du mois).
    
    Exemple d'utilisation:
        ./adl-submit.py --file event.xml --start-date 2005-12-10
    
        Ajoutera l'évènement décrit dans le fichier event.xml
        (donné ci-dessous) pour la date du 10 décembre 2005. Puisque
        le champ end-date n'est pas spécifié, alors il vaudra la
        même chose que start-date, c'est à dire le 10 décembre
        2005.
    
        Pour vérifier que le formatage est correct avant l'envoi,
        on pourra utiliser:
    
        ./adl-submit.py --file event.xml --start-date 2005-12-10
            --test-output test.html
    
        et regarder le fichier test.html avec un navigateur Web.
    """
        sys.exit (1)
    
    def HandleXmlFile(file, values):
        dom = xml.dom.minidom.parse(file)
        for node in dom.getElementsByTagName("event")[0].childNodes:
            if node.nodeType == node.ELEMENT_NODE:
                val = node.childNodes[0]
                for field in eventFields:
                    if node.nodeName == field:
                        values[field] = val.data
    
    def HandleParamValue(param, val, values):
        for field in eventFields:
            if param == "--" + field:
                values[field] = val
    
    def ParseOptions(options):
        getoptOptions = map (lambda elt: elt + "=", eventFields)
        getoptOptions.append ("file=")
        getoptOptions.append ("help")
        getoptOptions.append("test-output=")
        eventFieldValues = {}
    
        testOutputFile = ""
    
        try:
            opts, args = getopt.getopt(options, "", getoptOptions)
        except getopt.GetoptError:
            print u"Option inconnue."
            Usage()
    
        if opts == []:
            Usage()
    
        for param, val in opts:
            if param == "--help":
                Usage()
    
            if param == "--file":
                HandleXmlFile(val, eventFieldValues)
    
            if param == "--test-output":
                testOutputFile = val
    
        for param, val in opts:
            HandleParamValue (param, val, eventFieldValues)
    
        return (eventFieldValues, testOutputFile)
    
    def getAuthToken(baseUrl):
    
        curl = pycurl.Curl()
    
        contents = StringIO.StringIO()
        curl.setopt(curl.WRITEFUNCTION, contents.write)
    
        curl.setopt(curl.URL, baseUrl)
        curl.setopt(pycurl.COOKIEJAR, '/tmp/cookie.txt')
        curl.setopt(pycurl.COOKIEFILE, '/tmp/cookie.txt')
    
        curl.perform()
    
        m = re.search(r'(<meta content="(.*?)" name="csrf-token" />)', contents.getvalue())
        m = re.search(r'"(.*?)"', m.group())
        return m.group().strip('"')
    
    def SubmitEvent(event, testOutputFile):
    
        if not event.has_key ("end-date") and event.has_key('start-date'):
            event ["end-date"] = event ["start-date"]
    
        if not event.has_key("submitter") and event.has_key('contact'):
            event ['submitter'] = event['contact']
    
        for field in eventFields:
            if not event.has_key(field):
                print u"Le champ '%s' n'est pas renseigné" % field
                return
    
        if re.compile(r'^[^\<\>]*$').search (event['title']) is None:
            print u"Problème de formatage dans le titre: '%s'. Les tags HTML ne sont pas autorisés." % event['title']
            return
    
        try:
            startDate = time.strptime(event['start-date'], "%Y-%m-%d")
        except ValueError:
            print u"Problème de formatage dans la date de début: '%s'. Elle doit être de la forme AAAA-MM-JJ" % event['start-date']
            return
    
        try:
            endDate = time.strptime(event['end-date'], "%Y-%m-%d")
        except ValueError:
            print u"Problème de formatage dans la date de fin: '%s'. Elle doit être de la forme AAAA-MM-JJ" % event['end-date']
            return
    
        try:
            startHour = time.strptime(event['start-hour'], "%H:%M")
        except ValueError:
            print u"Problème de formatage dans l'heure de début: '%s'. Elle doit être de la forme: HH:MM" % event['start-hour']
            return
    
        try:
            endHour = time.strptime(event['end-hour'], "%H:%M")
        except ValueError:
            print u"Problème de formatage dans l'heure de fin: '%s'. Elle doit être de la forme HH:MM" % event['start-hour']
            return
    
        for tag in event['tags'].split(' '):
            if len(tag) < 3:
                print u"Le tag '%s' est trop petit, minimum de 3 caractères" % tag
                return
    
        startDate = (startDate[0], startDate[1], startDate[2], startHour[3],
                     startHour[4], startDate[5], startDate[6], startDate[7], startDate[8])
        endDate   = (endDate[0],   endDate[1],   endDate[2],   endHour[3],
                     endHour[4],   endDate[5],   endDate[6],   endDate[7],   endDate[8])
    
        if time.mktime(startDate) <= time.time():
            print u"ERREUR: La date de début de l'évènement est dans le passé."
            return
    
        if time.mktime(endDate) <= time.time():
            print u"ERREUR: La date de fin de l'évènement est dans le passé."
            return
    
        if time.mktime(endDate) < time.mktime(startDate):
            print u"ERREUR: La date de fin de l'évènement est avant la date de début."
            return
    
        if re.compile(r'^[^\<\>]*$').search (event['city']) is None:
            print u"ERREUR: Problème de formatage dans le nom de la ville: '%s'. Les tags HTML sont interdits." % event['city']
            return
    
        if regions.has_key(event['region']) is False:
            print u"ERREUR: La région '%s' n'existe pas." % event['region']
            print u"Les régions existantes sont:"
            for name in regions:
                print u" - " + name
            return
    
        if re.compile(r'^http://.*$').search (event['url']) is None and re.compile(r'^https://.*$').search (event['url']) is None:
            print u"ERREUR: Problème de formatage dans l'URL: '%s'. Elle doit commencer par http:// ou https://." % event['url']
            return
    
        if re.compile(r'^([A-Za-z0-9_\.\-]*)@([A-Za-z0-9_\-]*)\.([A-Za-z0-9_\.\-]*)$').search (event['contact']) is None:
            print u"ERREUR: Problème de formatage dans l'adresse e-mail." % event ['contact']
            return
    
        if re.compile(r'^([A-Za-z0-9_\.\-]*)@([A-Za-z0-9_\-]*)\.([A-Za-z0-9_\.\-]*)$').search (event['submitter']) is None:
            print u"ERREUR: Problème de formatage dans l'adresse e-mail." % event ['submitter']
            return
    
        monthstr = unicode(time.strftime("%B", startDate), 'utf-8')
        datestr  = unicode(time.strftime("%d %B", startDate), 'utf-8')
    
        event['description'] = event['description'].replace("$month", monthstr)
        event['description'] = event['description'].replace("$date", datestr)
    
        curl = pycurl.Curl()
    
        contents = StringIO.StringIO()
        curl.setopt(curl.WRITEFUNCTION, contents.write)
    
        if testOutputFile:
            curl.setopt (curl.URL, baseUrl + 'events?visu=true')
        else:
            curl.setopt (curl.URL, baseUrl + 'events')
    
        curl.setopt(curl.HTTPPOST,  [('authenticity_token',  str(getAuthToken(baseUrl+'events/new'))),
                                     ('event[title]',        event['title'].encode('utf-8')),
                                     ('event[start_time(3i)]',    str(startDate[2])),
                                     ('event[start_time(2i)]',  str(startDate[1])),
                                     ('event[start_time(1i)]',   str(startDate[0])),
                                     ('event[start_time(4i)]',   str(startDate[3])),
                                     ('event[start_time(5i)]', str(startDate[4])),
                                     ('event[end_time(3i)]',      str(endDate[2])),
                                     ('event[end_time(2i)]',    str(endDate[1])),
                                     ('event[end_time(1i)]',     str(endDate[0])),
                                     ('event[end_time(4i)]',     str(endHour[3])),
                                     ('event[end_time(5i)]',   str(endHour[4])),
                                     ('event[description]',  event['description'].encode('utf-8')),
                                     ('event[city]',         event['city'].encode('utf-8')),
                                     ('event[region]',       str(regions[event['region']])),
                                     ('event[locality]',     str(0)),
                                     ('event[url]',          event['url'].encode('utf-8')),
                                     ('event[contact]',      event['contact'].encode('utf-8')),
                                     ('event[submitter]',    event['submitter'].encode('utf-8')),
                                     ('event[tags]',         event['tags'].encode('utf-8'))])
    
        curl.setopt(pycurl.COOKIEJAR, '/tmp/cookie.txt')
        curl.setopt(pycurl.COOKIEFILE, '/tmp/cookie.txt')
        curl.perform()
    
        if testOutputFile:
            if curl.getinfo(curl.HTTP_CODE) != 200:
                print u"Erreur lors de la récupération de la sortie HTML"
                sys.exit(0)
            fp = open(testOutputFile, "wb")
            s = contents.getvalue()
            s = re.sub(r'href="([A-Za-z0-9]*).css"', r'href="'+baseUrl+'\1.css"', s)
            fp.write(s)
            fp.close()
    
        else:
            if curl.getinfo(curl.HTTP_CODE) != 302:
                print u"Erreur lors de la soumission de l'évènement"
                sys.exit(0)
            else:
                print u"Évènement soumis avec succès. Il sera prochainement validé par un modérateur."
    
    
    if (len(sys.argv) == 1) and sys.argv[1] == "--help":
        Usage()
    
    (event, testOutputFile) = ParseOptions(sys.argv[1:])
    
    # Check that we are running the latest version of the adl-submit
    # script
    if not testOutputFile:
        contents = StringIO.StringIO()
        curl = pycurl.Curl()
        curl.setopt(curl.WRITEFUNCTION, contents.write)
        curl.setopt (curl.URL, baseUrl + './adl-submit-latest-version')
        curl.perform()
        if curl.getinfo(curl.HTTP_CODE) == 200:
            if float(contents.getvalue()) != float('3.0'):
                print u"Votre script n'est plus à jour, merci de télécharger la nouvelle version à l'adresse"
                print u"%sadl-submit.py" % baseUrl
                sys.exit(1)
    
    SubmitEvent(event, testOutputFile)