nodelist-browser/mL-nlparse.mpy
2022-05-24 15:28:55 +01:00

447 lines
13 KiB
Plaintext
Executable File
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = ""
filter = ""
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)
KEY_HOME = chr(71)
KEY_END = chr(79)
KEY_PGUP = chr(73)
KEY_PGDN = chr(81)
KEY_QMARK = chr(63)
KEY_BSPACE = chr(8)
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(";") or line.startswith("Hub"):
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
for i in range(0,len(tmp)-1):
if "ITN" in tmp[i]:
if ":" in tmp[i]:
BBS_PORT = tmp[i].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 "EG" 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)
HELP = "|11Help [?]"
lHELP = len(stripmci(HELP))
gotoxy(1,screenDepth)
write(fBG+fFG+" "*screenWidth)
gotoxy((screenWidth/2)-(lMSG/2),screenDepth)
write(MSG)
gotoxy(screenWidth-lHELP,screenDepth); write(HELP)
write(cRESET)
def getBBS(o, s):
global barOffset, filter, fDictSortedLen
selectedBBS = ""
count = 0
tmpDict = sorted(dictNodelist, reverse=False)
fDict = {}
for BBS in tmpDict:
if filter.upper() in BBS.upper():
fDict[BBS] = {}
fDictSorted = sorted(fDict, reverse=False)
fDictSortedLen = len(fDictSorted)
for BBS in fDictSorted:
count += 1
if count == o+s:
selectedBBS = BBS
return selectedBBS
def showList(offset = 0):
global barOffset
global highlightedBBS
global filter
global fDictSortedLen
write('[?1000h')
#gotoxy(68,24); write("|19|11"+str(len(filter))+" ")
position = str(barOffset+offset).rjust(4)+"/"+str(fDictSortedLen).rjust(4)
gotoxy(10,1); write("|19|11["+position+"]")
R = 1
count = 0
gotoxy(1,2)
write("|16|07")
tmpDict = sorted(dictNodelist, reverse=False)
fDict = {}
for BBS in tmpDict:
if filter.upper() in BBS.upper():
fDict[BBS] = {}
fDictSorted = sorted(fDict, reverse=False)
fDictSortedLen = len(fDictSorted)
for BBS in fDictSorted:
count += 1
if count < offset+1:
pass
else:
R += 1
if R < screenDepth:
if barOffset > fDictSortedLen-1:
barOffset = fDictSortedLen
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"].ljust(15)[:15]
if "n/a" in C4:
SPC = "|08"
else:
SPC = ""
try:
C5 = ratingsDB[BBS]
except:
C5 = 0
C5Diff = 7 - C5
C5Text = "|10"+chr(254)*C5+"|08"+chr(254)*C5Diff
thisLine = C1+" "+C2+" "+C3+" "+SPC+C4+" "+C5Text.rjust(7)
pad = " "*(79-len(stripmci(thisLine)))
writeln(thisLine.ljust(79)+pad+"|16|07")
if count < screenDepth-1:
for i in range(count+2, screenDepth):
gotoxy(1,i); write("|[K")
gotoxy(1,24); write("|19|11"+filter.ljust(18)[:18]+"|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-2, 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-2,y1+1); write('|13'+chr(187))
gotoxy(x1+1,y2-2); write('|05'+chr(200))
gotoxy(x2-2,y2-2); write('|05'+chr(188))
def showHelp():
write("|SS")
drawWindow(10,2,70,23,"Help Menu")
gotoxy(13,4); write("|15To use this BBS lister just remember a few simple key")
gotoxy(13,5); write("|15bindings. There aren't many... ")
gotoxy(13,6); write("|15 ")
gotoxy(13,7); write("|15In the LIST view: ")
gotoxy(13,8);write("|15UP/DOWN Arrows move the bar UP/DOWN a line. ")
gotoxy(13,9);write("|15LEFT/RIGHT or PGUP/PGDN moves the list 1 page UP/DN ")
gotoxy(13,10);write("|15ENTER chooses the highlighted BBS to see more detail.")
gotoxy(13,11);write("|15 ")
gotoxy(13,12);write("|15Start typing letters/numbers to live-filter the list!")
gotoxy(13,13);write("|15 ")
gotoxy(13,14);write("|15In the BBS Detail view: ")
gotoxy(13,15);write("|15LEFT/RIGHT allows you to rate the BBS from 0-7 ")
gotoxy(13,16);write("|15If the BBS isn't Private, connect to it by pressing C")
gotoxy(13,17);write("|15To leave the detail view press Q or UP/DOWN arrows. ")
gotoxy(13,18);write("|15 ")
gotoxy(13,19);write("|15To exit the program press ESCAPE at the list view. ")
gotoxy(13,20);write("|15 ")
gotoxy(13,21); write("|PA")
write("|RS")
def showDetail(BBS):
write("|SS")
write('[?1000l')
bbs = BBS.replace('_',' ')[:22]
sysop = dictNodelist[BBS]["SYSOP"].replace('_',' ')
location = dictNodelist[BBS]["LOCATION"].replace('_',' ')
software = dictNodelist[BBS]["SOFTWARE"]
try:
rating = ratingsDB[BBS]
except:
rating = 0
address = dictNodelist[BBS]["ADDRESS"]
if not address:
address = "Unknown"
port = dictNodelist[BBS]["PORT"]
node_addresses = dictNodelist[BBS]["NODE_ADDRESSES"]
drawWindow(15,4,66,21,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)[:22])
gotoxy(18,10); write("|13BBS Address")
gotoxy(18,11); write('|15'+address+':'+str(port))
gotoxy(51,10); write("|13BBS Software")
gotoxy(48,11); write('|15'+software.rjust(15)[:15])
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,19); write("|13[ |15Q to go back |13]")
ratingDiff = 7 - rating
ratingText = "|10"+chr(254)*rating+"|08"+chr(254)*ratingDiff
gotoxy(35,19); write("|13[ "+ratingText.ljust(7)+" |13]")
if address and "Private" not in address and "Unknown" not in address:
gotoxy(47,19); write("|13[ |15C to connect |13]")
else:
gotoxy(47,19); write("|13[ |08C to connect |13]")
gotoxy(1,24);
canend = "no"
while not canend == "yes":
ch = onekey(chr(13) + 'CQ'+KEY_RIGHT+KEY_LEFT+KEY_UP+KEY_DOWN, False)
if ch == 'Q' or ch == KEY_UP or ch == KEY_DOWN:
canend = "yes"
if ch == 'C':
if address and "Private" not in address and "Unknown" not in address:
write('|SS'); write('|[1|CL')
menucmd('IT','/addr='+address+' /port='+str(port))
write('[0;26 D'); write('|RS|[0')
if ch == KEY_LEFT:
if rating > 0:
rating -= 1
ratingsDB[BBS] = rating
saveDB()
ratingDiff = 7 - rating
ratingText = "|10"+chr(254)*rating+"|08"+chr(254)*ratingDiff
gotoxy(35,19); write("|13[ "+ratingText.ljust(7)+" |13]")
if ch == KEY_RIGHT:
if rating < 7:
rating += 1
ratingsDB[BBS] = rating
saveDB()
ratingDiff = 7 - rating
ratingText = "|10"+chr(254)*rating+"|08"+chr(254)*ratingDiff
gotoxy(35,19); write("|13[ "+ratingText.ljust(7)+" |13]")
write("|RS")
def mainMenu():
global barOffset, offset, highlightedBBS, filter, fDictSortedLen
maxOffset = fDictSortedLen-(screenDepth-2)
finished = "no"
highlightedBBS = getBBS(barOffset, offset)
showList(offset)
char, extended = getkey()
if extended:
if char == KEY_UP:
if barOffset > 1:
barOffset -= 1
elif barOffset == 1:
if offset > 0:
offset -= 1
highlightedBBS = getBBS(barOffset, offset)
if char == KEY_DOWN:
if barOffset < fDictSortedLen:
if barOffset < screenDepth-2:
barOffset += 1
elif barOffset > screenDepth-3:
if offset < maxOffset:
offset += 1
highlightedBBS = getBBS(barOffset, offset)
if char == KEY_LEFT or char == KEY_PGUP:
if offset > screenDepth-3:
offset -= screenDepth-3
else:
offset = 0
if barOffset > 1 and offset < 1:
barOffset = 1
highlightedBBS = getBBS(barOffset, offset)
if char == KEY_RIGHT or char == KEY_PGDN:
if fDictSortedLen < screenDepth-2:
barOffset = fDictSortedLen
elif offset < maxOffset - (screenDepth-3):
offset += screenDepth-3
else:
offset = maxOffset
if barOffset < screenDepth-2 and offset > maxOffset-1:
barOffset = screenDepth-2
highlightedBBS = getBBS(barOffset, offset)
if char == KEY_HOME:
barOffset = 1
offset = 0
if char == KEY_END:
if fDictSortedLen < screenDepth-2:
barOffset = fDictSortedLen
else:
barOffset = screenDepth-2
offset = maxOffset
else:
if char == KEY_ENTER:
if fDictSortedLen > 0:
showDetail(highlightedBBS)
elif char == KEY_ESCAPE:
finished = "yes"
elif char == KEY_QMARK:
showHelp()
elif char == KEY_BSPACE:
if len(filter) > 0:
filter = filter[:-1]
else:
if char.isalnum() or char.isspace():
barOffset = 1
offset = 0
if len(filter) < 18:
filter = filter+char.upper().replace(' ', '_')
highlightedBBS = getBBS(barOffset, offset)
return finished
menucmd('NA','sIftIng fOr gOld')
write("|[0")
loadDB()
initNodelist()
offset = 0
init()
highlightedBBS = getBBS(0, 0)
while canexit == "no":
canexit = mainMenu()
write("|[1")
write('[?1000l')