Final
This commit is contained in:
45
README.md
Normal file
45
README.md
Normal file
@@ -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.
|
||||||
99
client.py
Normal file
99
client.py
Normal file
@@ -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()
|
||||||
21
db.xml
Normal file
21
db.xml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<data>
|
||||||
|
<topic name="Finland">
|
||||||
|
<note name="Lahti">
|
||||||
|
<text>Nice city</text>
|
||||||
|
<timestamp>03/11/2023 - 17:45:33</timestamp>
|
||||||
|
<info>https://en.wikipedia.org/wiki/Lahti</info>
|
||||||
|
</note>
|
||||||
|
<note name="Helsinki">
|
||||||
|
<text>Capital</text>
|
||||||
|
<timestamp>03/11/2023 - 17:49:27</timestamp>
|
||||||
|
<info>https://en.wikipedia.org/wiki/Helsinki</info>
|
||||||
|
</note>
|
||||||
|
</topic>
|
||||||
|
<topic name="Students">
|
||||||
|
<note name="Lahti campus">
|
||||||
|
<text>Sad</text>
|
||||||
|
<timestamp>03/11/2023 - 17:49:50</timestamp>
|
||||||
|
<info>No link</info>
|
||||||
|
</note>
|
||||||
|
</topic>
|
||||||
|
</data>
|
||||||
74
server.py
Normal file
74
server.py
Normal file
@@ -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()
|
||||||
Reference in New Issue
Block a user