def updateBirthday(): if request.method == "POST": try: birthday_str = f"{request.form.get('year')}/{request.form.get('month')}/{request.form.get('day')}" birthday = datetime.datetime.strptime(birthday_str, '%Y/%m/%d') utils.updateBirthday(current_user, birthday) except Exception as e: log.error(f'Error updating {current_user} birthday', exc_info=True) return redirect(url_for('dashboard'))
def addSubscription(current_user, widget_id, grid_location=default_widget_location): """ Subscribe User current_user to widget with primary_key = widget_id. Set initial grid_location. Parameters ---------- current_user : User widget_id : int grid_location : dict Returns ------- None """ # validate widget_id try: widget_id = int(widget_id) except: log.critical( f'{current_user} attempted to subscribe with non-int widget_id.') raise Exception(f'{error_msg_global}') widget = Widget.query.get(widget_id) if not widget: log.error( f'{current_user} attempted to subscribe to non-existing widget with id = \"{widget_id}\".' ) raise Exception(f'{error_msg_global}') if widget in current_user.widgets: log.info( f'{current_user} attempted to re-subscribe to existing {widget}.') raise Exception( f'{error_msg_global} You are already subscribed to {widget.name}.') try: new_subscription = Subscription(user=current_user, widget_id=widget_id, grid_location=grid_location) db.session.add(new_subscription) db.session.commit() log.info(f'{current_user} subscribed to {widget}.') except Exception as e: db.session.rollback() log.warning(f'Failed to subscribe {current_user} to {widget}.', exc_info=True) raise Exception(error_msg_global)
def updateNews(): log.info('Starting \'News\' widget update...') try: news_key = os.environ['NEWS_KEY'] news_url = f'http://newsapi.org/v2/top-headlines?country=us&apiKey={news_key}' response = requests.get(news_url) response.raise_for_status() data = response.json() except Exception as e: log.error('Failed to update \'News\' widget.', exc_info=True) return articles = data.get('articles') if not articles: return new_articles = [] for i, article in enumerate(articles): if i >= MAX_POSTS: break if not article: continue title = article.get('title') title = re.sub(r'-\s*[^-]+$', '', title).strip() source = article.get('source') if source: source = source.get('name') # source = re.sub(r'\.com.*$', '', source).strip() url = article.get('url') new_articles.append({'title': title, 'source': source, 'url': url}) with app.app_context(): news_widget = None try: news_widget = Widget.query.filter_by(alias_name='news').first() if not news_widget: log.critical('News widget not found') return except Exception as e: log.error('Error retrieving News Widget', exc_info=True) return try: db.session.query(CustomPost).filter(CustomPost.widget_id==news_widget.id).delete() for a in new_articles: article_post = CustomPost(content=a['title'], custom_author=a['source'], url=a['url'], widget=news_widget) db.session.add(article_post) news_widget.active = True db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating News Widget') try: news_widget.active = False db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating News Widget active status') log.info('Exiting \'News\' widget update.')
def updateBirthday(current_user, birthday): """ Set the current user's birthday. Parameters ---------- current_user : User birthday : Date Returns ------- None """ try: current_user.birthday = birthday db.session.commit() except Exception as e: log.error(f'Failed to set birthday for {current_user}') db.session.rollback()
def addPost(current_user, widget_id, post): """ Create a new post with `current_user` as author. Parameters ---------- current_user : User form : CreatePost Returns ------- None """ try: # check if valid widget widget_id = int(widget_id) widget = Widget.query.filter_by(id=widget_id).first() if not widget: raise Exception('Selected widget does not exist :(') if current_user not in widget.admins: raise Exception(f'You can\'t post to "{widget.name}" :(') # if post is empty, dont save. Update widget active to False. if not post.strip(): widget.active = False db.session.commit() return # if post, add and update widget active status to True post = Post(content=post, author=current_user, widget=widget) db.session.add(post) widget.active = True db.session.commit() except Exception as e: db.session.rollback() log.error(f'Error updating post to {widget} for {current_user}', exc_info=True) raise Exception(error_msg_global)
def updateCOVIDReport(): log.info('Starting \'COVID\' widget update...') covid_url = 'https://pomber.github.io/covid19/timeseries.json' try: response = requests.get(covid_url) response.raise_for_status() data = response.json() except Exception as e: log.error('Failed to update \'COVID\' widget.', exc_info=True) return country_data = data[country] today_confirmed = country_data[-1]['confirmed'] yesterday_confirmed = country_data[-2]['confirmed'] today_deaths = country_data[-1]['deaths'] yesterday_deaths = country_data[-2]['deaths'] post = f'Since yesterday, the US has witnessed an increase in total confirmed cases by {today_confirmed-yesterday_confirmed:n}, and an increase in total deaths by {today_deaths-yesterday_deaths:n}.' with app.app_context(): covid_widget = None try: covid_widget = Widget.query.filter_by(alias_name='covid').first() if not covid_widget: log.critical('COVID widget not found') return except Exception as e: log.error('Error retrieving COVID widget', exc_info=True) return try: db.session.query(CustomPost).filter( CustomPost.widget_id == covid_widget.id).delete() covid_post = CustomPost(content=post, custom_author="Johns Hopkins CSSE", widget=covid_widget) db.session.add(covid_post) covid_widget.active = True db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating COVID widget') try: covid_widget.active = False db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating COVID widget active status') log.info('Exiting \'COVID\' widget update.')
def deleteWidget(current_user, widget_id): """ Deletes widget of id widget_id adminstered by current_user. This action removes all user subscriptions, posts, and admins associated with the widget. This action cannot be undone. Parameters ---------- current_user : User widget_id : int Returns ------- None """ try: widget_id = int(widget_id) widget = Widget.query.filter_by(id=widget_id).first() if not widget: return None if current_user not in widget.admins: log.error( f'{current_user} tried to delete {widget}. They are not an admin!' ) return None widget_name = widget.name db.session.delete(widget) db.session.commit() log.info(f'{current_user} permanently deleted {widget}.') return widget_name except Exception as e: log.error(f'Failed to permanently delete {widget} for {current_user}', exc_info=True) db.session.rollback() raise Exception(error_msg_global)
def createNewWidget(current_user, form): """ Create a new widget with current_user as admin. Parameters ---------- current_user : User form : CreateWidget Returns ------- None """ try: log.info(f'{current_user} creating new widget...') widget = Widget(name=form.name.data.strip(), description=form.description.data.strip()) # place new widgets in top left corner of admins dashboard subscription = Subscription(user=current_user, widget=widget, grid_location=default_widget_location) # current_user is the admin of the new widget widget.admins.append(current_user) db.session.add(widget) db.session.add(subscription) db.session.commit() log.info(f'Success: {current_user} created a new widget: {widget}.') except Exception as e: db.session.rollback() log.error( f'Failed to create a widget = \"{form.name.data}\" for admin {current_user}.', exc_info=True) raise Exception( f'{error_msg_global} Could not create \"{form.name.data}\" :( ')
def removeSubscription(current_user, widget_id): """ Unsubscribe User current_user to widget with primary_key = widget_id. Parameters ---------- current_user : User widget_id : int Returns ------- None """ subscription = None widget = None try: widget_id = int(widget_id) widget = Widget.query.get(widget_id) if not widget: log.error( f'Failed to remove subscription for {current_user}. widget_id = {widget_id} does not exist.' ) return subscription = Subscription.query.filter_by(user=current_user, widget=widget).first() if not subscription: log.error( f'{current_user} tried unsubscribing from non-existing subscription of {widget}' ) return if current_user in widget.admins: log.warning( f'{current_user} tried unsubscribing from administered {widget}' ) raise Exception( f'You are an admin of {widget.name}. To permanently delete, visit admin settings.' ) except Exception as e: raise Exception(e.args[0]) try: db.session.delete(subscription) db.session.commit() log.info(f'{current_user} unsubscribed from {widget}') except Exception as e: db.session.rollback() log.error( f'Error removing subscription for widget {widget_id}. Rolling back.', exc_info=True) raise Exception(error_msg_global + f' \"{widget.name}\" cannot be removed.')
def updateSubscriptionLocation(current_user, widget_id, grid_location): """ Update widget grid_location. Parameters ---------- current_user : User widget_id : int grid_location : dict Returns ------- None """ if grid_location['width'] < default_widget_location['minWidth']: return subscription = None widget = None try: widget_id = int(widget_id) widget = Widget.query.get(widget_id) if not widget: log.error( f'Failed to update subscription for {current_user}. widget_id = {widget_id} does not exist.' ) return subscription = Subscription.query.filter_by(user=current_user, widget=widget).first() if not subscription: log.error( f'Error updating location: {current_user} not subscribed to {widget}.' ) return subscription.grid_location = grid_location db.session.commit() except Exception as e: db.session.rollback() log.error(f'Error updating location for {subscription}. Rolling back.', exc_info=True)
def updatePoem(): log.info('Starting \'Poem-A-Day\' widget update...') soup = None try: hdr = {'User-Agent': 'Mozilla/5.0'} # get daily poem url req = Request(daily_url, headers=hdr) page = urlopen(req, timeout=10) soup = BeautifulSoup(page, 'html.parser') a_div = soup.find('div', attrs={ 'class': 'c-feature' }).find('a', recursive=False) poem_url = a_div['href'] # get daily poem req = Request(poem_url, headers=hdr) page = urlopen(req, timeout=10) soup = BeautifulSoup(page, 'html.parser') except Exception as e: log.error('Error retrieving daily poem.', exc_info=True) return try: poem_body = soup.find("div", {"class": "o-poem"}) for elem in poem_body.find_all(["a", "p", "div", "h3", "br"]): elem.replace_with(elem.text + "\n\n") poem_body = '\n'.join( [line.strip() for line in poem_body.findAll(text=True)]) poem_body = poem_body.strip() poem_title_div = soup.find('div', {"class": "c-feature-hd"}) poem_title = poem_title_div.find('h1').text poem_title = poem_title.strip() poem_author_div = soup.find('div', {"class": "c-feature-sub"}) poem_author = poem_author_div.find('a').text poem_author = poem_author.strip() poem = '\n' + poem_title + '\n\n' + poem_body except Exception as e: log.error('Error scraping daily poem.', exc_info=True) return with app.app_context(): try: tangelo = User.query.filter_by(netid='tangelo').first() poem_widget = Widget.query.filter_by(alias_name='poems').first() db.session.query(CustomPost).filter( CustomPost.widget_id == poem_widget.id).delete() poem_post = CustomPost(content=poem, custom_author=poem_author, url=poem_url, widget=poem_widget) db.session.add(poem_post) poem_widget.active = True db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating daily poem post.', exc_info=True) try: poem_widget.active = False db.session.commit() except Exception as e: db.session.rollback() log.info('Exiting \'Poem-A-Day\' widget update.')
def setupTangelo(): try: with app.app_context(): db.session.remove() db.drop_all() db.create_all() user_1 = User(netid='tangelo') widget_1 = Widget( name='Welcome to Tangelo!', description= 'Here\'s a quick demo to get you started on Tangelo!', style='welcomeWidget.html', type='custom') widget_2 = Widget( name='🕒', description= 'Life as a Princeton tiger is hectic. Stay on time with this clock.', style='clock.html', type='custom') widget_3 = Widget( name='📅', description= 'Missing deadlines? Get back on track with this date widget.', style='date.html', type='custom') widget_4 = Widget( name='🌦️', description= 'Rain or shine, we\'ve got the current weather for you.', style='weather.html', type='custom') widget_5 = Widget( name='News', description='Keep up to date with the latest top headlines.', type='custom', alias_name='news', post_limit=10) widget_6 = Widget( name='COVID-19', description='The latest numbers on US COVID-19 Cases.', type='custom', alias_name="covid") widget_7 = Widget( name='Poem-a-Day', description= 'A daily poem for you sourced from Poetry Foundation.', type='custom', alias_name='poems') widget_8 = Widget( name='Princeton University News', description= 'The latest news and stories from Princeton University.', type='custom', alias_name='princeton_news', post_limit=10, handle_display='date_published') widget_9 = Widget( name='Happy Birthday!', description= 'We\'re counting down the days till your birthday celebration!🎉🎂', type='custom', style='birthday.html') widget_10 = Widget( name='Princeton Academic Calendar', description= 'Never miss course selection with this handy academic calendar.', type='custom', alias_name='pton_calendar', post_limit=10) db.session.add(widget_1) db.session.add(widget_2) db.session.add(widget_3) db.session.add(widget_4) db.session.add(widget_5) db.session.add(widget_6) db.session.add(widget_7) db.session.add(widget_8) db.session.add(widget_9) db.session.add(widget_10) widget_1.admins.append(user_1) widget_2.admins.append(user_1) widget_3.admins.append(user_1) widget_4.admins.append(user_1) widget_5.admins.append(user_1) widget_6.admins.append(user_1) widget_7.admins.append(user_1) widget_8.admins.append(user_1) widget_9.admins.append(user_1) widget_10.admins.append(user_1) db.session.add(user_1) db.session.commit() except Exception as e: db.session.rollback() log.error('Failed to setup Tangelo DB!', exc_info=True)
def updateNews(): log.info('Starting \'Princeton News\' widget update...') MAX_POSTS = None try: with app.app_context(): princeton_news_widget = Widget.query.filter_by( alias_name='princeton_news').first() if not princeton_news_widget: log.critical( 'Princeton News Widget not found when attempting to update' ) MAX_POSTS = princeton_news_widget.post_limit except Exception as e: return news_posts = None try: feed = feedparser.parse(princeton_news_url) if not feed: return news_posts_count = min(len(feed.entries), MAX_POSTS) if not news_posts_count: return news_posts = [None] * news_posts_count for i, post in enumerate(feed.entries): if i == news_posts_count: break title = post.title if not title: continue author = post.author if not author: author = 'Office of Communications' if post.published_parsed: date_published = datetime(*post.published_parsed[:6]) url = post.link news_posts[i] = { 'title': title, 'author': author, 'date_published': date_published, 'url': url } except Exception as e: log.error('Error retrieving new posts for Princeton News widget') return with app.app_context(): try: princeton_news_widget = Widget.query.filter_by( alias_name='princeton_news').first() db.session.query(CustomPost).filter( CustomPost.widget_id == princeton_news_widget.id).delete() for post in news_posts: news_post = CustomPost(content=post['title'], custom_author=post['author'], url=post['url'], create_dttm=post['date_published'], widget=princeton_news_widget) db.session.add(news_post) princeton_news_widget.active = True db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating daily poem post.', exc_info=True) try: princeton_news_widget.active = False db.session.commit() except Exception as e: db.session.rollback() log.info('Exiting \'Princeton News\' widget update.')
def updateCalendar(): log.info('Starting \'Academic Calendar\' widget update...') url = "https://registrar.princeton.edu/feeds/events/ical.ics" try: response = requests.get(url) response.raise_for_status() c = Calendar(response.text) except requests.exceptions.HTTPError as err: log.error("Error updating academic calendar widget", exc_info=True) return info = [] for event in c.events: info.append({ 'event_name': event.name, 'start_month': date_extraction(str(event.begin))[0], 'start_day': date_extraction(str(event.begin))[1], 'start_year': date_extraction(str(event.begin))[2] }) sorted_info = sorted(info, key=itemgetter('start_year', 'start_month', 'start_day')) current_month = datetime.datetime.today().month current_day = datetime.datetime.today().day current_year = datetime.datetime.today().year i = 0 for s in sorted_info: if s['start_year'] >= current_year: break i += 1 j = i while sorted_info[j]['start_month'] < current_month: j += 1 m = j while sorted_info[m]['start_day'] < current_day: m += 1 k = m next_ten_events = [] while k < 10 + m: next_ten_events.append(sorted_info[k]) if k + 1 > len(sorted_info): break k += 1 with app.app_context(): pton_calendar = None try: pton_calendar = Widget.query.filter_by( alias_name='pton_calendar').first() if not pton_calendar: log.critical('Pton Calendar Widget not found') return except Exception: log.error('Error retrieving pton calendar widget', exc_info=True) try: db.session.query(CustomPost).filter( CustomPost.widget_id == pton_calendar.id).delete() t = len(next_ten_events) - 1 while t >= 0: e = next_ten_events[t] content_string = str(e['event_name']) day = str(e['start_day']) if len(day) == 1: day = "0" + day author_string = str(e['start_month']) + "/" + day + "/" + str( e['start_year']) calendar_event = CustomPost(content=content_string, custom_author=author_string, widget=pton_calendar) db.session.add(calendar_event) t -= 1 pton_calendar.active = True db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating Pton Calendar Widget') log.error(e) try: pton_calendar.active = False db.session.commit() except Exception as e: db.session.rollback() log.error('Error updating Pton Calendar Widget active status') log.info('Exiting \'Academic Calendar\' widget update.')