Beispiel #1
0
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'))
Beispiel #2
0
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)
Beispiel #3
0
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.')
Beispiel #4
0
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()
Beispiel #5
0
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)
Beispiel #6
0
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.')
Beispiel #7
0
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)
Beispiel #8
0
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}\" :( ')
Beispiel #9
0
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.')
Beispiel #10
0
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)
Beispiel #11
0
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.')
Beispiel #12
0
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)
Beispiel #13
0
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.')
Beispiel #14
0
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.')