update format using black

This commit is contained in:
2019-05-08 05:06:37 +02:00
parent ad9eb25df0
commit 693711abc1
12 changed files with 488 additions and 408 deletions

View File

@@ -50,3 +50,19 @@ python -m infomentor --addcalendar <username>
The login process is a bit scary and mostly hacked. It happens often on the first run, that the login is not ready, the second run then should work without errors.
The script shall be run every 10 minutes, that will keep the session alive and minimize errors.
TODO:
::
{'id': 1342049, 'title': 'Jade LZK HSU 1. und 2. Klasse', 'time': '10:30 - 11:30', 'notes': '', 'enumType': 'Custom1', 'type': 'cal-custom1', 'info': {'id': 0, 'type': None,
'resources': [{'id': 589680, 'fileType': 'docx', 'title': 'Lernziele HSU das Jahr.docx', 'url': '/Resources/Resource/Download/589680?api=IM2', 'fileTypeName': 'Word processor', 'apiType': 'IM2', 'connectionId': 1342049, 'connectionType':
'Calendar'}]}, 'establishmentName': None, 'date': '18.01.2019', 'isEditable': False, 'isDeletable': False, 'startDate': '2019-01-18', 'startTime': '10:30', 'endDate': '2019-01-18', 'endTime': '11:30', 'allDayEvent': False, 'resourcesNeed
ingConnection': None, 'thirdPartyApiCalendarEventId': None, 'thirdPartyApiCalendarSeriesId': None, 'thirdPartyApiCalendarId': None, 'attendeeIds': None}

View File

@@ -7,45 +7,50 @@ import os
from infomentor import db, model, connector, informer
logformat='{asctime} - {name:25s} - {levelname:8s} - {message}'
logformat = "{asctime} - {name:25s} - {levelname:8s} - {message}"
def logtofile():
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler('log.txt', maxBytes=51200, backupCount=5)
handler = RotatingFileHandler("log.txt", maxBytes=51200, backupCount=5)
logging.basicConfig(
level=logging.INFO,
format=logformat,
handlers=[handler],
style='{'
)
def logtoconsole():
logging.basicConfig(
level=logging.DEBUG,
format=logformat,
style='{'
level=logging.INFO, format=logformat, handlers=[handler], style="{"
)
def logtoconsole():
logging.basicConfig(level=logging.DEBUG, format=logformat, style="{")
def parse_args(arglist):
parser = argparse.ArgumentParser(description='Infomentor Grabber and Notifier')
parser.add_argument('--nolog', action='store_true', help='print log instead of logging to file')
parser.add_argument('--adduser', type=str, help='add user')
parser.add_argument('--addfake', type=str, help='add fake')
parser.add_argument('--addpushover', type=str, help='add pushover')
parser.add_argument('--addmail', type=str, help='add mail')
parser.add_argument('--addcalendar', type=str, help='add icloud calendar')
parser.add_argument('--test', action='store_true', help='test')
parser = argparse.ArgumentParser(description="Infomentor Grabber and Notifier")
parser.add_argument(
"--nolog", action="store_true", help="print log instead of logging to file"
)
parser.add_argument("--adduser", type=str, help="add user")
parser.add_argument("--addfake", type=str, help="add fake")
parser.add_argument("--addpushover", type=str, help="add pushover")
parser.add_argument("--addmail", type=str, help="add mail")
parser.add_argument("--addcalendar", type=str, help="add icloud calendar")
parser.add_argument("--test", action="store_true", help="test")
args = parser.parse_args(arglist)
return args
def add_user(username):
session = db.get_db()
existing_user = session.query(model.User).filter(model.User.name == username).one_or_none()
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, change pw")
else:
print(f'Adding user: {username}')
print(f"Adding user: {username}")
import getpass
password = getpass.getpass(prompt='Password: ')
password = getpass.getpass(prompt="Password: ")
if existing_user is not None:
existing_user.password = password
else:
@@ -58,98 +63,111 @@ 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')
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)
print(f"Adding PUSHOVER for user: {username}")
id = input("PUSHOVER ID: ")
user.notification = model.Notification(
ntype=model.Notification.Types.PUSHOVER, info=id
)
session.commit()
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')
print("user does not exist")
return
else:
print(f'Adding FAKE for user: {username}')
user.notification = model.Notification(ntype=model.Notification.Types.FAKE, info='')
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')
print("user does not exist")
return
else:
print(f'Adding icloud calendar for user: {username}')
id = input('Apple ID: ')
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)
password = getpass.getpass(prompt="iCloud Password: ")
calendar = input("Calendar: ")
user.icalendar = model.ICloudCalendar(
icloud_user=id, password=password, calendarname=calendar
)
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')
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)
print(f"Adding MAIL for user: {username}")
address = input("MAIL ADDRESS: ")
user.notification = model.Notification(
ntype=model.Notification.Types.EMAIL, info=address
)
session.commit()
def notify_users():
logger = logging.getLogger(__name__)
session = db.get_db()
for user in session.query(model.User):
logger.info('==== USER: %s =====', user.name)
if user.password == '':
logger.warning('User %s not enabled', user.name)
logger.info("==== USER: %s =====", user.name)
if user.password == "":
logger.warning("User %s not enabled", user.name)
continue
now = datetime.datetime.now()
im = connector.Infomentor(user.name)
im.login(user.password)
logger.info('User loggedin')
statusinfo = {'datetime': now, 'ok': False, 'info': '', 'degraded_count':0}
logger.info("User loggedin")
statusinfo = {"datetime": now, "ok": False, "info": "", "degraded_count": 0}
if user.apistatus is None:
user.apistatus = model.ApiStatus(**statusinfo)
logger.info('Former API status: %s', user.apistatus)
logger.info("Former API status: %s", user.apistatus)
try:
i = informer.Informer(user, im, logger=logger)
i.update_news()
i.update_homework()
i.update_calendar()
statusinfo['ok'] = True
statusinfo['degraded'] = False
statusinfo["ok"] = True
statusinfo["degraded"] = False
except Exception as e:
inforstr = 'Exception occured:\n{}:{}\n'.format(type(e).__name__, e)
statusinfo['ok'] = False
statusinfo['info'] = inforstr
inforstr = "Exception occured:\n{}:{}\n".format(type(e).__name__, e)
statusinfo["ok"] = False
statusinfo["info"] = inforstr
logger.exception("Something went wrong")
finally:
if user.apistatus.ok == True and statusinfo['ok'] == False:
logger.error('Switching to degraded state %s', user.name)
statusinfo['degraded_count'] = 1
if user.apistatus.ok == False and statusinfo['ok'] == False:
if user.apistatus.ok == True and statusinfo["ok"] == False:
logger.error("Switching to degraded state %s", user.name)
statusinfo["degraded_count"] = 1
if user.apistatus.ok == False and statusinfo["ok"] == False:
if user.apistatus.degraded_count == 1 and user.wantstatus:
im.send_status_update(statusinfo['info'])
im.send_status_update(statusinfo["info"])
try:
statusinfo['degraded_count'] = user.apistatus['degraded_count'] + 1
statusinfo["degraded_count"] = user.apistatus["degraded_count"] + 1
except Exception as e:
statusinfo['degraded_count'] = 1
if user.apistatus.ok == False and statusinfo['ok'] == True:
statusinfo['info'] = 'Works as expected, failed {} times'.format(user.apistatus.degraded_count)
statusinfo['degraded_count'] = 0
statusinfo["degraded_count"] = 1
if user.apistatus.ok == False and statusinfo["ok"] == True:
statusinfo["info"] = "Works as expected, failed {} times".format(
user.apistatus.degraded_count
)
statusinfo["degraded_count"] = 0
if user.wantstatus:
im.send_status_update(statusinfo['info'])
im.send_status_update(statusinfo["info"])
user.apistatus.updateobj(statusinfo)
logger.info('New API status: %s', user.apistatus)
logger.info("New API status: %s", user.apistatus)
session.commit()
@@ -161,12 +179,12 @@ def main():
logtoconsole()
else:
logtofile()
logger = logging.getLogger('Infomentor Notifier')
logger.info('STARTING-------------------- %s', os.getpid())
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')
logger.info("EXITING - PREVIOUS IS RUNNING")
raise Exception()
if args.addfake:
add_fake(args.addfake)
@@ -181,10 +199,11 @@ def main():
else:
notify_users()
except Exception as e:
logger.info('Exceptional exit')
logger.exception('Info')
logger.info("Exceptional exit")
logger.exception("Info")
finally:
logger.info('EXITING--------------------- %s', os.getpid())
logger.info("EXITING--------------------- %s", os.getpid())
if __name__ == "__main__":
main()

