324 lines
8.8 KiB
Plaintext
Executable File
324 lines
8.8 KiB
Plaintext
Executable File
import sys, pickle
|
||
from random import randint
|
||
from pprint import pprint as pp
|
||
from mystic_bbs import *
|
||
|
||
NODELIST = "/mystic/data/nodelist.txt"
|
||
RATING_FILE = "/mystic/scripts/mL-nlparse.dat"
|
||
dictNodelist = {}
|
||
ratingsDB = {}
|
||
canexit = "no"
|
||
screenWidth = 80
|
||
screenDepth = 24
|
||
AUTHOR = "MeaTLoTioN"
|
||
cRESET = "|16|07"
|
||
hBG = "|19"
|
||
hFG = "|14"
|
||
fBG = "|19"
|
||
fFG = "|14"
|
||
barOffset = 1
|
||
highlightedBBS = ""
|
||
|
||
KEY_UP = chr(72)
|
||
KEY_DOWN = chr(80)
|
||
KEY_ESCAPE = chr(27)
|
||
KEY_ENTER = chr(13)
|
||
KEY_TAB = chr(9)
|
||
KEY_LEFT = chr(75)
|
||
KEY_RIGHT = chr(77)
|
||
|
||
def saveDB():
|
||
global ratingsDB
|
||
global RATING_FILE
|
||
with open(RATING_FILE, 'wb') as fhandle:
|
||
pickle.dump(ratingsDB, fhandle, protocol=pickle.HIGHEST_PROTOCOL)
|
||
|
||
def loadDB():
|
||
global ratingsDB
|
||
global RATING_FILE
|
||
try:
|
||
with open(RATING_FILE, 'rb') as fhandle:
|
||
ratingsDB = pickle.load(fhandle)
|
||
except:
|
||
pass
|
||
|
||
def stripmci(str):
|
||
pos = str.find("|")
|
||
while pos != -1 :
|
||
str = str[:pos] + str[pos+3:]
|
||
pos = str.find("|")
|
||
return str
|
||
|
||
def initNodelist():
|
||
with open(NODELIST) as f:
|
||
lines = f.readlines()
|
||
|
||
for line in lines:
|
||
if line.startswith(";"):
|
||
pass
|
||
else:
|
||
tmp = line.strip("\n").split(",")
|
||
if tmp[0] == "Zone":
|
||
ZONE = tmp[1]
|
||
elif tmp[0] == "Region" or tmp[0] == "Host":
|
||
REGION = tmp[1]
|
||
else:
|
||
NODE = tmp[1]
|
||
BBS_NAME = tmp[2]
|
||
if BBS_NAME not in dictNodelist:
|
||
dictNodelist[BBS_NAME] = {}
|
||
|
||
BBS_NAME_PRETTY = BBS_NAME.replace("_"," ")
|
||
BBS_LOCATION = tmp[3]
|
||
BBS_SYSOP = tmp[4]
|
||
|
||
test = [string for string in tmp if "NA" in string]
|
||
if test:
|
||
BBS_ADDRESS_FULL = test[0][4:]
|
||
else:
|
||
BBS_ADDRESS_FULL = "Private"
|
||
|
||
BBS_ADDRESS = BBS_ADDRESS_FULL.split(":")[0]
|
||
|
||
if ":" in BBS_ADDRESS_FULL:
|
||
BBS_PORT = BBS_ADDRESS_FULL.split(":")[1]
|
||
else:
|
||
BBS_PORT = 23
|
||
|
||
try:
|
||
if [match for match in tmp if "MY" in match]:
|
||
BBS_SOFTWARE = "Mystic"
|
||
elif [match for match in tmp if "SC" in match]:
|
||
BBS_SOFTWARE = "Synchronet"
|
||
elif [match for match in tmp if "SYNC" in match]:
|
||
BBS_SOFTWARE = "Synchronet"
|
||
elif [match for match in tmp if "MB" in match]:
|
||
BBS_SOFTWARE = "MBSE"
|
||
elif [match for match in tmp if "LGCX" in match]:
|
||
BBS_SOFTWARE = "Legacy/X"
|
||
elif [match for match in tmp if "ENIG" in match]:
|
||
BBS_SOFTWARE = "Enigma1/2"
|
||
elif [match for match in tmp if "CNET" in match]:
|
||
BBS_SOFTWARE = "CNET"
|
||
elif [match for match in tmp if "PCB" in match]:
|
||
BBS_SOFTWARE = "PC Board"
|
||
elif [match for match in tmp if "OBV2" in match]:
|
||
BBS_SOFTWARE = "Oblivion 2"
|
||
elif [match for match in tmp if "WLDC" in match]:
|
||
BBS_SOFTWARE = "Wildcat"
|
||
else:
|
||
BBS_SOFTWARE = "n/a"
|
||
except:
|
||
BBS_SOFTWARE = "Undefined"
|
||
|
||
d = dictNodelist[BBS_NAME]
|
||
d["NAME"] = BBS_NAME_PRETTY
|
||
d["LOCATION"] = BBS_LOCATION
|
||
d["SYSOP"] = BBS_SYSOP
|
||
d["ADDRESS"] = BBS_ADDRESS
|
||
d["PORT"] = BBS_PORT
|
||
d["SOFTWARE"] = BBS_SOFTWARE
|
||
d["RATING"] = 0
|
||
|
||
if "NODE_ADDRESSES" not in d:
|
||
d["NODE_ADDRESSES"] = []
|
||
NODE_ADDRESS = "%s:%s/%s" % (ZONE,REGION,NODE)
|
||
d["NODE_ADDRESSES"].append(NODE_ADDRESS)
|
||
|
||
def init():
|
||
write("|CL")
|
||
header()
|
||
footer()
|
||
gotoxy(1,2)
|
||
|
||
def header():
|
||
MSG = "BBS Name".ljust(22)+" "+"SysOp".ljust(15)+" "+"Location".ljust(15)+" "+"Software".ljust(15)+" "+"Rating".ljust(6)+" "
|
||
gotoxy(1,1)
|
||
write(hBG+hFG+" "*screenWidth)
|
||
gotoxy(1,1)
|
||
write(MSG+cRESET)
|
||
|
||
def footer():
|
||
MSG = "Mystic Nodelist Browser v1.0 by "+AUTHOR
|
||
lMSG = len(MSG)
|
||
gotoxy(1,screenDepth)
|
||
write(fBG+fFG+" "*screenWidth)
|
||
gotoxy((screenWidth/2)-(lMSG/2),screenDepth)
|
||
write(MSG)
|
||
write(cRESET)
|
||
|
||
def getBBS(o, s):
|
||
global barOffset
|
||
selectedBBS = ""
|
||
count = 0
|
||
tmpDict = sorted(dictNodelist, reverse=False)
|
||
for BBS in tmpDict:
|
||
count += 1
|
||
if count == o+s:
|
||
selectedBBS = BBS
|
||
return selectedBBS
|
||
|
||
def showList(offset = 0):
|
||
global barOffset
|
||
global highlightedBBS
|
||
R = 1
|
||
count = 0
|
||
gotoxy(1,2)
|
||
write("|16|07")
|
||
tmpDict = sorted(dictNodelist, reverse=False)
|
||
for BBS in tmpDict:
|
||
count += 1
|
||
if count < offset+1:
|
||
pass
|
||
else:
|
||
R += 1
|
||
if R < screenDepth:
|
||
if barOffset+1 == R:
|
||
gotoxy(1,R)
|
||
write('|21|15')
|
||
C1 = BBS.replace('_',' ').ljust(22)[:22]
|
||
C2 = dictNodelist[BBS]["SYSOP"].replace('_',' ').ljust(15)[:15]
|
||
C3 = dictNodelist[BBS]["LOCATION"].replace('_',' ').ljust(15)[:15]
|
||
C4 = dictNodelist[BBS]["SOFTWARE"].replace('_',' ').ljust(15)[:15]
|
||
try:
|
||
C5 = ratingsDB[BBS]
|
||
except:
|
||
C5 = 0
|
||
thisLine = C1+" "+C2+" "+C3+" "+C4+" "+"|10"+(chr(254)*C5).rjust(7)
|
||
pad = " "*(79-len(thisLine))
|
||
writeln(thisLine.ljust(79)+pad+"|16|07")
|
||
|
||
def drawWindow(x1, y1, x2, y2, title = ""):
|
||
for Y in range(y1, y2):
|
||
for X in range(x1, x2):
|
||
gotoxy(X, Y); write(' ')
|
||
for I in range(x1+1, x2-1):
|
||
gotoxy(I, y1+1); write('|13'+chr(205))
|
||
gotoxy(I, y2-2); write('|05'+chr(205))
|
||
for I in range(y1+1, y2-1):
|
||
gotoxy(x1+1, I); write('|13'+chr(186))
|
||
gotoxy(x2-1, I); write('|05'+chr(186))
|
||
if title:
|
||
ntitle = "[ |15"+title+"|13 ]"
|
||
ltitle = len(stripmci(ntitle))
|
||
center = ((x2-x1)/2)-(ltitle/2)+x1
|
||
gotoxy(center, y1+1); write('|13'+ntitle)
|
||
gotoxy(x1+1,y1+1); write('|13'+chr(201))
|
||
gotoxy(x2-1,y1+1); write('|13'+chr(187))
|
||
gotoxy(x1+1,y2-2); write('|05'+chr(200))
|
||
gotoxy(x2-1,y2-2); write('|05'+chr(188))
|
||
|
||
def showDetail(BBS):
|
||
write("|SS")
|
||
bbs = BBS.replace('_',' ')[:22]
|
||
sysop = dictNodelist[BBS]["SYSOP"].replace('_',' ')
|
||
location = dictNodelist[BBS]["LOCATION"].replace('_',' ')
|
||
software = dictNodelist[BBS]["SOFTWARE"]
|
||
#rating = dictNodelist[BBS]["RATING"]
|
||
try:
|
||
rating = ratingsDB[BBS]
|
||
except:
|
||
rating = 0
|
||
address = dictNodelist[BBS]["ADDRESS"]
|
||
port = dictNodelist[BBS]["PORT"]
|
||
node_addresses = dictNodelist[BBS]["NODE_ADDRESSES"]
|
||
drawWindow(15,4,65,20,bbs)
|
||
|
||
gotoxy(18,7); write("|13BBS SysOp")
|
||
gotoxy(18,8); write('|15'+sysop)
|
||
gotoxy(51,7); write("|13BBS Location")
|
||
gotoxy(41,8); write('|15'+location.rjust(22))
|
||
|
||
gotoxy(18,10); write("|13BBS Address")
|
||
gotoxy(18,11); write('|15'+address+':'+str(port))
|
||
gotoxy(51,10); write("|13BBS Software")
|
||
gotoxy(41,11); write('|15'+software.rjust(22))
|
||
|
||
gotoxy(18,14); write("|13Node Address(es)")
|
||
count = 0
|
||
row = 1
|
||
for node_address in node_addresses:
|
||
count += 1
|
||
if count > 3:
|
||
count = 1
|
||
row += 1
|
||
gotoxy(6+(count*12), 14+row); write('|15'+node_address)
|
||
|
||
gotoxy(18,18); write("|13[ |15Q to go back |13]")
|
||
gotoxy(35,18); write("|13[ |10"+(chr(254)*rating).ljust(7)+" |13]")
|
||
gotoxy(47,18); write("|13[ |15C to connect |13]")
|
||
gotoxy(1,25);
|
||
canend = "no"
|
||
while not canend == "yes":
|
||
ch = onekey(chr(13) + 'CQ'+KEY_RIGHT+KEY_LEFT, False)
|
||
if ch == 'Q':
|
||
canend = "yes"
|
||
if ch == 'C':
|
||
if address and "Private" not in address:
|
||
write('|SS'); write('|CL')
|
||
menucmd('IT','/addr='+address+' /port='+str(port))
|
||
write('[0;26 D'); write('|RS')
|
||
if ch == KEY_LEFT:
|
||
if rating > 0:
|
||
rating -= 1
|
||
ratingsDB[BBS] = rating
|
||
saveDB()
|
||
gotoxy(35,18); write("|13[ |10"+(chr(254)*rating).ljust(7)+" |13]")
|
||
if ch == KEY_RIGHT:
|
||
if rating < 7:
|
||
rating += 1
|
||
ratingsDB[BBS] = rating
|
||
saveDB()
|
||
gotoxy(35,18); write("|13[ |10"+(chr(254)*rating).ljust(7)+" |13]")
|
||
write("|RS")
|
||
|
||
def mainMenu():
|
||
global barOffset, offset, highlightedBBS
|
||
maxOffset = len(dictNodelist)-screenDepth-1
|
||
finished = "no"
|
||
highlightedBBS = getBBS(barOffset, offset)
|
||
showList(offset)
|
||
char, extended = getkey()
|
||
|
||
if extended:
|
||
if char == KEY_UP:
|
||
if barOffset > 1:
|
||
barOffset -= 1
|
||
if barOffset == 1:
|
||
if offset > 0:
|
||
offset -= 1
|
||
highlightedBBS = getBBS(barOffset, offset)
|
||
if char == KEY_DOWN:
|
||
if barOffset < screenDepth-2:
|
||
barOffset += 1
|
||
elif barOffset > screenDepth-3:
|
||
if offset < maxOffset:
|
||
offset += 1
|
||
highlightedBBS = getBBS(barOffset, offset)
|
||
if char == KEY_LEFT:
|
||
if offset > screenDepth-3:
|
||
offset -= screenDepth-3
|
||
else:
|
||
offset = 0
|
||
highlightedBBS = getBBS(barOffset, offset)
|
||
if char == KEY_RIGHT:
|
||
if offset < maxOffset - (screenDepth-3):
|
||
offset += screenDepth-3
|
||
else:
|
||
offset = maxOffset
|
||
highlightedBBS = getBBS(barOffset, offset)
|
||
else:
|
||
if char == KEY_ENTER:
|
||
showDetail(highlightedBBS)
|
||
if char == KEY_ESCAPE:
|
||
finished = "yes"
|
||
return finished
|
||
|
||
loadDB()
|
||
initNodelist()
|
||
offset = 0
|
||
init()
|
||
highlightedBBS = getBBS(0, 0)
|
||
while canexit == "no":
|
||
canexit = mainMenu()
|