diff --git a/infomentor/__init__.py b/infomentor/__init__.py
index 38c8aa7..e04f80f 100644
--- a/infomentor/__init__.py
+++ b/infomentor/__init__.py
@@ -1 +1 @@
-#from infomentor.__main__ import *
+# from infomentor.__main__ import *
diff --git a/infomentor/__main__.py b/infomentor/__main__.py
index 546ee46..ba09a49 100644
--- a/infomentor/__main__.py
+++ b/infomentor/__main__.py
@@ -8,13 +8,15 @@ import requests
from infomentor import db, model, connector, informer, config
-logformat = "{asctime} - {name:25s}[{filename:20s}:{lineno:3d}] - {levelname:8s} - {message}"
+logformat = (
+ "{asctime} - {name:25s}[{filename:20s}:{lineno:3d}] - {levelname:8s} - {message}"
+)
def logtofile():
from logging.handlers import RotatingFileHandler
- handler = RotatingFileHandler("log.txt", maxBytes=1024*1024, backupCount=10)
+ handler = RotatingFileHandler("log.txt", maxBytes=1024 * 1024, backupCount=10)
logging.basicConfig(
level=logging.INFO, format=logformat, handlers=[handler], style="{"
)
@@ -29,109 +31,78 @@ def parse_args(arglist):
parser.add_argument(
"--nolog", action="store_true", help="print log instead of logging to file"
)
- parser.add_argument("--adduser", action='store_true', help="add user")
- parser.add_argument("--addfake", action='store_true', help="add fake")
- parser.add_argument("--addpushover", action='store_true', help="add pushover")
- parser.add_argument("--addmail", action='store_true', help="add mail")
- parser.add_argument("--addcalendar", action='store_true', help="add icloud calendar")
- parser.add_argument("--addinvitation", action='store_true', help="add calendar invitation")
- parser.add_argument("--test", action="store_true", help="test")
- parser.add_argument("--username", type=str, nargs='?', help="username")
+ parser.add_argument("--username", type=str, nargs="?", help="infomentor username")
+ parser.add_argument("--password", type=str, nargs="?", help="infomentor password")
+ parser.add_argument("--fake", action="store_true", help="add fake")
+ parser.add_argument("--pushover", type=str, nargs="?", help="pushover user id")
+ parser.add_argument("--mail", type=str, nargs="?", help="e-mail for notification")
+ parser.add_argument(
+ "--iclouduser", type=str, nargs="?", help="icloud calendar user"
+ )
+ parser.add_argument(
+ "--icloudpwd", type=str, nargs="?", help="icloud calendar password"
+ )
+ parser.add_argument(
+ "--icloudcalendar", type=str, nargs="?", help="icloud calendar calendar"
+ )
+ parser.add_argument(
+ "--invitationmail", type=str, nargs="?", help="e-mail for notification"
+ )
args = parser.parse_args(arglist)
return args
-def add_user(username):
+def perform_user_update(args):
+ username = args.username
session = db.get_db()
existing_user = (
session.query(model.User).filter(model.User.name == username).one_or_none()
)
if existing_user is not None:
- print("user exists, change pw")
+ print("user exists, changing pw")
else:
print(f"Adding user: {username}")
- import getpass
+ if args.password is None:
+ import getpass
+
+ password = getpass.getpass(prompt="Password: ")
+ else:
+ password = args.password
- password = getpass.getpass(prompt="Password: ")
if existing_user is not None:
existing_user.password = password
else:
user = model.User(name=username, password=password)
session.add(user)
- session.commit()
+ if args.pushover is not None:
+ user.notification = model.Notification(
+ ntype=model.Notification.Types.PUSHOVER, info=args.pushover
+ )
+ elif args.mail:
+ user.notification = model.Notification(
+ ntype=model.Notification.Types.EMAIL, info=args.mail
+ )
+ elif args.fake:
+ user.notification = model.Notification(
+ ntype=model.Notification.Types.FAKE, info=""
+ )
-def add_pushover(username):
- session = db.get_db()
- user = session.query(model.User).filter(model.User.name == username).one_or_none()
- if user is None:
- print("user does not exist")
- return
- else:
- print(f"Adding PUSHOVER for user: {username}")
- id = input("PUSHOVER ID: ")
- user.notification = model.Notification(
- ntype=model.Notification.Types.PUSHOVER, info=id
- )
- session.commit()
+ if (
+ args.iclouduser is not None
+ and args.icloudpwd is not None
+ and args.icloudcalendar is not None
+ ):
+ user.icalendar = model.ICloudCalendar(
+ icloud_user=args.iclouduser,
+ password=args.icloudpwd,
+ calendarname=args.icloudcalendar,
+ )
+ if args.invitationmail:
+ user.invitation = model.Invitation(email=mail)
-def add_fake(username):
- session = db.get_db()
- user = session.query(model.User).filter(model.User.name == username).one_or_none()
- if user is None:
- print("user does not exist")
- return
- else:
- print(f"Adding FAKE for user: {username}")
- user.notification = model.Notification(ntype=model.Notification.Types.FAKE, info="")
- session.commit()
-
-
-def add_calendar(username):
- session = db.get_db()
- user = session.query(model.User).filter(model.User.name == username).one_or_none()
- if user is None:
- print("user does not exist")
- return
- else:
- print(f"Adding icloud calendar for user: {username}")
- id = input("Apple ID: ")
- import getpass
-
- password = getpass.getpass(prompt="iCloud Password: ")
- calendar = input("Calendar: ")
- user.icalendar = model.ICloudCalendar(
- icloud_user=id, password=password, calendarname=calendar
- )
- session.commit()
-
-def add_invitation(username):
- session = db.get_db()
- user = session.query(model.User).filter(model.User.name == username).one_or_none()
- if user is None:
- print("user does not exist")
- return
- else:
- print(f"Adding Mail for calendar invitation for user: {username}")
- mail = input("Mail: ")
- user.invitation = model.Invitation(email=mail)
- session.commit()
-
-
-def add_mail(username):
- session = db.get_db()
- user = session.query(model.User).filter(model.User.name == username).one_or_none()
- if user is None:
- print("user does not exist")
- return
- else:
- print(f"Adding MAIL for user: {username}")
- address = input("MAIL ADDRESS: ")
- user.notification = model.Notification(
- ntype=model.Notification.Types.EMAIL, info=address
- )
session.commit()
@@ -140,7 +111,7 @@ def notify_users():
session = db.get_db()
cfg = config.load()
if cfg["healthchecks"]["url"] != "":
- requests.get(cfg["healthchecks"]["url"] + '/start')
+ requests.get(cfg["healthchecks"]["url"] + "/start")
for user in session.query(model.User):
logger.info("==== USER: %s =====", user.name)
@@ -195,8 +166,6 @@ def notify_users():
def main():
args = parse_args(sys.argv[1:])
- if args.test:
- return
if args.nolog:
logtoconsole()
else:
@@ -206,20 +175,10 @@ def main():
try:
lock = flock.flock()
if not lock.aquire():
- logger.info("EXITING - PREVIOUS IS RUNNING")
+ logger.info("EXITING - PREVIOUS IS STILL RUNNING")
raise Exception()
- if args.addfake:
- add_fake(args.username)
- elif args.adduser:
- add_user(args.username)
- elif args.addpushover:
- add_pushover(args.username)
- elif args.addmail:
- add_mail(args.username)
- elif args.addcalendar:
- add_calendar(args.username)
- elif args.addinvitation:
- add_invitation(args.username)
+ if args.username:
+ perform_user_update(args)
else:
notify_users()
except Exception as e:
@@ -228,64 +187,6 @@ def main():
finally:
logger.info("EXITING--------------------- %s", os.getpid())
-def run_notify():
- run_without_args(notify_users)
-
-def run_adduser():
- run_with_args(add_user)
-
-def run_addfake():
- run_with_args(add_fake)
-
-def run_addpushover():
- run_with_args(add_pushover)
-
-def run_addmail():
- run_with_args(add_mail)
-
-def run_addcalendar():
- run_with_args(add_calendar)
-
-def run_addinvitation():
- run_with_args(add_invitation)
-
-
-def run_with_args(fct):
- args = parse_args(sys.argv[1:])
- logtofile()
- logger = logging.getLogger("Infomentor Notifier")
- logger.info("STARTING-------------------- %s", os.getpid())
- lock = flock.flock()
- try:
- if not lock.aquire():
- logger.info("EXITING - PREVIOUS IS RUNNING")
- raise Exception()
- if args.username is None:
- print('Provide Username using --username')
- raise Exception('No username provided')
- fct(args.username)
- except Exception as e:
- logger.info("Exceptional exit")
- logger.exception("Info")
- finally:
- logger.info("EXITING--------------------- %s", os.getpid())
-
-def run_without_args(fct):
- args = parse_args(sys.argv[1:])
- logtofile()
- logger = logging.getLogger("Infomentor Notifier")
- logger.info("STARTING-------------------- %s", os.getpid())
- try:
- lock = flock.flock()
- if not lock.aquire():
- logger.info("EXITING - PREVIOUS IS RUNNING")
- raise Exception()
- fct()
- except Exception as e:
- logger.info("Exceptional exit")
- logger.exception("Info")
- finally:
- logger.info("EXITING--------------------- %s", os.getpid())
if __name__ == "__main__":
main()
diff --git a/infomentor/config.py b/infomentor/config.py
index 052495a..51e88ad 100644
--- a/infomentor/config.py
+++ b/infomentor/config.py
@@ -4,9 +4,7 @@ import os
_config = None
_defaults = {
- "pushover": {
- "apikey": "",
- },
+ "pushover": {"apikey": ""},
"general": {
"secretkey": "",
"baseurl": "",
@@ -14,16 +12,11 @@ _defaults = {
"im1url": "https://im1.infomentor.de/Germany/Germany/Production",
"mimrul": "https://mein.infomentor.de",
},
- "smtp": {
- "server": "",
- "username": "",
- "password": "",
- },
- "healthchecks": {
- "url": "",
- },
+ "smtp": {"server": "", "username": "", "password": ""},
+ "healthchecks": {"url": ""},
}
+
def _set_defaults(config):
config = _defaults
diff --git a/infomentor/connector.py b/infomentor/connector.py
index 310dbdc..ffa5bce 100644
--- a/infomentor/connector.py
+++ b/infomentor/connector.py
@@ -18,11 +18,13 @@ from infomentor import model, config
class InfomentorFile(object):
"""Represent a file which is downloaded"""
- def __init__(self, directory, filename, seed=''):
+ def __init__(self, directory, filename, seed=""):
if directory is None:
raise Exception("directory is required")
self.filename = filename
- self.randomid = hashlib.sha1('{}{}'.format(filename, seed).encode('utf-8')).hexdigest()
+ self.randomid = hashlib.sha1(
+ "{}{}".format(filename, seed).encode("utf-8")
+ ).hexdigest()
self.directory = directory
@property
@@ -266,7 +268,7 @@ class Infomentor(object):
self.logger.info("fetching news")
self._do_post(self._mim_url("Communication/News/GetNewsList"))
news_json = self.get_json_return()
- return news_json['items']
+ return news_json["items"]
def get_news_article(self, news_entry):
"""Receive all the article information"""
diff --git a/infomentor/icloudcalendar.py b/infomentor/icloudcalendar.py
index b746be3..16495d2 100644
--- a/infomentor/icloudcalendar.py
+++ b/infomentor/icloudcalendar.py
@@ -20,7 +20,6 @@ class iCloudConnector(object):
password = None
propfind_principal = ''
propfind_calendar_home_set = " "
-
def __init__(self, username, password, **kwargs):
self.username = username
@@ -30,7 +29,6 @@ class iCloudConnector(object):
self.discover()
self.get_calendars()
-
# discover: connect to icloud using the provided credentials and discover
#
# 1. The principal URL
@@ -45,10 +43,7 @@ class iCloudConnector(object):
headers = {"Depth": "1"}
auth = HTTPBasicAuth(self.username, self.password)
principal_response = self.repeated_request(
- "PROPFIND",
- self.icloud_url,
- auth=auth,
- data=self.propfind_principal
+ "PROPFIND", self.icloud_url, auth=auth, data=self.propfind_principal
)
# Parse the resulting XML response
soup = BeautifulSoup(principal_response.content, "lxml")
@@ -60,15 +55,20 @@ class iCloudConnector(object):
# Next use the discovery URL to get more detailed properties - such as
# the calendar-home-set
home_set_response = self.repeated_request(
- "PROPFIND",
- discovery_url,
- auth=auth,
- data=self.propfind_calendar_home_set,
+ "PROPFIND", discovery_url, auth=auth, data=self.propfind_calendar_home_set
)
_logger.debug("Result code: {}".format(home_set_response.status_code))
if home_set_response.status_code != 207:
- _logger.error("Failed to retrieve calendar-home-set {}".format(home_set_response.status_code))
- raise Exception("failed to retrieve calender home set {}".format(home_set_response.content))
+ _logger.error(
+ "Failed to retrieve calendar-home-set {}".format(
+ home_set_response.status_code
+ )
+ )
+ raise Exception(
+ "failed to retrieve calender home set {}".format(
+ home_set_response.content
+ )
+ )
# And then extract the calendar-home-set URL
soup = BeautifulSoup(home_set_response.content, "lxml")
self.calendar_home_set_url = soup.find(
@@ -77,18 +77,20 @@ class iCloudConnector(object):
def repeated_request(self, *args, **kwargs):
for _ in range(0, 5):
- response = requests.request(
- *args, **kwargs
- )
+ response = requests.request(*args, **kwargs)
_logger.debug("Request result code: {}".format(response.status_code))
if response.status_code != 207:
- _logger.error("Failed to retrieve response: {}".format(response.status_code))
+ _logger.error(
+ "Failed to retrieve response: {}".format(response.status_code)
+ )
_logger.error("Retry")
time.sleep(0.25)
if response.status_code == 207:
break
else:
- raise Exception("failed to retrieve {} {}".format(response.content, response.headers))
+ raise Exception(
+ "failed to retrieve {} {}".format(response.content, response.headers)
+ )
return response
# get_calendars
@@ -135,4 +137,3 @@ class iCloudConnector(object):
):
# to do
pass
-
diff --git a/infomentor/informer.py b/infomentor/informer.py
index 28c91c7..d138a46 100755
--- a/infomentor/informer.py
+++ b/infomentor/informer.py
@@ -56,13 +56,13 @@ class Informer(object):
for news_entry in newslist:
news = (
session.query(model.News)
- .filter(model.News.news_id == news_entry['id'])
- .filter(model.News.date == news_entry['publishedDate'])
+ .filter(model.News.news_id == news_entry["id"])
+ .filter(model.News.date == news_entry["publishedDate"])
.with_parent(self.user, "news")
.one_or_none()
)
if news is not None:
- self.logger.debug('Skipping news %s', news_entry['id'])
+ self.logger.debug("Skipping news %s", news_entry["id"])
continue
news = self.im.get_news_article(news_entry)
self._notify_news(news)
@@ -71,7 +71,7 @@ class Informer(object):
def _notify_news(self, news):
if self.user.notification is None:
- self.logger.debug('Warn: no notification for user')
+ self.logger.debug("Warn: no notification for user")
return
if self.user.notification.ntype == model.Notification.Types.PUSHOVER:
self._notify_news_pushover(news)
@@ -93,7 +93,9 @@ class Informer(object):
for attachment in news.attachments:
fid, fname = attachment.localpath.split("/")
text += """
Attachment {0}: {2}/{1}
""".format(
- fname, urllib.parse.quote(attachment.localpath), cfg["general"]["baseurl"]
+ fname,
+ urllib.parse.quote(attachment.localpath),
+ cfg["general"]["baseurl"],
)
parsed_date = dateparser.parse(news.date)
now = datetime.datetime.now()
@@ -177,7 +179,9 @@ class Informer(object):
for attachment in hw.attachments:
fid, fname = attachment.localpath.split("/")
text += """
Attachment {0}: {2}/{1}
""".format(
- fname, urllib.parse.quote(attachment.localpath), cfg["general"]["baseurl"]
+ fname,
+ urllib.parse.quote(attachment.localpath),
+ cfg["general"]["baseurl"],
)
if len(text) > 900:
url = self._make_site(text)
@@ -240,37 +244,38 @@ class Informer(object):
def _send_invitation(self, calobj, to, fr="infomentor@09a.de"):
event = calobj.subcomponents[0]
- eml_body = event['description']
- eml_body_bin = event['description']
- msg = MIMEMultipart('mixed')
- msg['Reply-To']=fr
- msg['Subject'] = event['summary']
- msg['From'] = fr
- msg['To'] = to
+ eml_body = event["description"]
+ eml_body_bin = event["description"]
+ msg = MIMEMultipart("mixed")
+ msg["Reply-To"] = fr
+ msg["Subject"] = event["summary"]
+ msg["From"] = fr
+ msg["To"] = to
- part_email = MIMEText(eml_body,"html")
- part_email_text = MIMEText(eml_body,"plain")
- part_cal = MIMEText(calobj.to_ical().decode('utf-8'),'calendar;method=REQUEST')
+ part_email = MIMEText(eml_body, "html")
+ part_email_text = MIMEText(eml_body, "plain")
+ part_cal = MIMEText(calobj.to_ical().decode("utf-8"), "calendar;method=REQUEST")
- msgAlternative = MIMEMultipart('alternative')
+ msgAlternative = MIMEMultipart("alternative")
msg.attach(msgAlternative)
- ical_atch = MIMEBase('application/ics',' ;name="%s"'%("invite.ics"))
- ical_atch.set_payload(calobj.to_ical().decode('utf-8'))
+ ical_atch = MIMEBase("application/ics", ' ;name="%s"' % ("invite.ics"))
+ ical_atch.set_payload(calobj.to_ical().decode("utf-8"))
encoders.encode_base64(ical_atch)
- ical_atch.add_header('Content-Disposition', 'attachment; filename="%s"'%("invite.ics"))
+ ical_atch.add_header(
+ "Content-Disposition", 'attachment; filename="%s"' % ("invite.ics")
+ )
- eml_atch = MIMEBase('text/plain','')
- eml_atch.set_payload('')
+ eml_atch = MIMEBase("text/plain", "")
+ eml_atch.set_payload("")
encoders.encode_base64(eml_atch)
- eml_atch.add_header('Content-Transfer-Encoding', "")
+ eml_atch.add_header("Content-Transfer-Encoding", "")
msg.attach(part_email)
msg.attach(part_email_text)
msg.attach(part_cal)
self._send_mail(msg)
-
def _setup_icloudconnector(self):
if self.cal is None:
try:
@@ -284,17 +289,19 @@ class Informer(object):
self.logger.warn("using icloud")
except Exception as e:
self.logger.exception("using icloud dummy connector")
+
class Dummy(object):
def add_event(self, *args, **kwargs):
pass
+
self.cal = Dummy()
-
+
def _write_icalendar(self, calend):
try:
self._setup_icloudconnector()
self.cal.add_event(calend.to_ical())
except Exception as e:
- self.logger.exception('Calendar failed')
+ self.logger.exception("Calendar failed")
def update_calendar(self):
session = db.get_db()
@@ -304,7 +311,9 @@ class Informer(object):
calentries = self.im.get_calendar()
for entry in calentries:
self.logger.debug(entry)
- uid = str(uuid.uuid5(uuid.NAMESPACE_URL, "infomentor_{}".format(entry["id"])))
+ uid = str(
+ uuid.uuid5(uuid.NAMESPACE_URL, "infomentor_{}".format(entry["id"]))
+ )
event_details = self.im.get_event(entry["id"])
calend = Calendar()
event = Event()
@@ -319,13 +328,13 @@ class Informer(object):
event.add("dtend", dateparser.parse(entry["end"]).date())
description = event_details["notes"]
- eventinfo = event_details['info']
+ eventinfo = event_details["info"]
new_cal_entry = calend.to_ical().replace(b"\r", b"")
new_cal_hash = hashlib.sha1(new_cal_entry).hexdigest()
- for res in eventinfo['resources']:
+ for res in eventinfo["resources"]:
f = self.im.download_file(res["url"], directory="files")
description += """\nAttachment {0}: {2}/{1}""".format(
- res['title'], urllib.parse.quote(f), cfg["general"]["baseurl"]
+ res["title"], urllib.parse.quote(f), cfg["general"]["baseurl"]
)
event.add("description", description)
@@ -364,4 +373,4 @@ class Informer(object):
self.user.calendarentries.append(calendarentry)
session.commit()
except Exception as e:
- self.logger.exception('Calendar failed')
+ self.logger.exception("Calendar failed")
diff --git a/infomentor/model.py b/infomentor/model.py
index 98c150d..c87ce94 100755
--- a/infomentor/model.py
+++ b/infomentor/model.py
@@ -252,8 +252,5 @@ class Invitation(ModelBase):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
-
def __repr__(self):
- return "" % (
- self.email,
- )
+ return "" % (self.email,)