View File

@@ -5,21 +5,22 @@ _config = None
def _set_defaults(config):
config.add_section('pushover')
config.add_section('general')
config.add_section('smtp')
config['pushover']['apikey'] = ''
config['general']['secretkey'] = ''
config['general']['baseurl'] = ''
config['general']['adminmail'] = ''
config['general']['im1url'] = 'https://im1.infomentor.de/Germany/Germany/Production'
config['general']['mimurl'] = 'https://mein.infomentor.de'
config['smtp']['server'] = ''
config['smtp']['username'] = ''
config['smtp']['password'] = ''
config.add_section("pushover")
config.add_section("general")
config.add_section("smtp")
config["pushover"]["apikey"] = ""
config["general"]["secretkey"] = ""
config["general"]["baseurl"] = ""
config["general"]["adminmail"] = ""
config["general"]["im1url"] = "https://im1.infomentor.de/Germany/Germany/Production"
config["general"]["mimurl"] = "https://mein.infomentor.de"
config["smtp"]["server"] = ""
config["smtp"]["username"] = ""
config["smtp"]["password"] = ""
def load(cfg_file='infomentor.ini'):
'''Load the config from the file'''
def load(cfg_file="infomentor.ini"):
"""Load the config from the file"""
global _config
if _config is None:
_config = configparser.ConfigParser()
@@ -29,8 +30,9 @@ def load(cfg_file='infomentor.ini'):
_config.read(cfg_file)
return _config
def save(cfg_file='infomentor.ini'):
'''Write config to file'''
def save(cfg_file="infomentor.ini"):
"""Write config to file"""
global _config
with open(cfg_file, 'w+') as f:
with open(cfg_file, "w+") as f:
_config.write(f)

