- Forecast: Inline-Mode + Optimierungen
- Weather: Optimierungen
This commit is contained in:
		| @@ -1,5 +1,7 @@ | |||||||
| local forecast = {} | local forecast = {} | ||||||
|  |  | ||||||
|  | require("./otouto/plugins/weather") | ||||||
|  |  | ||||||
| function forecast:init(config) | function forecast:init(config) | ||||||
| 	if not cred_data.forecastio_apikey then | 	if not cred_data.forecastio_apikey then | ||||||
| 		print('Missing config value: forecastio_apikey.') | 		print('Missing config value: forecastio_apikey.') | ||||||
| @@ -21,6 +23,12 @@ function forecast:init(config) | |||||||
| 	"^(/forecasth)$", | 	"^(/forecasth)$", | ||||||
| 	"^(/forecasth) (.*)$" | 	"^(/forecasth) (.*)$" | ||||||
| 	} | 	} | ||||||
|  | 	forecast.inline_triggers = { | ||||||
|  | 	  "^(f) (.+)$", | ||||||
|  | 	  "^(fh) (.+)$", | ||||||
|  | 	  "^(fh)$", | ||||||
|  | 	  "^(f)$" | ||||||
|  | 	} | ||||||
| 	forecast.doc = [[* | 	forecast.doc = [[* | ||||||
| ]]..config.cmd_pat..[[f*:  Wettervorhersage für deinen Wohnort _(/location set <Ort>)_ | ]]..config.cmd_pat..[[f*:  Wettervorhersage für deinen Wohnort _(/location set <Ort>)_ | ||||||
| *]]..config.cmd_pat..[[f* _<Ort>_: Wettervorhersage für diesen Ort | *]]..config.cmd_pat..[[f* _<Ort>_: Wettervorhersage für diesen Ort | ||||||
| @@ -35,39 +43,26 @@ local BASE_URL = "https://api.forecast.io/forecast" | |||||||
| local apikey = cred_data.forecastio_apikey | local apikey = cred_data.forecastio_apikey | ||||||
| local google_apikey = cred_data.google_apikey | local google_apikey = cred_data.google_apikey | ||||||
|  |  | ||||||
| function get_city_name(lat, lng) | function forecast:get_condition_symbol(weather_data) | ||||||
|   local city = redis:hget('telegram:cache:weather:pretty_names', lat..','..lng) |   if weather_data.icon == 'clear-day' then | ||||||
|   if city then return city end |  | ||||||
|   local url = 'https://maps.googleapis.com/maps/api/geocode/json?latlng='..lat..','..lng..'&result_type=political&language=de&key='..google_apikey |  | ||||||
|   local res, code = https.request(url) |  | ||||||
|   if code ~= 200 then return 'Unbekannte Stadt' end |  | ||||||
|   local data = json.decode(res).results[1] |  | ||||||
|   local city = data.formatted_address |  | ||||||
|   print('Setting '..lat..','..lng..' in redis hash telegram:cache:weather:pretty_names to "'..city..'"') |  | ||||||
|   redis:hset('telegram:cache:weather:pretty_names', lat..','..lng, city) |  | ||||||
|   return city |  | ||||||
| end |  | ||||||
|  |  | ||||||
| function get_condition_symbol(weather, n) |  | ||||||
|   if weather.data[n].icon == 'clear-day' then |  | ||||||
| 	return '☀️' | 	return '☀️' | ||||||
|   elseif weather.data[n].icon == 'clear-night' then |   elseif weather_data.icon == 'clear-night' then | ||||||
|     return '🌙' |     return '🌙' | ||||||
|   elseif weather.data[n].icon == 'rain' then |   elseif weather_data.icon == 'rain' then | ||||||
|     return '☔️' |     return '☔️' | ||||||
|   elseif weather.data[n].icon == 'snow' then |   elseif weather_data.icon == 'snow' then | ||||||
| 	return '❄️' | 	return '❄️' | ||||||
|   elseif weather.data[n].icon == 'sleet' then |   elseif weather_data.icon == 'sleet' then | ||||||
|     return '🌨' |     return '🌨' | ||||||
|   elseif weather.data[n].icon == 'wind' then |   elseif weather_data.icon == 'wind' then | ||||||
|     return '💨' |     return '💨' | ||||||
|   elseif weather.data[n].icon == 'fog' then |   elseif weather_data.icon == 'fog' then | ||||||
|     return '🌫' |     return '🌫' | ||||||
|   elseif weather.data[n].icon == 'cloudy' then |   elseif weather_data.icon == 'cloudy' then | ||||||
|     return '☁️☁️' |     return '☁️☁️' | ||||||
|   elseif weather.data[n].icon == 'partly-cloudy-day' then |   elseif weather_data.icon == 'partly-cloudy-day' then | ||||||
|     return '🌤' |     return '🌤' | ||||||
|   elseif weather.data[n].icon == 'partly-cloudy-night' then |   elseif weather_data.icon == 'partly-cloudy-night' then | ||||||
|     return '🌙☁️' |     return '🌙☁️' | ||||||
|   else |   else | ||||||
|     return '' |     return '' | ||||||
| @@ -75,22 +70,34 @@ function get_condition_symbol(weather, n) | |||||||
| end | end | ||||||
|  |  | ||||||
| function get_temp(weather, n, hourly) | function get_temp(weather, n, hourly) | ||||||
|  |   local weather_data = weather.data[n] | ||||||
|   if hourly then |   if hourly then | ||||||
|     local temperature = string.gsub(round(weather.data[n].temperature, 1), "%.", ",") |     local temperature = string.gsub(round(weather_data.temperature, 1), "%.", ",") | ||||||
| 	local condition = weather.data[n].summary | 	local condition = weather_data.summary | ||||||
| 	return temperature..'°C | '..get_condition_symbol(weather, n)..' '..condition | 	return temperature..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition | ||||||
|   else |   else | ||||||
|     local day = string.gsub(round(weather.data[n].temperatureMax, 1), "%.", ",") |     local day = string.gsub(round(weather_data.temperatureMax, 1), "%.", ",") | ||||||
|     local night = string.gsub(round(weather.data[n].temperatureMin, 1), "%.", ",") |     local night = string.gsub(round(weather_data.temperatureMin, 1), "%.", ",") | ||||||
|     local condition = weather.data[n].summary |     local condition = weather_data.summary | ||||||
|     return '☀️ '..day..'°C | 🌙 '..night..'°C | '..get_condition_symbol(weather, n)..' '..condition |     return '☀️ '..day..'°C | 🌙 '..night..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition | ||||||
|   end |   end | ||||||
| end | end | ||||||
|  |  | ||||||
| function forecast:get_forecast(lat, lng) | function forecast:get_forecast(lat, lng, is_inline) | ||||||
|   print('Finde Wetter in '..lat..', '..lng) |   print('Finde Wetter in '..lat..', '..lng) | ||||||
|   local text = redis:get('telegram:cache:forecast:'..lat..','..lng) |   local hash = 'telegram:cache:forecast:'..lat..','..lng | ||||||
|   if text then print('...aus dem Cache..') return text end |   local text = redis:hget(hash, 'text') | ||||||
|  |   if text then | ||||||
|  |     print('...aus dem Cache..') | ||||||
|  | 	if is_inline then | ||||||
|  | 	  local ttl = redis:ttl(hash) | ||||||
|  | 	  local city = redis:hget(hash, 'city') | ||||||
|  | 	  local summary = redis:hget(hash, 'summary') | ||||||
|  | 	  return city, summary, text, ttl | ||||||
|  | 	else | ||||||
|  | 	  return text | ||||||
|  | 	end | ||||||
|  |   end | ||||||
|  |  | ||||||
|   local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,hourly,alerts,flags' |   local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,hourly,alerts,flags' | ||||||
|    |    | ||||||
| @@ -100,43 +107,61 @@ function forecast:get_forecast(lat, lng) | |||||||
|       method = "GET", |       method = "GET", | ||||||
|       sink = ltn12.sink.table(response_body) |       sink = ltn12.sink.table(response_body) | ||||||
|    } |    } | ||||||
|   local ok, response_code, response_headers, response_status_line = https.request(request_constructor) |   local ok, response_code, response_headers = https.request(request_constructor) | ||||||
|   if not ok then return nil end |   if not ok then return nil end | ||||||
|   local data = json.decode(table.concat(response_body)) |   local weather = json.decode(table.concat(response_body)).daily | ||||||
|   local ttl = string.sub(response_headers["cache-control"], 9) |   local ttl = tonumber(string.sub(response_headers["cache-control"], 9)) | ||||||
|  |  | ||||||
|    |  | ||||||
|   local weather = data.daily |  | ||||||
|   local city = get_city_name(lat, lng) |   local city = get_city_name(lat, lng) | ||||||
|  |   local weather_summary = weather.summary | ||||||
|    |    | ||||||
|   local header = '*Vorhersage für '..city..':*\n_'..weather.summary..'_\n' |   local header = '*Vorhersage für '..city..':*\n_'..weather_summary..'_\n' | ||||||
|    |    | ||||||
|   local text = '*Heute:* '..get_temp(weather, 1) |   local text = '*Heute:* '..get_temp(weather, 1) | ||||||
|   local text = text..'\n*Morgen:* '..get_temp(weather, 2) |   local text = text..'\n*Morgen:* '..get_temp(weather, 2) | ||||||
|    |    | ||||||
|   for day in pairs(weather.data) do |   local weather_data = weather.data | ||||||
|  |   for day in pairs(weather_data) do | ||||||
| 	if day > 2 then  | 	if day > 2 then  | ||||||
| 	  text = text..'\n*'..convert_timestamp(weather.data[day].time, '%a, %d.%m')..'*: '..get_temp(weather, day) | 	  text = text..'\n*'..convert_timestamp(weather_data[day].time, '%a, %d.%m')..'*: '..get_temp(weather, day) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|    |    | ||||||
|   local text = string.gsub(text, "Mon", "Mo") |   local text = text:gsub("Mon", "Mo") | ||||||
|   local text = string.gsub(text, "Tue", "Di") |   local text = text:gsub("Tue", "Di") | ||||||
|   local text = string.gsub(text, "Wed", "Mi") |   local text = text:gsub("Wed", "Mi") | ||||||
|   local text = string.gsub(text, "Thu", "Do") |   local text = text:gsub("Thu", "Do") | ||||||
|   local text = string.gsub(text, "Fri", "Fr") |   local text = text:gsub("Fri", "Fr") | ||||||
|   local text = string.gsub(text, "Sat", "Sa") |   local text = text:gsub("Sat", "Sa") | ||||||
|   local text = string.gsub(text, "Sun", "So") |   local text = text:gsub("Sun", "So") | ||||||
|    |    | ||||||
|   cache_data('forecast', lat..','..lng, header..text, tonumber(ttl), 'key') |   print('Caching data...') | ||||||
|  |   redis:hset(hash, 'city', city) | ||||||
|  |   redis:hset(hash, 'summary', weather_summary) | ||||||
|  |   redis:hset(hash, 'text', header..text) | ||||||
|  |   redis:expire(hash, ttl) | ||||||
|    |    | ||||||
|   return header..text |   if is_inline then | ||||||
|  |     return city, weather_summary, header..text, ttl | ||||||
|  |   else | ||||||
|  |     return header..text | ||||||
|  |   end | ||||||
| end | end | ||||||
|  |  | ||||||
| function forecast:get_forecast_hourly(lat, lng) | function forecast:get_forecast_hourly(lat, lng, is_inline) | ||||||
|   print('Finde stündliches Wetter in '..lat..', '..lng) |   print('Finde stündliches Wetter in '..lat..', '..lng) | ||||||
|   local text = redis:get('telegram:cache:forecast:'..lat..','..lng..':hourly') |   local hash = 'telegram:cache:forecast:'..lat..','..lng..':hourly' | ||||||
|   if text then print('...aus dem Cache..') return text end |   local text = redis:hget(hash, 'text') | ||||||
|  |   if text then | ||||||
|  |     print('...aus dem Cache..') | ||||||
|  | 	if is_inline then | ||||||
|  | 	  local ttl = redis:ttl(hash) | ||||||
|  | 	  local city = redis:hget(hash, 'city') | ||||||
|  | 	  local summary = redis:hget(hash, 'summary') | ||||||
|  | 	  return city, summary, text, ttl | ||||||
|  | 	else | ||||||
|  | 	  return text | ||||||
|  | 	end | ||||||
|  |   end | ||||||
|  |  | ||||||
|   local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,daily,alerts,flags' |   local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,daily,alerts,flags' | ||||||
|    |    | ||||||
| @@ -146,32 +171,67 @@ function forecast:get_forecast_hourly(lat, lng) | |||||||
|       method = "GET", |       method = "GET", | ||||||
|       sink = ltn12.sink.table(response_body) |       sink = ltn12.sink.table(response_body) | ||||||
|    } |    } | ||||||
|   local ok, response_code, response_headers, response_status_line = https.request(request_constructor) |   local ok, response_code, response_headers = https.request(request_constructor) | ||||||
|   if not ok then return nil end |   if not ok then return nil end | ||||||
|   local data = json.decode(table.concat(response_body)) |   local weather = json.decode(table.concat(response_body)).hourly | ||||||
|   local ttl = string.sub(response_headers["cache-control"], 9) |   local ttl = tonumber(string.sub(response_headers["cache-control"], 9)) | ||||||
|  |  | ||||||
|    |  | ||||||
|   local weather = data.hourly |  | ||||||
|   local city = get_city_name(lat, lng) |   local city = get_city_name(lat, lng) | ||||||
|  |   local weather_summary = weather.summary | ||||||
|    |    | ||||||
|   local header = '*24-Stunden-Vorhersage für '..city..':*\n_'..weather.summary..'_' |   local header = '*24-Stunden-Vorhersage für '..city..':*\n_'..weather_summary..'_' | ||||||
|   local text = "" |   local text = "" | ||||||
|    |    | ||||||
|   for hour in pairs(weather.data) do |   local weather_data = weather.data | ||||||
|  |   for hour in pairs(weather_data) do | ||||||
| 	if hour < 26 then  | 	if hour < 26 then  | ||||||
| 	  text = text..'\n*'..convert_timestamp(weather.data[hour].time, '%H:%M Uhr')..'* | '..get_temp(weather, hour, true) | 	  text = text..'\n*'..convert_timestamp(weather_data[hour].time, '%H:%M Uhr')..'* | '..get_temp(weather, hour, true) | ||||||
| 	end | 	end | ||||||
|   end |   end | ||||||
|    |    | ||||||
|   cache_data('forecast', lat..','..lng..':hourly', header..text, tonumber(ttl), 'key') |   print('Caching data...') | ||||||
|  |   redis:hset(hash, 'city', city) | ||||||
|  |   redis:hset(hash, 'summary', weather_summary) | ||||||
|  |   redis:hset(hash, 'text', header..text) | ||||||
|  |   redis:expire(hash, ttl) | ||||||
|    |    | ||||||
|   return header..text |   if is_inline then | ||||||
|  |     return city, weather_summary, header..text, ttl | ||||||
|  |   else | ||||||
|  |     return header..text | ||||||
|  |   end | ||||||
|  | end | ||||||
|  |  | ||||||
|  | function forecast:inline_callback(inline_query, config, matches) | ||||||
|  |   local user_id = inline_query.from.id | ||||||
|  |   if matches[2] then | ||||||
|  |     city = matches[2] | ||||||
|  | 	is_personal = false | ||||||
|  |   else | ||||||
|  |     local set_location = get_location(user_id) | ||||||
|  | 	is_personal = true | ||||||
|  | 	if not set_location then | ||||||
|  | 	  city = 'Berlin, Deutschland' | ||||||
|  | 	else | ||||||
|  | 	  city = set_location | ||||||
|  | 	end | ||||||
|  |   end | ||||||
|  |    | ||||||
|  |   local lat, lng = get_city_coordinates(city, config) | ||||||
|  |   if not lat and not lng then utilities.answer_inline_query(self, inline_query) return end | ||||||
|  |   if matches[1] == 'f' then | ||||||
|  |     title, description, text, ttl = forecast:get_forecast(lat, lng, true) | ||||||
|  |   else | ||||||
|  |     title, description, text, ttl = forecast:get_forecast_hourly(lat, lng, true) | ||||||
|  |   end | ||||||
|  |   if not title and not description and not text and not ttl then utilities.answer_inline_query(self, inline_query) return end | ||||||
|  |  | ||||||
|  |   local text = text:gsub('\n', '\\n') | ||||||
|  |   local results = '[{"type":"article","id":"28062013","title":"'..title..'","description":"'..description..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/weather/cloudy.jpg","thumb_width":80,"thumb_height":80,"input_message_content":{"message_text":"'..text..'", "parse_mode":"Markdown"}}]' | ||||||
|  |   utilities.answer_inline_query(self, inline_query, results, ttl, is_personal) | ||||||
| end | end | ||||||
|  |  | ||||||
| function forecast:action(msg, config, matches) | function forecast:action(msg, config, matches) | ||||||
|   local user_id = msg.from.id |   local user_id = msg.from.id | ||||||
|   local city = get_location(user_id) |  | ||||||
|    |    | ||||||
|   if matches[2] then |   if matches[2] then | ||||||
|     city = matches[2] |     city = matches[2] | ||||||
| @@ -184,22 +244,11 @@ function forecast:action(msg, config, matches) | |||||||
| 	end | 	end | ||||||
|   end |   end | ||||||
|    |    | ||||||
|   local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat') |   local lat, lng = get_city_coordinates(city, config) | ||||||
|   local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng') |  | ||||||
|   if not lat and not lng then |   if not lat and not lng then | ||||||
|     print('Koordinaten nicht eingespeichert, frage Google...') | 	utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true) | ||||||
|     coords = utilities.get_coords(city, config) |  | ||||||
| 	lat = coords.lat |  | ||||||
| 	lng = coords.lon |  | ||||||
|   end |  | ||||||
|    |  | ||||||
|   if not lat and not lng then |  | ||||||
|     utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true) |  | ||||||
|     return |     return | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   redis:hset('telegram:cache:weather:'..string.lower(city), 'lat', lat) |  | ||||||
|   redis:hset('telegram:cache:weather:'..string.lower(city), 'lng', lng) |  | ||||||
|    |    | ||||||
|   if matches[1] == '/forecasth' or matches[1] == '/fh' then |   if matches[1] == '/forecasth' or matches[1] == '/fh' then | ||||||
|     text = forecast:get_forecast_hourly(lat, lng) |     text = forecast:get_forecast_hourly(lat, lng) | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ function get_city_name(lat, lng) | |||||||
|   return city |   return city | ||||||
| end | end | ||||||
|  |  | ||||||
| function weather:get_city_coordinates(city, config) | function get_city_coordinates(city, config) | ||||||
|   local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat') |   local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat') | ||||||
|   local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng') |   local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng') | ||||||
|   if not lat and not lng then |   if not lat and not lng then | ||||||
| @@ -92,7 +92,7 @@ function weather:get_weather(lat, lng, is_inline) | |||||||
|       method = "GET", |       method = "GET", | ||||||
|       sink = ltn12.sink.table(response_body) |       sink = ltn12.sink.table(response_body) | ||||||
|    } |    } | ||||||
|   local ok, response_code, response_headers, response_status_line = https.request(request_constructor) |   local ok, response_code, response_headers = https.request(request_constructor) | ||||||
|   if not ok then return nil end |   if not ok then return nil end | ||||||
|   local data = json.decode(table.concat(response_body)) |   local data = json.decode(table.concat(response_body)) | ||||||
|   local ttl = tonumber(string.sub(response_headers["cache-control"], 9)) |   local ttl = tonumber(string.sub(response_headers["cache-control"], 9)) | ||||||
| @@ -166,7 +166,7 @@ function weather:inline_callback(inline_query, config, matches) | |||||||
| 	  city = set_location | 	  city = set_location | ||||||
| 	end | 	end | ||||||
|   end |   end | ||||||
|   local lat, lng = weather:get_city_coordinates(city, config) |   local lat, lng = get_city_coordinates(city, config) | ||||||
|   if not lat and not lng then utilities.answer_inline_query(self, inline_query) return end |   if not lat and not lng then utilities.answer_inline_query(self, inline_query) return end | ||||||
|    |    | ||||||
|   local title, description, icon, text, ttl = weather:get_weather(lat, lng, true) |   local title, description, icon, text, ttl = weather:get_weather(lat, lng, true) | ||||||
| @@ -203,7 +203,7 @@ function weather:action(msg, config, matches) | |||||||
| 	end | 	end | ||||||
|   end |   end | ||||||
|    |    | ||||||
|   local lat, lng = weather:get_city_coordinates(city, config) |   local lat, lng = get_city_coordinates(city, config) | ||||||
|   if not lat and not lng then |   if not lat and not lng then | ||||||
| 	utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true) | 	utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true) | ||||||
|     return |     return | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Andreas Bielawski
					Andreas Bielawski