Codi del bot @temps@mastodont.cat alliberat

master
spla 5 months ago
commit 9669469b54
  1. 61
      apikey-setup.py
  2. BIN
      canviats/1.png
  3. BIN
      canviats/10.png
  4. BIN
      canviats/11.png
  5. BIN
      canviats/12.png
  6. BIN
      canviats/13.png
  7. BIN
      canviats/14.png
  8. BIN
      canviats/15.png
  9. BIN
      canviats/16.png
  10. BIN
      canviats/17.png
  11. BIN
      canviats/18.png
  12. BIN
      canviats/19.png
  13. BIN
      canviats/2.png
  14. BIN
      canviats/20.png
  15. BIN
      canviats/21.png
  16. BIN
      canviats/22.png
  17. BIN
      canviats/23.png
  18. BIN
      canviats/24.png
  19. BIN
      canviats/25.png
  20. BIN
      canviats/26.png
  21. BIN
      canviats/27.png
  22. BIN
      canviats/28.png
  23. BIN
      canviats/29.png
  24. BIN
      canviats/3.png
  25. BIN
      canviats/4.png
  26. BIN
      canviats/5.png
  27. BIN
      canviats/6.png
  28. BIN
      canviats/7.png
  29. BIN
      canviats/8.png
  30. BIN
      canviats/9.png
  31. 185
      db-setup.py
  32. BIN
      fonts/DejaVuSerif.ttf
  33. BIN
      humitat/humedad.png
  34. BIN
      images/fons.jpg
  35. BIN
      images/fonsorig.jpg
  36. BIN
      images/logo.png
  37. 8
      requeriments.txt
  38. 191
      setup.py
  39. BIN
      sol/solsurt.png
  40. BIN
      temperatura/temperature.png
  41. 981
      temps.py
  42. BIN
      wd/C.png
  43. BIN
      wd/E.png
  44. BIN
      wd/ENE.png
  45. BIN
      wd/ESE.png
  46. BIN
      wd/N.png
  47. BIN
      wd/NE.png
  48. BIN
      wd/NNE.png
  49. BIN
      wd/NNW.png
  50. BIN
      wd/NO.png
  51. BIN
      wd/NW.png
  52. BIN
      wd/O.png
  53. BIN
      wd/S.png
  54. BIN
      wd/SE.png
  55. BIN
      wd/SO.png
  56. BIN
      wd/SSE.png
  57. BIN
      wd/SSW.png
  58. BIN
      wd/SW.png
  59. BIN
      wd/VRB.png
  60. BIN
      wd/W.png
  61. BIN
      wd/WNW.png
  62. BIN
      wd/WSW.png
  63. BIN
      wi/1.png
  64. BIN
      wi/11.png
  65. BIN
      wi/18.png
  66. BIN
      wi/19.png
  67. BIN
      wi/1n.png
  68. BIN
      wi/2.png
  69. BIN
      wi/21.png
  70. BIN
      wi/21n.png
  71. BIN
      wi/22.png
  72. BIN
      wi/24.png
  73. BIN
      wi/25.png
  74. BIN
      wi/28.png
  75. BIN
      wi/29.png
  76. BIN
      wi/2n.png
  77. BIN
      wi/30.png
  78. BIN
      wi/33.png
  79. BIN
      wi/33n.png
  80. BIN
      wi/4.png
  81. BIN
      wi/4n.png
  82. BIN
      wi/51.png
  83. BIN
      wi/51n.png
  84. BIN
      wi/54.png
  85. BIN
      wi/6.png
  86. BIN
      wi/6n.png
  87. BIN
      wi/7.png
  88. BIN
      wi/9.png
  89. BIN
      wi/9n.png
  90. BIN
      wi/nd.png

