Browse Source

added support for contribution's to indiegogo without reward

Fabian Peter Hammerle 7 years ago
parent
commit
7aabaef37f

+ 26 - 5
dingguo/__init__.py

@@ -169,7 +169,7 @@ class Sum(ScalarFigure):
     @staticmethod
     def parse_text(text):
         match = re.search(
-            ur'^(?P<curr_pre>[\$])(?P<value>\d+(.\d{2})?)( (?P<currency>USD))?$',
+            ur'^(?P<curr_pre>[\$])(?P<value>\d+([\.,]\d{2})?)( (?P<currency>USD))?$',
             text,
             re.UNICODE,
             )
@@ -179,7 +179,7 @@ class Sum(ScalarFigure):
         if currency == u'$':
             currency = u'USD'
         return Sum(
-                value = float(attr['value']),
+                value = float(attr['value'].replace(',', '.')),
                 currency = currency,
                 )
 
@@ -256,14 +256,19 @@ class Campaign(_YamlInitConstructor):
             end = None,
             founder = None,
             name = None,
+            website_url = None,
             ):
         assert type(name) is unicode
         self.name = name
         assert type(founder) is unicode
         self.founder = founder
-        assert type(end) is datetime.datetime
-        assert not end.tzinfo is None, '%r' % end
-        self.end = end
+        if not end is None:
+            assert type(end) is datetime.datetime
+            assert not end.tzinfo is None, '%r' % end
+            self.end = end
+        if not website_url is None:
+            assert type(website_url) is unicode
+            self.website_url = website_url
 
 class Pledge(Item):
 
@@ -281,6 +286,22 @@ class Pledge(Item):
             assert type(reward) is unicode
             self.reward = reward
 
+class Contribution(Item):
+
+    yaml_tag = u'!contribution'
+
+    def __init__(self,
+            campaign = None,
+            reward = None,
+            **kwargs
+            ):
+        super(Contribution, self).__init__(**kwargs)
+        assert type(campaign) is Campaign
+        self.campaign = campaign
+        if not reward is None:
+            assert type(reward) is unicode
+            self.reward = reward
+
 class Article(Item):
 
     yaml_tag = u'!article'

+ 2 - 0
dingguo/parser/__init__.py

@@ -7,6 +7,7 @@ import amazon
 import banggood
 import hm
 import ikea
+import indiegogo
 import ingdiba
 import kickstarter
 import lieferservice
@@ -22,6 +23,7 @@ order_confirmation_parsers = [
     banggood.parse_order_confirmation_mail,
     hm.parse_order_confirmation_mail,
     ikea.parse_order_confirmation_mail,
+    indiegogo.parse_order_confirmation_mail,
     kickstarter.parse_order_confirmation_mail,
     lieferservice.parse_order_confirmation_mail,
     mytaxi.parse_order_confirmation_mail,

+ 48 - 0
dingguo/parser/indiegogo.py

@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+import BeautifulSoup
+import datetime
+import dateutil.parser
+import dingguo
+import email.message
+import ioex
+import re
+
+def parse_order_confirmation_mail(mail):
+
+    assert isinstance(mail, email.message.Message)
+
+    html = mail.get_payload()[1].get_payload(decode = True).decode('utf-8')
+
+    if not 'indiegogo' in html:
+        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']))
+        )
+    order = dingguo.Order(
+        platform = u'indiegogo',
+        order_id = '%s-%s' % (email_recipient_address, email_date.isoformat()),
+        order_date = email_date,
+        customer_id = email_recipient_address,
+        )
+
+    doc = BeautifulSoup.BeautifulSoup(html)
+
+    campaign_name_tag = doc.find(text = re.compile(u'vielen Dank für deinen Beitrag')).findNext('a')
+
+    order.items.append(dingguo.Contribution(
+        campaign = dingguo.Campaign(
+            name = campaign_name_tag.text,
+            founder = doc.find(text = re.compile(u'Kontaktiere den Kampagnenstarter')).findNext().text,
+            website_url = campaign_name_tag['href'],
+            ),
+        price_brutto = dingguo.Sum.parse_text(
+            doc.find(text = re.compile(u'Unterstützung:')).findNext().text
+            ),
+        reward = None,
+        ))
+
+    return [order]

+ 5 - 0
tests/test_.py

