Browse Source

indiegogo: support reward

Fabian Peter Hammerle 7 years ago
parent
commit
630198eb73

+ 13 - 16
dingguo/__init__.py

@@ -2,29 +2,20 @@
 
 import copy
 import datetime
+import ioex.datetimeex
 import pytz
 import re
 import yaml
 import yaml.representer
 
 yaml.Dumper.add_representer(unicode, yaml.representer.SafeRepresenter.represent_unicode)
-
 yaml.Loader.add_constructor(
     u'tag:yaml.org,2002:str',
     lambda loader, node: unicode(loader.construct_scalar(node)),
     )
-
-def yaml_construct_timestamp(loader, node):
-    loaded_dt = loader.construct_yaml_timestamp(node)
-    if type(loaded_dt) is datetime.datetime and loaded_dt.tzinfo is None:
-        timezone_match = re.search(
-            ur'[\+-](?P<h>\d{2}):(?P<m>\d{2})$',
-            loader.construct_python_unicode(node),
-            )
-        if timezone_match:
-            loaded_dt = loaded_dt.replace(tzinfo = pytz.utc)
-    return loaded_dt
-yaml.Loader.add_constructor(u'tag:yaml.org,2002:timestamp', yaml_construct_timestamp)
+ioex.datetimeex.register_yaml_timestamp_constructor(yaml.Loader)
+ioex.datetimeex.Period.register_yaml_constructor(yaml.Loader)
+ioex.datetimeex.Period.register_yaml_representer(yaml.Dumper)
 
 class _Object(object):
 
@@ -213,9 +204,9 @@ class Order(_YamlInitConstructor):
             order_id = unicode(order_id)
         assert type(order_id) is unicode
         self.order_id = order_id
-        if type(order_date) is datetime.datetime:
-            order_date = order_date.date()
-        assert type(order_date) is datetime.date
+        assert type(order_date) in [datetime.date, datetime.datetime]
+        if type(order_date) is datetime.datetime and order_date.tzinfo:
+            order_date = order_date.astimezone(pytz.utc)
         self.order_date = order_date
         if customer_id is not None:
             assert type(customer_id) is unicode
@@ -382,6 +373,7 @@ class Transportation(Item):
             departure_point = None,
             destination_point = None,
             distance = None,
+            estimated_arrival_time = None,
             passenger = None,
             route_map = None,
             ticket_url = None,
@@ -416,6 +408,11 @@ class Transportation(Item):
         if ticket_url is not None:
             assert type(ticket_url) is unicode
             self.ticket_url = ticket_url
+        if estimated_arrival_time is not None:
+            assert type(estimated_arrival_time) is ioex.datetimeex.Period
+            assert not estimated_arrival_time.start.tzinfo is None
+            assert not estimated_arrival_time.end.tzinfo is None
+            self.estimated_arrival_time = estimated_arrival_time
 
 class Shipping(Transportation):
 

+ 1 - 1
dingguo/parser/amazon.py

