ProyectoFinalPython/app/chat_server/Server.py

95 lines
3.2 KiB
Python

import threading
import time
import flask
from werkzeug.serving import make_server
import logging
class Server:
"""
This server does NOT use Flask's built-in development server.
Instead, it uses Werkzeug's make_server to create a WSGI server.
This server is thread-safe and can be stopped by setting the stop_event.
This server works as a chat server by polling, not by using websockets (to keep it simple).
"""
def __init__(self, host: str, port: int, stop_event: threading.Event):
self.host = host
self.port = port
self.stop_event = stop_event
# Flask definition
self.flask = flask.Flask(__name__)
self.flask.add_url_rule('/status', methods=['POST'], view_func=self.status)
self.flask.add_url_rule('/send_message', methods=['POST'], view_func=self.send_message)
self.flask.add_url_rule('/get_messages', methods=['POST'], view_func=self.get_messages)
self.server = make_server(self.host, self.port, self.flask)
self.watcher_thread = threading.Thread(target=self.__watcher)
self.server_thread = threading.Thread(target=self.server.serve_forever)
self.server_thread.start()
self.watcher_thread.start()
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
self.flask.logger.setLevel(logging.ERROR)
# Message initialization
self.message_id = 0
self.messages = self.__init_messages()
def __watcher(self):
while not self.stop_event.is_set():
time.sleep(1)
self.shutdown()
def shutdown(self):
self.__persist_messages()
self.server.shutdown()
def __init_messages(self):
messages = []
try:
with open('chat_server/messages.txt', 'r') as f:
for line in f:
parts = line.strip().split('|')
messages.append({
'id': int(parts[0]),
'sender': parts[1],
'content': parts[2]
})
self.message_id = messages[-1]['id'] if messages else 0
except FileNotFoundError:
with open('chat_server/messages.txt', 'w+') as f:
pass
return messages
def __persist_messages(self):
with open('chat_server/messages.txt', 'w') as f:
for message in self.messages:
f.write(f"{message['id']}|{message['sender']}|{message['content']}\n")
def status(self):
return 'OK'
def send_message(self):
sender = flask.request.json['sender']
content = flask.request.json['content']
self.message_id += 1
message = {
'id': self.message_id,
'sender': sender,
'content': content
}
self.messages.append(message)
return {'id': self.message_id}
def get_messages(self):
try: last_id = flask.request.json.get('last_id')
# last_id is a mandatory parameter
except AttributeError: return flask.Response('Last ID not specified', status=400)
new_messages = [msg for msg in self.messages if msg['id'] > last_id]
return {'messages': new_messages}