@@ -42,10 +42,13 @@ def test_person_last_name_string():
         p.last_name = 'äbc'
 
 @pytest.mark.parametrize(('text', 'sum'), [
+    [u'$1,23 USD',  dingguo.Sum(1.23, u'USD')],
     [u'$1.23 USD',  dingguo.Sum(1.23, u'USD')],
     [u'$30 USD',    dingguo.Sum(30.0, u'USD')],
+    [u'$30,00 USD', dingguo.Sum(30.0, u'USD')],
     [u'$30.00 USD', dingguo.Sum(30.0, u'USD')],
     [u'$8',         dingguo.Sum(8.0,  u'USD')],
+    [u'$8,00',      dingguo.Sum(8.0,  u'USD')],
     [u'$8.00',      dingguo.Sum(8.0,  u'USD')],
     ])
 def test_sum_parse_text(text, sum):
@@ -54,6 +57,8 @@ def test_sum_parse_text(text, sum):
 @pytest.mark.parametrize(('text'), [
     u'pre$1.23 USD',
     u'$1.23 USDpost',
+    u'$1#23 USD',
+    u'1#23 USD',
     ])
 def test_sum_parse_text_fail(text):
     with pytest.raises(Exception):

+ 18 - 1
tests/test_comparison.py

@@ -97,6 +97,18 @@ def get_pledge_b():
             price_brutto = dingguo.Sum(4.0, u'EUR'),
             )
 
+def get_contribution_a():
+    return dingguo.Contribution(
+            campaign = get_campaign_a(),
+            price_brutto = dingguo.Sum(10.0, u'EUR'),
+            )
+
+def get_contribution_b():
+    return dingguo.Contribution(
+            campaign = get_campaign_a(),
+            price_brutto = dingguo.Sum(4.0, u'EUR'),
+            )
+
 def get_person_a():
     return dingguo.Person(
         first_name = u'Fabian Peter',
@@ -119,6 +131,8 @@ def get_shipping():
     [dingguo.Figure(1, u'mm'), dingguo.Figure(1, u'mm')],
     [get_campaign_a(), get_campaign_a()],
     [get_campaign_b(), get_campaign_b()],
+    [get_contribution_a(), get_contribution_a()],
+    [get_contribution_b(), get_contribution_b()],
     [get_discount_a(), get_discount_a()],
     [get_discount_b(), get_discount_b()],
     [get_item_a(), get_item_a()],
@@ -145,6 +159,8 @@ def test_eq(a, b):
 
 @pytest.mark.parametrize('a,b', [
     [dingguo.Figure(1, u'mm'), dingguo.Figure(2, u'mm')],
+    [get_contribution_a(), get_contribution_b()],
+    [get_contribution_a(), get_item_b()],
     [get_discount_a(), get_discount_b()],
     [get_item_a(), get_item_b()],
     [get_order_a(), get_order_a(items = False)],
@@ -152,7 +168,8 @@ def test_eq(a, b):
     [get_order_a(), get_order_c()],
     [get_order_b(), get_order_c()],
     [get_person_a(), get_person_b()],
-    [get_pledge_a(), get_order_b()],
+    [get_pledge_a(), get_contribution_b()],
+    [get_pledge_a(), get_item_b()],
     [get_pledge_a(), get_pledge_b()],
     ])
 def test_neq(a, b):

+ 1 - 0
tests/test_parser.py

@@ -14,6 +14,7 @@ test_data_path = os.path.join(project_root_path, 'tests', 'data')
     ('banggood', os.path.join(test_data_path, 'banggood', '1.eml')),
     ('hm', os.path.join(test_data_path, 'hm', '1.eml')),
     ('ikea', os.path.join(test_data_path, 'ikea', '1.eml')),
+    ('indiegogo', os.path.join(test_data_path, 'indiegogo', 'mail_without_reward.eml')),
     ('kickstarter', os.path.join(test_data_path, 'kickstarter', 'mail_orbitkey.eml')),
     ('lieferservice.at', os.path.join(test_data_path, 'lieferservice.at', 'mail_1.eml')),
     ('mytaxi', os.path.join(test_data_path, 'mytaxi', 'mail_1.eml')),

+ 24 - 0
tests/test_parser_indiegogo.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+import pytest
+
+import dingguo.parser.indiegogo
+import email
+import glob
+import os
+import test_yaml
+import yaml
+
+project_root_path = os.path.realpath(os.path.join(__file__, '..', '..'))
+test_data_path = os.path.join(project_root_path, 'tests', 'data', 'indiegogo')
+
+@pytest.mark.parametrize('mail_path', glob.glob(os.path.join(test_data_path, '*.eml')))
+def test_parse_confirmation_mail(mail_path):
+    with open(mail_path) as mail:
+        parsed_orders = dingguo.parser.indiegogo.parse_order_confirmation_mail(
+                email.message_from_file(mail)
+                )
+    with open(mail_path.replace('.eml', '.yml')) as yaml_file:
+        expected_orders = yaml.load(yaml_file.read())
+    assert expected_orders == parsed_orders, \
+            test_yaml.yaml_diff(expected_orders, parsed_orders)

+ 44 - 4
tests/test_yaml.py

@@ -45,20 +45,34 @@ def get_person_b():
         last_name = u'贵姓',
         )
 