File diff suppressed because it is too large Load Diff

View File

@@ -4,14 +4,14 @@ from sqlalchemy.orm import sessionmaker
_session = None
def get_db(filename='infomentor.db'):
'''Get the database session for infomentor'''
def get_db(filename="infomentor.db"):
"""Get the database session for infomentor"""
global _session
if _session is None:
engine = create_engine(f'sqlite:///{filename}')
engine = create_engine(f"sqlite:///{filename}")
model.ModelBase.metadata.create_all(engine)
model.ModelBase.metadata.bind = engine
DBSession = sessionmaker(bind=engine)
_session = DBSession()
return _session

View File

@@ -1,44 +1,46 @@
import os
class flock(object):
'''A simple filelocking mechanism to prevent execution at the same time'''
filename = '.im.lock'
"""A simple filelocking mechanism to prevent execution at the same time"""
filename = ".im.lock"
def __init__(self):
'''Creates an object with the current pid'''
"""Creates an object with the current pid"""
self.pid = os.getpid()
def aquire(self):
'''Try to get the lock, if it fails it returns False'''
"""Try to get the lock, if it fails it returns False"""
if self.is_locked():
return False
with open(self.filename, 'w+') as f:
f.write('{}'.format(self.pid))
with open(self.filename, "w+") as f:
f.write("{}".format(self.pid))
return True
def release(self):
'''Release the lock'''
"""Release the lock"""
if self.own_lock():
os.unlink(self.filename)
def __del__(self):
'''Release on delete'''
"""Release on delete"""
self.release()
def own_lock(self):
'''Check if the lock is assigned to the current pid'''
"""Check if the lock is assigned to the current pid"""
lockinfo = self._get_lockinfo()
return lockinfo == self.pid
def is_locked(self):
'''Check if it is currently locked'''
"""Check if it is currently locked"""
lockinfo = self._get_lockinfo()
if not lockinfo:
return False
return self._is_process_active(lockinfo)
def _is_process_active(self, pid):
'''Check if the processed having the lock is still running'''
"""Check if the processed having the lock is still running"""
try:
os.kill(pid, 0)
return pid != self.pid
@@ -46,12 +48,11 @@ class flock(object):
return False
def _get_lockinfo(self):
'''Retrieve the information about the lock'''
"""Retrieve the information about the lock"""
try:
lock = {}
with open(self.filename, 'r') as f:
with open(self.filename, "r") as f:
pid = int(f.read().strip())
return pid
except Exception as e:
return False

