amazon.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. # -*- coding: utf-8 -*-
  2. import datetime
  3. import dateutil
  4. import dateutil.tz
  5. import dingguo
  6. import email
  7. import ioex
  8. import re
  9. def parse_order_confirmation_mail(mail):
  10. assert isinstance(mail, email.message.Message)
  11. msg_text = mail.get_payload()[0].get_payload(decode = True).decode('utf-8')
  12. if not u'Amazon.de Bestellbestätigung' in msg_text:
  13. raise Exception('no amazon order confirmation')
  14. orders = []
  15. order_texts = re.split(ur'={32,}', msg_text)[1:-1]
  16. for order_text in order_texts:
  17. order_id = re.search(r'Bestellnummer #(.+)', order_text).group(1)
  18. order_date_formatted = re.search(ur'Aufgegeben am (.+)', order_text, re.UNICODE).group(1)
  19. mail_date = dateutil.parser.parse(mail['date'])
  20. with ioex.setlocale('de_DE.UTF-8'):
  21. order_date = datetime.datetime.strptime(
  22. order_date_formatted.encode('utf-8'),
  23. '%d. %B %Y',
  24. )
  25. assert order_date.date() == mail_date.date()
  26. order = dingguo.Order(
  27. u'amazon.de',
  28. order_id,
  29. order_date.date(),
  30. )
  31. for articles_text in re.findall(
  32. ur'Bestellte\(r\) Artikel:\s+'
  33. + ur'([\W\w]+?)\s+'
  34. + ur'(Lieferung \d|_{10,})',
  35. order_text,
  36. re.UNICODE,
  37. ):
  38. for article_text in re.split(ur'\n\t*\n', articles_text[0]):
  39. article_match = re.match(
  40. ur' *((?P<quantity>\d+) x )?(?P<name>.*)\n'
  41. + ur'( *von (?P<authors>.*)\n)?'
  42. + ur' *(?P<price_brutto_currency>[A-Z]+) (?P<price_brutto>\d+,\d+)\n'
  43. + ur'( *Zustand: (?P<state>.*)\n)?'
  44. + ur' *Verkauft von: (?P<reseller>.*)'
  45. + ur'(\n *Versand durch (?P<shipper>.*))?',
  46. article_text,
  47. re.MULTILINE | re.UNICODE
  48. )
  49. assert article_match is not None, repr(article_text)
  50. article = article_match.groupdict()
  51. order.items.append(dingguo.Article(
  52. name = article['name'],
  53. price_brutto = dingguo.Sum(
  54. float(article['price_brutto'].replace(',', '.')),
  55. article['price_brutto_currency']
  56. ),
  57. quantity = int(article['quantity']) if article['quantity'] else 1,
  58. authors = article['authors'].split(',') if article['authors'] else None,
  59. state = article['state'],
  60. reseller = article['reseller'],
  61. shipper = article['shipper'],
  62. ))
  63. assert re.search(
  64. ur'Verpackung und Versand: \w+ (\d+,\d+)',
  65. order_text,
  66. ).group(1) == '0,00'
  67. shipping_match = re.finditer(
  68. ur'(Zustellung|Lieferung voraussichtlich):\s+(?P<t>[\W\w]+?)\s+'
  69. + ur'Versandart',
  70. order_text if len(order_texts) > 1 else msg_text,
  71. re.UNICODE,
  72. )
  73. for shipping_attr in [m.groupdict() for m in shipping_match]:
  74. r = shipping_attr['t'].split('-')
  75. with ioex.setlocale('de_AT.UTF-8'):
  76. s = datetime.datetime.strptime(
  77. r[0].strip().encode('utf8'),
  78. '%A, %d. %B',
  79. ).replace(
  80. year = order.order_date.year,
  81. tzinfo = dateutil.tz.gettz('Europe/Berlin'),
  82. )
  83. assert s.date() > order.order_date
  84. if len(r) == 1:
  85. e = s + datetime.timedelta(days = 1)
  86. else:
  87. with ioex.setlocale('de_AT.UTF-8'):
  88. e = datetime.datetime.strptime(
  89. r[1].strip().encode('utf8'),
  90. '%A, %d. %B',
  91. ).replace(year = s.year, tzinfo = s.tzinfo)
  92. e += datetime.timedelta(days = 1)
  93. assert e > s
  94. order.items.append(dingguo.Shipping(
  95. price_brutto = dingguo.Sum(0.0, u'EUR'),
  96. estimated_arrival_time = ioex.datetimeex.Period(start = s, end = e),
  97. ))
  98. orders.append(order)
  99. return orders