def remove_notification(title):
    '''This function will remove a notification from the notifications json file'''
    with open('./json_files/notifications.json') as jfile:
        data = json.load(jfile)
        #getting the notificatios from the json file
        temp = data['notifications']
        #the number of notifications in the file
        length = len(temp[0])
    #getting the seen notifications file
    with open('./json_files/seen.json') as jfil:
        seen_data = json.load(jfil)
        #getting the notificatios from the json file
        seen = seen_data['notifications']
    #looping through each notifications in the list
    for i in range(length):
        #then checking each notification title agaist the input title,
        #and if they are the same this will remove it
        if temp[0][i]["title"] == title:
            # appending data to seen notifications file
            seen.append(temp[0][i])
            with open('./json_files/seen.json', 'w') as jfile:
                json.dump(seen_data, jfile, indent=4)
            log("notifications json file updated")
            log("notification for '" + title + "' has been removed")
            break
def get_covid():
    '''This function gets the date for today and
    gets the key from teh confic json file and
    it then calls the api and returns the response'''
    #getting the users region from the config json file
    with open("./json_files/config.json", "r") as jfile:
        key = json.load(jfile)
        key = key["config"]
        area_name = key[4]['Area_location']
    #concatonating the url fro teh api call, involving the location and the structure\
    #which is, area name, date, new cases & new deaths
    complete_url = 'https://api.coronavirus.data.gov.uk/v1/data?filters=areaName='+ area_name +'&structure={"areaName":"areaName","date":"date",'\
            +'"newCases":"newCasesByPublishDate","newDeaths":"newDeaths28DaysByPublishDate"}'
    #trying to get the data from the api call, if it can't
    #it will return failed so that the program can continue
    try:
        #making an api call with the requests module and the url
        response = requests.get(complete_url)
        report = response.json()
        #getting the data from the call
        report = report['data']
        #logging that the data has been retrieved
        log("covid data retrieved -- " + str(requests.get(complete_url)))
        #returning the latest data from the report data
        return report[0]
    except:
        #logging and returning that the api calling has errored
        log("FAILED to get covid data from api" +
            str(requests.get(complete_url)))
        return "error getting covid info, api call error"
def write_json(data, alarm):
    '''This function opens the alarm json file
    and then adds the date passed to the function
    to the file'''
    with open('./json_files/alarms.json', 'w') as jfile:
        json.dump(data, jfile, indent=4)
    log("alarm for " + alarm + " has been added")
def write_json(data):
    '''This function opens the notification json file
    and then adds the data passed to the function
    to the file'''
    with open('./json_files/notifications.json', 'w') as jfile:
        json.dump(data, jfile, indent=4)
    log("notifications have been added to the json file")
Exemple #5
0
def weathers():
    '''This function does the api call to the website and it gets
    the api key from the config json file, then it returns the json file
    from the api call'''
    #setting the base url for the api call
    base_url = "http://api.openweathermap.org/data/2.5/weather?"
    #getting the users api key and their location (city name or town) from the config json file
    with open("./json_files/config.json", "r") as jfile:
        key = json.load(jfile)
        key = key["config"]
        api_key = key[0]['weatherkey']
        city_name = key[3]['weather_city_or_town']
    #adding this information to the base url so the api call can be made
    complete_url = base_url + "q=" + city_name + "&appid=" + api_key
    try:
        #making an api call with the requests module and the complete url
        response = requests.get(complete_url)
        weather_json = response.json()
        #logging that the weather has been retrieved
        if weather_json['cod'] == 200:
            log("weather retrieved -- " + str(requests.get(complete_url)))
        else:
            log("error getting the api data")
            log(requests.get(complete_url))
            log(weather_json)
        #returning the weather data
        return weather_json
    except:
        #logging and returning that the api calling has errored
        log("FAILED to get Weather data from api" +
            str(requests.get(complete_url)))
        return [{'cod': '404', 'message': "FAILED couldn't get weather data"}]