View File

@@ -8,26 +8,27 @@ from lxml import etree
import requests
from requests.auth import HTTPBasicAuth
class iCloudConnector(object):
icloud_url = "https://caldav.icloud.com"
username = None
password = None
propfind_principal = (
u'''<?xml version="1.0" encoding="utf-8"?><propfind xmlns='DAV:'>'''
u'''<prop><current-user-principal/></prop></propfind>'''
u"""<?xml version="1.0" encoding="utf-8"?><propfind xmlns='DAV:'>"""
u"""<prop><current-user-principal/></prop></propfind>"""
)
propfind_calendar_home_set = (
u'''<?xml version="1.0" encoding="utf-8"?><propfind xmlns='DAV:' '''
u'''xmlns:cd='urn:ietf:params:xml:ns:caldav'><prop>'''
u'''<cd:calendar-home-set/></prop></propfind>'''
u"""<?xml version="1.0" encoding="utf-8"?><propfind xmlns='DAV:' """
u"""xmlns:cd='urn:ietf:params:xml:ns:caldav'><prop>"""
u"""<cd:calendar-home-set/></prop></propfind>"""
)
def __init__(self, username, password, **kwargs):
self.username = username
self.password = password
if 'icloud_url' in kwargs:
self.icloud_url = kwargs['icloud_url']
if "icloud_url" in kwargs:
self.icloud_url = kwargs["icloud_url"]
self.discover()
self.get_calendars()
@@ -42,45 +43,40 @@ class iCloudConnector(object):
def discover(self):
# Build and dispatch a request to discover the prncipal us for the
# given credentials
headers = {
'Depth': '1',
}
headers = {"Depth": "1"}
auth = HTTPBasicAuth(self.username, self.password)
principal_response = requests.request(
'PROPFIND',
"PROPFIND",
self.icloud_url,
auth=auth,
headers=headers,
data=self.propfind_principal.encode('utf-8')
data=self.propfind_principal.encode("utf-8"),
)
if principal_response.status_code != 207:
print('Failed to retrieve Principal: ',
principal_response.status_code)
print("Failed to retrieve Principal: ", principal_response.status_code)
exit(-1)
# Parse the resulting XML response
soup = BeautifulSoup(principal_response.content, 'lxml')
self.principal_path = soup.find(
'current-user-principal'
).find('href').get_text()
soup = BeautifulSoup(principal_response.content, "lxml")
self.principal_path = (
soup.find("current-user-principal").find("href").get_text()
)
discovery_url = self.icloud_url + self.principal_path
# Next use the discovery URL to get more detailed properties - such as
# the calendar-home-set
home_set_response = requests.request(
'PROPFIND',
"PROPFIND",
discovery_url,
auth=auth,
headers=headers,
data=self.propfind_calendar_home_set.encode('utf-8')
data=self.propfind_calendar_home_set.encode("utf-8"),
)
if home_set_response.status_code != 207:
print('Failed to retrieve calendar-home-set',
home_set_response.status_code)
print("Failed to retrieve calendar-home-set", home_set_response.status_code)
exit(-1)
# And then extract the calendar-home-set URL
soup = BeautifulSoup(home_set_response.content, 'lxml')
soup = BeautifulSoup(home_set_response.content, "lxml")
self.calendar_home_set_url = soup.find(
'href',
attrs={'xmlns':'DAV:'}
"href", attrs={"xmlns": "DAV:"}
).get_text()
# get_calendars
@@ -88,9 +84,9 @@ class iCloudConnector(object):
# we can create a local object to control calendars (thin wrapper around
# CALDAV library)
def get_calendars(self):
self.caldav = caldav.DAVClient(self.calendar_home_set_url,
username=self.username,
password=self.password)
self.caldav = caldav.DAVClient(
self.calendar_home_set_url, username=self.username, password=self.password
)
self.principal = self.caldav.principal()
self.calendars = self.principal.calendars()
@@ -98,16 +94,16 @@ class iCloudConnector(object):
if len(self.calendars) > 0:
for calendar in self.calendars:
properties = calendar.get_properties([dav.DisplayName(), ])
display_name = properties['{DAV:}displayname']
properties = calendar.get_properties([dav.DisplayName()])
display_name = properties["{DAV:}displayname"]
if display_name == name:
return calendar
return None
def create_calendar(self,name):
def create_calendar(self, name):
return self.principal.make_calendar(name=name)
def delete_all_events(self,calendar):
def delete_all_events(self, calendar):
for event in calendar.events():
event.delete()
return True
@@ -116,12 +112,14 @@ class iCloudConnector(object):
# to do
pass
def create_simple_timed_event(self,start_datetime, end_datetime, summary,
description):
def create_simple_timed_event(
self, start_datetime, end_datetime, summary, description
):
# to do
pass
def create_simple_dated_event(self,start_datetime, end_datetime, summary,
description):
def create_simple_dated_event(
self, start_datetime, end_datetime, summary, description
):
# to do
pass

