2 More Milestones
I have added the feature for the BBS to be able to accept user messages and display all messages. Still to be done: asc pages for messages and implementation of that. Yes, I do know that I'm still including my test data in the json files. I do not care.
This commit is contained in:
parent
b6b67576c1
commit
6577e6b051
3
bbs.py
3
bbs.py
@ -42,8 +42,7 @@ class bbsServer():
|
||||
try:
|
||||
comms(conn, addr, node + 1)
|
||||
|
||||
|
||||
except RuntimeError:
|
||||
except (RuntimeError, OSError):
|
||||
print("Node %s hung up..." % (node + 1))
|
||||
|
||||
print("Node %s offline." % (node + 1))
|
||||
|
@ -1,8 +1,9 @@
|
||||
[Main]
|
||||
Port = 2043
|
||||
Port = 2062
|
||||
DefaultSplash = "Welcome to the SB17 BBS on %node%!"
|
||||
MaxConnections = 5
|
||||
Menus = 2
|
||||
msgDb = messages.json
|
||||
|
||||
[Auth]
|
||||
userDb = users.json
|
||||
|
@ -1,5 +1,4 @@
|
||||
# Configuration
|
||||
|
||||
This file contains the information necessary to configure Pyscii-BBS. The default configuration provided will run, but you will likely want to change many of these values.
|
||||
|
||||
## String Replacements
|
||||
|
@ -26,10 +26,10 @@ Remember these rules for working on the following features:
|
||||
- BBS Server can show a menu to the user after logging in ✓
|
||||
- BBS Server menu allows user to modify their own profile ✓
|
||||
- BBS Server can display pre-coded messages in a messages space ✓
|
||||
- BBS Server can accept messages from users ✓
|
||||
- BBS Server can display user submitted messages to message boards ✓
|
||||
|
||||
#### ToDo
|
||||
- BBS Server can accept messages from users
|
||||
- BBS Server can display user submitted messages to message boards
|
||||
- BBS Server can show only certain users a different menu option (RBAC implementation)
|
||||
|
||||
At this point we have the bare minimum of a functioning BBS. The user flow at this stage is they connect, log in, and are presented with a menu that will let them edit their profile or visit a message board. The message board will be a single flow of messages and the user will have to select what messages to read. No unread/read list exists. It is a simple text-based telnet message board with an auth system.
|
||||
|
31
docs/message.schema.json
Normal file
31
docs/message.schema.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://bbs.sb17.space/message.schema.json",
|
||||
"title": "Message",
|
||||
"description": "A Pyscii-BBS message object",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id" : {
|
||||
"description": "The unique ID of the message entity",
|
||||
"type": "integer"
|
||||
},
|
||||
"subject": {
|
||||
"description": "The subject of the message entity",
|
||||
"type": "string"
|
||||
},
|
||||
"body": {
|
||||
"description": "The message body.",
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"description": "The date the message is posted",
|
||||
"type": "datetime",
|
||||
},
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"subject",
|
||||
"body",
|
||||
"date"
|
||||
]
|
||||
}
|
66
functions.py
66
functions.py
@ -4,11 +4,15 @@ import sys
|
||||
import comms
|
||||
import menus
|
||||
import auth
|
||||
import datetime
|
||||
|
||||
config = configparser.ConfigParser()
|
||||
config.read(sys.argv[1])
|
||||
|
||||
userDb = config.get("Auth","userDb")
|
||||
msgDB = config.get("Main","msgDb")
|
||||
|
||||
date_format_string = "%Y-%m-%d HH:MM:SS"
|
||||
|
||||
def printProfile(conn, userId, node, lastMenu):
|
||||
comms.sendString(conn, "\u001B[2JProfile:\r\n")
|
||||
@ -50,8 +54,66 @@ def editProfile(conn, userID, node, lastMenu):
|
||||
menus.printMenu(conn, lastMenu, node, userID)
|
||||
|
||||
def pubMessages(conn, userID, node, lastMenu):
|
||||
comms.sendString(conn, "There are no messages!\r\nPress any key to go back... ")
|
||||
comms.sendString(conn, "\u001B[2JMessages:\r\n")
|
||||
with open(msgDB) as msgdb:
|
||||
messages = json.loads(msgdb.read())
|
||||
for message in messages['messages']:
|
||||
msgListElement = str(message['id']) + "\t|\t" + message['date'] + "\t|\t" + message['author'] + "\t|\t" + message['subject'] + "\t\t\t"
|
||||
comms.sendString(conn,msgListElement+"\r\n")
|
||||
|
||||
comms.sendString(conn, "\r\nSend the M and the message number (eg. M0) number to read a message.\r\nPress C to Write a Message \r\nSend B to go back to the Menu: ")
|
||||
response = comms.getString(conn,3)
|
||||
if response.strip('\x00') == "B":
|
||||
menus.printMenu(conn, lastMenu, node, userID)
|
||||
|
||||
elif response.strip('\x00')[0] == "M":
|
||||
printMessage(conn, int(response.strip('\x00').replace('M','')))
|
||||
|
||||
elif response.strip('\x00') == "C":
|
||||
writeMessage(conn, userID)
|
||||
|
||||
pubMessages(conn, userID, node, lastMenu)
|
||||
|
||||
def printMessage(conn, messageNum):
|
||||
comms.sendString(conn, "\u001B[2JMessage:\r\n")
|
||||
with open(msgDB) as msgdb:
|
||||
messages = json.loads(msgdb.read())
|
||||
for message in messages['messages']:
|
||||
if message['id'] == int(messageNum):
|
||||
comms.sendString(conn, "\r\nDate Published: " + message['date'])
|
||||
comms.sendString(conn, "\r\nSubject: " + message['subject'])
|
||||
comms.sendString(conn, "\r\nAuthor: " + message['author'])
|
||||
comms.sendString(conn, "\r\nMessage: " + message['body'])
|
||||
|
||||
comms.sendString(conn, "\r\nPress any key to go back... ")
|
||||
comms.getString(conn,2)
|
||||
return
|
||||
|
||||
def writeMessage(conn, userid):
|
||||
comms.sendString(conn, "\u001B[2JCompose Message:\r\n")
|
||||
with open(userDb) as userdb:
|
||||
users = json.load(userdb)
|
||||
for user in users['users']:
|
||||
if user['id'] == userid:
|
||||
username = user['name']
|
||||
with open(msgDB) as msgdb:
|
||||
messages = json.load(msgdb)
|
||||
|
||||
message = {}
|
||||
message["id"] = messages['messages'][-1]["id"] + 1
|
||||
|
||||
message['date'] = datetime.datetime.now().strftime(date_format_string)
|
||||
comms.sendString(conn,"Subject: ")
|
||||
message['subject'] = comms.getString(conn, 150)
|
||||
message['author'] = username
|
||||
comms.sendString(conn,"Message Body: ")
|
||||
message['body'] = comms.getString(conn, 1500)
|
||||
messages['messages'].append(message)
|
||||
|
||||
with open(msgDB,'w') as output:
|
||||
json.dump(messages, output, indent=4)
|
||||
|
||||
comms.sendString(conn, "Message Published!\r\nPress any key to go back... ")
|
||||
comms.getChar(conn)
|
||||
menus.printMenu(conn, lastMenu, node, userID)
|
||||
|
||||
|
||||
|
1
menus.py
1
menus.py
@ -34,6 +34,7 @@ def parseResponse(conn, menu, node, user, response):
|
||||
comms.sendString(conn, "\u001B[2J\r")
|
||||
if response.strip('\x00') == "X":
|
||||
comms.sendString(conn, "Goodbye!")
|
||||
conn.close()
|
||||
|
||||
if response.strip('\x00') == "P":
|
||||
functions.printProfile(conn, user, node, menu)
|
||||
|
18
messages.json
Normal file
18
messages.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"messages": [
|
||||
{
|
||||
"id": 0,
|
||||
"author": "Default",
|
||||
"subject": "Welcome!",
|
||||
"body": "This is the first message in every PyScii BBS. It sets up the messages json.",
|
||||
"date": "1970-01-01 00:00:00"
|
||||
},
|
||||
{
|
||||
"id": 1,
|
||||
"date": "2025-07-19 HH:MM:SS",
|
||||
"subject": "\u0000First User Message",
|
||||
"author": "J4YC33",
|
||||
"body": "\u0000This is the first messsage on the Pyscii BBS!\\nIt's a fun thing!"
|
||||
}
|
||||
]
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
"name": "J4YC33",
|
||||
"password": "d32190c6322e27087c934b7bd9ff642bbe71d5782f2242028c3c15298c7aeac6",
|
||||
"salt": "SI13YMJl8kWLBhNN",
|
||||
"description": "J4YC33 IS SPARTACUS!"
|
||||
"description": "\u0000I *AM* Spartacus!"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user