import codecs
import json
import os.path
from .tintin import TinTin
DATABASE_FILE = "data/secret_exits.json"
SAMPLE_DATABASE_FILE = "data/secret_exits.json.sample"
VALID_DIRECTIONS = ["north", "south", "east", "west", "up", "down"]
class Secrets(object):
def __init__(self):
if os.path.exists(DATABASE_FILE):
if not os.path.isdir(DATABASE_FILE):
path = DATABASE_FILE
else:
TinTin.echo("Error: '{0}' is a directory, not a file.".format(DATABASE_FILE), "python")
elif os.path.exists(SAMPLE_DATABASE_FILE):
if not os.path.isdir(SAMPLE_DATABASE_FILE):
path = SAMPLE_DATABASE_FILE
else:
TinTin.echo("Error: '{0}' is a directory, not a file.".format(SAMPLE_DATABASE_FILE), "python")
else:
path = None
TinTin.echo("Error: neither '{0}' nor '{1}' can be found.".format(DATABASE_FILE, SAMPLE_DATABASE_FILE), "mume")
if not path:
self.rooms = {}
else:
try:
with codecs.open(path, "rb", encoding="utf-8") as data:
self.rooms = json.load(data)
except IOError as e:
self.rooms = {}
TinTin.echo("{0}: '{1}'".format(e.strerror, e.filename), "mume")
except ValueError as e:
self.rooms = {}
TinTin.echo("Corrupted file: '{0}'".format(path), "mume")
def uniq(self, lst):
last = object()
for item in lst:
if item != last:
yield item
last = item
def save(self):
with codecs.open(DATABASE_FILE, "wb", encoding="utf-8") as data:
json.dump(self.rooms, data, sort_keys=True, indent=2, separators=(",", ": "))
def info(self, roomName="", searchString=""):
roomName = roomName.strip().lower()
searchString = searchString.strip().lower()
results = []
if searchString:
results.extend([name for name in self.rooms if searchString in name])
elif roomName and roomName in self.rooms:
searchString = roomName
results.append(searchString)
else:
return TinTin.echo("Error! Room undefined.", "mume")
if not results:
TinTin.echo("There aren't any rooms named '{0}' in the database.".format(searchString), "mume")
else:
for result in sorted(results):
exits = []
for door, direction in self.rooms[result]:
if direction:
exits.append("{0} ({1})".format(direction, door))
else:
exits.append("({0})".format(door))
TinTin.echo("{0}: {1}".format(result, ", ".join(exits)), "mume")
def actionAll(self, roomName="", action=""):
roomName = roomName.strip().lower()
if not roomName:
return TinTin.echo("Error! Current room undefined.", "mume")
elif roomName not in self.rooms:
return TinTin.echo("There aren't any rooms named '{0}' in the database.".format(roomName), "mume")
elif not action:
return TinTin.echo("Error! You must specify an action to perform.", "mume")
for door, direction in self.rooms[roomName]:
if direction:
TinTin.send("{0} {1} {2}".format(action, door, direction), "mume")
else:
TinTin.send("{0} {1}".format(action, door), "mume")
def add(self, roomName="", newDoor="", newDirection=""):
roomName = roomName.strip().lower()
newDoor = newDoor.strip().lower()
newDirection = newDirection.strip().lower()
# If the direction name is shortened, expand it to its full form.
newDirection = "".join(dir for dir in VALID_DIRECTIONS if newDirection and dir.startswith(newDirection))
if not roomName:
return TinTin.echo("Error! Current room undefined.", "mume")
elif not newDoor or not newDirection:
return TinTin.echo("Syntax: dadd [door] [{0}]".format("|".join(VALID_DIRECTIONS)), "mume")
elif roomName not in self.rooms:
self.rooms[roomName] = []
TinTin.echo("adding the door '{0}' located '{1}' to '{2}'.".format(newDoor, newDirection, roomName), "mume")
self.rooms[roomName].append([newDoor, newDirection])
self.rooms[roomName].sort(key=lambda room: (VALID_DIRECTIONS.index(room[1]) if room[1] in VALID_DIRECTIONS else len(VALID_DIRECTIONS), room[0]))
self.rooms[roomName] = list(self.uniq(self.rooms[roomName]))
self.save()
def delete(self, roomName="", delDoor="", delDirection=""):
roomName = roomName.strip().lower()
delDoor = delDoor.strip().lower()
delDirection = delDirection.strip().lower()
# If the direction name is shortened, expand it to its full form.
delDirection = "".join(dir for dir in VALID_DIRECTIONS + ["all"] if delDirection and dir.startswith(delDirection))
if not roomName:
return TinTin.echo("Error! Room is undefined.", "mume")
elif roomName not in self.rooms:
return TinTin.echo("Error! The current room isn't in the database.", "mume")
elif not delDoor or not delDirection:
return TinTin.echo("Syntax: ddel [door|all] [{0}|all]".format("|".join(VALID_DIRECTIONS)), "mume")
elif delDoor != "all" and delDirection != "all":
if [delDoor, delDirection] in self.rooms[roomName]:
TinTin.echo("Deleting '{0}' located '{1}' from '{2}'.".format(delDoor, delDirection, roomName), "mume")
self.rooms[roomName].remove([delDoor, delDirection])
else:
return TinTin.echo("'{0}' does not have any exits to the '{1}' with the name '{2}'.".format(roomName, delDirection, delDoor), "mume")
elif delDirection != "all":
# Check to see if the current room has any secrets in the given direction.
if [[door, direction] for door, direction in self.rooms[roomName] if direction == delDirection]:
TinTin.echo("Deleting all exits '{0}' from '{1}'.".format(delDirection, roomName), "mume")
self.rooms[roomName] = [[door, direction] for door, direction in self.rooms[roomName] if direction != delDirection]
else:
return TinTin.echo("'{0}' does not have any exits to the '{1}'.".format(roomName, delDirection), "mume")
elif delDoor != "all":
# Check to see if the current room has any secret doors with the given name.
if [[door, direction] for door, direction in self.rooms[roomName] if door == delDoor]:
TinTin.echo("Deleting all secret doors with the name '{0}' from '{1}'.".format(delDoor, roomName), "mume")
self.rooms[roomName] = [[door, direction] for door, direction in self.rooms[roomName] if door != delDoor]
else:
return TinTin.echo("'{0}' does not have any secret doors called '{1}'.".format(roomName, delDoor), "mume")
if delDoor == "all" and delDirection == "all" or not self.rooms[roomName]:
TinTin.echo("Deleting the room '{0}' from the database.".format(roomName), "mume")
del self.rooms[roomName]
self.save()