View File

@@ -266,12 +266,17 @@ class Informer(object):
new_cal_hash = hashlib.sha1(new_cal_entry).hexdigest()
session = db.get_db()
storedata = {
'calendar_id': uid,
'ical': new_cal_entry,
'hash': new_cal_hash
"calendar_id": uid,
"ical": new_cal_entry,
"hash": new_cal_hash,
}
calendarentry = session.query(model.CalendarEntry).filter(model.CalendarEntry.calendar_id == uid) .with_parent(self.user, "calendarentries").one_or_none()
if calendarentry is not None :
calendarentry = (
session.query(model.CalendarEntry)
.filter(model.CalendarEntry.calendar_id == uid)
.with_parent(self.user, "calendarentries")
.one_or_none()
)
if calendarentry is not None:
if calendarentry.hash == new_cal_hash:
self.logger.info("no change for calendar entry {}".format(uid))
continue
@@ -286,6 +291,5 @@ class Informer(object):
self.user.calendarentries.append(calendarentry)
session.commit()
self.logger.debug(new_cal_entry.decode('utf-8'))
self.logger.debug(new_cal_entry.decode("utf-8"))
cal.add_event(calend.to_ical())

View File

@@ -11,17 +11,23 @@ cfg = config.load()
ModelBase = declarative_base()
_PASSWORD_SECRET_KEY = cfg['general']['secretkey']
_PASSWORD_SECRET_KEY = cfg["general"]["secretkey"]
BS = 16
def pad(s):
diff = BS - len(s) % BS
return (s + (diff) * chr(diff)).encode('utf8')
return (s + (diff) * chr(diff)).encode("utf8")
def unpad(s):
return s[0:-s[-1]].decode('utf8')
return s[0 : -s[-1]].decode("utf8")
class User(ModelBase):
'''The infomentor user.'''
__tablename__ = 'users'
"""The infomentor user."""
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
@@ -31,7 +37,7 @@ class User(ModelBase):
icalendar = relationship("ICloudCalendar", back_populates="user", uselist=False)
wantstatus = Column(Boolean)
homeworks = relationship("Homework", back_populates="user")
news = relationship("News",back_populates="user")
news = relationship("News", back_populates="user")
calendarentries = relationship("CalendarEntry", back_populates="user", uselist=True)
def __init__(self, *args, **kwargs):
@@ -39,9 +45,9 @@ class User(ModelBase):
super().__init__(*args, **kwargs)
def _setup_cipher(self):
if not hasattr(self, 'cipher'):
if not hasattr(self, "cipher"):
aeskey = hashlib.sha256(_PASSWORD_SECRET_KEY.encode()).digest()
self.cipher = AES.new(aeskey,AES.MODE_ECB)
self.cipher = AES.new(aeskey, AES.MODE_ECB)
@property
def password(self):
@@ -57,33 +63,37 @@ class User(ModelBase):
def __repr__(self):
return "<User(name='%s', password='%s')>" % (
self.name, '*' * len(self.password))
self.name,
"*" * len(self.password),
)
class Notification(ModelBase):
'''This contains the information about the type of notification and additional the key to reach out to the user'''
__tablename__ = 'notifications'
"""This contains the information about the type of notification and additional the key to reach out to the user"""
__tablename__ = "notifications"
class Types(enum.Enum):
'''Supported notification types'''
"""Supported notification types"""
PUSHOVER = 1
EMAIL = 2
FAKE = 3
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
ntype = Column(Enum(Types))
info = Column(String)
user = relationship("User", back_populates="notification")
def __repr__(self):
return "<Notification(type='{}', info='{}')>".format(
self.ntype, self.info)
return "<Notification(type='{}', info='{}')>".format(self.ntype, self.info)
class Attachment(ModelBase):
'''General attachment type for homework and news'''
__tablename__ = 'attachments'
"""General attachment type for homework and news"""
__tablename__ = "attachments"
id = Column(Integer, primary_key=True)
attachment_id = Column(Integer)
@@ -91,20 +101,21 @@ class Attachment(ModelBase):
url = Column(String)
title = Column(String)
localpath = Column(String)
news_id = Column(Integer, ForeignKey('news.id'))
homework_id = Column(Integer, ForeignKey('homework.id'))
news_id = Column(Integer, ForeignKey("news.id"))
homework_id = Column(Integer, ForeignKey("homework.id"))
news = relationship("News", back_populates="attachments")
homework = relationship("Homework", back_populates="attachments")
class News(ModelBase):
'''A News entry'''
__tablename__ = 'news'
"""A News entry"""
__tablename__ = "news"
id = Column(Integer, primary_key=True)
news_id = Column(Integer)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
title = Column(String)
content = Column(String)
category = Column(String)
@@ -113,50 +124,62 @@ class News(ModelBase):
imagefile = Column(String)
notified = Column(Boolean, default=False)
raw = Column(String)
attachments = relationship("Attachment", order_by=Attachment.id, back_populates="news", uselist=True)
attachments = relationship(
"Attachment", order_by=Attachment.id, back_populates="news", uselist=True
)
user = relationship("User", back_populates="news")
def __repr__(self):
return "<News(id='%d', title='%s')>" % (
self.id, self.title)
return "<News(id='%d', title='%s')>" % (self.id, self.title)
class CalendarEntry(ModelBase):
'''A News entry'''
__tablename__ = 'calendarentries'
"""A News entry"""
__tablename__ = "calendarentries"
id = Column(Integer, primary_key=True)
calendar_id = Column(Integer)
title = Column(String)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
ical = Column(String)
hash = Column(String)
user = relationship("User", back_populates="calendarentries")
def __repr__(self):
return "<CalendarEntry(id='%d', title='%s', hash='%s')>" % (
self.id, self.title, hash)
self.id,
self.title,
hash,
)
class Homework(ModelBase):
'''A homework entry'''
__tablename__ = 'homework'
"""A homework entry"""
__tablename__ = "homework"
id = Column(Integer, primary_key=True)
homework_id = Column(Integer)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
subject = Column(String)
courseElement = Column(String)
text = Column(String)
date = Column(String)
imageUrl = Column(String)
attachments = relationship("Attachment", order_by=Attachment.id, back_populates="homework")
attachments = relationship(
"Attachment", order_by=Attachment.id, back_populates="homework"
)
user = relationship("User", back_populates="homeworks")
class ApiStatus(ModelBase):
'''Representing the result of the last trys to access the api, represented as one status'''
__tablename__ = 'api_status'
"""Representing the result of the last trys to access the api, represented as one status"""
__tablename__ = "api_status"
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
degraded_count = Column(Integer)
datetime = Column(DateTime)
info = Column(String)
@@ -169,14 +192,19 @@ class ApiStatus(ModelBase):
def __repr__(self):
return "<ApiStatus(ok='%s', NOKs='%d', info='%s')>" % (
self.ok, self.degraded_count, self.info)
self.ok,
self.degraded_count,
self.info,
)
class ICloudCalendar(ModelBase):
'''An icloud account with a calendar name'''
__tablename__ = 'icloud_calendar'
"""An icloud account with a calendar name"""
__tablename__ = "icloud_calendar"
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
user_id = Column(Integer, ForeignKey("users.id"))
icloud_user = Column(String)
icloud_pwd = Column(String)
calendarname = Column(String)
@@ -187,9 +215,9 @@ class ICloudCalendar(ModelBase):
super().__init__(*args, **kwargs)
def _setup_cipher(self):
if not hasattr(self, 'cipher'):
if not hasattr(self, "cipher"):
aeskey = hashlib.sha256(_PASSWORD_SECRET_KEY.encode()).digest()
self.cipher = AES.new(aeskey,AES.MODE_ECB)
self.cipher = AES.new(aeskey, AES.MODE_ECB)
@property
def password(self):
@@ -205,5 +233,6 @@ class ICloudCalendar(ModelBase):
def __repr__(self):
return "<ICloudCalendar(user='%s' cal='%s')>" % (
self.icloud_user, self.calendarname)
self.icloud_user,
self.calendarname,
)