def refresh(covid, articles, weather):
    '''This function will update the alarms with the latest covid,weather&news'''
    #getting all the alarms from the alarms json file
    with open("./json_files/alarms.json", "r") as jfile:
        alarm = json.load(jfile)
        alarmj = alarm["alarms"]
    #the length of the alarms (how many alarms ar set)
    length = len(alarmj)
    #a blank variable to use in the alarms call
    temp = ''
    #looping through each item in the alarm
    for i in range(length):
        #setting variables to tell the add alarm function if\
        #there is a news and/or weather item in this alarm
        incl_news = alarmj[i]['pick_news']
        incl_weather = alarmj[i]['pick_weather']
        #setting the alarm title from the alarm in the json file
        alarm = alarmj[i]['title']
        content = alarmj[i]['content']
        #setting content to a string
        content = str(content)
        #the length of content
        content_length = len(content)
        #looping through the content to get the message that\
        #the user entered
        for j in range(content_length):
            if content[j] == "'" and content[j + 1] == "'":
                ending = j
                break
        content = content[:(ending - 3)]
        #then removing the old alarm so there are no duplicates again
        remove_alarm(alarm, True)
        #logging that the alarm is updated
        log("alarm for " + alarm + " has been updated")
        #adding this to the alarms with the add alarm function\
        #accoding to if the news and weather has been set
        if incl_news and incl_weather:
            #calling the add alarm function to add the updated alarm
            add_alarm(alarm, content, weather, articles, covid, incl_news,
                      incl_weather)
        elif incl_weather:
            add_alarm(alarm, content, weather, temp, covid, incl_news,
                      incl_weather)
        elif incl_news:
            add_alarm(alarm, content, temp, articles, covid, incl_news,
                      incl_weather)
        else:
            add_alarm(alarm, content, temp, temp, covid, incl_news,
                      incl_weather)
    return end()
def print_job_name(alarm, name, weather, article, covid):
    '''This function takes in input strings and then says them
    with pyttsx3'''
    #initiating the pyttsx3
    engine = pyttsx3.init()
    alarm1 = alarm[11:]
    #adding the strings that have been passed to the function\
    #to the say engine
    engine.say(alarm1)
    engine.say(name)
    engine.say(weather)
    engine.say(article)
    engine.say(covid)
    try:
        #saying the strings that are in the say engine
        engine.runAndWait()
        #logging that the alam has been said
        log("alarm for " + alarm + " has been said")
        ##removing the alarm as it has happened
        remove_alarm(alarm)
    except:
        log("FAILED speech run failed due to another item in the scheduler")
def news():
    '''This function does the api call to the news website and it gets
    the api key from the config json file, then it returns the json file
    from the api call'''
    length = len(current_time_hhmm())
    #looping through the time to find the middle (:)
    for i in range(length):
        if current_time_hhmm()[i] == ":":
            start = i + 1
    #only getting the news from the api every 15 mins, or when the function is first called
    if int(current_time_hhmm()[start:]) % 15 == 0 or current_time_hhmm(
    )[start:] == '' or len(lst) == 0:
        if len(lst) == 0:
            lst.append('1')
        #setting the base url
        base_url = "https://newsapi.org/v2/top-headlines?"
        #getting the user key from the config json file
        with open("./json_files/config.json", "r") as jfile:
            key = json.load(jfile)
            key = key["config"]
            api_key = key[1]['newskey']
        #adding these (key an country) to the base url to get the url for an api call
        complete_url = base_url + "country=gb&apiKey=" + api_key
        #trying to get the data from the api call, if it can't
        #it will return failed so that the program can continue
        try:
            #making an api call with the requests module and the complete url
            response = requests.get(complete_url)
            articles = response.json()
            #getting the articles from the api call response
            articles = articles["articles"]
            #logging that the articles have been retrieved
            log("articles retrieved -- " + str(requests.get(complete_url)))
            #returning the list of articles
            return articles
        except:
            #logging and returning that the api calling has errored
            log('FAILED to get news data from api' +
                str(requests.get(complete_url)))
            return [{'title': 'FAILED', 'content': "couldn't get news data"}]
    else:
        #opening the json file to read from it
        with open('./json_files/notifications.json') as jfile:
            data = json.load(jfile)
            #getting the notifications from the json file
            data = data['notifications'][0]
        log('notifications got from the json file')
        return data[2:]
def remove_alarm(title, status=False):
    '''This function opens the json file for the alarms and
    then it loops through the file until the title is the same
    and it removes that alarm'''
    with open('./json_files/alarms.json') as jfile:
        data = json.load(jfile)
        #getting the alarms from the json file
        temp = data['alarms']
        #the number of alarms in the file
        length = len(temp)
        #looping through each alarm in the list
        for i in range(length):
            #then checkign each alarm title agaist the input title,
            #and if they are the same this will remove it
            if temp[i]["title"] == title:
                temp.pop(i)
                log("alarm for " + title + " has been removed")
                break
    #re-wrtiting the updated alarms to the json file
    with open('./json_files/alarms.json', 'w') as jfile:
        json.dump(data, jfile, indent=4)
    length = len(lst)
    if status:
        #looping through the scheduler list
        for i in range(length):
            try:
                #canceling the events in the list
                s.cancel(lst[i])
                #logging that this has been done
                log('alarm ' + title + ' removed from scheduler')
            except:
                log('alarm' + title +
                    'could not be removed from the scheduler')
            #removing the item from the list
        lst.clear()
    if not status:
        refresh(get_covid(), news(), weathers())
