Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jalbarracinv/python-cbm-petscii-bbs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: petscii
Choose a base ref
...
head repository: jalbarracinv/python-cbm-petscii-bbs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref

Commits on Dec 19, 2021

  1. Update README.md

    jalbarracinv authored Dec 19, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    b04e2d2 View commit details
  2. Update README.md

    jalbarracinv authored Dec 19, 2021
    Copy the full SHA
    4c81e1e View commit details

Commits on Dec 26, 2021

  1. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    3b30946 View commit details
  2. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    4a04e43 View commit details
  3. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    8e66eed View commit details
  4. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    0859677 View commit details
  5. Add files via upload

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    ed0bb44 View commit details
  6. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    d973c09 View commit details
  7. Add files via upload

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    5c9e057 View commit details
  8. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    ffef0b6 View commit details
  9. Add files via upload

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    b56d6cf View commit details
  10. Delete headbbs.seq

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    729ccc4 View commit details
  11. Update README.md

    jalbarracinv authored Dec 26, 2021
    Copy the full SHA
    90690fa View commit details

Commits on Dec 27, 2021

  1. Create seq.seq

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    334710f View commit details
  2. Add files via upload

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    bb5f6ac View commit details
  3. Delete welcome.seq

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    ddf8ad9 View commit details
  4. Delete menu.seq

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    f287127 View commit details
  5. Delete seq.seq

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    8ab3ba8 View commit details
  6. Add files via upload

    jalbarracinv authored Dec 27, 2021
    Copy the full SHA
    d4535be View commit details

Commits on Mar 22, 2022

  1. missing step in README.md

    TechCowboy committed Mar 22, 2022
    Copy the full SHA
    f81f59b View commit details

Commits on Aug 11, 2022

  1. Update README.md

    jalbarracinv authored Aug 11, 2022
    Copy the full SHA
    a1b01f1 View commit details
  2. Merge pull request #3 from TechCowboy/main

    missing step in README.md
    jalbarracinv authored Aug 11, 2022
    1
    Copy the full SHA
    a1642de View commit details
Showing with 273 additions and 63 deletions.
  1. +51 −2 README.md
  2. +172 −39 bbs.py
  3. BIN commander.png
  4. +47 −21 funct.py
  5. +0 −1 headbbs.seq
  6. +1 −0 seq/colaburger.seq
  7. +1 −0 seq/menu.seq
  8. +1 −0 seq/welcome.seq
53 changes: 51 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,62 @@
# python-cbm-bbs-petscii
# Python cbm bbs petscii

<img src="https://github.com/jalbarracinv/python-cbm-petscii-bbs/raw/main/commander.png" width="500"/>

Python Commodore BBS multi-client
This is intended for commodore 64, c128 and most commodore compatible machines (as the new Commander X16 under development)

This is a working Python 3.X script that will help you implement a Commodore Petscii BBS.
- You have to setup MySQL database "cbmbbs" with the instructions below this readme
- Basic functionality: Login and Register a NEW user
- In progress: Sample board read and write posts. (*not* in this release)

Included Files:

1) bbs.py -> main file. Just run in terminal user@yourcomputer:~/yourdirectory $ python3 bbs.py

2) funct.py -> main bbs functions

3) head.seq -> a sequence (random chars) file generated with http://petscii.krissz.hu/
3) welcome.seq -> a sequence (random chars) file generated with http://petscii.krissz.hu/ this is a welcome banner example.
menu.seq -> a sequence (random chars) file generated with http://petscii.krissz.hu/ this is a menu example.
## To start, first create the needed databases in MySQL with the following commands:

CREATE DATABASE `cbmbbs` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `cbmbbs`

CREATE TABLE `accounts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL,
`active` int(11) NOT NULL,
`level` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE KEY `idx_accounts_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