View File

@@ -5,34 +5,47 @@ from flask_bootstrap import Bootstrap
app = Flask(__name__)
Bootstrap(app)
@app.route('/')
@app.route("/")
def home():
return render_template('notfound.html')
return render_template("notfound.html")
@app.route('/addlogin')
@app.route("/addlogin")
def extra():
return render_template('addlogin.html')
return render_template("addlogin.html")
@app.route('/create', methods=['POST'])
@app.route("/create", methods=["POST"])
def create():
if request.form['accesscode'] != 'fhKjzgV/BXWq4YRxUPO4qYlHWCDf':
return redirect(url_for('home'))
if request.form["accesscode"] != "fhKjzgV/BXWq4YRxUPO4qYlHWCDf":
return redirect(url_for("home"))
session = db.get_db()
username = request.form['username']
existing_user = session.query(model.User).filter(model.User.name == username).one_or_none()
username = request.form["username"]
existing_user = (
session.query(model.User).filter(model.User.name == username).one_or_none()
)
if existing_user is not None:
return redirect(url_for('home'))
return redirect(url_for("home"))
password = request.form['password']
password = request.form["password"]
user = model.User(name=username, password=password)
if request.form['notify'] == 'mail':
user.notification = [model.Notification(ntype=model.Notification.Types.EMAIL, info=request.form['info'])]
if request.form["notify"] == "mail":
user.notification = [
model.Notification(
ntype=model.Notification.Types.EMAIL, info=request.form["info"]
)
]
else:
user.notification = [model.Notification(ntype=model.Notification.Types.PUSHOVER, info=request.form['info'])]
user.notification = [
model.Notification(
ntype=model.Notification.Types.PUSHOVER, info=request.form["info"]
)
]
session.add(user)
session.commit()
return "success"
if __name__ == '__main__':
app.run(debug=True)
if __name__ == "__main__":
app.run(debug=True)

View File

@@ -1,12 +1,23 @@
from setuptools import setup, find_packages
setup(
name = 'infomentor',
version = '1.0.0',
url = 'https://github.com/mypackage.git',
author = 'Matthias Bilger',
author_email = 'matthias@bilger.info',
description = 'grab infomentor news and push or mail them',
packages = find_packages(),
install_requires = ['pycrypto', 'request', 'sqlalchemy', 'dateparser', 'python-pushover', 'flask', 'flask-bootstrap', 'caldav', 'bs4', 'icalendar' ],
name="infomentor",
version="1.0.0",
url="https://github.com/mypackage.git",
author="Matthias Bilger",
author_email="matthias@bilger.info",
description="grab infomentor news and push or mail them",
packages=find_packages(),
install_requires=[
"pycrypto",
"request",
"sqlalchemy",
"dateparser",
"python-pushover",
"flask",
"flask-bootstrap",
"caldav",
"bs4",
"icalendar",
],
)