You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

373 lines
12 KiB

# -*- coding: utf-8 -*-
# ! /usr/bin/env python
import logging
import requests
import sys
import datetime
import random
from bs4 import BeautifulSoup
from telegram.ext import (Updater, CommandHandler, MessageHandler,
Filters)
from telegram.ext.jobqueue import Job
from telegram import ChatAction
from config import config
# Constants
WEEKDAYS = {
1: "lunes",
2: "martes",
3: "miércoles",
4: "jueves",
5: "viernes",
6: "sábado",
7: "domingo"
}
# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO)
logger = logging.getLogger(__name__)
autoapods = dict()
# Define a few command handlers. These usually take the two arguments bot and
# update. Error handlers also receive the raised TelegramError object in error.
def start(bot, update):
bot.sendMessage(update.message.chat_id, text='Traigo las cervezas, vosotros los telescopios. ¡Vamos allá!')
def help(bot, update):
bot.sendMessage(update.message.chat_id, text="""Astro Beer Bot v1.0:
Para mostrar la APOD actual, escribe /apod y te la mostraré, con /autoapod la programo para traerla todos los días.
Con /tiempo te diré qué tal se presenta el tiempo esta misma noche.
Si usas /faselunar te diré qué fase lunar tenemos hoy.
Para ver las manchas solares, /manchas te mostrará el sol actualizado.
El comando /estanoche te dirá qué tal están los parámetros de tiempo específicos para astrónomos esta noche.
""")
def error(bot, update, error):
logger.warn('Update "%s" caused error "%s"' % (update, error))
# This is were the fun begins
def fetch_apod(bot, chat_id):
apod_key = config.get('APOD', 'DEMO_KEY')
payload = {'api_key': apod_key}
apod = requests.get('https://api.nasa.gov/planetary/apod', params=payload)
if apod.status_code > 299:
bot.sendMessage(chat_id, text='La NASA esta como las grecas, así que no hay APOD.')
return
data = apod.json()
img_url = data['url']
title = data['title']
description = data['explanation']
bot.sendMessage(chat_id, text=title)
if data['media_type'] == 'image':
bot.sendChatAction(chat_id, action=ChatAction.UPLOAD_PHOTO)
bot.sendPhoto(chat_id, photo=img_url)
else:
bot.sendMessage(chat_id, text=img_url)
bot.sendMessage(chat_id, text=description)
def apod(bot, update):
fetch_apod(bot, update.message.chat_id)
def autoapod_job(bot, job):
fetch_apod(bot, job.context)
def autoapod(bot, update, job_queue):
chat_id = update.message.chat_id # Remember the channel where the command came from
if chat_id in autoapods:
old_job = autoapods[chat_id]
old_job.schedule_removal()
job = Job(autoapod_job, 3600*24, repeat=True, context=chat_id)
autoapods[chat_id] = job
job_queue.put(job)
bot.sendMessage(chat_id, text="APOD automática activada, cada día a esta hora os la traigo. ¿Una cervecita para celebrarlo?")
def stopautoapod(bot, update):
chat_id = update.message.chat_id
if chat_id in autoapods:
job = autoapods[chat_id]
job.schedule_removal()
del autoapods[chat_id]
else:
bot.sendMessage(chat_id, text="No hay nada programado, astropirado.")
def tiempo(bot, update, args):
appkey = config.get('OWM')
if not appkey:
bot.sendMessage(update.message.chat_id, text='Deja la cerveza y configura el servicio de OWM.')
return
# Now we accept parameters on this call
city = " ".join(args)
if not city:
city = "Madrid"
params = {"q": city.lower(), "APPID": appkey, "units": "metric"}
weather_message = "A alguien se le ha pirado (jeje) la perola y no me ha dicho lo que tengo que contaros..."
weatherdata = requests.get('http://api.openweathermap.org/data/2.5/forecast/city', params=params)
if "list" in weatherdata.json():
weather = weatherdata.json()['list']
today = datetime.datetime.now()
current_day = today
weather_message = "El tiempo en los próximos días:\n"
for day in range(0, 5):
if day > 0:
current_day = today + datetime.timedelta(days=day)
if current_day.hour > 23:
current_day -= datetime.timedelta(hours=4)
if day == 1:
date_string = "Mañana por la noche en " + city
else:
date_string = "El {0} por la noche en ".format(WEEKDAYS[current_day.isoweekday()]) + city
else:
date_string = "Esta noche en " + city
night = None
for element in weather:
forecast_time = datetime.datetime.fromtimestamp(element['dt'])
if forecast_time.month == current_day.month and forecast_time.day == current_day.day and (forecast_time.hour >= 23 or forecast_time.hour <= 4):
night = element
break
if not night and day == 0:
weather_message += "Asómate a la ventana, o sal del bar, que ya es de noche.\n"
else:
if night and night['main']:
weather_message += date_string + " tendremos unos {0}º con una humedad relativa de {1}%, ".format(
night['main']['temp'],
night['main']['humidity'])
if night['wind']:
weather_message += "vientos de {0} km\\h y una cobertura de nubes del {1}%".format(
night['wind']['speed'],
night['clouds']['all'])
else:
weather_message += "sin vientos y con una cobertura de nubes del {0}%".format(
night['clouds']['all'])
weather_message += "\n"
else:
print("Main not found: {}".format(night))
else:
weather_message = 'El meteorólogo anda chuzo, así que no sabe de chuzos de punta'
bot.sendMessage(update.message.chat_id, text=weather_message)
def faselunar(bot, update):
fases = [
"nueva 🌑",
"creciente 🌒",
"cuarto creciente 🌓",
"creciente gibosa 🌔",
"llena 🌕",
"gibosa menguante 🌖",
"cuarto menguante 🌗",
"menguante 🌘"
]
today = datetime.datetime.now()
year = today.year
month = today.month
day = today.day
if month < 3:
year -= 1
month += 12
month += 1
c = 365.25 * year
e = 30.6 * month # Blame C coders saving on characters...
jd = c + e + day - 694039.09
jd /= 29.53
jd -= round(jd)
b = (jd * 8) + 0.5
b = int(b % 7)
message = "Hoy tenemos luna " + fases[b]
bot.sendMessage(update.message.chat_id, text=message)
def manchas(bot, update):
soho = requests.get('https://sohowww.nascom.nasa.gov/sunspots/', verify=False)
if soho.status_code > 299:
bot.sendMessage(update.message.chat_id, text='La NASA esta como las grecas, así que no hay SOHO.')
return
soup = BeautifulSoup(soho.text, 'html.parser')
img_url = None
for tag in soup.find_all('img'):
if 'synoptic' in tag['src']:
img_url = 'http://sohowww.nascom.nasa.gov' + tag['src']
bot.sendChatAction(update.message.chat_id, action=ChatAction.UPLOAD_PHOTO)
bot.sendPhoto(update.message.chat_id, photo=img_url)
def randomchat(bot, update):
msg = update.message.text.lower()
reply = None
if "jawa" in msg:
reply = random.choice([
"Y un objetivo de regalo.",
"Te lo dejo a mitad de precio, porque la caja está abierta.",
"Hombre, es un poco básico este ocular de 9mm de 70 euros.",
"Sólo se ha usado una vez",
"Tengo stock de sobra",
"Estos los estoy vendiendo muy bien"
])
if reply is not None:
bot.sendMessage(update.message.chat_id, text=reply)
def estanoche(bot, update):
# Initalize coordinates
lon = None
lat = None
# TODO pass location as argument an resolve coordinates
if not lon or not lat:
# Yeah, Robledo de Chavela coordinates by default
lat = 40.498333
lon = -4.238889
# Building URL to query the service
url_service = 'http://202.127.24.18/bin/astro.php'
url_params = {'lon': str(lon), 'lat': str(lat), 'output': "json", 'tzshift': "0", 'unit': "metric", 'ac': "0"}
# Query service
timer7 = requests.get(url_service, params=url_params)
if timer7.status_code > 299:
bot.sendMessage(update.message.chat_id, text='Servicio de informacion astronómica esta a por uvas. Relax')
return
json_timer7 = timer7.json()
timer7_data = json_timer7["dataseries"][1]
timer7_cloud = timer7_data["cloudcover"]
timer7_seeing = timer7_data["seeing"]
timer7_transparency = timer7_data["transparency"]
timer7_temp = timer7_data["temp2m"]
timer7_precipitation = timer7_data["prec_type"]
# Conditions where observation is imposible: 100% cloud or rain
if timer7_precipitation == "rain":
bot.sendMessage(update.message.chat_id, text='Esta noche llueve en Base Alfa, deja el telescopio en casa.')
return
if timer7_cloud > 5:
bot.sendMessage(update.message.chat_id, text='Demasiado nublado en Base Alfa para hacer observación.')
return
# Compose messages about clouds
if 3 < timer7_cloud < 5:
mensaje_cloud = " habrá bastantes nubes"
elif 3 > timer7_cloud > 1:
mensaje_cloud = " habrá pocas nubes"
elif timer7_cloud == 1:
mensaje_cloud = " habrá cielo despejado"
# Compose messages about seeing
if timer7_seeing > 6:
mensaje_seeing = " insuficiente seeing"
elif 6 >= timer7_seeing > 4:
mensaje_seeing = " bastante poco seeing"
elif 4 >= timer7_seeing > 2:
mensaje_seeing = " seeing bastante aceptable"
elif 2 >= timer7_seeing > 0:
mensaje_seeing = " seeing estupendo"
# Compose messages about transparency
if timer7_transparency > 6:
mensaje_transparency = " insuficiente transparencia atmosferica"
elif 6 >= timer7_transparency > 4:
mensaje_transparency = " bastante poca transparencia atmosferica"
elif 4 >= timer7_transparency > 2:
mensaje_transparency = " transparencia atmosferica bastante aceptable"
elif 2 >= timer7_transparency > 0:
mensaje_transparency = " transparencia atmosferica estupenda"
# Message about temperature
mensaje_temp = " y una temperatura de " + str(timer7_temp) + " grados celsius (via timer7)"
# Now compose full message
mensaje = "(6h) Esta noche en Robledo de Chavela" + mensaje_cloud + "," + mensaje_seeing + "," + mensaje_transparency + mensaje_temp
# Vomit the response
bot.sendMessage(update.message.chat_id, text=mensaje)
return
def main():
token = config.get('TOKEN')
if token is None:
print("Please, configure your token first")
sys.exit(1)
updater = Updater(token)
dispatcher = updater.dispatcher
# on different commands - answer in Telegram
dispatcher.add_handler(CommandHandler("start", start))
dispatcher.add_handler(CommandHandler("help", help))
dispatcher.add_handler(CommandHandler("apod", apod))
dispatcher.add_handler(CommandHandler("autoapod", autoapod, pass_job_queue=True))
dispatcher.add_handler(CommandHandler("stopautoapod", stopautoapod, pass_job_queue=True))
dispatcher.add_handler(CommandHandler("tiempo", tiempo, pass_args=True))
dispatcher.add_handler(CommandHandler("faselunar", faselunar))
dispatcher.add_handler(CommandHandler("manchas", manchas))
dispatcher.add_handler(CommandHandler("estanoche", estanoche))
# on noncommand i.e message - echo the message on Telegram
dispatcher.add_handler(MessageHandler([Filters.text], randomchat))
# log all errors
dispatcher.add_error_handler(error)
# Start the Bot
updater.start_polling()
# Run the bot until the you presses Ctrl-C or the process receives SIGINT,
# SIGTERM or SIGABRT. This should be used most of the time, since
# start_polling() is non-blocking and will stop the bot gracefully.
updater.idle()
if __name__ == "__main__":
print("Starting AstroBeerBot")
main()