wienerlinien.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. # -*- coding: utf-8 -*-
  2. import datetime
  3. import dateutil.parser
  4. import dingguo
  5. import email
  6. import email.utils
  7. import ioex
  8. import pytz
  9. import re
  10. class UtcOffsetTimezone(datetime.tzinfo):
  11. def __init__(self, seconds):
  12. assert type(seconds) is int
  13. self.seconds = seconds
  14. def utcoffset(self, dt):
  15. return datetime.timedelta(seconds = self.seconds)
  16. def dst(self, dt):
  17. return None
  18. def tzname(self, dt):
  19. return self.__class__.__name__ + '(seconds = %d)' % self.seconds
  20. def parse_order_confirmation_mail(mail):
  21. assert isinstance(mail, email.message.Message)
  22. msg_text = mail.get_payload(decode = True).decode('utf8')
  23. if not 'Wiener Linien' in msg_text:
  24. raise Exception()
  25. order_match = re.search(
  26. r'(?P<name>.*Ticket.*)\s+'
  27. + r'Valid from: (?P<valid_from>\d{1,2} \w+ \d{4} \d{1,2}:\d{2})\s+'
  28. + r'(Valid until: (?P<valid_until>\d{1,2} \w+ \d{4} \d{1,2}:\d{2})\s+)?'
  29. + r'Type: (?P<type>.* ticket)\s+'
  30. + r'For\:\s+'
  31. + r'(?P<passenger_first_name>Fabian Peter)\s+'
  32. + r'(?P<passenger_last_name>Hammerle)\s+'
  33. + ur'Price: (?P<currency>€)(?P<price>\d+.\d{2})\s+'
  34. + r'Quantity: (?P<quantity>1)\s+'
  35. ,
  36. msg_text,
  37. re.MULTILINE | re.UNICODE
  38. )
  39. if not order_match:
  40. print(repr(msg_text))
  41. order_match_groups = order_match.groupdict()
  42. email_recipient_address = mail['delivered-to'].decode('utf8')
  43. email_date = dateutil.parser.parse(mail['date'])
  44. order = dingguo.Order(
  45. platform = u'wiener_linien',
  46. order_id = '%s-%sZ' % (
  47. email_recipient_address,
  48. email_date.astimezone(pytz.utc).replace(tzinfo = None).isoformat(),
  49. ),
  50. order_date = email_date,
  51. customer_id = email_recipient_address,
  52. )
  53. assert int(order_match_groups['quantity']) == 1
  54. ticket_url_match = re.search(
  55. ur'following link:\s+(http[^\s]+)',
  56. msg_text,
  57. re.MULTILINE | re.UNICODE,
  58. )
  59. with ioex.setlocale('en_US.UTF-8'):
  60. timezone = UtcOffsetTimezone(email.utils.parsedate_tz(mail['date'])[9])
  61. order.items.append(dingguo.Transportation(
  62. name = order_match_groups['name'],
  63. price_brutto = dingguo.Sum(
  64. float(order_match_groups['price']),
  65. order_match_groups['currency'],
  66. ),
  67. passenger = dingguo.Person(
  68. first_name = order_match_groups['passenger_first_name'],
  69. last_name = order_match_groups['passenger_last_name'],
  70. ),
  71. valid_from = datetime.datetime.strptime(order_match_groups['valid_from'], '%d %B %Y %H:%M')
  72. .replace(tzinfo = timezone),
  73. valid_until = datetime.datetime.strptime(order_match_groups['valid_until'], '%d %B %Y %H:%M')
  74. .replace(tzinfo = timezone) if order_match_groups['valid_until'] else None,
  75. ticket_url = ticket_url_match.group(1) if ticket_url_match else None,
  76. ))
  77. return [order]