@ -0,0 +1,61 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pdb
import getpass
import fileinput,re
import os
import sys
def create_dir():
if not os.path.exists('secrets'):
os.makedirs('secrets')
def create_file():
if not os.path.exists('secrets/apikey.txt'):
with open('secrets/apikey.txt', 'w'): pass
print(secrets_filepath + " created!")
def write_params():
with open(secrets_filepath, 'a') as the_file:
print("Writing api key parameter to " + secrets_filepath)
the_file.write('api_key: \n')
def modify_file(file_name,pattern,value=""):
fh=fileinput.input(file_name,inplace=True)
for line in fh:
replacement=pattern + value
line=re.sub(pattern,replacement,line)
sys.stdout.write(line)
fh.close()
def get_parameter( parameter, file_path ):
# Check if secrets file exists
if not os.path.isfile(file_path):
print("File %s not found, creating it."%file_path)
create_dir()
create_file()
write_params()
api_key = input('Enter your API key: ')
modify_file(file_path, "api_key: ", value=api_key)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
# main
if __name__ == '__main__':
# Load secrets from secrets file
secrets_filepath = "secrets/apikey.txt"
api_key = get_parameter("api_key", secrets_filepath)

Binary file not shown.

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

@ -0,0 +1,185 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import getpass
import os
import sys
from mastodon import Mastodon
from mastodon.Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout, MastodonAPIError
import psycopg2
from psycopg2 import sql
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
# Returns the parameter from the specified file
def get_parameter( parameter, file_path ):
# Check if secrets file exists
if not os.path.isfile(file_path):
print("File %s not found, asking."%file_path)
write_parameter( parameter, file_path )
#sys.exit(0)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
def write_parameter( parameter, file_path ):
if not os.path.exists('config'):
os.makedirs('config')
print("Setting up finances parameters...")
print("\n")
alarm_db = input("alarm db name: ")
alarm_db_user = input("alarm db user: ")
with open(file_path, "w") as text_file:
print("alarm_db: {}".format(alarm_db), file=text_file)
print("alarm_db_user: {}".format(alarm_db_user), file=text_file)
def create_table(db, db_user, table, sql):
conn = None
try:
conn = psycopg2.connect(database = db, user = db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
print("Creating table.. "+table)
# Create the table in PostgreSQL database
cur.execute(sql)
conn.commit()
print("Table "+table+" created!")
print("\n")
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
def create_index(db, db_user, table, index, sql_index):
conn = None
try:
conn = psycopg2.connect(database = db, user = db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
print(f"Creating index...{index}")
# Create the table in PostgreSQL database
cur.execute(sql_index)
conn.commit()
print(f"Index {index} created!\n")
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
###############################################################################
# main
if __name__ == '__main__':
# Load configuration from config file
config_filepath = "config/db_config.txt"
alarm_db = get_parameter("alarm_db", config_filepath)
alarm_db_user = get_parameter("alarm_db_user", config_filepath)
############################################################
# create database
############################################################
conn = None
try:
conn = psycopg2.connect(dbname='postgres',
user=alarm_db_user, host='',
password='')
conn.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)
cur = conn.cursor()
print("Creating database " + alarm_db + ". Please wait...")
cur.execute(sql.SQL("CREATE DATABASE {}").format(
sql.Identifier(alarm_db))
)
print("Database " + alarm_db + " created!")
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
############################################################
try:
conn = None
conn = psycopg2.connect(database = alarm_db, user =alarm_db_user, password = "", host = "/var/run/postgresql", port = "5432")
except (Exception, psycopg2.DatabaseError) as error:
print(error)
# Load configuration from config file
os.remove("config/db_config.txt")
print("Exiting. Run db-setup again with right parameters")
sys.exit(0)
finally:
if conn is not None:
conn.close()
print("\n")
print("alarm parameters saved to db-config.txt!")
print("\n")
############################################################
# Create needed tables
############################################################
db = alarm_db
db_user = alarm_db_user
table = 'alarms'
sql = "create table " + table + " (username varchar(30), visibility varchar(8), time time, city varchar(30))"
create_table(db, db_user, table, sql)
index = "alarm_pkey"
sql_index = f'CREATE UNIQUE INDEX {index} ON {table} (username, city)'
create_index(db, db_user, table, index, sql_index)
############################################################
print("Done!")
print("Now you can run setup.py!")
print("\n")

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -0,0 +1,8 @@
Mastodon.py>=1.5.1
urllib3-1.26.4->urllib3-1.26.7
unidecode>=1.2.0
psycopg2>=2.8.6
geopy>=2.1.0 -> 2.2.0
pillow>=8.2.0
geotiler>=0.14.4
geocoder>=1.38.1

@ -0,0 +1,191 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pdb
import getpass
from mastodon import Mastodon
from mastodon.Mastodon import MastodonMalformedEventError, MastodonNetworkError, MastodonReadTimeout, MastodonAPIError, MastodonIllegalArgumentError
import fileinput,re
import os
import sys
def create_dir():
if not os.path.exists('secrets'):
os.makedirs('secrets')
def create_file():
if not os.path.exists('secrets/secrets.txt'):
with open('secrets/secrets.txt', 'w'): pass
print(secrets_filepath + " created!")
def create_config():
if not os.path.exists(config_filepath):
print(config_filepath + " created!")
with open('config.txt', 'w'): pass
def write_params():
with open(secrets_filepath, 'a') as the_file:
print("Writing secrets parameter names to " + secrets_filepath)
the_file.write('uc_client_id: \n'+'uc_client_secret: \n'+'uc_access_token: \n')
def write_config():
with open(config_filepath, 'a') as the_file:
the_file.write('mastodon_hostname: \n')
print("adding parameter name 'mastodon_hostname' to "+ config_filepath)
def read_client_lines(self):
client_path = 'app_clientcred.txt'
with open(client_path) as fp:
line = fp.readline()
cnt = 1
while line:
if cnt == 1:
print("Writing client id to " + secrets_filepath)
modify_file(secrets_filepath, "uc_client_id: ", value=line.rstrip())
elif cnt == 2:
print("Writing client secret to " + secrets_filepath)
modify_file(secrets_filepath, "uc_client_secret: ", value=line.rstrip())
line = fp.readline()
cnt += 1
def read_token_line(self):
token_path = 'app_usercred.txt'
with open(token_path) as fp:
line = fp.readline()
print("Writing access token to " + secrets_filepath)
modify_file(secrets_filepath, "uc_access_token: ", value=line.rstrip())
def read_config_line():
with open(config_filepath) as fp:
line = fp.readline()
modify_file(config_filepath, "mastodon_hostname: ", value=hostname)
def log_in():
error = 0
try:
global hostname
hostname = input("Enter Mastodon hostname: ")
user_name = input("User name, ex. user@" + hostname +"? ")
user_password = getpass.getpass("User password? ")
app_name = input("This app name? ")
Mastodon.create_app(app_name, scopes=["read","write"],
to_file="app_clientcred.txt", api_base_url=hostname)
mastodon = Mastodon(client_id = "app_clientcred.txt", api_base_url = hostname)
mastodon.log_in(
user_name,
user_password,
scopes = ["read", "write"],
to_file = "app_usercred.txt"
)
except MastodonIllegalArgumentError as i_error:
error = 1
if os.path.exists("secrets/secrets.txt"):
print("Removing secrets/secrets.txt file..")
os.remove("secrets/secrets.txt")
if os.path.exists("app_clientcred.txt"):
print("Removing app_clientcred.txt file..")
os.remove("app_clientcred.txt")
sys.exit(i_error)
except MastodonNetworkError as n_error:
error = 1
if os.path.exists("secrets/secrets.txt"):
print("Removing secrets/secrets.txt file..")
os.remove("secrets/secrets.txt")
if os.path.exists("app_clientcred.txt"):
print("Removing app_clientcred.txt file..")
os.remove("app_clientcred.txt")
sys.exit(n_error)
except MastodonReadTimeout as r_error:
error = 1
if os.path.exists("secrets/secrets.txt"):
print("Removing secrets/secrets.txt file..")
os.remove("secrets/secrets.txt")
if os.path.exists("app_clientcred.txt"):
print("Removing app_clientcred.txt file..")
os.remove("app_clientcred.txt")
sys.exit(r_error)
except MastodonAPIError as a_error:
error = 1
if os.path.exists("secrets/secrets.txt"):
print("Removing secrets/secrets.txt file..")
os.remove("secrets/secrets.txt")
if os.path.exists("app_clientcred.txt"):
print("Removing app_clientcred.txt file..")
os.remove("app_clientcred.txt")
sys.exit(a_error)
finally:
if error == 0:
create_dir()
create_file()
#Your client id and secret are the two lines in `app_clientcred.txt`, your access
#token is the line in `app_usercred.txt`.
write_params()
client_path = 'app_clientcred.txt'
read_client_lines(client_path)
token_path = 'app_usercred.txt'
read_token_line(token_path)
if os.path.exists("app_clientcred.txt"):
print("Removing app_clientcred.txt temp file..")
os.remove("app_clientcred.txt")
if os.path.exists("app_usercred.txt"):
print("Removing app_usercred.txt temp file..")
os.remove("app_usercred.txt")
print("Secrets setup done!\n")
print("\n")
print("Now you can run versions.py!")
def modify_file(file_name,pattern,value=""):
fh=fileinput.input(file_name,inplace=True)
for line in fh:
replacement=pattern + value
line=re.sub(pattern,replacement,line)
sys.stdout.write(line)
fh.close()
# Returns the parameter from the specified file
def get_parameter( parameter, file_path ):
# Check if secrets file exists
if not os.path.isfile(file_path):
print("File %s not found, creating it."%file_path)
log_in()
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
# Returns the parameter from the specified file
def get_hostname( parameter, config_filepath ):
# Check if secrets file exists
if not os.path.isfile(config_filepath):
print("File %s not found, creating it."%config_filepath)
create_config()
# Find parameter in file
with open( config_filepath ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(config_filepath + " Missing parameter %s "%parameter)
write_config()
read_config_line()
print("hostname setup done!")
sys.exit(0)
# Load secrets from secrets file
secrets_filepath = "secrets/secrets.txt"
uc_client_id = get_parameter("uc_client_id", secrets_filepath)
uc_client_secret = get_parameter("uc_client_secret", secrets_filepath)
uc_access_token = get_parameter("uc_access_token", secrets_filepath)
# Load configuration from config file
config_filepath = "config.txt"
mastodon_hostname = get_hostname("mastodon_hostname", config_filepath) # E.g., mastodon.social

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

@ -0,0 +1,981 @@
# https://medium.com/nexttech/how-to-use-the-openweathermap-api-with-python-c84cc7075cfc
import urllib3
import datetime
import time
from mastodon import Mastodon
import psycopg2
import unidecode
import time
import re
import os
import json
import sys
import os.path # For checking whether secrets file exists
import requests # For doing the web stuff, dummy!
from datetime import timedelta, datetime
import urllib.request
import geopy
from geopy.geocoders import Nominatim
from PIL import Image, ImageFont, ImageDraw
import geotiler
import geocoder
import ssl
import pdb
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def cleanhtml(raw_html):
cleanr = re.compile('<.*?>')
cleantext = re.sub(cleanr, '', raw_html)
return cleantext
def translate(i, detall, dir_vent):
if detall == 'Parcialmente nuboso':
detall = 'Parcialment ennuvolat'
if detall == 'Parcialmente nuboso con niebla':
detall = 'Parcialment ennuvolat amb boira'
if detall == 'Parcialmente nuboso con lluvias':
detall = 'Parcialment ennuvolat amb aiguats'
if detall == 'Nubes dispersas':
detall = 'Núvols dispersos'
if detall == 'Muy nuboso con nevadas':
detall = 'Molt ennuvolat amb nevades'
if detall == 'Muy nuboso con lluvia':
detall = 'Molt ennuvolat amb pluja'
if detall == 'Muy nuboso con niebla':
detall = 'Molt ennuvolat amb boira'
if detall == 'Muy nuboso con lluvias':
detall = 'Molt ennuvolat amb pluges'
if detall == 'Cubierto':
detall = 'Tapat'
if detall == 'Cubierto con lluvia':
detall = 'Tapat amb pluja'
if detall == 'Cubierto con lluvias':
detall = 'Tapat amb pluges'
if detall == 'Cubierto con probabilidad de lluvia':
detall = 'Tapat amb possible pluja'
if detall == 'Cubierto con nevadas':
detall = 'Tapat amb nevades'
if detall == 'Muy nuboso':
detall = 'Molt ennuvolat'
if detall == 'Despejado':
detall = 'Clar'
if dir_vent == 'Suroeste':
dir_vent = 'Sud-oest'
if dir_vent == 'Noroeste':
dir_vent = 'Nord-oest'
if dir_vent == 'Nordeste':
dir_vent = 'Nord-est'
if dir_vent == 'Sureste':
dir_vent = 'Sud-est'
if dir_vent == 'Norte':
dir_vent = 'Nord'
if dir_vent == 'Este':
dir_vent = 'Est'
if dir_vent == 'Sur':
dir_vent = 'Sud'
if dir_vent == 'Oeste':
dir_vent = 'Oest'
return i, detall, dir_vent
def createtilehours(data, pregunta):
i = 1
x = 10
y = 10
while i < 13:
hour_data = data['hour_hour']['hour'+str(i)]['hour_data']
temperature = data['hour_hour']['hour'+str(i)]['temperature']
detall = data['hour_hour']['hour'+str(i)]['text']
icona = data['hour_hour']['hour'+str(i)]['icon']
dir_vent = data['hour_hour']['hour'+str(i)]['wind_direction']
i, detall, dir_vent = translate(i, detall, dir_vent)
if i == 1:
fons = Image.open('images/fonsorig.jpg')
else:
fons = Image.open('images/tempsperhores'+str(i-1)+'.png')
if i == 1:
logo_img = Image.open('images/logo.png')
fons.paste(logo_img, (470, 16), logo_img)
# hi afegim l'icona del temps
icona_path = 'wi/'+icona+'.png'
temps_img = Image.open(icona_path)
fons.paste(temps_img, (x,y+30), temps_img)
fons.save('images/temphour'+str(i)+'.png',"PNG")
base = Image.open('images/temphour'+str(i)+'.png').convert('RGBA')
txt = Image.new('RGBA', base.size, (255,255,255,0))
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 25, layout_engine=ImageFont.LAYOUT_BASIC)
# get a drawing context
draw = ImageDraw.Draw(txt)
if i == 1:
draw.text((10,10), pregunta + ', 12 hores', font=fnt, fill=(255,255,255,255)) ## half opacity
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 18, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((x+50,y+45), str(temperature)+'\u00b0'+ ' ' +hour_data+' '+detall, font=fnt, fill=(255,255,255,200)) ## half opacity
if i == 1:
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 12, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((380,490), 'temps@mastodont.cat', font=fnt, fill=(255,255,255,200)) #fill=(255,255,255,255)) ## full opacity
draw.text((400,510), 'API: tutiempo.net', font=fnt, fill=(155,0,200,200)) #fill=(255,255,255,255)) ## full opacity
out = Image.alpha_composite(base, txt)
out.save('images/tempsperhores'+str(i)+'.png')
y = y + 40
i += 1
def createtiletoday(people, long, lat, data, days):
i = 1
while i < days+1:
temperatura_max = data['day'+str(i)]['temperature_max']
temperatura_min = data['day'+str(i)]['temperature_min']
icona = data['day'+str(i)]['icon']
detall = data['day'+str(i)]['text']
vent = data['day'+str(i)]['wind']
icona_vent = data['day'+str(i)]['icon_wind']
dir_vent = data['day'+str(i)]['wind_direction']
humitat = data['day'+str(i)]['humidity']
solsurt = data['day'+str(i)]['sunrise']
solamaga = data['day'+str(i)]['sunset']
llunasurt = data['day'+str(i)]['moonrise']
llunaamaga = data['day'+str(i)]['moonset']
icona_lluna = data['day'+str(i)]['moon_phases_icon']
i, detall, dir_vent = translate(i, detall, dir_vent)
if people > 1000000:
zoom = 10
elif people > 100000 and people < 999999:
zoom = 11
elif people > 50000 and people < 99999:
zoom = 12
elif people < 49999:
zoom = 15
map = geotiler.Map(center=(long, lat), zoom=zoom, size=(256, 256))
image = geotiler.render_map(map)
image.save('images/map.png')
fons = Image.open("images/fons.jpg")
#hi afegim el mapa de la ciutat
map_img = Image.open('images/map.png')
fons.paste(map_img, (390,65), map_img)
if i == 1:
logo_img = Image.open('images/logo.png')
fons.paste(logo_img, (310, 320), logo_img)
# hi afegim l'icona del temps
icona_path = 'wi/'+icona+'.png'
temps_img = Image.open(icona_path)
fons.paste(temps_img, (10,55), temps_img)
# hi afegim l'icona del termometre
icona_temperature_path = 'temperatura/temperature.png'
temperature_img = Image.open(icona_temperature_path)
fons.paste(temperature_img, (10,115), temperature_img)
# hi afegim l'icona del vent
icona_vent_path = 'wd/'+icona_vent+'.png'
vent_img = Image.open(icona_vent_path)
fons.paste(vent_img, (22,180), vent_img)
# hi afegim l'icona d'humitat
icona_humitat_path = 'humitat/humedad.png'
hum_img = Image.open(icona_humitat_path)
fons.paste(hum_img, (8,210), hum_img)
# hi afegim l'icona del sol sortint
icona_sun_path = 'sol/solsurt.png'
sun_img = Image.open(icona_sun_path)
fons.paste(sun_img, (10,270), sun_img)
# hi afegim l'icona de la lluna
icona_lluna_path = 'canviats/'+icona_lluna+'.png'
lluna_img = Image.open(icona_lluna_path)
fons.paste(lluna_img, (12,315), lluna_img)
fons.save('images/temporal.png',"PNG")
base = Image.open('images/temporal.png').convert('RGBA')
txt = Image.new('RGBA', base.size, (255,255,255,0))
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 35, layout_engine=ImageFont.LAYOUT_BASIC)
# get a drawing context
draw = ImageDraw.Draw(txt)
draw.text((10,10), pregunta, font=fnt, fill=(255,255,255,255))
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 30, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((70,60), detall, font=fnt, fill=(255,255,255,200)) ## half opacity
draw.text((70,120), str(temperatura_max)+'\u00b0 / '+str(temperatura_min)+'\u00b0', font=fnt, fill=(255,255,255,200)) #fill=(255,255,255,255)) ## full opacity
draw.text((70,170), str(dir_vent)+', '+str(vent)+'km/h', font=fnt, fill=(255,255,255,200))
draw.text((70,220), str(humitat)+'%', font=fnt, fill=(255,255,255,200))
draw.text((70,270), str(solsurt)+', '+str(solamaga), font=fnt, fill=(255,255,255,200))
draw.text((70,320), str(llunasurt)+', '+str(llunaamaga), font=fnt, fill=(255,255,255,200))
if i == 1:
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 12, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((380,350), 'temps@mastodont.cat', font=fnt, fill=(255,255,255,200)) #fill=(255,255,255,255)) ## full opacity
draw.text((540,350), 'API: tutiempo.net', font=fnt, fill=(155,0,200,200)) #fill=(255,255,255,255)) ## full opacity
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 10, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((395,300),"© Col·laboradors d'OpenStreetMap, CC-BY-SA", font=fnt, fill=(155,0,200,200)) #fill=(255,255,255,255)) ## full opacity
out = Image.alpha_composite(base, txt)
out.save('images/temps.png')
i += 1
return detall
def createtileweek(data, days):
week_days= ['Dilluns', 'Dimarts', 'Dimecres', 'Dijous', 'Divendres', 'Dissabte','Diumenge']
x = 10
y = 10
i = 1
while i < days+1:
weather_date = data['day'+str(i)]['date']
temperatura_max = data['day'+str(i)]['temperature_max']
temperatura_min = data['day'+str(i)]['temperature_min']
icona = data['day'+str(i)]['icon']
detall = data['day'+str(i)]['text']
vent = data['day'+str(i)]['wind']
icona_vent = data['day'+str(i)]['icon_wind']
dir_vent = data['day'+str(i)]['wind_direction']
humitat = data['day'+str(i)]['humidity']
solsurt = data['day'+str(i)]['sunrise']
solamaga = data['day'+str(i)]['sunset']
llunasurt = data['day'+str(i)]['moonrise']
llunaamaga = data['day'+str(i)]['moonset']
icona_lluna = data['day'+str(i)]['moon_phases_icon']
i, detall, dir_vent = translate(i, detall, dir_vent)
date_list = list(map(str, weather_date. split('-')))
day=datetime(int(date_list[0]),int(date_list[1]),int(date_list[2])).weekday()
if i == 1:
fons = Image.open('images/fons.jpg')
else:
fons = Image.open('images/tempsweek'+str(i-1)+'.png')
# hi afegim l'icona del temps
icona_path = 'wi/'+icona+'.png'
temps_img = Image.open(icona_path)
fons.paste(temps_img, (y+10, x+80), temps_img)
if i == 1:
logo_img = Image.open('images/logo.png')
fons.paste(logo_img, (15, 320), logo_img)
fons.save('images/tempweek'+str(i)+'.png',"PNG")
base = Image.open('images/tempweek'+str(i)+'.png').convert('RGBA')
txt = Image.new('RGBA', base.size, (255,255,255,0))
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 35, layout_engine=ImageFont.LAYOUT_BASIC)
# get a drawing context
draw = ImageDraw.Draw(txt)
if i == 1:
draw.text((15,10), pregunta+', 7 dies', font=fnt, fill=(255,255,255,255))
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 16, layout_engine=ImageFont.LAYOUT_BASIC)
if i == 1:
draw.text((y+10,x+50), "Avui", font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
elif week_days[day] == 'Dimarts':
draw.text((y+4,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
elif week_days[day] == 'Dimecres':
draw.text((y-5,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
elif week_days[day] == 'Dijous':
draw.text((y+6,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
elif week_days[day] == 'Divendres':
draw.text((y-6,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
elif week_days[day] == 'Dissabte':
draw.text((y,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
else:
draw.text((y+4,x+50), str(week_days[day]), font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 24, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((y+18,x+140), str(temperatura_max)+'\u00b0', font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
draw.text((y+20,x+190), str(temperatura_min)+'\u00b0', font=fnt, fill=(255,255,255,220)) #fill=(255,255,255,255)) ## full opacity
if i == 1:
fnt = ImageFont.truetype('fonts/DejaVuSerif.ttf', 15, layout_engine=ImageFont.LAYOUT_BASIC)
draw.text((60,330), 'temps@mastodont.cat - 2020', font=fnt, fill=(255,255,255,200)) #fill=(255,255,255,255)) ## full opacity
draw.text((520,330), 'API: tutiempo.net', font=fnt, fill=(155,0,200,200)) #fill=(255,255,255,255)) ## full opacity
out = Image.alpha_composite(base, txt)
out.save('images/tempsweek'+str(i)+'.png')
y += 95
i += 1
return detall
def format_query(pregunta):
if pregunta.find("'") != -1:
pregunta = pregunta.replace('&apos;', "'")
elif pregunta.find("") != -1:
pregunta = pregunta.replace("", "'")
elif pregunta.find("&apos;") != -1:
pregunta = pregunta.replace('&apos;', "'")
return pregunta
def get_weather_data(pregunta):
nom = Nominatim(user_agent="temps@mastodont.cat")
coords = nom.geocode(pregunta)
if coords != None:
long = coords.longitude
lat = coords.latitude
headers = {"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 12_0_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36"}
g = geocoder.geonames(pregunta, key='spla')
people = g.population if g.ok else 0
url = 'https://api.tutiempo.net/json/?lan=es&apid={}&ll={},{}'.format(api_key, lat, long)
res = requests.get(url, headers=headers, verify=False)
data = res.json()
else:
data = None
people = None
long = None
lat = None
return (data, people, long, lat)
def get_query(contingut):
inici = contingut.index("@")
final = contingut.index(" ")
if len(contingut) > final:
contingut = contingut[0: inici:] + contingut[final +1::]
neteja = contingut.count('@')
i = 0
while i < neteja :
inici = contingut.rfind("@")
final = len(contingut)
contingut = contingut[0: inici:] + contingut[final +1::]
i += 1
pregunta = contingut.lstrip(" ")
return pregunta
def get_country(pregunta):
if pregunta.find(',') != -1:
pais = pregunta.rsplit(',', 1)[1]
pais = pais.replace(' ', '')
pais = pais.upper()
else:
pais = 'ES'
return pais
def set_alarm(username, visibility, alarm_time, alarm_city):
insert_sql = "INSERT INTO alarms(username, visibility, time, city) VALUES(%s,%s,%s,%s) ON CONFLICT DO NOTHING"
conn = None
try:
conn = psycopg2.connect(database = alarm_db, user = alarm_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute(insert_sql, (username, visibility, alarm_time, alarm_city))
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
def get_alarms():
alarm_user = []
alarm_visibility = []
alarm_time = []
alarm_city = []
conn = None
try:
conn = psycopg2.connect(database = alarm_db, user = alarm_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute('select username, visibility, time, city from alarms')
rows = cur.fetchall()
for row in rows:
alarm_user.append(row[0])
alarm_visibility.append(row[1])
alarm_time.append(row[2])
alarm_city.append(row[3])
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
return (alarm_user, alarm_visibility, alarm_time, alarm_city)
def check_alarm(username, city):
sql_query = 'select username, city from alarms where username=(%s) and city=(%s)'
alarm_exists = False
conn = None
try:
conn = psycopg2.connect(database = alarm_db, user = alarm_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute(sql_query, (username, city))
row = cur.fetchone()
if row != None:
alarm_exists = True
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
return alarm_exists
def delete_alarm(username, city):
delete_sql = 'delete from alarms where username=(%s) and city=(%s)'
conn = None
try:
conn = psycopg2.connect(database = alarm_db, user = alarm_db_user, password = "", host = "/var/run/postgresql", port = "5432")
cur = conn.cursor()
cur.execute(delete_sql, (username, city))
conn.commit()
cur.close()
except (Exception, psycopg2.DatabaseError) as error:
print(error)
finally:
if conn is not None:
conn.close()
def alarm_post(username, visibility, city):
data, people, long, lat = get_weather_data(city)
if data != None and 'error' not in data:
days = 1
detall = createtilehours(data, city)
toot_text = f"@{username} \n"
toot_text += f"El temps per hores a {city} \n"
image_id = mastodon.media_post('images/tempsperhores12.png', "image/png", description='temps').id
mastodon.status_post(toot_text, in_reply_to_id=None, visibility=visibility, media_ids={image_id})
else:
toot_text = f"@{username} \n"
toot_text += f"No trobo {city} :-(\n"
mastodon.status_post(toot_text, in_reply_to_id=status_id, visibility=visibility)
def get_parameter( parameter, file_path ):
# Check if secrets file exists
if not os.path.isfile(file_path):
print("File %s not found, exiting."%file_path)
sys.exit(0)
# Find parameter in file
with open( file_path ) as f:
for line in f:
if line.startswith( parameter ):
return line.replace(parameter + ":", "").strip()
# Cannot find parameter, exit
print(file_path + " Missing parameter %s "%parameter)
sys.exit(0)
def create_dir():
if not os.path.exists('images'):
os.makedirs('images')
def mastodon():
# Load secrets from secrets file
secrets_filepath = "secrets/secrets.txt"
uc_client_id = get_parameter("uc_client_id", secrets_filepath)
uc_client_secret = get_parameter("uc_client_secret", secrets_filepath)
uc_access_token = get_parameter("uc_access_token", secrets_filepath)
# Load configuration from config file
config_filepath = "config/config.txt"
mastodon_hostname = get_parameter("mastodon_hostname", config_filepath)
# Initialise Mastodon API
mastodon = Mastodon(
client_id=uc_client_id,
client_secret=uc_client_secret,
access_token=uc_access_token,
api_base_url='https://' + mastodon_hostname,
)
# Initialise access headers
headers = {'Authorization': 'Bearer %s'%uc_access_token}
return (mastodon, mastodon_hostname)
def dbconfig():
# Load configuration from config file
config_filepath = "config/db_config.txt"
alarm_db = get_parameter("alarm_db", config_filepath)
alarm_db_user = get_parameter("alarm_db_user", config_filepath)
return (alarm_db, alarm_db_user)
def read_apikey():
# Load secrets from secrets file
secrets_filepath = "secrets/apikey.txt"
api_key = get_parameter("api_key", secrets_filepath)
return api_key
# main