From 2353eec18fa3da5d80fad2912b84730bf8d3681d Mon Sep 17 00:00:00 2001 From: AndrewTrieu Date: Sat, 11 Mar 2023 17:54:51 +0200 Subject: [PATCH] Final --- README.md | 45 +++++++++++++++++++++++++ client.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ db.xml | 21 ++++++++++++ server.py | 74 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 README.md create mode 100644 client.py create mode 100644 db.xml create mode 100644 server.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..53af4dc --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +# Note-Taking Application with XML-RPC + +This is a simple note-taking application that allows users to add notes to different topics and retrieve them later. The application uses XML-RPC to communicate between the client and server. + +## Getting Started + +To use the application, you need to run the `server.py` script first. This starts the XML-RPC server on `localhost:7777`. Once the server is running, you can start the client by running the `client.py` script. The client will prompt you to choose an option: + +1. Add note +2. Get notes +3. Quit + +## Adding a Note + +To add a note, choose option 1 and enter the topic, note name, note text, and optionally a link to a Wikipedia page related to the topic. If the topic already exists, the note will be added to it. Otherwise, a new topic will be created and the note added to it. If a Wikipedia link is added, it will be stored along with the note in the database. + +## Getting Notes + +To get notes, choose option 2 and enter the topic. The application will retrieve all the notes for the topic and display them on the console. If a Wikipedia link was added to a note, it will be displayed along with the note. + +## Quitting + +To quit the application, choose option 3. + +## Demonstration + +This video is recorded for the course CT30A3401 Distributed Systems at LUT University, Finland. + +## File Structure + +`client.py`: The client script that communicates with the server. + +`server.py`: The server script that handles the XML-RPC server and database operations. + +`db.xml`: The XML file that stores the notes and topics data. + +## Dependencies + +`xmlrpc.client`: Required for client-server communication using XML-RPC. + +`xmlrpc.server`: Required for server-side XML-RPC implementation. + +`requests`: Required for making HTTP requests to retrieve data from Wikipedia API. + +`datetime`: Required for generating timestamps for notes. diff --git a/client.py b/client.py new file mode 100644 index 0000000..8227228 --- /dev/null +++ b/client.py @@ -0,0 +1,99 @@ +import xmlrpc.client +import requests +from datetime import datetime + +# Create a client class + + +class Client: + def __init__(self): + self.server = None + + def connect_server(self): + try: + self.server = xmlrpc.client.ServerProxy('http://localhost:7777') + except ConnectionRefusedError: + print("Error: Could not connect to server.") + exit() + + # Start the client + def start_client(self): + while True: + action = input( + "Options:\n1) Add note\n2) Get notes\n3) Quit\nEnter your choice: ") + + if action == "1": + # Get user input + topic = input("Enter the topic: ") + note = input("Enter the note topic: ") + text = input("Enter the note text: ") + date_time = datetime.now() + timestamp = date_time.strftime("%m/%d/%Y - %H:%M:%S") + + result = self.server.check_topic(topic) + # Check if the topic exists + if result: + # Append note to existing topic + adding = self.server.add_note(topic, note, text, timestamp) + if (not adding): + print("Error: Could not add note to topic.") + return + else: + # Create new topic and add note + create = self.server.create_topic(topic) + if (not create): + print("Error: Could not create topic.") + return + adding = self.server.add_note(topic, note, text, timestamp) + if (not adding): + print("Error: Could not add note to topic.") + return + + # Ask if user wants to add a link from Wikipedia + wiki_query = input( + "Do you want to add a link to the note topic from Wikipedia? (y/n): ") + if wiki_query == 'y': + search_term = input("Enter search term for Wikipedia: ") + wiki_data = requests.get( + f"https://en.wikipedia.org/w/api.php?action=opensearch&format=json&search={search_term}").json() + if wiki_data[3]: + link = wiki_data[3][0] + else: + no_wiki = print( + "No Wikipedia article found!") + link = 'No link' + else: + link = "No link" + + # Add the link to the note topic + add_link = self.server.add_link(topic, link) + if (not add_link): + print("Error: Could not add link to note.") + return + + elif action == "2": + # Get all the notes of a topic + topic = input("Enter the topic: ") + notes = self.server.get_notes(topic) + if (not notes): + print("Error: Could not get notes.") + return + print() + for note in notes: + print( + f"{note['name']} - {note['text']} ({note['timestamp']}): {note['info']}") + print() + + elif action == "3": + # Quit the client + break + + else: + print("Invalid option!") + + +# Run the client +if __name__ == '__main__': + client = Client() + client.connect_server() + client.start_client() diff --git a/db.xml b/db.xml new file mode 100644 index 0000000..825304c --- /dev/null +++ b/db.xml @@ -0,0 +1,21 @@ + + + + Nice city + 03/11/2023 - 17:45:33 + https://en.wikipedia.org/wiki/Lahti + + + Capital + 03/11/2023 - 17:49:27 + https://en.wikipedia.org/wiki/Helsinki + + + + + Sad + 03/11/2023 - 17:49:50 + No link + + + \ No newline at end of file diff --git a/server.py b/server.py new file mode 100644 index 0000000..da99bcd --- /dev/null +++ b/server.py @@ -0,0 +1,74 @@ +import xmlrpc.server +import xml.etree.ElementTree as ET + +# Class to handle the server side of the XML-RPC server + + +class Server: + def __init__(self): + self.db = ET.parse('db.xml') + self.root = self.db.getroot() + + # Check if the topic exists + def check_topic(self, topic): + for child in self.root: + if child.attrib['name'] == topic: + return True + return False + + # Create a new topic if it doesn't exist + def create_topic(self, topic): + new_topic = ET.Element('topic', {'name': topic}) + self.root.append(new_topic) + self.db.write('db.xml') + return True + + # Add a note of a topic to the database + def add_note(self, topic, note, text, timestamp): + for child in self.root: + if child.attrib['name'] == topic: + new_note = ET.Element('note', {'name': note}) + new_text = ET.Element('text') + new_text.text = text + new_note.append(new_text) + new_timestamp = ET.Element('timestamp') + new_timestamp.text = timestamp + new_note.append(new_timestamp) + child.append(new_note) + self.db.write('db.xml') + return True + return False + + # Add a Wikipedia link to the note + def add_link(self, topic, info): + for child in self.root: + if child.attrib['name'] == topic: + # get the last note element + last_note = child.findall('note')[-1] + new_info = ET.Element('info') + new_info.text = info + last_note.append(new_info) + self.db.write('db.xml') + return True + return False + + # Get all the notes of a topic + def get_notes(self, topic): + for child in self.root: + if child.attrib['name'] == topic: + notes = [] + for note in child.findall('note'): + notes.append({ + 'name': note.attrib['name'], + 'text': note.find('text').text, + 'timestamp': note.find('timestamp').text, + 'info': note.find('info').text + }) + return notes + + +# Start the server +if __name__ == '__main__': + server = xmlrpc.server.SimpleXMLRPCServer(('localhost', 7777)) + server.register_instance(Server()) + server.serve_forever()