CREATE TABLE `boards` (
`idboard` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`idboard`,`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

CREATE TABLE `posts` (
`idmessage` int(11) NOT NULL AUTO_INCREMENT,
`date` datetime DEFAULT NULL,
`subject` varchar(128) DEFAULT NULL,
`userid` int(11) DEFAULT NULL,
`idboard` int(11) DEFAULT NULL,
`body` blob DEFAULT NULL,
`status` int(11) DEFAULT NULL,
`idreply` int(11) DEFAULT NULL,
PRIMARY KEY (`idmessage`),
KEY `idx_boardmessages_userid` (`userid`),
KEY `idx_boardmessages_boardid` (`idboard`),
KEY `idx_boardmessages_date` (`date`),
KEY `idx_boardmessages_replyid` (`idreply`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO boards (`idboard`,`name`) VALUES (1,'General');


211 changes: 172 additions & 39 deletions bbs.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
import mysql.connector
import socket
import time
import os
from _thread import *
from funct import *

#DEFINE LISTENING HOST AND PORT
BBS = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = '' # leave empty for any IP
port = 8818 # you can change the incoming port to any desired
UsersCount = 0

# Conect to mysql (to make it work: pip install mysql-connector)
mydb = mysql.connector.connect(
host="localhost", #mysql server address
user="bbs", #bbs user you created on mysql
password="bbspass",
database="cbmbbs"
)

# Define a database cursor to make the queries
mycursor = mydb.cursor(dictionary=True)

try:
BBS.bind((host, port))
BBS.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,True)
@@ -17,80 +30,200 @@

print('SERVER > Waiting for a Connection..\r')

BBS.listen(8)
BBS.listen()

def do_welcome(connection):

#CLEAR SCREEN
connection.send(cbmcursor("clear"))
connection.send(cbmcursor("home"))
send_cr(connection, "clear") #sends a coded cursor
send_cr(connection, "home") #sends a coded cursor

#SEND HEADER FILE (.SEQ)
# print ("STATUS > will send seq")
send_file(connection, "headbbs.seq")
send_ln(connection, "\n\n") #sends text
send_seq(connection, "seq/welcome.seq") #sends a seq file to screen

#THIS SECTION SENDS RANDOM THINGS (FOR YOU TO LEARN HOW)
connection.send(cbmcursor("red")) #cbmcursor sends color red code
connection.send(cbmencode("\n\nWelcome")) #cbmencode sends message
connection.send(cbmcursor("blue"))
connection.send(cbmencode(" a "))
connection.send(cbmcursor("purple"))
connection.send(cbmencode("CBMBBS\n\n"))
connection.send(cbmcursor("grey"))
send_cr(connection, "red") #cbmcursor sends color red code
send_ln(connection, "\n\nWelcome") # sends message
send_cr(connection, "blue") #cbmcursor sends color blue code
send_ln(connection, " to ") # sends message
send_cr(connection, "purple") #cbmcursor sends color purple code
send_ln(connection, "CBMBBS\n\n") # sends message
send_cr(connection, "gray") #cbmcursor sends color gray code
welcome2="This is a text is a text" #You can also declare a string
connection.send(cbmencode(welcome2)) #and send it after cbmencode it
send_ln(connection, welcome2) #and send it after cbmencode it
cursorxy(connection,1,1) #cursorxy positions cursor on x,y on screen
connection.send(cbmencode("i am at 1,1"))
send_ln(connection, "up1")
cursorxy(connection,1,25)
connection.send(cbmencode("i am at 1,25"))
time.sleep(2)
send_ln(connection, "down25")
cursorxy(connection,10,20)
get_char(connection)

send_cr(connection, "clear") #sends a coded cursor
send_cr(connection, "home") #sends a coded cursor
send_seq(connection, "seq/colaburger.seq")
cursorxy(connection,30,5)
get_char(connection)

def do_login(connection):

#CLEAR SCREEN
connection.send(cbmcursor("clear"))
connection.send(cbmcursor("home"))
cursorxy(connection,1,3)
#CLEAR SCREEN
send_cr(connection,"clear")
send_cr(connection,"home")
cursorxy(connection,1,3) #positions cursor on third line
maxtries=3 #max tries
attempts=0

while True:
#Login (not finished)
connection.send(cbmencode("Username (new): "))
namex=input_line(connection) #input_line function reads a line
print("decoded name: ",cbmdecode(namex)) # this is displayed on system side

connection.send(cbmencode("Password: "))
pword=input_pass(connection) #input_pass reads a line but shows '*'
print("decoded pass: ",cbmdecode(pword)) # this is displayed on system side

uname=cbmdecode(namex) #receives the name of the user
send_ln(connection,"Username (or 'new'): ")
uname=input_line(connection) #input_line function reads a line

return uname
if (uname=="new"):
uname,realid = do_newuser(connection)
print("NEW user created")
break

def do_bucle(connection,namex):
connection.send(cbmencode("Password: "))
upass=input_pass(connection) #input_pass reads a line but shows '*'

# Define QUERY
query="SELECT id,username,password FROM accounts WHERE username='%s'"
query=query % (uname)

# Execute QUERY
mycursor.execute(query)
myresult = mycursor.fetchone()

if (myresult == None):
send_ln(connection, "\n\nIncorrect username or password.\n\n")
attempts=attempts+1
else:
realpass = myresult['password']
realid = myresult['id']

# Check if there is a match
if(realpass==upass):
break
else:
send_ln(connection, "\n\nIncorrect username or password.\n\n")
attempts=attempts+1
if (attempts>=maxtries):
connection.send(cbmencode("\n\nSorry maximum number of attempts reached..\n\n"))
connection.close()
print("JUST LOGGED IN -> uname->",uname,"realid->",realid)
return uname,realid;

def do_newuser(connection):
#CLEAR SCREEN
send_cr(connection, "clear")
send_cr(connection, "home")
cursorxy(connection,1,3) #positions cursor on third line
send_ln(connection, "Welcome new user!\nLet's create a new username.\n\n")

#DEFINE Variables to control loop
maxtries=5 #max tries
attempts=0

while True:
send_ln(connection, "Type your username: ")
uname=input_line(connection) #input_line function reads a line

# Define QUERY
query="SELECT id,username,password FROM accounts WHERE username='%s'"
query=query % (uname)

# Execute QUERY
mycursor.execute(query)
myresult = mycursor.fetchone()

#IF user does not exists
if(myresult == None and uname!="" and uname !="new"):
send_ln(connection, "Your username is: "+uname+"\nAre you sure? (y/n): ")
letter=get_char(connection)
send_ln(connection, "\n\n")
attempts=attempts+1
if(letter=="y" or letter=="Y"):
break
else:
send_ln(connection, "\nError: User already exists.\n")
attempts=attempts+1

if attempts >=maxtries:
send_ln(connection, "Sorry, maximum number of attempts.\nConnection closed.")
connection.close()

attempts=0

#Asks for password
while True:
send_ln(connection,"\nType your password: ")
pass1=input_pass(connection) #input_line function reads a line
send_ln(connection, "\nRepeat your password: ")
pass2=input_pass(connection) #input_line function reads a line
if(pass1!="" and pass2==pass1):
break
attempts=attempts+1
if attempts >= maxtries:
send_ln(connection, "Sorry, maximum number of attempts.\nConnection closed. ")
connection.close()
send_ln(connection, "\nError: Passwords don't match.\nTry Again.\n\n")

attempts=0

#Asks for email
while True:
send_ln(connection, "\nType your email: ")
mail1=input_line(connection) #input_line function reads a line
send_ln(connection, "\nRepeat your email: ")
mail2=input_line(connection) #input_line function reads a line
if(mail1!="" and mail2==mail1):
break
attempts=attempts+1
if attempts >= maxtries:
send_ln(connection, "Sorry, maximum number of attempts.\nConnection closed. ")
connection.close()
send_ln(connection,"\nError: Emails don't match.\nTry Again.\n\n")

print("Creating account:",uname)
## Creates user here
query="INSERT INTO accounts (username, password, email, active, level) VALUES ('%s','%s','%s',1,1)"
query=query % (uname,pass1,mail1)
mycursor.execute(query)
mydb.commit() #imperative
realid=mycursor.lastrowid
print("NEW User just registered with id:",realid)
return uname,realid;

def do_bucle(connection,namex,idx):

while True:
print("Hola, ",namex)
connection.send(cbmencode("\n\nTYPE CHAR: "))
#bucl=input_line(connection)
#Clears Screen and sends MENU
print("USER -> ",namex,"->",idx,"Main Menu") #Outputs for sysop
send_ln(connection, "\n\nChoose an option: ")
bucl=get_char(connection)
print(bucl)
print("decoded: ",cbmdecode(bucl))


###########################################
# MAIN BBS FUNCTIONS
###########################################

def user_session(connection):
time.sleep(3)

while True:

#initializes terminal
#initializes terminal
send_cr(connection,"clear")
send_cr(connection,"home")
send_ln(connection, "Connected. Hit any key...")
bucl=input_line(connection)

do_welcome(connection)

userx = do_login(connection)
userx,idx = do_login(connection)

do_bucle(connection,userx)
do_bucle(connection,userx,idx)

#############################################################################

Binary file added commander.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 47 additions & 21 deletions funct.py
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
'\x12':b'\x12','\x92':b'\x92','\x81':b'\x81','\x90':b'\x90','\x95':b'\x95','\x96':b'\x96',
'\x97':b'\x97','\x98':b'\x98','\x99':b'\x99','\x9a':b'\x9a','\x9b':b'\x9b','\x9e':b'\x9e',
'\x9f':b'\x9f','\x13':b'\x13',
"'":b"\x27"}
"'":b"\x27","=":b"\x3d","[":b"[","]":b"]",";":b";","↑":b"\x5e","←":b"\x5f"}

#This function moves the cursor and changes color, clear screen
def cbmcursor(tx):
@@ -33,6 +33,8 @@ def cbmcursor(tx):
if tx=="brown": out =b'\x95'
if tx=="pink": out =b'\x96'
if tx=="dark grey": out=b'\x97'
if tx=="dark gray": out=b'\x97'
if tx=="gray": out=b'\x98'
if tx=="grey": out=b'\x98'
if tx=="lightgreen": out=b'\x99'
if tx=="lightblue": out=b'\x9a'
@@ -42,7 +44,7 @@ def cbmcursor(tx):
if tx=="cyan": out=b'\x9f'
if tx=="revon": out=b'\x12'
if tx=="revoff": out=b'\x92'
if tx=="rand":
if tx=="randc":
m=random.randint(0, 15)
if m==0: out =b'\x1f'
if m==1: out =b'\x81'
@@ -126,21 +128,32 @@ def input_line(connection):
print("no data - closed connection")
connection.close()
break
delchar=0
if (data==b'\xff' or data==b'\xfb' or data==b'\x00' or data==b'\x01' or data==b'\xfd'):
if (data==b'\xff' or data==b'\xe6' or data==b'\xfe' or data==b'\xfb' or data==b'\x00' or data==b'\x01' or data==b'\xfd'):
data=b''
if (data==b'\xff\xfb\x01'):
data=b''
if (data==b'\xff\xfb\x00'):
data=b''
if (data==b'\xff\xfb\x00\xff\xfd\x00'):
data=b''
if (data==b'\xff\xfb\x00\xff\xfb\x00'):
data=b''
if (data==b'\xff\xfb\x01\xff\xfb\x00\xff\xfd\x00'):
data=b''
if (data==b'\x14'):
delchar=1
tline=tline+data
if (delchar==1):
tline=tline[0:len(tline)-2]
connection.send(data)
if (len(tline)==0):
data=b''
tline=tline[0:len(tline)-1]
if (tline==b'\xff\xfb\x01\xff\xfb\x00\xff\xfd\x00'):
tline=b''
connection.send(data)
if (data==b'\r' or data==b'\r\n' or data==b'\n'):
break
if (data==b'\x14'):
tline=tline
else:
tline=tline+data
tline=cbmdecode(tline)
return tline

#reads a password (and when typing it shows '*' to the user)
@@ -158,41 +171,54 @@ def input_pass(connection):
data=b''
if (data==b'\xff\xfb\x01\xff\xfb\x00\xff\xfd\x00'):
data=b''
if (data==b'\r' or data==b'\r\n' or data==b'\n' or data==b'\n\r'):
data=b''
bbb=999
if (data==b'\x14'):
delchar=1
tline=tline+data
if (delchar==1):
tline=tline[0:len(tline)-2]
if (len(tline)==0):
data=b''
tline=tline[0:len(tline)-1]
if (tline==b'\xff\xfb\x01\xff\xfb\x00\xff\xfd\x00'):
tline=b''
if (bbb==999):
if (data==b'\x14' or data==b'\r' or data==b'\r\n' or data==b'\n' or data==b''):
connection.send(data)
else:
connection.send(b'*')
if (data==b'\r' or data==b'\r\n' or data==b'\n'):
break
if (data==b'\x14'):
tline=tline
else:
connection.send(b'*')
tline=tline+data
tline=cbmdecode(tline)
return tline

#similar to commodore basic get command (it just wait to type one char)
def get_char(connection):
while True:
data = connection.recv(256, 0x40) #funciona como un input
data = connection.recv(256, 0x40) #works like a get
if not data:
print("no data - closed connection")
connection.close()
break
rchar=data[0:1]
connection.send(rchar)
rchar=cbmdecode(rchar)
return(rchar)

#this is to send the SEQ file to the user (useful for petscii graphics portions)
def send_file(connection, filen):
print (filen)
def send_seq(connection, filen):
print("inicio send_seq")
print("FN->",filen)
with open(filen, "rb") as f:
nb=b''
byte = f.read(1)
while byte:
nb = byte
connection.send(nb)
byte = f.read(1)

def send_ln(connection, line):
linet=cbmencode(line)
connection.send(linet)

def send_cr(connection, charx):
chrxx=cbmcursor(charx)
connection.send(chrxx)
1 change: 0 additions & 1 deletion headbbs.seq

This file was deleted.

1 change: 1 addition & 0 deletions seq/colaburger.seq
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
�� ��� � � �� ����� wELCOME! �� ��� �hAVE A cOLA bURGER bbs�tIME ��� ��� pRESS ANY KEY �� � � � ��� � � ���� ���������� �� ������������� ���������� ��� ��������� ������� ����������� � ���� �� � � ����. � � � � �� ������� �� ��� � � � ���� � � � ��� ��������� ��� � � ������� . � � � � ���������� ��� ���� """""""" ��� ������� � �� ���p������������������������ �� � � ������� �� �� ������������������������������ ���������������� ��� � � ������������������ � � �� � ����������� ��� ������ � ���i� �� �����  �� � �����"""""". ������""��� �����������  ��� �� ���~~~� ����������������� ��������������� ��� ��������������� ��~~���� �������� ��������� ��� ��� ��� � � ����� ���������� � � �� ��� ������ �l����� ���� � ����� . � � ��� ������������� �� ���� """""" �������� � ����� � � ���������������� � � � � � �
1 change: 1 addition & 0 deletions seq/menu.seq
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
���``````````````````````````````````````�} }}mAIN mENU }�``````````````````````````````````````�} �}}�1] bOARDS� }}�2] gOOD BYE� �}}� �}}� �}}� �}�``````````````````````````````````````�
1 change: 1 addition & 0 deletions seq/welcome.seq
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
���� ������� � ��� ���� ���� ������������ �� ���� ����������� �c�O�M�M�A�N�D�E�R� ��������������������� ������� x-�16