@@ -31,7 +31,7 @@ def parse_order_confirmation_mail(mail):
         order = dingguo.Order(
             u'amazon.de',
             order_id,
-            order_date
+            order_date.date(),
             )
 
         for articles_text in re.findall(

+ 1 - 1
dingguo/parser/banggood.py

@@ -25,7 +25,7 @@ def parse_order_confirmation_mail(mail):
         order = dingguo.Order(
                 platform = u'banggood',
                 order_id = order_attr['id'],
-                order_date = datetime.datetime.strptime(order_attr['date'], '%A %d %B, %Y'),
+                order_date = datetime.datetime.strptime(order_attr['date'], '%A %d %B, %Y').date(),
                 customer_id = None,
                 )
 

+ 1 - 1
dingguo/parser/hm.py

@@ -26,7 +26,7 @@ def parse_order_confirmation_mail(mail):
     user = ''.join([c if (c in string.printable) else '' for c in order_attr['user']])
     order = dingguo.Order(
             customer_id = user,
-            order_date = datetime.datetime.strptime(order_attr['date'], '%d%m%y'),
+            order_date = datetime.datetime.strptime(order_attr['date'], '%d%m%y').date(),
             order_id = u'%s-%s' % (user, order_attr['date']),
             platform = u'hm',
             )

+ 27 - 6
dingguo/parser/indiegogo.py

@@ -6,6 +6,7 @@ import dateutil.parser
 import dingguo
 import email.message
 import ioex
+import pytz
 import re
 
 def parse_order_confirmation_mail(mail):
@@ -18,13 +19,13 @@ def parse_order_confirmation_mail(mail):
         raise Exception()
 
     email_recipient_address = mail['delivered-to'].decode('utf8')
-    email_date = datetime.datetime.utcfromtimestamp(
-        # seconds since the Epoch in UTC
-        email.utils.mktime_tz(email.utils.parsedate_tz(mail['date']))
-        )
+    email_date = dateutil.parser.parse(mail['date'])
     order = dingguo.Order(
         platform = u'indiegogo',
-        order_id = '%s-%s' % (email_recipient_address, email_date.isoformat()),
+        order_id = '%s-%sZ' % (
+            email_recipient_address,
+            email_date.astimezone(pytz.utc).replace(tzinfo = None).isoformat(),
+            ),
         order_date = email_date,
         customer_id = email_recipient_address,
         )
@@ -32,6 +33,7 @@ def parse_order_confirmation_mail(mail):
     doc = BeautifulSoup.BeautifulSoup(html)
 
     campaign_name_tag = doc.find(text = re.compile(u'vielen Dank für deinen Beitrag')).findNext('a')
+    reward_label_tag = doc.find(text = re.compile(u'Perk:'))
 
     order.items.append(dingguo.Contribution(
         campaign = dingguo.Campaign(
@@ -42,7 +44,26 @@ def parse_order_confirmation_mail(mail):
         price_brutto = dingguo.Sum.parse_text(
             doc.find(text = re.compile(u'Unterstützung:')).findNext().text
             ),
-        reward = None,
+        reward = reward_label_tag.findNext().text if reward_label_tag else None,
         ))
 
+    shipping_costs_label_tag = doc.find(text = re.compile(u'Versand:'))
+    if shipping_costs_label_tag:
+        with ioex.setlocale('de_AT.utf8'):
+            estimated_arrival_start = datetime.datetime.strptime(
+                    doc.find(text = re.compile('Voraussichtliche Lieferung:')).findNext().text,
+                    '%B %Y'
+                    ).replace(tzinfo = email_date.tzinfo)
+        order.items.append(dingguo.Shipping(
+            price_brutto = dingguo.Sum.parse_text(
+                shipping_costs_label_tag.findNext().text
+                ),
+            estimated_arrival_time = ioex.datetimeex.Period(
+                start = estimated_arrival_start,
+                end = (estimated_arrival_start + datetime.timedelta(days = 32)).replace(day = 1),
+                ),
+            destination_point = doc.find(text = re.compile('Lieferadresse:'))
+                .findNext().text.replace('\r\n', '\n'),
+            ))
+
     return [order]

+ 6 - 5
dingguo/parser/kickstarter.py

@@ -6,6 +6,7 @@ import dateutil.parser
 import dingguo
 import email.message
 import ioex
+import pytz
 import re
 
 def parse_order_confirmation_mail(mail):
@@ -18,13 +19,13 @@ def parse_order_confirmation_mail(mail):
         raise Exception()
 
     email_recipient_address = mail['delivered-to'].decode('utf8')
-    email_date = datetime.datetime.utcfromtimestamp(
-        # seconds since the Epoch in UTC
-        email.utils.mktime_tz(email.utils.parsedate_tz(mail['date']))
-        )
+    email_date = dateutil.parser.parse(mail['date'])
     order = dingguo.Order(
         platform = u'kickstarter',
-        order_id = '%s-%s' % (email_recipient_address, email_date.isoformat()),
+        order_id = '%s-%sZ' % (
+            email_recipient_address,
+            email_date.astimezone(pytz.utc).replace(tzinfo = None).isoformat(),
+            ),
         order_date = email_date,
         customer_id = email_recipient_address,
         )

+ 3 - 7
dingguo/parser/lieferservice.py

@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 
 import datetime
+import dateutil.parser
 import dingguo
 import email
 import email.utils
@@ -17,7 +18,7 @@ def parse_order_confirmation_mail(mail):
     if not 'Lieferservice.at' in text:
         raise Exception('no lieferservice.at confirmation')
     msg_text = mail.get_payload()[0].get_payload(decode = True).decode('utf-8')
-    
+
     order_match = re.search(
             ur'(Your order|Ihre Bestellung) \(.+\) (at|bei) (?P<restaurant>.*)\s+'
                 + ur'(Your order reference is|Ihre Bestellnummer lautet): (?P<order_id>.*)\s+'
@@ -30,15 +31,10 @@ def parse_order_confirmation_mail(mail):
             )
     order_match_groups = order_match.groupdict()
 
-    import time
-    order_date = datetime.datetime.fromtimestamp(
-            time.mktime(email.utils.parsedate(mail['Date']))
-            )
-
     order = dingguo.Order(
         u'lieferservice.at',
         order_match_groups['order_id'].strip(),
-        order_date
+        order_date = dateutil.parser.parse(mail['Date']),
         )
 
     restaurant = order_match_groups['restaurant'].strip('"')

+ 1 - 1
dingguo/parser/mytaxi.py

@@ -61,7 +61,7 @@ def parse_order_confirmation_mail(mail):
     order = dingguo.Order(
         u'mytaxi',
         order_id,
-        arrival_time,
+        order_date = arrival_time.date(),
         )
     with ioex.setlocale('en_US.UTF-8'):
         order.items.append(dingguo.TaxiRide(

+ 1 - 1
dingguo/parser/oebb.py

@@ -46,7 +46,7 @@ def parse_order_confirmation_mail(mail):
     order = dingguo.Order(
         u'oebb',
         order_match_groups['order_id'],
-        order_date,
+        order_date.date(),
         customer_id = order_match_groups['customer_id'],
         )
 

+ 1 - 1
dingguo/parser/uber.py

@@ -39,7 +39,7 @@ def parse_order_confirmation_mail(mail):
             datetime.datetime.strptime(
                 doc.find(attrs = {'class': 'date'}).text,
                 '%B %d, %Y',
-                ),
+                ).date(),
             )
 
         departure_time_tag = doc.find(attrs = {'class': 'from time'})

+ 7 - 5
dingguo/parser/wienerlinien.py

@@ -1,10 +1,12 @@
 # -*- coding: utf-8 -*-
 
 import datetime
+import dateutil.parser
 import dingguo
 import email
 import email.utils
 import ioex
+import pytz
 import re
 
 class UtcOffsetTimezone(datetime.tzinfo):
@@ -49,13 +51,13 @@ def parse_order_confirmation_mail(mail):
     order_match_groups = order_match.groupdict()
 
     email_recipient_address = mail['delivered-to'].decode('utf8')
-    email_date = datetime.datetime.utcfromtimestamp(
-        # seconds since the Epoch in UTC
-        email.utils.mktime_tz(email.utils.parsedate_tz(mail['date']))
-        )
+    email_date = dateutil.parser.parse(mail['date'])
     order = dingguo.Order(
         platform = u'wiener_linien',
-        order_id = '%s-%s' % (email_recipient_address, email_date.isoformat()),
+        order_id = '%s-%sZ' % (
+            email_recipient_address,
+            email_date.astimezone(pytz.utc).replace(tzinfo = None).isoformat(),
+            ),
         order_date = email_date,
         customer_id = email_recipient_address,
         )

+ 3 - 1
dingguo/parser/yipbee.py

@@ -2,6 +2,7 @@
 
 import BeautifulSoup
 import datetime
+import dateutil.parser
 import dingguo
 import email
 import ioex
@@ -29,7 +30,8 @@ def parse_order_confirmation_mail(mail):
     order = dingguo.Order(
         u'yipbee',
         order_match_groups['order_id'],
-        datetime.datetime.strptime(order_match_groups['order_time'], '%d.%m.%Y %H:%M:%S'),
+        datetime.datetime.strptime(order_match_groups['order_time'], '%d.%m.%Y %H:%M:%S')
+            .replace(tzinfo = dateutil.parser.parse(mail['Date']).tzinfo),
         )
 
     for article_match in re.finditer(

+ 1 - 0
setup.py

@@ -18,6 +18,7 @@ setup(
         ],
     scripts = glob.glob('scripts/*'),
     install_requires = [
+        'ioex>=0.5',
         'pdfminer>=20140328', 
         'pytz',
         ],

+ 22 - 11
tests/test_yaml.py

@@ -2,12 +2,13 @@
 
 import pytest
 
+import datetime
+import difflib
+import dingguo
+import ioex.datetimeex
 import os
 import pytz
 import yaml
-import dingguo
-import difflib
-import datetime
 
 def get_figure_a():
     return dingguo.Figure(12.3, u'km')
@@ -101,6 +102,10 @@ def get_transportation():
             valid_from = datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')),
             valid_until = datetime.datetime(2016, 7, 14, 18, 50, 4, 0, tzinfo = pytz.utc),
             ticket_url = u'https://www.example.com',
+            estimated_arrival_time = ioex.datetimeex.Period(
+                start = pytz.timezone('Europe/Vienna').localize(datetime.datetime(2016, 7, 24, 23, 47, 2)),
+                end = pytz.utc.localize(datetime.datetime(2016, 7, 24, 23, 48, 5)),
+                ),
             )
 
 def get_shipping():
@@ -242,7 +247,7 @@ items:
 - !item
   name: item β
   price_brutto: !sum '20.45 EUR'
-order_date: 2016-05-08
+order_date: 2016-05-08 00:18:17
 order_id: id
 platform: platformπ
 """],
@@ -268,6 +273,9 @@ width: !scalar '1.23 m'
 departure_point: home
 destination_point: city
 distance: !distance '3.21 km'
+estimated_arrival_time: !period
+  end: 2016-07-24 23:48:05+00:00
+  start: 2016-07-24 23:47:02+02:00
 name: ticket
 passenger: !person
   first_name: Fabian Peter
@@ -297,13 +305,13 @@ platformπ:
     customer_id: customer
     discounts: []
     items: []
-    order_date: 2016-05-08
+    order_date: 2016-05-08 00:18:17
     order_id: id
     platform: platformπ
   order_b: !order
     discounts: []
     items: []
-    order_date: 2015-05-08
+    order_date: 2015-05-08 00:18:17
     order_id: order_b
     platform: platformπ
 γάμμα:
@@ -311,7 +319,7 @@ platformπ:
     customer_id: ρώ
     discounts: []
     items: []
-    order_date: 2014-05-08
+    order_date: 2014-05-08 00:18:17
     order_id: order_βήτα
     platform: γάμμα
 """],
@@ -389,6 +397,9 @@ passenger: !person
 ticket_url: https://www.example.com
 valid_from: 2016-07-14 13:50:04+01:05
 valid_until: 2016-07-14 18:50:04+00:00
+estimated_arrival_time: !period
+  end: 2016-07-24T23:48:05+00:00
+  start: 2016-07-24T23:47:02+02:00
 """],
     [get_shipping(), u"""!shipping
 destination_point: home
@@ -416,7 +427,7 @@ items:
 - !item
   name: item β
   price_brutto: !sum '20.45 EUR'
-order_date: 2016-05-08
+order_date: 2016-05-08 00:18:17
 order_id: id
 platform: platformπ
 """)
@@ -463,13 +474,13 @@ platformπ:
   id: !order
     customer_id: customer
     discounts: []
-    order_date: 2016-05-08
+    order_date: 2016-05-08 00:18:17
     order_id: id
     platform: platformπ
   order_b: !order
     customer_id: null
     items: []
-    order_date: 2015-05-08
+    order_date: 2015-05-08 00:18:17
     order_id: order_b
     platform: platformπ
 γάμμα:
@@ -477,7 +488,7 @@ platformπ:
     customer_id: ρώ
     discounts: []
     items: []
-    order_date: 2014-05-08
+    order_date: 2014-05-08 00:18:17
     order_id: order_βήτα
     platform: γάμμα
 """)