def add_alarm(alarm, name, weather, article, covid, pick_news, pick_weather):
    '''This function adds the alarms inputed to the function to
    the json file of alarms and or adds it to the scheduler
    depends on conditions'''
    #running the scheduler
    s.run(blocking=False)
    #setting alarm1 to be the time part of the alarm title
    alarm1 = alarm[11:]
    if alarm1:
        #convert alarm_time to a delay
        current_time = current_time_hhmm()
        #working out the delay by subtracting the current time (in seconds)\
        #from the time on the alarm (in seconds)
        delay = hhmm_to_seconds(alarm1) - hhmm_to_seconds(current_time)
        #setting a new name variable to append to  what is in the input\
        #and still keep the input var
        new_name = name
        #The conditions on whether to manipulate the weather,news & covid\
        #depending on whether they were inputted
        if weather != '' and weather["cod"] == 200:
            #setting weath to the main attributes of the weather input
            weath = weather["main"]
            #getting the tempurature
            current_temp = weath["temp"]
            #getting the pressure
            current_press = weath["pressure"]
            #getting the humidity
            current_humid = weath["humidity"]
            #setting weath to the weather attribute of the weather input
            weath = weather["weather"]
            #getting the description from the weather input (from weath)
            weather_desc = weath[0]["description"]
            #gettign the wind speed
            weath = weather["wind"]
            #concatonating all the variables gathered on weather into one string with\
            #more descriptions of them
            weather = "The temperature outside is "+str(int(current_temp - 273.15))\
                + "degrees centigrade; The atmospheric pressure is "\
                    + str(current_press) + "hectopascals; The humidity is " + str(current_humid) +\
                        "percent; The wind speed is "+str(weath['speed'])+\
                            "metres per second; And it is "+str(weather_desc)
            #adding this to the newname variable
            new_name = str(new_name) + ".  '''''''' " + str(weather)
        #inputting to the alarm that there is an error if false weather data is added to an alarm
        elif weather != '' and weather["cod"] != 200:
            wdic = {'title': weather["cod"], 'content': weather['message']}
            new_name = str(new_name) + ".  '''''''' " + str(wdic)
        if article != '':
            #getting the title from the news input
            article = article[0]['title']
            article = str('The top news story is: ') + str(article)
            #adding this information plus a description to the newname variable
            new_name = str(new_name) + ". '''''''' " + str(article)
        if covid != '':
            covid = 'The local coronavirus infection rates are: ' + str(covid)
            #adding the information on covid to the newname variable
            new_name = str(new_name) + ".  ''''''' " + str(covid)
        #setting the details abotu the news alarm from the inputs
        new_alarm = {"title": alarm, "content": new_name, "pick_news": pick_news,\
            "pick_weather": pick_weather}
        #opening the alarm json file and getting all the alarms from it
        with open('./json_files/alarms.json') as jfile:
            data = json.load(jfile)
            temp = data['alarms']
        in_alarms = False
        if len(temp) != 0:
            #looping though the alarms json if it isnt empty
            for i in temp:
                if i['title'] == alarm:
                    #if the alarm exists that is being added then in alarms is true if not its false
                    in_alarms = True
                    break
        #appending the json file if that alarm doesnt exist
        if not in_alarms:
            # appending data to alarms
            temp.append(new_alarm)
            #calling the write function to add the new alarms to the json file
            write_json(data, alarm)
        else:
            log('cannot make alarm as there is already an alarm for this time')
            return end()
        #saying the event if it is set for the time now\
        #and if the date on the alarm is the same as todays date
        if alarm[:10] == current_date() and int(delay) == 0:
            print_job_name(alarm, name, weather, article, covid)
        #Not adding the alarm if it is set in the past
        elif alarm[:10] == current_date() and int(delay) < 0:
            log("alarm " + alarm + " is set in the past")
            remove_alarm(alarm, True)
        #only adding an item to the scheduler if it has less than 60 seconds\
        #and if the date on the alarm is the same as todays date
        elif alarm[:10] == current_date() and 0 < int(delay) < 61:
            lst.append(
                s.enter(int(delay), 1, print_job_name, [
                    alarm,
                    name,
                    weather,
                    article,
                    covid,
                ]))
            #logging that the alarm has been added to the scheduler
            log("alarm " + alarm + " added to the scheduler")
        return end()
    #returning end if there is nothing to do
    return end()
