pax_global_header 0000666 0000000 0000000 00000000064 14575653726 0014536 g ustar 00root root 0000000 0000000 52 comment=5f3d558793b537a74480241ac6981479f5938cd3
woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/ 0000775 0000000 0000000 00000000000 14575653726 0024630 5 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/ 0000775 0000000 0000000 00000000000 14575653726 0026300 5 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre/ 0000775 0000000 0000000 00000000000 14575653726 0031066 5 ustar 00root root 0000000 0000000 __init__.py 0000664 0000000 0000000 00000001515 14575653726 0033122 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2014 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
from .module import AgendadulibreModule
__all__ = ['AgendadulibreModule']
browser.py 0000664 0000000 0000000 00000003767 14575653726 0033061 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2014 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
from woob.browser import PagesBrowser, URL
from .pages import EventListPage, EventPage
from datetime import timedelta, date
class AgendadulibreBrowser(PagesBrowser):
event_list_page = URL('events\?start_date=(?P.*)(?P.*)', EventListPage)
event_page = URL('events/(?P<_id>.*)', EventPage)
def __init__(self, website, region, *args, **kwargs):
self.BASEURL = u'%s/' % website
self.region = '®ion=%s' % region if region else ''
PagesBrowser.__init__(self, *args, **kwargs)
def list_events(self, date_from, date_to, city=None, categories=None, max_date=None):
_max_date = date_from + timedelta(days=365)
max_date = date(year=_max_date.year, month=_max_date.month, day=_max_date.day)
return self.event_list_page.go(date_from=date_from.strftime("%Y-%m-%d"),
region=self.region)\
.list_events(date_from=date_from,
date_to=date_to,
city=city,
categories=categories,
max_date=max_date)
def get_event(self, event_id, event=None):
_id = event_id.split('#')[-1]
return self.event_page.go(_id=_id).get_event(obj=event)
calendar.py 0000664 0000000 0000000 00000002133 14575653726 0033131 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2013 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
from woob.capabilities.calendar import BaseCalendarEvent, TRANSP, STATUS, CATEGORIES
class AgendaDuLibreCalendarEvent(BaseCalendarEvent):
def __init__(self):
BaseCalendarEvent.__init__(self)
self.sequence = 1
self.transp = TRANSP.TRANSPARENT
self.status = STATUS.CONFIRMED
self.category = CATEGORIES.CONF
favicon.png 0000664 0000000 0000000 00000003431 14575653726 0033143 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre PNG
IHDR @ @ iq gAMA a pHYs od tEXtAuthor Jakub Steiner/ !tEXtSource http://jimmac.musichall.czif^ ItEXtCopyright Public Domain http://creativecommons.org/licenses/publicdomain/Y tEXtSoftware paint.net 4.0.3P IDATx^OIg!TSPKN9TApzA0H uXdo+~X_WV6=̑igO.zz8Ç>|#JHCCCyY"%Hyy:uJ̙3 !2dggKII(ƍjSSSKrE(ZDwQ]]-SyKggtuu%W^+WH~~ܾ}}%=zTPS .4illt"$vGAAr@nn
-{tJ80++DIr1G^kî04iҞ$ZDwA0Pw
F_C]Q 89tw0 999+X?|<"c11;;{ I'C. 9߽{=%I%Z;7G>cftO̹gϔc"v~6lGVVT]ō??/ hݩ90ۙNt7 hݩ90wQ+j hݩ9ɓ' 27"Єݩ9ɝu )?J@`7}( W@$ .?3鄃
D֢hu˃?~,yyyS@kkpH0T\*@/21vMMM|Jɀ| ?֯>R/`[#v$SXؕtBFMVlBM JɌmuV?`ccC%Ev"uA D'p!>Êh`fҳا"#Dg7sqJcm|h;
߿/*پ"=p UMנȲrݤQ{UY^^9u'`phHەlSx*f!?Q 1%?i2*@@
pP7>~,pNd5c2u+N%3RbRׯs)pg %%%6N a?ʇݻw"o߾7oׯeiiIeaaA]/^%*rɓ'*>gffdzzZ6GÇebbB˽{N[wܑ[n͛7nUZrP
@ ,B9̹y ky9|"Tp)XU"M!655)r(녨zeZEBRU!f0{xVd@?b/bb.VRTEI zhmMܓqd!4JxF Myj'
!F5GZ{
%א;QȈ,DL chWY/i*;3NT|Jb$WbOVӸzxޜDNEn,O8Ç>|#G~>scZ IENDB` module.py 0000664 0000000 0000000 00000014561 14575653726 0032655 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2014 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
from collections import OrderedDict
from woob.tools.backend import Module, BackendConfig
from woob.capabilities.calendar import CapCalendarEvent, CATEGORIES
from woob.tools.value import Value
from .browser import AgendadulibreBrowser
__all__ = ['AgendadulibreModule']
class AgendadulibreModule(Module, CapCalendarEvent):
NAME = 'agendadulibre'
DESCRIPTION = u'agendadulibre website'
MAINTAINER = u'Bezleputh'
EMAIL = 'carton_ben@yahoo.fr'
LICENSE = 'AGPLv3+'
VERSION = '3.6'
ASSOCIATED_CATEGORIES = [CATEGORIES.CONF]
BROWSER = AgendadulibreBrowser
region_choices = OrderedDict([(k, u'%s (%s)' % (v, k)) for k, v in sorted({
"https://www.agendadulibre.org": u'--France--',
"https://www.agendadulibre.org#3": u'Auvergne-Rhône-Alpes',
"https://www.agendadulibre.org#5": u'Bourgogne-Franche-Comté',
"https://www.agendadulibre.org#6": u'Bretagne',
"https://www.agendadulibre.org#7": u'Centre-Val de Loire',
"https://www.agendadulibre.org#30": u'Collectivité sui generis',
"https://www.agendadulibre.org#29": u'Collectivités d\'outre-mer',
"https://www.agendadulibre.org#9": u'Corse',
"https://www.agendadulibre.org#1": u'Grand Est',
"https://www.agendadulibre.org#23": u'Guadeloupe',
"https://www.agendadulibre.org#24": u'Guyane',
"https://www.agendadulibre.org#17": u'Hauts-de-France',
"https://www.agendadulibre.org#12": u'Île-de-France',
"https://www.agendadulibre.org#31": u'Internet',
"https://www.agendadulibre.org#26": u'La Réunion',
"https://www.agendadulibre.org#25": u'Martinique',
"https://www.agendadulibre.org#28": u'Mayotte',
"https://www.agendadulibre.org#4": u'Normandie',
"https://www.agendadulibre.org#2": u'Nouvelle-Aquitaine',
"https://www.agendadulibre.org#13": u'Occitanie',
"https://www.agendadulibre.org#18": u'Pays de la Loire',
"https://www.agendadulibre.org#21": u'Provence-Alpes-Côte d\'Azur',
"https://www.agendadulibre.be": u'--Belgique--',
"https://www.agendadulibre.be#11": u'Antwerpen',
"https://www.agendadulibre.be#10": u'Brabant wallon',
"https://www.agendadulibre.be#9": u'Bruxelles-Capitale',
"https://www.agendadulibre.be#8": u'Hainaut',
"https://www.agendadulibre.be#7": u'Liege',
"https://www.agendadulibre.be#6": u'Limburg',
"https://www.agendadulibre.be#5": u'Luxembourg',
"https://www.agendadulibre.be#4": u'Namur',
"https://www.agendadulibre.be#3": u'Oost-Vlaanderen',
"https://www.agendadulibre.be#2": u'Vlaams-Brabant',
"https://www.agendadulibre.be#1": u'West-Vlaanderen',
"https://www.agendadulibre.ch": u'--Suisse--',
"https://www.agendadulibre.ch#15": u'Appenzell Rhodes-Extérieures',
"https://www.agendadulibre.ch#16": u'Appenzell Rhodes-Intérieures',
"https://www.agendadulibre.ch#19": u'Argovie',
"https://www.agendadulibre.ch#13": u'Bâle-Campagne',
"https://www.agendadulibre.ch#12": u'Bâle-Ville',
"https://www.agendadulibre.ch#2": u'Berne',
"https://www.agendadulibre.ch#10": u'Fribourg',
"https://www.agendadulibre.ch#25": u'Genève',
"https://www.agendadulibre.ch#8": u'Glaris',
"https://www.agendadulibre.ch#18": u'Grisons',
"https://www.agendadulibre.ch#26": u'Jura',
"https://www.agendadulibre.ch#3": u'Lucerne',
"https://www.agendadulibre.ch#24": u'Neuchâtel',
"https://www.agendadulibre.ch#7": u'Nidwald',
"https://www.agendadulibre.ch#6": u'Obwald',
"https://www.agendadulibre.ch#17": u'Saint-Gall',
"https://www.agendadulibre.ch#14": u'Schaffhouse',
"https://www.agendadulibre.ch#5": u'Schwytz',
"https://www.agendadulibre.ch#11": u'Soleure',
"https://www.agendadulibre.ch#21": u'Tessin',
"https://www.agendadulibre.ch#20": u'Thurgovie',
"https://www.agendadulibre.ch#4": u'Uri',
"https://www.agendadulibre.ch#23": u'Valais',
"https://www.agendadulibre.ch#22": u'Vaud',
"https://www.agendadulibre.ch#9": u'Zoug',
"https://www.agendadulibre.ch#1": u'Zurich',
}.items())])
CONFIG = BackendConfig(Value('region', label=u'Region', choices=region_choices))
def create_default_browser(self):
choice = self.config['region'].get().split('#')
selected_region = '' if len(choice) < 2 else choice[-1]
return self.create_browser(website=choice[0], region=selected_region)
def search_events(self, query):
return self.browser.list_events(query.start_date,
query.end_date,
query.city,
query.categories)
def list_events(self, date_from, date_to=None):
return self.browser.list_events(date_from, date_to)
def get_event(self, event_id):
return self.browser.get_event(event_id)
def fill_obj(self, event, fields):
event = self.browser.get_event(event.id, event)
choice = self.config['region'].get().split('#')
selected_region = '' if len(choice) < 2 else choice[-1]
if selected_region == '23':
event.timezone = 'America/Guadeloupe'
elif selected_region == '24':
event.timezone = 'America/Guyana'
elif selected_region == '26':
event.timezone = 'Indian/Reunion'
elif selected_region == '25':
event.timezone = 'America/Martinique'
else:
event.timezone = 'Europe/Paris'
return event
OBJECTS = {AgendadulibreBrowser: fill_obj}
pages.py 0000664 0000000 0000000 00000017053 14575653726 0032466 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2014 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
import re
from datetime import time, datetime, date
from woob.browser.pages import HTMLPage, pagination
from woob.browser.elements import ItemElement, ListElement, method
from woob.browser.filters.standard import Regexp, CleanText, DateTime, Env, Format, BrowserURL
from woob.browser.filters.html import Link, XPath, CleanHTML
from woob.tools.date import parse_french_date
from .calendar import AgendaDuLibreCalendarEvent
class EventPage(HTMLPage):
@method
class get_event(ItemElement):
klass = AgendaDuLibreCalendarEvent
obj_id = Env('_id')
obj_url = BrowserURL('event_page', _id=Env('_id'))
obj_summary = Format('%s %s',
CleanText('//meta[@name="geo:placename"]/@content'),
CleanText('//meta[@name="DC:title"]/@content'))
obj_description = CleanHTML('//div[@class="description"]')
obj_location = CleanText('//p[@class="full_address"]/span[1]')
obj_city = CleanText('//meta[@name="geo:placename"]/@content')
def obj_start_date(self):
m = re.findall(r'\w* \w* \d?\d \w* \d{4} \w* \d{2}h\d{2}', CleanText('(//p)[1]')(self), re.UNICODE)
if m:
return DateTime(Regexp(CleanText('(//p)[1]'),
'\w* \w* (\d?\d \w* \d{4}) \w* (\d{2}h\d{2}).*',
'\\1 \\2',
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
def obj_end_date(self):
m = re.findall(r'\w* \w* \d?\d \w* \d{4} \w* \d{2}h\d{2}', CleanText('(//p)[1]')(self), re.UNICODE)
if m:
if len(m) == 1:
return DateTime(Regexp(CleanText('(//p)[1]'),
r'\w* \w* (\d?\d \w* \d{4}) \w* \d{2}h\d{2} \w* (\d{2}h\d{2})',
'\\1 \\2',
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
else:
return DateTime(Regexp(CleanText('(//p)[1]'),
r'\w* \w* (\d?\d \w* \d{4}) \w* (\d{2}h\d{2})',
'\\1 \\2',
nth=-1,
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
class EventListPage(HTMLPage):
@pagination
@method
class list_events(ListElement):
item_xpath = '//td[starts-with(@class, "day")]/ul/li'
def next_page(self):
m = re.match('.*/events\?start_date=(\d{4})-(\d{2})-(\d{2})(®ion=.*)?', self.page.url)
if m:
start = date(year=int(m.group(1)), month=int(m.group(2)), day=1)
region = m.group(4) if m.group(4) else ''
try:
next_month = start.replace(month=start.month + 1)
except ValueError:
if start.month == 12:
next_month = start.replace(year=start.year + 1, month=1)
else:
raise
if (self.env['date_to'] is None and
start < self.env['max_date']) or\
(self.env['date_to'] is not None and
datetime.combine(next_month, time.min) < self.env['date_to']):
return '/events?start_date=%s%s' % (next_month.strftime("%Y-%m-%d"), region)
class item(ItemElement):
klass = AgendaDuLibreCalendarEvent
def condition(self):
return len(XPath('.')(self.el)) > 0 and \
('current-month' in XPath('./ancestor::td/@class')(self.el)[0])
obj_id = Format('%s#%s',
CleanText('./ancestor::td/div[@class="day_number"]'),
Regexp(Link('./a'), '/events/(.*)'))
obj_city = CleanText('./a/strong[@class="city"]')
obj_summary = CleanText('./a')
def obj_start_date(self):
m = re.findall(r'\w* \w* \d?\d \w* \d{4} \w* \d{2}h\d{2}', CleanText('./@title')(self), re.UNICODE)
if m:
return DateTime(Regexp(CleanText('./@title'),
'\w* \w* (\d?\d \w* \d{4}) \w* (\d{2}h\d{2}).*',
'\\1 \\2',
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
def obj_end_date(self):
m = re.findall(r'\w* \w* \d?\d \w* \d{4} \w* \d{2}h\d{2}', CleanText('./@title')(self), re.UNICODE)
if m:
if len(m) == 1:
return DateTime(Regexp(CleanText('./@title'),
r'\w* \w* (\d?\d \w* \d{4}) \w* \d{2}h\d{2} \w* (\d{2}h\d{2})',
'\\1 \\2',
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
else:
return DateTime(Regexp(CleanText('./@title'),
r'\w* \w* (\d?\d \w* \d{4}) \w* (\d{2}h\d{2})',
'\\1 \\2',
nth=-1,
flags=re.UNICODE),
parse_func=parse_french_date,
strict=False)(self)
def validate(self, obj):
return (self.is_valid_event(obj, self.env['city'], self.env['categories']) and
self.is_event_in_valid_period(obj.start_date, self.env['date_from'], self.env['date_to']))
def is_valid_event(self, event, city, categories):
if city and city != '' and city.upper() != event.city.upper():
return False
if categories and len(categories) > 0 and event.category not in categories:
return False
return True
def is_event_in_valid_period(self, event_date, date_from, date_to):
if event_date >= datetime.combine(date_from, time.min):
if not date_to:
return True
else:
if event_date <= date_to:
return True
return False
requirements.txt 0000664 0000000 0000000 00000000014 14575653726 0034266 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre woob ~= 3.2
test.py 0000664 0000000 0000000 00000002516 14575653726 0032344 0 ustar 00root root 0000000 0000000 woob-master-5f3d558793b537a74480241ac6981479f5938cd3-modules-agendadulibre/modules/agendadulibre # -*- coding: utf-8 -*-
# Copyright(C) 2014 Bezleputh
#
# This file is part of a woob module.
#
# This woob module is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This woob module 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this woob module. If not, see .
from woob.tools.test import BackendTest
from woob.tools.value import Value
from datetime import datetime
class AgendadulibreTest(BackendTest):
MODULE = 'agendadulibre'
def setUp(self):
if not self.is_backend_configured():
self.backend.config['region'] = Value(value='https://www.agendadulibre.org')
def test_agendadulibre(self):
l = list(self.backend.list_events(datetime.now()))
assert len(l)
event = self.backend.get_event(l[0].id)
self.assertTrue(event.url, 'URL for event "%s" not found: %s' % (event.id, event.url))