Skip to content

Commit

Permalink
move number parse to component
Browse files Browse the repository at this point in the history
  • Loading branch information
ljmerza committed Nov 17, 2022
1 parent 4072fd9 commit a90865c
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 23 deletions.
4 changes: 1 addition & 3 deletions custom_components/email/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@
CONF_IMAP_PORT = 'imap_port'
CONF_EMAIL_FOLDER = 'folder'
CONF_SHOW_ALL = 'show_all'
CONF_SSL = 'ssl'

ATTR_COUNT = 'count'
ATTR_EMAILS = 'emails'
ATTR_TRACKING_NUMBERS = 'tracking_numbers'
CONF_SSL = 'ssl'

EMAIL_ATTR_FROM = 'from'
EMAIL_ATTR_SUBJECT = 'subject'
Expand Down
4 changes: 2 additions & 2 deletions custom_components/email/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
],
"requirements": [
"beautifulsoup4==4.7.1",
"imapclient==2.1.0",
"imapclient==2.3.1",

This comment has been minimized.

Copy link
@IvanNik

IvanNik Nov 18, 2022

Will we have a release?
IMAP clisent doesn't work in the latest HA, not sure if this is the reason..
@ljmerza

"mail-parser==3.9.3"
],
"version": "2.14.1"
"version": "3.0.0"
}
7 changes: 4 additions & 3 deletions custom_components/email/parsers/home_depot.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ def parse_home_depot(email):

try:
tracking_number = element.text
_LOGGER.error(tracking_number)
isNan = math.isnan(int(tracking_number))

if not isNan and tracking_number not in tracking_numbers:
tracking_numbers.append(tracking_number)
stripped_number = tracking_number.rstrip()

if not isNan and stripped_number not in tracking_numbers:
tracking_numbers.append(stripped_number)
except:
pass

Expand Down
Empty file modified custom_components/email/parsers/manta_sleep.py
100644 → 100755
Empty file.
100 changes: 85 additions & 15 deletions custom_components/email/sensor.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Support for Google - Calendar Event Devices."""
from datetime import timedelta
import logging
import re

from imapclient import IMAPClient
from mailparser import parse_from_bytes
Expand All @@ -12,7 +13,7 @@

from .const import (
CONF_EMAIL, CONF_PASSWORD, CONF_SHOW_ALL, CONF_IMAP_SERVER,
CONF_IMAP_PORT, CONF_SSL, CONF_EMAIL_FOLDER, ATTR_EMAILS, ATTR_COUNT,
CONF_IMAP_PORT, CONF_SSL, CONF_EMAIL_FOLDER,
ATTR_TRACKING_NUMBERS, EMAIL_ATTR_FROM, EMAIL_ATTR_SUBJECT,
EMAIL_ATTR_BODY)

Expand Down Expand Up @@ -94,6 +95,73 @@
vol.Required(CONF_SHOW_ALL, default=False): cv.boolean,
})

TRACKING_NUMBER_CARD_URLS = {
'ups': "https://www.ups.com/track?loc=en_US&tracknum=",
'usps': "https://tools.usps.com/go/TrackConfirmAction?tLabels=",
'fedex': "https://www.fedex.com/apps/fedextrack/?tracknumbers=",
'dhl': 'https://www.logistics.dhl/us-en/home/tracking/tracking-parcel.html?submit=1&tracking-id=',
'swiss_post': 'https://www.swisspost.ch/track?formattedParcelCodes=',
'unknown': 'https://www.google.com/search?q=',
}

def find_carrier(tracking_number, email_domain):
"""Try to compute the carrier of a given tracking number / email domain"""
link = ""
carrier = ""

isNumber = False
try:
val = int(tracking_number)
isNumber = True
except ValueError:
pass

length = len(tracking_number) if not isNumber else 0

if bool(re.search('^1Z', tracking_number)):
link = TRACKING_NUMBER_CARD_URLS["ups"]
carrier = "UPS"

elif bool(re.search('CN$', tracking_number)):
link = TRACKING_NUMBER_CARD_URLS["usps"]
carrier = "USPS"

else:
if email_domain == EMAIL_DOMAIN_UPS:
link = TRACKING_NUMBER_CARD_URLS["ups"]
carrier = "UPS"
elif email_domain == EMAIL_DOMAIN_FEDEX:
link = TRACKING_NUMBER_CARD_URLS["fedex"]
carrier = "FedEx"
elif email_domain == EMAIL_DOMAIN_USPS:
link = TRACKING_NUMBER_CARD_URLS["usps"]
carrier = "USPS"
elif email_domain == EMAIL_DOMAIN_DHL:
link = TRACKING_NUMBER_CARD_URLS["dhl"]
carrier = "DHL"
elif email_domain == EMAIL_DOMAIN_SWISS_POST:
link = TRACKING_NUMBER_CARD_URLS["swiss_post"]
carrier = "Swiss Post"
else:
if (isNumber and (length == 12 or length == 15 or length == 20)):
link = TRACKING_NUMBER_CARD_URLS["fedex"]
carrier = "FedEx"
elif (isNumber and length == 22):
link = TRACKING_NUMBER_CARD_URLS["usp"]
carrier = "USPS"
elif (length > 25):
link = TRACKING_NUMBER_CARD_URLS["dh"]
carrier = "DHL"
else:
link = TRACKING_NUMBER_CARD_URLS["unknown"]
carrier = email_domain

return {
'tracking_number': tracking_number,
'carrier': carrier,
'origin': email_domain,
'link': f'{link}{tracking_number}',
}

def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Email platform."""
Expand All @@ -105,7 +173,9 @@ class EmailEntity(Entity):

