diff --git a/api_fonction.py b/api_fonction.py new file mode 100644 index 0000000..44711f3 --- /dev/null +++ b/api_fonction.py @@ -0,0 +1,104 @@ +from config import * +from contextlib import closing +from urllib.request import urlopen +import json + + +def getSearch(query): + if METEOCONCEPT_TOKEN is None and WEATHERSTACK_TOKEN is None: + log('Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed') + return 'Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed' + elif query is None: + log('GET/POST search variable not passed') + return 'GET/POST search variable not passed' + else: + log('Env variable METEOCONCEPT_TOKEN or/and WEATHERSTACK_TOKEN passed') + with closing(urlopen( + API_LOCATION_CITIES_METEOCONCEPT + + API_TOKEN_METEOCONCEPT + + METEOCONCEPT_TOKEN + + API_SEARCH_METEOCONCEPT + query)) as f: + cities_METEOCONCEPT = json.loads(f.read())['cities'] + + with closing(urlopen( + API_LOCATION_CITIES_WEATHERSTACK + + API_TOKEN_WEATHERSTACK + + WEATHERSTACK_TOKEN + + API_SEARCH_WEATHERSTACK + query)) as f: + cities_WEATHERSTACK = json.loads(f.read()) + return {"query": query, + "cities": { + "METEOCONCEPT": cities_METEOCONCEPT, + "WEATHERSTACK": cities_WEATHERSTACK + } + } + + +def getCurrent(query): + if METEOCONCEPT_TOKEN is None and WEATHERSTACK_TOKEN is None: + log('Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed') + return 'Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed' + elif query is None: + log('GET/POST query variable not passed') + return 'GET/POST query variable not passed' + else: + log('Env variable METEOCONCEPT_TOKEN or/and WEATHERSTACK_TOKEN passed') + try: + query = int(query) + with closing(urlopen( + API_OBSERVATIONS_AROUND_METEOCONCEPT + + API_TOKEN_METEOCONCEPT + + METEOCONCEPT_TOKEN + + API_INSEE_METEOCONCEPT + + str(query) + + API_RADIUS_METEOCONCEPT + + '0')) as f: + around_METEOCONCEPT = json.loads(f.read()) + return {"query": query, "around": { + "METEOCONCEPT": around_METEOCONCEPT, + "WEATHERSTACK": None + } + } + except: + with closing(urlopen( + API_OBSERVATIONS_AROUND_WEATHERSTACK + + API_TOKEN_WEATHERSTACK + + WEATHERSTACK_TOKEN + + API_SEARCH_WEATHERSTACK + + query + ",France")) as f: + around_WEATHERSTACK = json.loads(f.read()) + return {"query": query, "around": { + "METEOCONCEPT": None, + "WEATHERSTACK": around_WEATHERSTACK + } + } + + + +# def getEphemeride(insee): +# if METEOCONCEPT_TOKEN is None: +# log('Env variable METEOCONCEPT_TOKEN not passed') +# return 'Env variable METEOCONCEPT_TOKEN not passed' +# elif insee is None: +# log('GET/POST insee variable not passed') +# return 'GET/POST insee variable not passed' +# else: +# log('Env variable METEOCONCEPT_TOKEN passed') +# with closing(urlopen(API_EPHEMERIDE + API_TOKEN + METEOCONCEPT_TOKEN + API_INSEE + insee)) as f: +# cityEph = json.loads(f.read()) +# return [insee, cityEph] +# +# +# def getCity(insee): +# if METEOCONCEPT_TOKEN is None and WEATHERSTACK_TOKEN is None: +# log('Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed') +# return 'Env variable METEOCONCEPT_TOKEN and WEATHERSTACK_TOKEN not passed' +# elif search is None: +# log('GET/POST search variable not passed') +# return 'GET/POST search variable not passed' +# else: +# log('Env variable METEOCONCEPT_TOKEN or/and WEATHERSTACK_TOKEN passed') +# +# with closing(urlopen(API_LOCATION_CITY + API_TOKEN + METEOCONCEPT_TOKEN + API_INSEE + insee)) as f: +# city = json.loads(f.read())['city'] +# return [insee, city] diff --git a/app.py b/app.py index 793f29e..facf9e8 100644 --- a/app.py +++ b/app.py @@ -1,152 +1,12 @@ import os - -from flask import Flask, request, render_template - -from contextlib import closing -from urllib.request import urlopen -import json from config import * -from forms import * - -def getApiCity(search): - if METEOCONCEPT_TOKEN is None: - log('Env variable METEOCONCEPT_TOKEN not passed') - return 'Env variable METEOCONCEPT_TOKEN not passed' - elif search is None: - log('GET/POST search variable not passed') - return 'GET/POST search variable not passed' - else: - log('Env variable METEOCONCEPT_TOKEN passed') - with closing(urlopen(API_LOCATION_CITIES + API_TOKEN + METEOCONCEPT_TOKEN + API_SEARCH + search)) as f: - cities = json.loads(f.read())['cities'] - return [search, cities] - - -def getAround(insee, radius): - if METEOCONCEPT_TOKEN is None: - log('Env variable METEOCONCEPT_TOKEN not passed') - return 'Env variable METEOCONCEPT_TOKEN not passed' - elif insee is None or radius is None: - log('GET/POST insee or radius variable not passed') - return 'GET/POST insee or radiu variable not passed' - else: - log('Env variable METEOCONCEPT_TOKEN passed') - with closing( - urlopen( - API_OBSERVATIONS_AROUND + API_TOKEN + METEOCONCEPT_TOKEN + API_INSEE + insee + API_RADIUS + radius)) as f: - around = json.loads(f.read()) - return [insee, radius, around] - - -def getEphemeride(insee): - if METEOCONCEPT_TOKEN is None: - log('Env variable METEOCONCEPT_TOKEN not passed') - return 'Env variable METEOCONCEPT_TOKEN not passed' - elif insee is None: - log('GET/POST insee variable not passed') - return 'GET/POST insee variable not passed' - else: - log('Env variable METEOCONCEPT_TOKEN passed') - with closing(urlopen(API_EPHEMERIDE + API_TOKEN + METEOCONCEPT_TOKEN + API_INSEE + insee)) as f: - cityEph = json.loads(f.read()) - return [insee, cityEph] - - -def getCity(insee): - if METEOCONCEPT_TOKEN is None: - log('Env variable METEOCONCEPT_TOKEN not passed') - return 'Env variable METEOCONCEPT_TOKEN not passed' - elif insee is None: - log('GET/POST insee variable not passed') - return 'GET/POST insee variable not passed' - else: - log('Env variable METEOCONCEPT_TOKEN passed') - with closing(urlopen(API_LOCATION_CITY + API_TOKEN + METEOCONCEPT_TOKEN + API_INSEE + insee)) as f: - city = json.loads(f.read())['city'] - return [insee, city] - - -app = Flask(__name__) - - -@app.route('/config') -def config(): # put application's code here - return str(INDENT) + str(WEATHER) + str(WINDDIRS) - - -@app.route('/', methods=['POST', 'GET']) -def index(): - response_cities = False - response_ephemeride = False - response_around = False - - search = Search() - city = City() - around = Around() - - if search.submit_search.data and search.validate_on_submit(): - return render_template('index.html', cities=getApiCity(search)) - - if city.submit_city.data and city.validate_on_submit(): - return render_template('index.html', ephemeride=getEphemeride(city)) - - if around.submit_around.data and around.validate_on_submit(): - return render_template('index.html', around=getAround(around, 1)) - - # TODO Multiple form for insee ? or ajax ? - insee = request.form['insee'] - response_ephemeride = getEphemeride(insee) - response_around = getAround(insee, 1) - - return render_template('index.html', cities=response_cities, ephemeride=response_ephemeride, around=response_around) - - -# Recherche d'une ville -@app.route('/searchCity', methods=['POST', 'GET']) -def searchCity(): # put application's code here - if request.method == 'POST': - search = request.form['search'] - else: - search = request.args.get('search') - return json.dumps(getApiCity(search), indent=INDENT, sort_keys=True) - - -# Informations sur la Ville -@app.route('/city', methods=['POST', 'GET']) -def getCity(): # put application's code here - if request.method == 'POST': - insee = request.form['insee'] - else: - insee = request.args.get('insee') - return json.dumps(getCity(insee), indent=INDENT, sort_keys=True) - - -# Information sur la ville et Ephéméride -@app.route('/ephemeride', methods=['POST', 'GET']) -def ephemeride(): # put application's code here - if request.method == 'POST': - insee = request.form['insee'] - else: - insee = request.args.get('insee') - return json.dumps(getEphemeride(insee), indent=INDENT, sort_keys=True) - - -# Information sur les alentours d'une ville -@app.route('/around', methods=['POST', 'GET']) -def around(): # put application's code here - if request.method == 'POST': - insee = request.form['insee'] - radius = request.form['radius'] - else: - insee = request.args.get('insee') - radius = request.args.get('radius') - return json.dumps(getAround(insee, radius), indent=INDENT, sort_keys=True) - +from flask_route import * if __name__ == '__main__': PORT = int(os.environ.get('PORT', 33507)) # On Linux or MAC 'export METEOCONCEPT_TOKEN=...' (check shell echo $METEOCONCEPT_TOKEN) # On Windows 'set METEOCONCEPT_TOKEN=...' (check on Powershell echo $Env:METEOCONCEPT_TOKEN) - METEOCONCEPT_TOKEN = os.environ.get('METEOCONCEPT_TOKEN', None) + METEOCONCEPT_TOKEN = os.environ.get('METEOCONCEPT_TOKEN', METEOCONCEPT_TOKEN) + WEATHERSTACK_TOKEN = os.environ.get('WEATHERSTACK_TOKEN', WEATHERSTACK_TOKEN) app.config['SECRET_KEY'] = 'secret_key' app.run(host='0.0.0.0', port=PORT, debug=True) \ No newline at end of file diff --git a/config.py b/config.py index de6f00f..61e4c0a 100644 --- a/config.py +++ b/config.py @@ -1,30 +1,24 @@ import sys - - -# logging helper def log(*args): print(args[0] % (len(args) > 1 and args[1:] or [])) sys.stdout.flush() - # JSON DUMPS +JSON_PRETTYFIER = True INDENT = 4 -# API URL -BASE_API_URL = 'https://api.meteo-concept.com/api/' - -API_TOKEN = '?token=' -API_SEARCH = '&search=' -API_INSEE = '&insee=' -API_RADIUS = '&radius=' - -API_LOCATION_CITIES = BASE_API_URL + 'location/cities' -API_LOCATION_CITY = BASE_API_URL + 'location/city' -API_EPHEMERIDE = BASE_API_URL + 'ephemeride/1' -API_OBSERVATIONS_AROUND = BASE_API_URL + 'observations/around' - -# STATIC VARIABLES -WINDDIRS = [ +# METEOCONCEPT API URL +BASE_API_URL_METEOCONCEPT = 'https://api.meteo-concept.com/api/' +METEOCONCEPT_TOKEN = "e93ee091ba7cd6ce1882fb55f9c030bbbafa0defaa0d8dd4f780b00897b989e1" +API_TOKEN_METEOCONCEPT = '?token=' +API_SEARCH_METEOCONCEPT = '&search=' +API_INSEE_METEOCONCEPT = '&insee=' +API_RADIUS_METEOCONCEPT = '&radius=' +API_LOCATION_CITIES_METEOCONCEPT = BASE_API_URL_METEOCONCEPT + 'location/cities' +API_LOCATION_CITY_METEOCONCEPT = BASE_API_URL_METEOCONCEPT + 'location/city' +API_EPHEMERIDE_METEOCONCEPT = BASE_API_URL_METEOCONCEPT + 'ephemeride/1' +API_OBSERVATIONS_AROUND_METEOCONCEPT = BASE_API_URL_METEOCONCEPT + 'observations/around' +WINDDIRS_METEOCONCEPT = [ 'Nord', 'Nord-Nord-Est', 'Nord-Est', @@ -43,7 +37,7 @@ WINDDIRS = [ 'Nord-Nord-Ouest', 'Nord' ] -WEATHER = { +WEATHER_METEOCONCEPT = { 0: "Soleil", 1: "Peu nuageux", 2: "Ciel voilé", @@ -133,3 +127,12 @@ WEATHER = { 232: "Pluie et neige mêlées", 235: "Averses de grêle", } + + +# WEATHERSTACK API URL +BASE_API_URL_WEATHERSTACK = 'http://api.weatherstack.com/' +WEATHERSTACK_TOKEN = "e43f819bbbf50da109d7076840cd3f11" +API_TOKEN_WEATHERSTACK = '?access_key=' +API_SEARCH_WEATHERSTACK = '&query=' +API_LOCATION_CITIES_WEATHERSTACK = BASE_API_URL_WEATHERSTACK + 'autocomplete' +API_OBSERVATIONS_AROUND_WEATHERSTACK = BASE_API_URL_WEATHERSTACK + 'current' \ No newline at end of file diff --git a/flask_route.py b/flask_route.py new file mode 100644 index 0000000..f05947e --- /dev/null +++ b/flask_route.py @@ -0,0 +1,89 @@ +from flask import Flask, request, render_template +from config import * +from forms import * +from api_fonction import * + +app = Flask(__name__) + +def app_response(results): + if JSON_PRETTYFIER: + json_results = json.dumps(results, indent=INDENT, sort_keys=True) + else: + json_results = json.dumps(results, sort_keys=True) + response = app.response_class( + response=json_results, + status=200, + mimetype='application/json' + ) + response.headers['Access-Control-Allow-Origin'] = '*' + return response + +@app.route('/config') +def config(): # put application's code here + return app_response({}) + + +# Recherche d'une ville +@app.route('/search', methods=['POST', 'GET']) +def search(): # put application's code here + if request.method == 'POST': + query = request.form['query'] + else: + query = request.args.get('query') + return app_response(getSearch(query)) + + +# Information sur les alentours d'une ville +@app.route('/current', methods=['POST', 'GET']) +def current(): # put application's code here + if request.method == 'POST': + query = request.form['query'] + else: + query = request.args.get('query') + return app_response(getCurrent(query)) + +# # Informations sur la Ville +# @app.route('/city', methods=['POST', 'GET']) +# def getCity(): # put application's code here +# if request.method == 'POST': +# insee = request.form['insee'] +# else: +# insee = request.args.get('insee') +# return app_response(json.dumps(getCity(insee), indent=INDENT, sort_keys=True)) +# +# +# # Information sur la ville et Ephéméride +# @app.route('/ephemeride', methods=['POST', 'GET']) +# def ephemeride(): # put application's code here +# if request.method == 'POST': +# insee = request.form['insee'] +# else: +# insee = request.args.get('insee') +# return app_response(json.dumps(getEphemeride(insee), indent=INDENT, sort_keys=True)) + + +# @app.route('/', methods=['POST', 'GET']) +# def index(): +# response_cities = False +# response_ephemeride = False +# response_around = False +# +# search = Search() +# city = City() +# around = Around() +# +# if search.submit_search.data and search.validate_on_submit(): +# return render_template('index.html', cities=getApiCity(search)) +# +# if city.submit_city.data and city.validate_on_submit(): +# return render_template('index.html', ephemeride=getEphemeride(city)) +# +# if around.submit_around.data and around.validate_on_submit(): +# return render_template('index.html', around=getAround(around, 1)) +# +# # TODO Multiple form for insee ? or ajax ? +# insee = request.form['insee'] +# response_ephemeride = getEphemeride(insee) +# response_around = getAround(insee, 1) +# +# return render_template('index.html', cities=response_cities, ephemeride=response_ephemeride, around=response_around) \ No newline at end of file