diff --git a/.gitignore b/.gitignore index 113294a..49ec7cf 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,6 @@ ENV/ # mypy .mypy_cache/ + + +.DS_Store diff --git a/termWeather/conf/GeoLite2-City.mmdb b/termWeather/conf/GeoLite2-City.mmdb deleted file mode 100644 index e7839d8..0000000 Binary files a/termWeather/conf/GeoLite2-City.mmdb and /dev/null differ diff --git a/termWeather/emojiParser.py b/termWeather/emojiParser.py deleted file mode 100755 index aff67a2..0000000 --- a/termWeather/emojiParser.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python3.6 -# -*- coding: utf-8 -*- -# @Author: KevinMidboe -# @Date: 2017-07-29 11:56:24 -# @Last Modified by: KevinMidboe -# @Last Modified time: 2017-07-30 13:17:19 - -from fuzzywuzzy import process - -# Find the first word, if it is a noun or a adjective. ✔️ -# Remove the adjective and split if there is a AND ✔️ -# Then match the first noun to list and add that emoji ✔️ -# and then match the second to list and add that emoji ✔️ -# REGEX this bitch up - -symbol_table = { - 'clear sky': '☀️', - 'fair': '🌤', - 'partly cloudy': '⛅️', - 'cloudy': ' ☁️ ', - 'thunder': '⚡️', - - 'rain showers': '🌦', - 'rain': '🌧', - 'sleet showers': '🌦 💦', - 'sleet': '🌨 💦', - 'snow showers': '⛅ ❄️', - 'snow': '🌨', - - 'rain': '🌧', - 'sleet': '🌧', - 'snow': '🌨', - - 'showers': '🌤' - } - -severity = { - 'rain': ['', ' ☂️', ' ☔️'], - 'sleet': [' 💦 ', ' 💧 ', ' 💧 💦 '], - 'snow': [' ❄️ ', ' ❄️ ❄️ ', ' ❄️ ❄️ ❄️ '] - } - -class EmojiParser(object): - def __init__(self, condition_text): - self.condition_expression = condition_text.lower() - self.severity = None - self.nouns = [] - - self.weather_nouns = ['cleary sky', 'fair', 'cloudy', 'rain', 'rain showers', 'sleet', - 'sleet showers', 'snow showers', 'thunder', 'snow'] - self.weather_adjectives = {'light': 0, 'normal': 1, 'heavy': 2} - - def __str__(self): - return str([self.condition_expression, self.severity, self.nouns]) - - # Splits and lowers the condition text for easier parsing - def splitCondition(self, condition): - return condition.split() - - # Takes a input or uses condition_expression to find adjective in sentence - def findAdjective(self, sentence=None): - if sentence is None: - sentence = self.condition_expression - - # Splits and iterates over each word in sentence - expression = self.splitCondition(sentence) - for word in expression: - if word in self.weather_adjectives: - # Return the word if matched with weather_adjectives - return word - - return None - - # Removes the first adjective in the a given sentence - def removeAdjective(self): - adjective = self.findAdjective() - if adjective: # Adjective is not None - expression = self.splitCondition(self.condition_expression) - expression.remove(adjective) - return ' '.join(expression) - else: - return self.condition_expression - - - def severityValue(self): - adjective = self.findAdjective() - - if adjective: - self.severity = self.weather_adjectives[adjective] - else: - self.severity = self.weather_adjectives['normal'] - - def findWeatherTokens(self): - # If present removes the leading adjective - sentence = self.removeAdjective() - - # If multiple tokens/weather_nouns split all between the 'and' - if 'and' in sentence: - self.nouns = sentence.split(' and ') - else: - self.nouns = [sentence] - - - # Use the symbol_table to convert the forecast name to emoji - def emojify(self, noun): - return symbol_table[noun] - - # Does as emojify above, but iterates over a list if multiple elements - def emojifyList(self, noun_list): - returnList = [] - - # TODO use more like a map function? - for noun in noun_list: - returnList.append(self.emojify(noun)) - - return ' '.join(returnList) - - def findPrimaryForecast(self): - # Copies the contents not the refrence to the list - noun_list = list(self.nouns) - forecast = noun_list.pop(0) - - # Translates to emoji once here instead of twice below - forecast_emoji = self.emojify(forecast) - - if forecast in severity: - return ('%s %s' % (forecast_emoji, severity[forecast])) - else: - return forecast_emoji - - - # Trying to analyze the semantics of the condition text - def emojifyWeatherForecast(self): - # Finds the tokens/nouns of weather for the given input text and severity value - self.findWeatherTokens() - self.severityValue() - - primary_forecast = self.findPrimaryForecast() - secondary_forecast = self.emojifyList(self.nouns[1:]) - - return ('%s %s' % (primary_forecast, secondary_forecast)) - - - def convertSematicsToEmoji(self): - return self.emojifyWeatherForecast() - - -def main(): - emojiParser = EmojiParser('Cloudy') - print(emojiParser.convertSematicsToEmoji()) - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/termWeather/loadingAnimation.py b/termWeather/loadingAnimation.py deleted file mode 100755 index 1fc9436..0000000 --- a/termWeather/loadingAnimation.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3.6 -# -*- coding: utf-8 -*- -# @Author: KevinMidboe -# @Date: 2017-07-30 13:53:38 -# @Last Modified by: KevinMidboe -# @Last Modified time: 2017-07-30 13:53:46 - -import itertools -from threading import Thread -from time import sleep -from sys import stdout - -class LoadingAnimation(object): - def __init__(self): - self.done = False - - def start(self): - t = Thread(target=self.animate) - t.start() - - def animate(self): - for c in itertools.cycle(['|', '/', '-', '\\']): - if self.done: - break - stdout.write('\rFetching ' + c) - stdout.flush() - sleep(0.1) - - def stop(self): - self.done = True - -def main(): - loadingAnimation = LoadingAnimation() - loadingAnimation.start() - sleep(2) - loadingAnimation.stop() - stdout.write('\rTemp \n') - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/termWeather/term_weather.py b/termWeather/term_weather.py deleted file mode 100755 index d2766db..0000000 --- a/termWeather/term_weather.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python3.6 -# -*- coding: utf-8 -*- -# @Author: KevinMidboe -# @Date: 2017-07-27 21:26:53 -# @Last Modified by: KevinMidboe -# @Last Modified time: 2017-07-30 18:56:27 - -# TODO LIST -# Get coordinates from IP ✔ -# Fetch coordinates from YR ✔ -# Convert coordinates to place name w/ google GeoCode api ✔ -# Parse return data -# Match weather description to icons ✔ -# Check internet connection in a strict way -# Add table for time periode -# Add cache for quicker location for same ip - -import fire, json, geoip2.database, ssl, os -from yr.libyr import Yr -from requests import get -from pprint import pprint -from sys import stdout - -from emojiParser import EmojiParser -from loadingAnimation import LoadingAnimation - - -class Location(object): - def __init__(self): - - abspath = os.path.abspath(__file__) - dname = os.path.dirname(abspath) - os.chdir(dname) - self.reader = geoip2.database.Reader('conf/GeoLite2-City.mmdb') - self.getIP() - - def getIP(self): - ip = get('https://api.ipify.org').text - self.ip = self.reader.city(ip) - - def getCoordinates(self): - lat = self.ip.location.latitude - long = self.ip.location.longitude - return [lat, long] - - def getAreaName(self): - lat, long = self.getCoordinates() - coordinates = ','.join([str(lat), str(long)]) - areaURL = 'https://maps.googleapis.com/maps/api/geocode/json?&latlng=' - - areaAPIResponse = json.loads(get(areaURL + coordinates).text) - closestArea = areaAPIResponse['results'][0]['address_components'] - - area = {} - - for item in closestArea: - if 'route' in item['types']: - area['street'] = item['long_name'] - - if 'locality' in item['types']: - area['town'] = item['long_name'] - - if 'administrative_area_level_1' in item['types']: - area['municipality'] = item['long_name'] - - if 'country' in item['types']: - area['country'] = item['long_name'] - - return area - - -class WeatherForecast(object): - def __init__(self, area=None): - # TODO search for area coordinates in a map - self.area = area - - self.name = None - self.number = None - self.variable = None - - def symbolVariables(self, symbol_obj): - self.name = symbol_obj['@name'] - self.number = symbol_obj['@number'] - self.variable = symbol_obj['@var'] - - def parseYrTemperature(self, temperature_obj): - return temperature_obj['@value'] + ' ' + temperature_obj['@unit'] - - def now(self): - location = Location() - self.area = location.getAreaName() - - # Create seperate function for formatting - locationName = '/'.join([self.area['country'], self.area['municipality'], self.area['town'], self.area['street']]) - - # Use the defined location name with yr API for location based weather information - weather = Yr(location_name=locationName) - now = json.loads(weather.now(as_json=True)) - - - temperature_output = self.parseYrTemperature(now['temperature']) - - emojiParser = EmojiParser(now['symbol']['@name']) - weatherIcon_output = emojiParser.convertSematicsToEmoji() - - return ('%s %s' % (temperature_output, weatherIcon_output)) - - -class TermWeather(object): - # Add now, forecast as args - def auto(self): - loadingAnimation = LoadingAnimation() - loadingAnimation.start() - weatherForecast = WeatherForecast() - forecast = weatherForecast.now() - loadingAnimation.stop() - stdout.write('\r%s \n' % forecast) - - def fetch(self, area=None): - weatherForecast = WeatherForcast(area) - weatherForecast.now() - - -if __name__ == '__main__': - ssl._create_default_https_context = ssl._create_unverified_context - - fire.Fire(TermWeather()) \ No newline at end of file diff --git a/term_weather.py b/term_forecast/term_weather.py old mode 100755 new mode 100644 similarity index 96% rename from term_weather.py rename to term_forecast/term_weather.py index b13ac0f..d43c23b --- a/term_weather.py +++ b/term_forecast/term_weather.py @@ -3,7 +3,7 @@ # @Author: KevinMidboe # @Date: 2017-07-27 21:26:53 # @Last Modified by: KevinMidboe -# @Last Modified time: 2017-07-30 14:05:28 +# @Last Modified time: 2017-07-30 19:56:18 # TODO LIST # Get coordinates from IP ✔ @@ -107,6 +107,9 @@ class WeatherForecast(object): class TermWeather(object): + def __init__(self): + print('here') + # Add now, forecast as args def auto(self): loadingAnimation = LoadingAnimation()