def org_func(covid, weather, articles):
    '''This function takes in the 3 dictionsaries covid, weather & articles
    and then it formats them and returns them in one list'''
    length = len(current_time_hhmm())
    for i in range(length):
        if current_time_hhmm()[i] == ":":
            start = i + 1
    #refreshing the seen file so it doesn't contain irrelevent info, and because by ever hour\
    #normally all of the nes has been updated and the data in the seen file is different to the\
    #new nes anyway
    if current_time_hhmm()[start:] == '':
        with open('./json_files/seen.json', 'w') as jfile:
            json.dump({'notifications': []}, jfile, indent=4)
    #this wil update the notifications collumn every 15 mins or when the function is first called
    if int(current_time_hhmm()[start:]) % 15 == 0 or current_time_hhmm(
    )[start:] == '' or len(lst) == 0:
        #updating the list if it is the first time the function is called
        if len(lst) == 0:
            lst.append('1')
        length = len(articles)
        i = 0
        #this will loop through every item (article) in articles
        #if the api call didn't fail
        if articles[0]['title'] != 'FAILED':
            while i < length:
                #adding the url of the website in the article to the content variable as\
                #markup so it can be displayed on the website (with html)
                content = Markup(
                    ("<a href='%s'target='_blank'>click_here</a>" %
                     (articles[i]['url'])))
                #then adding this to the content of the spcific article
                articles[i]['content'] = str(
                    articles[i]['description']) + ' ------ ' + content
                i += 1
        #setting the covid input to be added as a dictionary
        dic = {
            'title': 'Daily local covid infection rates',
            'content': str(covid),
            'url': ''
        }
        #adding this dictionary to articles
        articles.insert(0, dic)
        #chekcing if there has been weather data inputted and that there hasn't been an error
        if weather != [] and weather["cod"] == 200:
            #setting weath to the main attributes of the weather input
            weath = weather["main"]
            #getting the tempurature
            current_temp = weath["temp"]
            #getting the pressure
            current_press = weath["pressure"]
            #getting the humidity
            current_humid = weath["humidity"]
            #setting weath to the weather attribute of the weather input
            weath = weather["weather"]
            #getting the description from the weather input (from weath)
            weather_desc = weath[0]["description"]
            #getting the wind speed
            weath = weather["wind"]
            #concatonating all the variables gathered on weather into one string with\
            #more descriptions of them
            description = "The temperature outside is "+str(int(current_temp - 273.15))\
                + " degrees centigrade; The atmospheric pressure is "\
                    + str(current_press) + "hPa; The humidity is " + str(current_humid) +\
                        "%; The wind speed is "+str(weath['speed'])+"m/s; And it is "+\
                            str(weather_desc)
            #putting this description into a dictionary with the other informaiont about weather
            wdic = {
                'title': 'Weather in Exeter',
                'content': description,
                'url': ''
            }
            #adding this dictionary to articles
            articles.insert(1, wdic)
        #adding to articles that there has been an error with the api call
        elif weather != [] and weather["cod"] != 200:
            wdic = {
                'title': weather["cod"],
                'content': weather['message'],
                'url': ''
            }
            articles.insert(1, wdic)
        #logging that the inputs have been organised into notifications
        log("notifications organised")
        data = {'notifications': [articles]}
        #calling the write function to add the new notifications to the json file
        write_json(data)
    #opening the json file to read from it
    with open('./json_files/notifications.json') as jfile:
        data = json.load(jfile)
        #getting the notifications from the json file
        data = data['notifications'][0]
    log('notifications from json file returned')
    #looping through the json file and adding the urls as links
    length = len(data)
    if data[2]['title'] != 'FAILED':
        for i in range(length):
            if data[i]['url']:
                #adding the url of the website in the article to the content variable as\
                #markup so it can be displayed on the website (with html)
                content = Markup(
                    ("<a href='%s'target='_blank'>click_here</a>" %
                     (data[i]['url'])))
                #then adding this to the content of the spcific article
                data[i]['content'] = str(
                    data[i]['description']) + ' ------ ' + content
    notifications = []
    #getting the seen notifications file
    with open('./json_files/seen.json') as jfil:
        seen = json.load(jfil)
        #getting the notificatios from the json file
        seen = seen['notifications']
    for i in data:
        if i not in seen:
            notifications.append(i)
    #returning the notifications in the json file
    return notifications
def logg():
    '''This logs when the python service is closed'''
    log('-------FINISHED-------')
def rootindex():
    '''This adds, started, to the logfile and redirects the
    user to the index page'''
    log('-------STARTED-------')
    return redirect("/index")