-def get_campaign():
+def get_campaign_a():
     return dingguo.Campaign(
             name = u'campaign a',
             founder = u'company',
             end = datetime.datetime(2016, 7, 23, 9, 23, 17, tzinfo = pytz.timezone('Europe/Vienna')),
             )
 
+def get_campaign_b():
+    return dingguo.Campaign(
+            founder = u'company',
+            name = u'campaign without end',
+            website_url = u'http://campaign.com',
+            )
+
 def get_pledge():
     return dingguo.Pledge(
-            campaign = get_campaign(),
+            campaign = get_campaign_a(),
             price_brutto = dingguo.Sum(10.0, u'EUR'),
             reward = u'great',
             )
 
+def get_contribution():
+    return dingguo.Contribution(
+            campaign = get_campaign_a(),
+            price_brutto = dingguo.Sum(10.0, u'EUR'),
+            reward = u'product',
+            )
+
 def get_article():
     return dingguo.Article(
             authors = ['a', 'b'],
@@ -186,10 +200,15 @@ def yaml_diff(a, b):
     [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'],
     [get_sum_a(), u"!sum '1.23 EUR'\n"],
     [get_sum_b(), u"!sum '20.45 EUR'\n"],
-    [get_campaign(), u"""!campaign
+    [get_campaign_a(), u"""!campaign
 end: 2016-07-23 09:23:17+01:05
 founder: company
 name: campaign a
+"""],
+    [get_campaign_b(), u"""!campaign
+founder: company
+name: campaign without end
+website_url: http://campaign.com
 """],
     [get_pledge(), u"""!pledge
 campaign: !campaign
@@ -198,6 +217,14 @@ campaign: !campaign
   name: campaign a
 price_brutto: !sum '10.0 EUR'
 reward: great
+"""],
+    [get_contribution(), u"""!contribution
+campaign: !campaign
+  end: 2016-07-23 09:23:17+01:05
+  founder: company
+  name: campaign a
+price_brutto: !sum '10.0 EUR'
+reward: product
 """],
     [get_order_a(), u"""!order
 customer_id: customer
@@ -315,10 +342,15 @@ def test_to_yaml(source_object, expected_yaml):
     [get_sum_a(), u"!sum '1.23 EUR'"],
     [get_sum_a(), u"!sum '1.23 EUR'"],
     [get_sum_a(), u"!sum 1.23 EUR"],
-    [get_campaign(), u"""!campaign
+    [get_campaign_a(), u"""!campaign
 name: campaign a
 founder: company
 end: 2016-07-23 09:23:17+01:05
+"""],
+    [get_campaign_b(), u"""!campaign
+founder: company
+name: campaign without end
+website_url: http://campaign.com
 """],
     [get_pledge(), u"""!pledge
 campaign: !campaign
@@ -327,6 +359,14 @@ campaign: !campaign
   end: 2016-07-23 09:23:17+01:05
 price_brutto: !sum '10.0 EUR'
 reward: great
+"""],
+    [get_contribution(), u"""!contribution
+campaign: !campaign
+  end: 2016-07-23 09:23:17+01:05
+  founder: company
+  name: campaign a
+price_brutto: !sum '10.0 EUR'
+reward: product
 """],
     [get_sum_a(), u"!sum 1.23 €"],
     [[get_person_a(), get_person_b()], u"""