From e158eb862e66334b4a4da5eeb60f5af823c39fb6 Mon Sep 17 00:00:00 2001 From: spla Date: Wed, 25 Nov 2020 11:38:16 +0100 Subject: [PATCH] New feature! %1 - send game anotations to players --- README.md | 9 ++- mastochess.py | 161 ++++++++++++++++++++++++++++++++++++++++++++++++-- smtp_setup.py | 55 +++++++++++++++++ 3 files changed, 217 insertions(+), 8 deletions(-) create mode 100644 smtp_setup.py diff --git a/README.md b/README.md index c96845a..b55e907 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,11 @@ To finish game at any time: To list on going games: -@your_bot_username games +@your_bot_username games + +To get any game anotations, in ex. game 1: + +@your_bot_username send 1 ### Dependencies @@ -41,6 +45,7 @@ Within Python Virtual Environment: ![board](board.png) -20.11.2020 - New feature! added link to on going games in games list +20.11.2020 - New feature! Added link to on going games in games list 21.11.2020 - New feature! Added a warning to player in turn when has been captured one of its pieces 23.11.2020 - New feature! Now all moves are saved to file (with san anotation). +25.11.2020 - New feature! Get any game anotations via email. diff --git a/mastochess.py b/mastochess.py index 33eb7d9..e480968 100644 --- a/mastochess.py +++ b/mastochess.py @@ -6,6 +6,14 @@ import re import unidecode from datetime import datetime, timedelta from mastodon import Mastodon +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.base import MIMEBase +from email import encoders +import smtplib +from smtplib import SMTPException, SMTPAuthenticationError, SMTPConnectError, SMTPRecipientsRefused +import socket +from socket import gaierror import psycopg2 import chess import chess.svg @@ -159,7 +167,7 @@ def get_notification_data(): url_lst = [] - search_text = ['fi','mou','nova','jocs'] + search_text = ['fi','mou','nova','jocs', 'envia'] conn = None @@ -511,7 +519,7 @@ def save_annotation(): moved_piece_name = get_moved_piece_name(moved_piece) - game_file = "anotations/" + str(game_id) + game_file = "anotations/" + str(game_id) + ".txt" if moved_piece_name == 'P': @@ -569,6 +577,108 @@ def save_annotation(): f.write(line_data) +def get_email_address(username): + + try: + + conn = None + + conn = psycopg2.connect(database = mastodon_db, user = mastodon_db_user, password = "", host = "/var/run/postgresql", port = "5432") + + cur = conn.cursor() + + cur.execute("select email from users where account_id = (select id from accounts where username = (%s) and domain is null)", (username,)) + + row = cur.fetchone() + + username_email = row[0] + + cur.close() + + return username_email + + except (Exception, psycopg2.DatabaseError) as error: + + sys.exit(error) + + finally: + + if conn is not None: + + conn.close() + +def send_anotation(game_id): + + emailed = False + + game_found = False + + username_email = get_email_address(username) + + # Create message object instance + msg = MIMEMultipart() + + # Declare message elements + msg['From'] = smtp_user_login + msg['To'] = username_email + msg['Subject'] = "Anotaciones partida n." + game_id + + # Attach the game anotation + file_to_attach = "anotations/" + game_id + ".txt" + try: + + attachment = open(file_to_attach, 'rb') + + game_found = True + + except FileNotFoundError as not_found_error: + + print(not_found_error) + return (emailed, game_id, game_found) + + obj = MIMEBase('application', 'octet-stream') + obj.set_payload(attachment.read()) + encoders.encode_base64(obj) + obj.add_header('Content-Disposition', "attachment; filename= "+file_to_attach) + + # Add the message body to the object instance + msg.attach(obj) + + try: + + # Create the server connection + server = smtplib.SMTP(smtp_host) + # Switch the connection over to TLS encryption + server.starttls() + # Authenticate with the server + server.login(smtp_user_login, smtp_user_password) + # Send the message + server.sendmail(msg['From'], msg['To'], msg.as_string()) + # Disconnect + server.quit() + + print("Successfully sent game anotations to %s" % msg['To']) + emailed = True + return (emailed, game_id, game_found) + + except SMTPAuthenticationError as auth_error: + + print(auth_error) + pass + return emailed + + except socket.gaierror as socket_error: + + print(socket_error) + pass + return emailed + + except SMTPRecipientsRefused as recip_error: + + print(recip_error) + pass + return emailed + def close_game(): now = datetime.now() @@ -874,6 +984,10 @@ def replying(): reply = True + elif query_word[0:5] == 'envia': + + reply = True + else: reply = False @@ -921,6 +1035,15 @@ def db_config(): return (mastodon_db, mastodon_db_user, chess_db, chess_db_user) +def smtp_config(): + + smtp_filepath = "config/smtp_config.txt" + smtp_host = get_parameter("smtp_host", smtp_filepath) + smtp_user_login = get_parameter("smtp_user_login", smtp_filepath) + smtp_user_password = get_parameter("smtp_user_password", smtp_filepath) + + return (smtp_host, smtp_user_login, smtp_user_password) + def get_parameter( parameter, file_path ): if not os.path.isfile(file_path): @@ -964,6 +1087,8 @@ if __name__ == '__main__': mastodon_db, mastodon_db_user, chess_db, chess_db_user = db_config() + smtp_host, smtp_user_login, smtp_user_password = smtp_config() + now = datetime.now() create_dir() @@ -1067,7 +1192,7 @@ if __name__ == '__main__': toot_text += '\n' - toot_text += '#escacs' + '\n' + toot_text += 'partida: ' + str(game_id) + ' ' + '#escacs' + '\n' image_id = mastodon.media_post(board_file, "image/png").id @@ -1079,6 +1204,30 @@ if __name__ == '__main__': update_replies(status_id, username, now) + elif query_word[0:5] == 'envia': + + query_word_length = len(query_word) + + send_game = query_word[6:query_word_length].replace(' ', '') + + emailed, game_id, game_found = send_anotation(send_game) + + if emailed == False and game_found == True: + + toot_text = "@"+username + " error al enviar les anotacions :-(" + + elif emailed == True and game_found == True: + + toot_text = "@"+username + " les anotaciones de la partida n." + str(game_id) + " enviades amb èxit!" + + elif emailed == False and game_found == False: + + toot_text = "@"+username + " la partida n." + str(game_id) + " no existeix..." + + mastodon.status_post(toot_text, in_reply_to_id=status_id,visibility=visibility) + + update_replies(status_id, username, now) + else: update_replies(status_id, username, now) @@ -1099,7 +1248,7 @@ if __name__ == '__main__': toot_text += '\n' - toot_text += '#escacs' + '\n' + toot_text += 'partida: ' + str(game_id) + ' ' + '#escacs' + '\n' board = chess.Board(on_going_game) @@ -1203,7 +1352,7 @@ if __name__ == '__main__': toot_text += "\n* has perdut " + piece_name + "!\n" - toot_text += '\n#escacs' + '\n' + toot_text += '\npartida: ' + str(game_id) + ' ' + '#escacs' + '\n' if username == white_user: @@ -1370,7 +1519,7 @@ if __name__ == '__main__': toot_text += '\n' - toot_text += '#escacs' + '\n' + toot_text += 'partida: ' + str(game_id) + ' ' + '#escacs' + '\n' board = chess.Board(on_going_game) diff --git a/smtp_setup.py b/smtp_setup.py new file mode 100644 index 0000000..e27bba5 --- /dev/null +++ b/smtp_setup.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import getpass +import fileinput,re +import os +import sys + +def create_dir(): + if not os.path.exists('config'): + os.makedirs('config') + +def create_file(): + if not os.path.exists('config/smtp_config.txt'): + with open('config/smtp_config.txt', 'w'): pass + print(smtp_filepath + " created!") + +def write_parameter( parameter, smtp_filepath ): + print("\n") + print("Setting up SMTP parameters...") + smtp_host = input("Enter SMTP hostname: ") + smtp_user_login = input("Enter SMTP user login, ex. user@" + smtp_host +"? ") + smtp_user_password = getpass.getpass("SMTP user password? ") + with open(smtp_filepath, "w") as text_file: + print("smtp_host: {}".format(smtp_host), file=text_file) + print("smtp_user_login: {}".format(smtp_user_login), file=text_file) + print("smtp_user_password: {}".format(smtp_user_password), file=text_file) + +# Returns the parameter from the specified file +def get_parameter( parameter, smtp_filepath ): + # Check if file exists + if not os.path.isfile(smtp_filepath): + print("File %s not found, creating it."%smtp_filepath) + create_dir() + create_file() + write_parameter( parameter, smtp_filepath ) + print("\n") + print("SMTP setup done!\n") + + # Find parameter in file + with open( smtp_filepath ) 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) + +# Load secrets from secrets file +smtp_filepath = "config/smtp_config.txt" +smtp_host = get_parameter("smtp_host", smtp_filepath) +smtp_user_login = get_parameter("smtp_user_login", smtp_filepath) +smtp_user_pass = get_parameter("smtp_user_pass", smtp_filepath) +