def main(): worldMain = zookeeper.Zookeeper(sys.argv[1]) for i in range(2, len(sys.argv) - 1): worldSub = zookeeper.Zookeeper(sys.argv[i]) boardOffsetMain = worldMain.world.total_boards for idx in range(0, worldSub.world.total_boards): boardSub: zookeeper.Board = worldSub.boards[idx] # transpose board IDs if boardSub.board_north > 0: boardSub.board_north += boardOffsetMain if boardSub.board_south > 0: boardSub.board_south += boardOffsetMain if boardSub.board_west > 0: boardSub.board_west += boardOffsetMain if boardSub.board_east > 0: boardSub.board_east += boardOffsetMain for statIdx in range(0, boardSub.stat_count): stat: zookeeper.Stat = boardSub.stats[statIdx] element: zookeeper.Element = boardSub.elements[( stat.x - 1 + ((stat.y - 1) * 60))] # Passage if element.id == 11: stat.param3 = stat.param3 + boardOffsetMain # append worldMain.boards.append(boardSub) worldMain.world._total_boards += worldSub.world._total_boards worldMain.save(sys.argv[-1])
def main(): pk = int(input("File ID: ")) f = File.objects.get(pk=pk) print("Selected:", f) zf = zipfile.ZipFile(f.phys_path()) file_list = zf.namelist() to_rip = [] for fname in file_list: if fname.upper().endswith(".COM"): to_rip.append(fname) print("Found {} font(s)".format(len(to_rip))) if to_rip: for font_file in to_rip: padded_id = ("0000" + str(f.id))[-4:] museum_name = padded_id + "-" + font_file[:-4] + ".png" museum_path = os.path.join(SITE_ROOT, "museum_site", "static", "images", "charsets", museum_name) print("Ripping", font_file, "as", museum_name) zf.extract(font_file, path=TEMP_PATH) z = zookeeper.Zookeeper() z.export_font(os.path.join(TEMP_PATH, font_file), museum_path) print("Wrote", museum_path) print("Removing", font_file) os.remove(os.path.join(TEMP_PATH, font_file)) print("Done.")
def extract_font(request, pk): data = {"title": "Extract Font"} f = File.objects.get(pk=pk) data["file"] = f zip_file = zipfile.ZipFile(f.phys_path()) data["files"] = zip_file.namelist() data["files"].sort(key=str.lower) if request.GET.get("font"): # Extract the file zip_file.extract(request.GET["font"], path=DATA_PATH) try: f_id = ("0000" + str(f.id))[-4:] z = zookeeper.Zookeeper() z.export_font( os.path.join(DATA_PATH, request.GET["font"]), os.path.join(CHARSET_PATH, "{}-{}.png".format(f_id, f.filename[:-4])), 1) data["result"] = "Ripped {}-{}.png".format(f_id, f.filename[:-4]) except Exception as e: data["result"] = "Could not rip font!" print(e) # Remove the file os.remove(os.path.join(DATA_PATH, request.GET["font"])) return render(request, "museum_site/tools/extract_font.html", data)
def main(): files = File.objects.all().order_by("letter", "title") z = zookeeper.Zookeeper() for f in files: #print(f.letter, f.filename) try: zf = zipfile.ZipFile("/var/projects/museum/zgames/" + f.letter + "/" + f.filename) except (FileNotFoundError, zipfile.BadZipFile): print("\tSkipping due to bad zip") continue file_list = zf.namelist() for file in file_list: name, ext = os.path.splitext(file) ext = ext.upper() if ext == ".COM": # Com File means a font to rip zf.extract(file, path="/var/projects/museum/tools/extract") # Rip the font fname = os.path.join("/var/projects/museum/tools/extract", file) try: id = ("0000" + str(f.id))[-4:] z.export_font(fname, "fonts/" + id + "-" + name + ".png", 1) print("Ripped", file, "as", f.id) except: print("Could not rip", file) return True
def generate_screenshot(self, world=None, board=0, font=None, filename=None): # Get zip contents zf = zipfile.ZipFile(self.phys_path()) # Guess the earliest dated world with a ZZT extension if world is None: all_files = zf.infolist() worlds = [] for f in all_files: if (f.filename.lower().endswith(".zzt")): worlds.append(f) if worlds: worlds = sorted(worlds, key=zipinfo_datetime_tuple_to_str) world = worlds[0].filename if world is None: return False # Name the screenshot if filename is None or filename == "": self.screenshot = self.filename[:-4] + ".png" else: self.screenshot = filename # Extract the file and render try: zf.extract(world, path=SITE_ROOT + "/museum_site/static/data/") except NotImplementedError: return False z = zookeeper.Zookeeper(SITE_ROOT + "/museum_site/static/data/" + world) z.boards[board].screenshot(self.screenshot_phys_path()[:-4], title_screen=(not bool(board))) self.save() # Delete the extracted world # TODO: This leaves lingering folders for zips in folders os.remove(SITE_ROOT + "/museum_site/static/data/" + world) # Optimize the image optimize_image(self.screenshot_phys_path()) return True
def test_new_world_against_kevedit(self): z = zookeeper.Zookeeper() z.new_world(engine="ZZT", name="BLANK-KE") self.assertEqual(z.save(os.path.join("output", "BLANK-ZK.zzt")), True) # Compare md5s with open(os.path.join("resources", "BLANK-KE.zzt"), "rb") as fh: kev_blank = fh.read() kev_md5 = hashlib.md5(kev_blank).hexdigest() with open(os.path.join("output", "BLANK-ZK.zzt"), "rb") as fh: zoo_blank = fh.read() zoo_md5 = hashlib.md5(zoo_blank).hexdigest() self.assertEqual(kev_md5, zoo_md5) os.remove(os.path.join("output", "BLANK-ZK.zzt"))
def main(): # TODO: Comment this path = sys.argv[-1] filename = os.path.basename(path) print(path) zoo = zookeeper.Zookeeper(path) for board in zoo.boards: print("=" * 80) print(board.title) print("-" * 80) for stat in board.stats: if stat.oop_length: print(stat.oop) return True
def test_font_export(self): z = zookeeper.Zookeeper() z.export_font(os.path.join("resources", "INVERTED.COM"), os.path.join("output", "cp437-inverted.png")) # Compare the generated PNG with the original. path = os.path.join("..", "zookeeper", "charsets", "cp437-inverted.png") with open(path, "rb") as source_fh: source_png = source_fh.read() path = os.path.join("output", "cp437-inverted.png") with open(path, "rb") as test_fh: test_png = test_fh.read() self.assertEqual(source_png, test_png, "Charset PNGs do not match.")
def test_new_world(self): z = zookeeper.Zookeeper() key_dict = {"Blue": True, "Purple": True, "White": True} z.new_world(engine="ZZT", health=255, ammo=32, torches=8, gems=4, score=2, keys=key_dict) self.assertEqual(z.world.engine, "ZZT") self.assertEqual(z.world.health, 255) self.assertEqual(z.world.ammo, 32) self.assertEqual(z.world.torches, 8) self.assertEqual(z.world.gems, 4) self.assertEqual(z.world.score, 2) self.assertEqual(z.world.keys["Purple"], True) self.assertEqual(z.world.keys.get("Yellow", False), False)
def generate_screenshot(self, world=None, board=0, font=None): # Get zip contents zf = zipfile.ZipFile(self.phys_path()) # Guess the earliest dated world with a ZZT extension if world is None: all_files = zf.infolist() worlds = [] for f in all_files: if ( f.file_size < UPLOAD_CAP and f.filename.lower().endswith(".zzt") ): worlds.append(f) sorted(worlds, key=lambda k: k.date_time) if worlds: world = worlds[0].filename if world is None: return False # Extract the file and render zf.extract(world, path=SITE_ROOT + "/museum_site/static/data/") z = zookeeper.Zookeeper(SITE_ROOT + "/museum_site/static/data/" + world) z.boards[board].screenshot( SITE_ROOT + "/museum_site/static/images/screenshots/" + self.letter + "/" + self.filename[:-4], title_screen=(not bool(board)) ) self.screenshot = self.filename[:-4] + ".png" self.save() # Delete the extracted world # TODO: This leaves lingering folders for zips in folders os.remove(SITE_ROOT + "/museum_site/static/data/" + world) return True
def main(): file1 = sys.argv[-2] file2 = sys.argv[-1] # Open the worlds z1 = zookeeper.Zookeeper(file1) z2 = zookeeper.Zookeeper(file2) # Compare worlds attrs = [ "_total_boards", "current_board", "_world_name", "health", "ammo", "torches", "gems", "score", "unused", "keys" ] print(" " * 20, z1.meta.file_name.ljust(20), z2.meta.file_name) for attr in attrs: attrib_name = attr.ljust(20) print(attrib_name, end=" ") print(str(getattr(z1.world, attr)).ljust(20), end=" ") print(str(getattr(z2.world, attr)).ljust(20), end=" ") if getattr(z1.world, attr) != getattr(z2.world, attr): print("MISMATCH", end=" ") #input("\nPress Enter to continue...") print("") print("=" * 78) # Compare board names print(z1.meta.file_name.ljust(40), z2.meta.file_name) for idx in range(0, max(z1.world.total_boards, z2.world.total_boards)): if idx < len(z1.boards): print(z1.boards[idx].title.ljust(40), end=" ") else: print(" " * 40, end=" ") if idx < len(z2.boards): print(z2.boards[idx].title.ljust(40), end=" ") else: print(" " * 40, end=" ") if idx >= len(z1.boards) or idx >= len(z2.boards): print("MISMATCH", end=" ") elif z1.boards[idx].title != z2.boards[idx].title: print("MISMATCH", end=" ") #input("\nPress Enter to continue...") print("") print("=" * 78) # Compare board RLE data for idx in range(0, max(z1.world.total_boards, z2.world.total_boards)): if idx < len(z1.boards): print(z1.boards[idx].title.ljust(40), end=" ") else: print(z2.boards[idx].title.ljust(40), end=" ") if idx < len(z1.boards): wip = md5() wip.update(str(z1.boards[idx].rle_elements).encode()) z1_board_md5 = wip.hexdigest() else: z1_board_md5 = " " * 32 if idx < len(z2.boards): wip = md5() wip.update(str(z2.boards[idx].rle_elements).encode()) z2_board_md5 = wip.hexdigest() else: z2_board_md5 = " " * 32 print(z1_board_md5, end=" ") print(z2_board_md5, end=" ") if z1_board_md5 != z2_board_md5: print("RLE ENCODING MISMATCH", end="") #input("\nPress Enter to continue...") print("") """ This works, but by using addresses as soon as one board is different all following boards will automatically be different as well. # Compare board content attrs = [ "size", "start_address", "element_address", "stats_address" ] for idx in range(0, z2.world.total_boards): print("-" * 78) print(z1.boards[idx].title) for attr in attrs: attrib_name = attr.ljust(20) print(attrib_name, end=" ") print(str(getattr(z1.boards[idx], attr)).ljust(20), end=" ") print(str(getattr(z2.boards[idx], attr)).ljust(20), end=" ") if getattr(z1.boards[idx], attr) != getattr(z2.boards[idx], attr): print("MISMATCH", end=" ") #input("\nPress Enter to continue...") print("") """ return True
def main(): # 7,19 through 35,23. 29x5 workable area, x=21 is center) init_lines = [] title1 = input("Line 1 (game title): ") init_lines.append(title1) title2 = input("Line 1 (game title 2): ") init_lines.append(title2) author = input("Line 3 (author): ") init_lines.append(author) company = input("Line 4 (company): ") init_lines.append(company) year = input("Line 5 (year): ") init_lines.append("-" + year + "-") # Center the text lines = [] for line in init_lines: while len(line) < 29: line = " " + line + " " lines.append(line[:29]) print(lines) # Open the world z = zookeeper.Zookeeper("/mnt/ez/486/ZZT/projects/WoZZT.zzt") # Find the board b = None for board in z.boards: if board.title == "Stream Intro": b = board break # Set coordinates x, y = (7, 19) # Begin writing elements for line in lines: for character in line: e = board.get_element((x, y)) # Write the element to the board e.id = 53 e.character = ord(character) e.color_id = ord(character) x += 1 x = 7 y += 1 # Save z.save() b.screenshot("/mnt/ez/pictures/streaming/intro") # Text overlay with open("/mnt/ez/documents/wozzt/stream_text.txt", "w") as fh: fh.write(title1 + " " + title2 + "\n") fh.write("By: " + author + "\n") fh.write(year) # Youtube Description with open("/mnt/ez/documents/wozzt/youtube_desc.txt", "w") as fh: letter = input("Letter for play/view URLS: ").lower() filename = input("Filename play/view URLS (with extension): ") formatted = YOUTUBE_DESC.format( title=(title1 + " " + title2).strip(), author=author, year=year, letter=letter, filename=filename ) fh.write(formatted) return True
def main(): # TODO: Comment this # Parse config parser = argparse.ArgumentParser(description="ZZT-OOP Code Search") parser.add_argument("-i", "--ignore-case", help="ignore the case of letters in the expression", action="store_true") parser.add_argument("-l", "--objects-with-matches", help="print the name of a matching object rather than \ any matched lines", action="store_true") parser.add_argument("file") parser.add_argument("expression") args = parser.parse_args() if args.ignore_case: regex = re.compile(args.expression, re.I) else: regex = re.compile(args.expression) zoo = zookeeper.Zookeeper(args.file) row = "+-------+-------------------------+" + ("-" * 44) + "+" print(row) if args.objects_with_matches: print("| COORD | BOARD | ELEMENT" + (" " * 36) + "|") else: print("| COORD | BOARD | LINE" + (" " * 39) + "|") print(row) for board in zoo.boards: known_matches = [] for stat in board.stats: if stat.oop_length: for line in stat.oop.split("\n"): if re.search(regex, line) is not None: if (args.objects_with_matches and (stat.x, stat.y) in known_matches): continue x = str(stat.x).zfill(2) y = str(stat.y).zfill(2) title = (board.title + (" " * 40))[:23] line = (line + (" " * 42))[:42] if args.objects_with_matches: known_matches.append((stat.x, stat.y)) if stat.oop[0][0] == "@": name = stat.oop[:stat.oop.find("\n")] else: name = board.get_element( (stat.x, stat.y)).name.title() name = (name + (" " * 42))[:42] print("|", "{},{}".format(x, y), "|", title, "|", name, "|") else: print("|", "{},{}".format(x, y), "|", title, "|", line, "|") print(row) return True
def calculate_boards(self): if self.is_uploaded(): return False self.playable_boards = None self.total_boards = None temp_playable = 0 temp_total = 0 zip_path = os.path.join(SITE_ROOT, "zgames", self.letter, self.filename) temp_path = os.path.join(SITE_ROOT, "temp") try: zf = zipfile.ZipFile(zip_path) except (FileNotFoundError, zipfile.BadZipFile): print("Skipping due to bad zip") return False file_list = zf.namelist() for file in file_list: name, ext = os.path.splitext(file) ext = ext.upper() if file.startswith("__MACOSX"): # Don't count OSX info files continue if ext == ".ZZT": # ZZT File # Extract the file try: zf.extract(file, path=temp_path) except: print("Could not extract {}. Aborting.".format(file)) return False else: continue z = zookeeper.Zookeeper( os.path.join(temp_path, file) ) to_explore = [] accessible = [] # Start with the starting board to_explore.append(z.world.current_board) false_positives = 0 for idx in to_explore: # Make sure the board idx exists in the file # (in case of imported boards with passages) if idx >= len(z.boards): false_positives += 1 continue # print(to_explore) # This board is clearly accessible accessible.append(idx) # Get the connected boards via edges if z.boards[idx].board_north != 0 and z.boards[idx].board_north not in to_explore: to_explore.append(z.boards[idx].board_north) if z.boards[idx].board_south != 0 and z.boards[idx].board_south not in to_explore: to_explore.append(z.boards[idx].board_south) if z.boards[idx].board_east != 0 and z.boards[idx].board_east not in to_explore: to_explore.append(z.boards[idx].board_east) if z.boards[idx].board_west != 0 and z.boards[idx].board_west not in to_explore: to_explore.append(z.boards[idx].board_west) # Get the connected boards via passages for stat in z.boards[idx].stats: # print("ON BOARD IDX", idx) try: stat_name = z.boards[idx].get_element((stat.x, stat.y)).name if stat_name == "Passage": # print("Found a passage at", stat.x, stat.y) if stat.param3 not in to_explore: to_explore.append(stat.param3) except IndexError: # Zookeeper raises this on corrupt boards continue # Title screen always counts (but don't count it twice) if 0 not in to_explore: to_explore.append(0) temp_playable += len(to_explore) - false_positives temp_total += len(z.boards) # Delete the extracted file from the temp folder os.remove(os.path.join(temp_path, file)) # Use null instead of 0 to avoid showing up in searches w/ board limits if self.playable_boards == 0: self.playable_boards = None else: self.playable_boards = temp_playable if self.total_boards == 0: self.total_boards = None else: self.total_boards = temp_total return True
def set_screenshot(request, pk): """ Returns page to generate and set a file's screenshot """ data = { "title": "Set Screenshot", } file = File.objects.get(pk=pk) data["file"] = file data["file_list"] = [] if not HAS_ZOOKEEPER: return HttpResponse("Zookeeper library not found.") with ZipFile(SITE_ROOT + file.download_url(), "r") as zf: all_files = zf.namelist() for f in all_files: if f.lower().endswith(".zzt"): data["file_list"].append(f) data["file_list"].sort() if request.GET.get("file"): with ZipFile(SITE_ROOT + file.download_url(), "r") as zf: zf.extract(request.GET["file"], path=SITE_ROOT + "/museum_site/static/data/") z = zookeeper.Zookeeper(SITE_ROOT + "/museum_site/static/data/" + request.GET["file"]) data["board_list"] = [] for board in z.boards: print(board.title) data["board_list"].append(board.title) if request.GET.get("board"): data["board_num"] = int(request.GET["board"]) if data["board_num"] != 0: z.boards[data["board_num"]].screenshot( SITE_ROOT + "/museum_site/static/data/temp") else: z.boards[data["board_num"]].screenshot( SITE_ROOT + "/museum_site/static/data/temp", title_screen=True) data["show_preview"] = True if request.POST.get("save"): src = SITE_ROOT + "/museum_site/static/data/temp.png" dst = SITE_ROOT + "/museum_site/static/images/screenshots/" + file.letter + "/" + file.filename[: -4] + ".png" shutil.copyfile(src, dst) file.screenshot = file.filename[:-4] + ".png" file.save() elif request.POST.get("b64img"): raw = request.POST.get("b64img").replace("data:image/png;base64,", "", 1) from io import BytesIO import base64 image = Image.open(BytesIO(base64.b64decode(raw))) image = image.crop((0, 0, 480, 350)) image.save(SITE_ROOT + "/museum_site/static/images/screenshots/" + file.letter + "/" + file.filename[:-4] + ".png") if os.path.isfile(SITE_ROOT + "/museum_site/static/data/" + request.GET.get("file", "")): os.remove(SITE_ROOT + "/museum_site/static/data/" + request.GET["file"]) return render(request, "museum_site/tools/set_screenshot.html", data)
def roll(self, category="wozzt", title_screen=False): self.uuid = str(uuid.uuid4()) self.category = category qs = File.objects.wozzt().order_by("?") # Find first non-banned file for f in qs: if f.id not in BANNED_FILES: self.file_id = f.id break # Select a random ZZT file in the zip zf = zipfile.ZipFile(f.phys_path()) files = zf.namelist() files.sort() world_choices = [] for f in files: filename = f.lower() if filename.endswith(".zzt") and ("__MACOSX" not in filename): world_choices.append(f) if not world_choices: record("WOZZT_QUEUE.PY: World choices was empty for", self.file_id) return False selected = random.choice(world_choices) self.zzt_file = selected # Extract it try: zf.extract(selected, TEMP_PATH) except NotImplementedError: record("WOZZT_QUEUE.PY: Failed to extract using file #", self.file_id) return False # Parse the world with Zookeeper z = zookeeper.Zookeeper(os.path.join(TEMP_PATH, selected)) # Select a random board (unless it's meant for Tuesday) if title_screen: board_possibilities = [0] else: board_possibilities = list(range(0, len(z.boards))) # Remove banned boards from list of possibilities banned_boards_key = str(self.file_id) + ":" + self.zzt_file if BANNED_BOARDS.get(banned_boards_key): banlist = BANNED_BOARDS[banned_boards_key] for idx in banlist[::-1]: board_possibilities.pop(idx) # Remove banned board titles from list of possibilities for idx in board_possibilities: if z.boards[idx].title in BANNED_BOARD_TITLES: try: board_possibilities.remove(idx) except ValueError: None # Already removed earlier if len(board_possibilities) == 0: record("WOZZT_QUEUE.PY: Ran out of board possibilities #", self.file_id) return False board_num = random.choice(board_possibilities) z.boards[board_num].screenshot(os.path.join(SITE_ROOT, "museum_site", "static", "wozzt-queue", self.uuid), title_screen=(board_num == 0)) self.board = board_num self.board_name = z.boards[board_num].title # Board properties # Dark if z.boards[board_num].is_dark: self.dark = True # Zap if z.boards[board_num].zap: self.zap = True # Can fire self.shot_limit = z.boards[board_num].can_fire # Time limit self.time_limit = z.boards[board_num].time_limit self.save() return True
def setUp(self): self.z = zookeeper.Zookeeper() self.z.load_file(os.path.join("resources", "ZOOKEEPR.zzt")) self.z.parse_world()
def worlds_of_zzt(request): if not HAS_ZOOKEEPER: return server_error_500(request) # Timestamp ts = int(time()) if request.GET.get("category") == "discord": entry = WoZZT_Queue.objects.filter( category="discord" ).order_by("-priority", "id").first() img_path = entry.image_path() f = entry.file selected = entry.zzt_file title = entry.board_name board_num = entry.board # Convert the image to base64 with open(img_path, "rb") as fh: data = fh.read() b64 = base64.b64encode(data).decode("utf-8") # Roll the next image WoZZT_Queue().roll(category="discord") entry.delete_image() entry.delete() else: # Select a randomly displayable file f = File.objects.filter(details__in=[DETAIL_ZZT]).exclude(details__in=[DETAIL_UPLOADED, DETAIL_GFX]).order_by("?")[0] # Open it zh = zipfile.ZipFile(f.phys_path()) # Find available ZZT worlds contents = zh.namelist() contents.sort() world_choices = [] for content in contents: filename = content.lower() if filename.endswith(".zzt"): world_choices.append(content) # Select a world and extract it selected = random.choice(world_choices) zh.extract(selected, TEMP_PATH) # Parse the world with Zookeeper z = zookeeper.Zookeeper(os.path.join(TEMP_PATH, selected)) board_num = random.randint(0, len(z.boards) - 1) img_path = os.path.join(TEMP_PATH, str(ts)) z.boards[board_num].screenshot(img_path, title_screen=(board_num == 0), format="RGB") title = z.boards[board_num].title # Convert the image to base64 with open(img_path + ".png", "rb") as fh: data = fh.read() b64 = base64.b64encode(data).decode("utf-8") # Delete the files os.remove(img_path + ".png") os.remove(os.path.join(TEMP_PATH, selected)) # Check if the file is playable online museum_link = "https://museumofzzt.com" + f.view_url() archive_link = "https://archive.org/details/" + f.archive_name if f.archive_name else None play_link = "https://museumofzzt.com" + f.play_url() output = { "status": "SUCCESS", "IMGPATH": img_path + ".png", "request_time": ts, "data": { "file": f.jsoned(), "world": selected, "board": {"title": title, "number": board_num}, "b64_image": b64, "museum_link": museum_link, "play_link": play_link, "archive_link": archive_link, } } return JsonResponse(output)
def main(): POST = True if "NOPOST" not in sys.argv else False CRON_ROOT = os.path.join(SITE_ROOT, "tools", "crons") ROOT = SITE_ROOT QUEUE = os.path.join(CRON_ROOT, "woz_queue.txt") APRIL = True if datetime.now().strftime("%m-%d") == "04-01" else False # Check if there's anything in the manual queue """ Queue Format: YYYY-MM-DD:HOUR:PK:FILENAME:BOARD Use * for wildcards in dates/hours Keep wildcard dates/hours below specific ones to allow first match 1:45 AM == 9 5:45 AM == 12 8:45 AM == 15 11:45 AM == 18 2:45 PM == 21 5:45 PM == 0 8:45 PM == 3 11:45 PM == 6 """ source = "RANDOM" queue_data = {} output = "" current_date = datetime.now().strftime("%Y-%m-%d") current_hour = datetime.now().strftime("%H") print("DATE/HOUR", current_date, current_hour) if os.path.isfile(QUEUE): with open(QUEUE) as fh: lines = fh.readlines() else: lines = [] for line in lines: line = line.strip() print("LINE", line) if line.strip() != "": date, hour, pk, filename, board = line.split(":") # Do we use this? if (source == "RANDOM") and ((date == "*" or date == current_date) and (hour == "*" or hour == current_hour)): source = "QUEUE" queue_data = {"pk":int(pk), "filename":filename, "board":int(board)} else: # if we don't use it, add it to the output text file output += line + "\n" print("---") # Write the new queue output = output[:-1] with open(QUEUE, "w") as fh: fh.write(output) print("SOURCE IS", source) print("DATA IS", queue_data) if source == "RANDOM": # Select a random zip # - Zip must have a ZZT World in it and be published # - Zip must not have modified graphics qs = File.objects.filter(details__in=[DETAIL_ZZT]).exclude(details__in=[DETAIL_UPLOADED, DETAIL_GFX, DETAIL_LOST], author__icontains="_ry0suke_").order_by("?") # Filter out blacklisted files for file_obj in qs: data = file_obj if data.id not in BLACKLISTED_FILES: break # Pull related articles in preparation of linking them later related_articles = data.articles.filter(published=True).order_by("date") # Select a random ZZT file in the zip zip = zipfile.ZipFile(ROOT + data.download_url()) files = zip.namelist() files.sort() world_choices = [] for file in files: filename = file.lower() if filename.endswith(".zzt"): world_choices.append(file) if not world_choices: abort("ERROR: World choices was empty for", file.id) selected = random.choice(world_choices) print(selected) # Extract it zip.extract(selected, CRON_ROOT) # Figure out if it's Title Screen Tuesday now = datetime.now() if int(now.strftime("%w")) == 2: tuesday = True else: tuesday = False # Parse the world with Zookeeper z = zookeeper.Zookeeper(os.path.join(CRON_ROOT, selected)) # Select a random board (unless it's Tuesday) processing = True board_name = "" bl_key = str(data.id) + ":" + selected # Blacklist key bl = BLACKLISTED_BOARDS.get(bl_key, []) while processing: if tuesday: board_num = 0 processing = False if (0 in BLACKLISTED_BOARDS.get(bl_key, [])): # In case the title screen is blacklisted and it's tuesday tuesday = False processing = True if not tuesday: board_num = random.randint(0, len(z.boards) - 1) # Verify the board isn't a common toolkit if processing and z.boards[board_num].title in BOARD_TITLE_BLACKLIST: continue # Verify the board isn't in the board blacklist if processing and board_num in bl: continue z.boards[board_num].screenshot(CRON_ROOT + "temp", title_screen=(board_num == 0)) board_name = z.boards[board_num].title # Board properties board_properties = [] # Dark if z.boards[board_num].is_dark: board_properties.append("🔦") # Zap if z.boards[board_num].zap: board_properties.append("⚡") # Can fire if z.boards[board_num].can_fire != 255: board_properties.append(str(z.boards[board_num].can_fire) + " 🔫") # Time limit if z.boards[board_num].time_limit != 0: board_properties.append(str(z.boards[board_num].time_limit) + " ⏳") processing = False elif source == "QUEUE": tuesday = False # Pull the zip data = File.objects.get(pk=queue_data["pk"]) selected = queue_data["filename"] board_num = queue_data["board"] # Select the ZZT file in the zip zip = zipfile.ZipFile(ROOT + data.download_url()) # Extract it zip.extract(queue_data["filename"], CRON_ROOT) # Parse the world with Zookeeper z = zookeeper.Zookeeper(os.path.join(CRON_ROOT, queue_data["filename"])) # Render z.boards[queue_data["board"]].screenshot(CRON_ROOT + "temp", title_screen=(queue_data["board"] == 0), dark=APRIL) board_name = z.boards[queue_data["board"]].title # Board properties board_properties = [] # Dark if z.boards[queue_data["board"]].is_dark: board_properties.append("🔦") # Zap if z.boards[queue_data["board"]].zap: board_properties.append("⚡") # Can fire if z.boards[queue_data["board"]].can_fire != 255: board_properties.append(str(z.boards[queue_data["board"]].can_fire) + " 🔫") # Time limit if z.boards[queue_data["board"]].time_limit != 0: board_properties.append(str(z.boards[queue_data["board"]].time_limit) + " ⏳") # Ignore related articles for April 1st TODO -- Make this an Apr. 1 thing related_articles = [] bp = "" if board_properties: bp = " {" for p in board_properties: bp += p + ", " bp = bp[:-2] + "}" # Remove the ZZT file. We're done with it. try: os.remove(os.path.join(CRON_ROOT, selected)) except: abort("Couldn't remove:", selected) # Prepare the posts # Tumblr """ tumblr_post = "<b>{title}</b> by <i>{author}</i>" if data.release_date: tumblr_post += " ({year})" if data.company: tumblr_post += "<br>\nPublished by: {company}" tumblr_post += "<br>\n" tumblr_post += "[{zzt_file}] - {board_title}<br>\n" tumblr_post += "<a href='https://museumofzzt.com{file_url}" tumblr_post += "?file={zzt_file}&board={board_idx}'>Download / Explore {zip_file} " tumblr_post += "on the Museum of ZZT</a><br>\n" if data.archive_name: tumblr_post += "<a href='https://museumofzzt.com{play_url}'>Play Online</a><br>\n" tumblr_post = tumblr_post.format( title=data.title, author=data.author, year=str(data.release_date)[:4], company=data.company, zzt_file=quote(selected), board_title=z.boards[board_num].title, file_url=quote(data.file_url()), board_idx=board_num, zip_file=data.filename, play_url=quote(data.play_url()) ) # Tumblr - Related Articles if len(related_articles) > 0: article_text = "<br>" for article in related_articles[:3]: article_text += "<a href='https://museumofzzt.com{url}'>{text}</a><br>\n" article_text = article_text.format( url=article.url(), text=article.title ) tumblr_post += article_text # Tumblr - Tags tags = ["ZZT", data.author, data.title, data.filename] if tuesday: tags.append("title screen tuesday") print(tumblr_post) client = pytumblr.TumblrRestClient(CONSUMER, SECRET, OAUTH_TOKEN, OAUTH_SECRET) """ if POST: """ print("Posting to tumblr...") print(tags) resp = client.create_photo("worldsofzzt", state="published", tags=tags, caption=tumblr_post, data=(CRON_ROOT + "temp.png")) print(resp) """ # Twitter twitter_post = "https://museumofzzt.com{file_url}" twitter_post += "?file={zzt_file}&board={board_idx}\n" twitter_post += "{title} by {author}" if data.release_date: twitter_post += " ({year})" if data.company: twitter_post += "\nPublished by: {company}" twitter_post += "\n[{zzt_file}] - \"{board_title}\"{board_properties}" if data.archive_name: twitter_post += "\nhttps://museumofzzt.com{play_url}" twitter_post = twitter_post.format( file_url=quote(data.file_url()), zzt_file=quote(selected), board_idx=board_num, board_title=z.boards[board_num].title, board_properties=bp, title=data.title, author=data.author, year=str(data.release_date)[:4], company=data.company, play_url=quote(data.play_url()), ) print(twitter_post) print("Posting to twitter...") # April #if APRIL: # twitter_post = "Room is dark - you need to light a torch!\n" + twitter_post with open(CRON_ROOT + "temp.png", "rb") as imagefile: imagedata = imagefile.read() t_up = Twitter(domain='upload.twitter.com', auth=OAuth(TWITTER_OAUTH_TOKEN, TWITTER_OAUTH_SECRET, TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET)) img1 = t_up.media.upload(media=imagedata)["media_id_string"] t = Twitter(auth=OAuth(TWITTER_OAUTH_TOKEN, TWITTER_OAUTH_SECRET, TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET)) resp = t.statuses.update(status=twitter_post, media_ids=img1, tweet_mode="extended") print(resp) twitter_id = resp.get("id") twitter_img = resp["entities"]["media"][0]["media_url"] # Twitter - Related Articles if len(related_articles) > 0: article_text = "For more related content about \"{title}\", check out:\n".format(title=data.title) for article in related_articles[:3]: article_text += "https://museumofzzt.com" + article.url() + "\n" resp = t.statuses.update(status=article_text, in_reply_to_status_id=twitter_id) # Discord webhook discord_post = "https://twitter.com/worldsofzzt/status/{}\n**{}** by {} ({})\n" if data.company: discord_post += "Published by: {}\n".format(data.company) discord_post += "`[{}] - \"{}\"` {}\n" discord_post += "Explore: https://museumofzzt.com" + quote(data.file_url()) + "?file=" + quote(selected) + "&board=" + str(board_num) + "\n" if data.archive_name: discord_post += "Play: https://museumofzzt.com" + quote(data.play_url()) discord_post = discord_post.format(twitter_id, data.title, data.author, str(data.release_date)[:4], selected, z.boards[board_num].title, bp) discord_data = { "content": discord_post, "embeds": [ {"image": {"url": twitter_img}} ] } resp = requests.post(WEBHOOK_URL, headers={"Content-Type": "application/json"}, data=json.dumps(discord_data)) print(resp) print(resp.content) else: print("DID NOT POST") return True
def main(): mode = "AUTO" while True: print("MODE:", mode) print("Enter AUTO or MANUAL to set mode") print("Generate screenshots for: ") print("ALL - All Files") print("BLANK - Files with no screenshot set") print("UPLOADED - Files that haven't been published") print("<#> - File ID #") print("<[a-z]> - Letter") print("TEMP - Whatever set I coded for this") choice = input("Enter choice: ").upper() if choice == "ALL": files = File.objects.all().order_by("letter", "title") elif choice == "UPLOADED": files = File.objects.filter(details__id__in=[18]) # UPLOADED elif choice == "BLANK": files = File.objects.filter(screenshot="").order_by( "letter", "title") elif choice in ([ "1", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" ]): files = File.objects.filter(letter=(choice.lower())) elif choice == "TEMP": ids = [ 42, 85, 97, 145, 2172, 593, 191, 188, 2116, 303, 314, 352, 365, 382, 1282, 392, 459, 2186, 525, 533, 601, 626, 1245, 674, 133, 966, 688, 689, 776, 758, 799, 848, 859, 1861, 1880, 878, 906, 950, 999, 1690, 1127, 1057, 1051, 1137, 1033, 1034, 1115, 1142, 1124, 3, 709, 1189, 1190, 2146, 1227, 17, 1263, 801, 1284, 1285, 1760, 1315, 1853, 1361, 1360, 1627, 1380, 1387, 1703, 625 ] files = File.objects.filter(id__in=ids) elif choice == "AUTO" or choice == "MANUAL": mode = choice continue else: files = File.objects.filter(pk=int(choice)) break for f in files: print(f.letter, f.filename) try: zf = zipfile.ZipFile("/var/projects/museum/zgames/" + f.letter + "/" + f.filename) except (FileNotFoundError, zipfile.BadZipFile): print("\tSkipping due to bad zip") continue file_list = zf.namelist() zzt_count = 0 zzt_list = [] com_count = 0 com_list = [] oldest_file = None oldest_date = "9999-12-31 23:59:59" for file in file_list: name, ext = os.path.splitext(file) ext = ext.upper() if ext == ".ZZT": # ZZT File zzt_count += 1 zzt_list.append(file) zzt_count += 1 info = zf.getinfo(file) ymd = (str(info.date_time[0]) + "-" + str(info.date_time[1]).zfill(2) + "-" + str(info.date_time[2]).zfill(2) + " " + str(info.date_time[3]).zfill(2) + ":" + str(info.date_time[4]).zfill(2) + ":" + str(info.date_time[5]).zfill(2)) if ymd < oldest_date: oldest_file = file oldest_date = ymd if ext == ".COM": # Com File means a font, and skip com_count += 1 com_list.append(file) continue # Confirm there's a ZZT file if oldest_file is None: print("\tSkipping due to no ZZT file") continue # Extract the file try: zf.extract(oldest_file, path="/var/projects/museum/tools/extract") except: print("\tSkipping due to bad zip to extract") continue if mode == "AUTO": zf.extract(oldest_file, path="/var/projects/museum/tools/extract") # Render the screenshot z = zookeeper.Zookeeper( os.path.join("/var/projects/museum/tools/extract", oldest_file)) z.boards[0].screenshot( ("/var/projects/museum/museum_site/static/images" "/screenshots/{}/{}").format(f.letter, f.filename[:-4]), title_screen=True) elif mode == "MANUAL": use_com = "" if com_list: if len(com_list) == 1: use_com = com_list[0] else: print(com_list) use_com = com_list[int(input("IDX of com file to use: "))] zf.extract(use_com, path="/var/projects/museum/tools/extract") use_zzt = "" print(zzt_list) if len(zzt_list) == 1: use_zzt = zzt_list[0] else: print("Oldest:", oldest_file) use_zzt = zzt_list[int(input("IDX of ZZT file to use: "))] zf.extract(use_zzt, path="/var/projects/museum/tools/extract") if use_com: # Rip the charset z = zookeeper.Zookeeper() ret = z.export_font( "/var/projects/museum/tools/extract/" + use_com, "extract/temp.png") charset = "/var/projects/museum/tools/extract/temp.png" z = zookeeper.Zookeeper( os.path.join("/var/projects/museum/tools/extract", use_zzt), charset) else: # Parse the file z = zookeeper.Zookeeper( os.path.join("/var/projects/museum/tools/extract", use_zzt)) board_idx = int(input("Enter board IDX to render: ")) z.boards[board_idx].screenshot( ("/var/projects/museum/museum_site/static/images" "/screenshots/{}/{}", title).format(f.letter, f.filename[:-4]), title_screen=True) # Update the DB entry f.screenshot = f.filename[:-4] + ".png" f.save() print("SAVED ({})".format(f.screenshot)) return True
def set_screenshot(request, key): """ Returns page to generate and set a file's screenshot """ data = { "title": "Set Screenshot", } zfile = File.objects.get(key=key) data["file"] = zfile data["file_list"] = [] if not HAS_ZOOKEEPER: return HttpResponse("Zookeeper library not found.") with ZipFile(SITE_ROOT + zfile.download_url(), "r") as zf: all_files = zf.namelist() for f in all_files: if f.lower().endswith(".zzt"): data["file_list"].append(f) data["file_list"].sort() if request.POST.get("manual"): upload_path = os.path.join( STATIC_PATH, "images/screenshots/{}/".format(zfile.letter)) file_path = move_uploaded_file(upload_path, request.FILES.get("uploaded_file"), custom_name=zfile.filename[:-4] + ".png") optimize_image(file_path) zfile.screenshot = zfile.filename[:-4] + ".png" zfile.basic_save() if request.GET.get("file"): with ZipFile(SITE_ROOT + zfile.download_url(), "r") as zf: zf.extract(request.GET["file"], path=SITE_ROOT + "/museum_site/static/data/") z = zookeeper.Zookeeper(SITE_ROOT + "/museum_site/static/data/" + request.GET["file"]) data["board_list"] = [] for board in z.boards: data["board_list"].append(board.title) if request.GET.get("board"): data["board_num"] = int(request.GET["board"]) if data["board_num"] != 0: z.boards[data["board_num"]].screenshot( SITE_ROOT + "/museum_site/static/data/temp") else: z.boards[data["board_num"]].screenshot( SITE_ROOT + "/museum_site/static/data/temp", title_screen=True) data["show_preview"] = True image_path = "" if request.POST.get("save"): src = SITE_ROOT + "/museum_site/static/data/temp.png" image_path = zfile.screenshot_phys_path() shutil.copyfile(src, image_path) zfile.screenshot = zfile.filename[:-4] + ".png" zfile.save() elif request.POST.get("b64img"): raw = request.POST.get("b64img").replace("data:image/png;base64,", "", 1) from io import BytesIO import base64 image = Image.open(BytesIO(base64.b64decode(raw))) image = image.crop((0, 0, 480, 350)) image_path = zfile.screenshot_phys_path() if image_path: image.save(image_path) else: image_path = os.path.join( SITE_ROOT + "/museum_site/static/images/screenshots/{}/{}".format( zfile.letter, zfile.filename[:-4]) + ".png") image.save(image_path) zfile.screenshot = zfile.filename[:-4] + ".png" zfile.basic_save() if os.path.isfile(SITE_ROOT + "/museum_site/static/data/" + request.GET.get("file", "")): os.remove(SITE_ROOT + "/museum_site/static/data/" + request.GET["file"]) # Optimize the image optimize_image(image_path) return render(request, "museum_site/tools/set_screenshot.html", data)