def __init__(self, config):
"""Init the Email Entity."""
self._attr = None
self._attr = {
ATTR_TRACKING_NUMBERS: {}
}

self.imap_server = config[CONF_IMAP_SERVER]
self.imap_port = config[CONF_IMAP_PORT]
Expand All @@ -119,9 +189,9 @@ def __init__(self, config):
def update(self):
"""Update data from Email API."""
self._attr = {
ATTR_EMAILS: [],
ATTR_TRACKING_NUMBERS: {}
}

emails = []
server = IMAPClient(self.imap_server, use_uid=True, ssl=self.ssl)

Expand All @@ -142,20 +212,13 @@ def update(self):
EMAIL_ATTR_SUBJECT: mail.subject,
EMAIL_ATTR_BODY: mail.body
})
self._attr[ATTR_EMAILS].append({
EMAIL_ATTR_FROM: mail.from_,
EMAIL_ATTR_SUBJECT: mail.subject,
})
except Exception as err:
_LOGGER.error(
_LOGGER.warning(
'mailparser parse_from_bytes error: {}'.format(err))

except Exception as err:
_LOGGER.error('IMAPClient update error: {}'.format(err))

self._attr[ATTR_COUNT] = len(emails)
self._attr[ATTR_TRACKING_NUMBERS] = {}

# empty out all parser arrays
for ATTR, EMAIL_DOMAIN, parser in parsers:
self._attr[ATTR_TRACKING_NUMBERS][ATTR] = []
Expand All @@ -177,10 +240,16 @@ def update(self):

# remove duplicates
for ATTR, EMAIL_DOMAIN, parser in parsers:
tracking_domain = self._attr[ATTR_TRACKING_NUMBERS][ATTR]
if len(tracking_domain) > 0 and isinstance(tracking_domain[0], str):
tracking_numbers = self._attr[ATTR_TRACKING_NUMBERS][ATTR]
if len(tracking_numbers) > 0 and isinstance(tracking_numbers[0], str):
self._attr[ATTR_TRACKING_NUMBERS][ATTR] = list(
dict.fromkeys(tracking_domain))
dict.fromkeys(tracking_numbers))

# format tracking numbers to add carrier type
for ATTR, EMAIL_DOMAIN, parser in parsers:
tracking_numbers = self._attr[ATTR_TRACKING_NUMBERS][ATTR]
self._attr[ATTR_TRACKING_NUMBERS][ATTR] = list(map(lambda x: find_carrier(x, EMAIL_DOMAIN), tracking_numbers))
_LOGGER.debug(self._attr[ATTR_TRACKING_NUMBERS][ATTR])

server.logout()

Expand All @@ -195,8 +264,9 @@ def state(self):
return self._attr.get('count', 0)

@property
def device_state_attributes(self):
def extra_state_attributes(self):
"""Return the state attributes."""
_LOGGER.debug(self._attr)
return self._attr

@property
Expand Down

0 comments on commit a90865c

Please sign in to comment.