Skip to content

Instantly share code, notes, and snippets.

@rgaudin
Created December 9, 2025 10:45
Show Gist options
  • Select an option

  • Save rgaudin/99bb6a0f5663e77d566447732e67968a to your computer and use it in GitHub Desktop.

Select an option

Save rgaudin/99bb6a0f5663e77d566447732e67968a to your computer and use it in GitHub Desktop.
Quick and dirty script to gen a ZIM of a CyberChef release
""" CyberChef to ZIM
Quick and dirty script to gen a ZIM of a CyberChef release
https://gchq.github.io/CyberChef/
"""
# /// script
# dependencies = [
# "zimscraperlib>=5,<6",
# ]
# ///
import argparse
import datetime
import logging
import os
import zipfile
from pathlib import Path
from zimscraperlib.download import stream_file
from zimscraperlib.image.illustration import get_zim_illustration
from zimscraperlib.zim import Creator
from zimscraperlib.zim.creator import mimetype_for
from zimscraperlib.zim.metadata import (
CreatorMetadata,
DateMetadata,
DefaultIllustrationMetadata,
DescriptionMetadata,
LanguageMetadata,
NameMetadata,
PublisherMetadata,
StandardMetadataList,
TitleMetadata,
)
NAME = "cyberchef2zim"
DEFAULT_VERSION = os.getenv("VERSION") or "v10.19.4"
__version__ = "0.1"
__description__ = "Create a ZIM file based on a CyberChef release"
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("NAME")
def entrypoint():
parser = argparse.ArgumentParser(
prog=NAME,
description="Create a ZIM file based on a CyberChef release",
epilog="https://github.com/gchq/CyberChef",
)
parser.add_argument(
"--version",
help="Display scraper version and exit",
action="version",
version=__version__,
)
parser.add_argument(
help="CyberChef release to use. "
"Use actual tag. Use `-` to use defaullt version",
dest="version",
)
args = parser.parse_args()
# Ignore unset values so they do not override the default specified in Context
args_dict = {key: value for key, value in args._get_kwargs() if value}
if args_dict.get("version", "-") == "-":
args_dict["version"] = DEFAULT_VERSION
main(**args_dict)
def main(version: str):
logger.info(f"Building ZIM of {version}")
today = datetime.datetime.today()
name = "gchq.github.io_en_cyberchef"
path = Path(f"{name}_{today.strftime('%Y-%m')}.zim")
# download release
url = f"https://github.com/gchq/CyberChef/releases/download/{version}/CyberChef_{version}.zip"
zip_path = Path(Path(url).name)
if not zip_path.exists():
logger.info(f"Downloading {zip_path} from Github…")
stream_file(url=url, fpath=zip_path)
else:
logger.info(f"{zip_path} present, assuming already downloaded")
homepage = f"CyberChef_{version}.html"
illus_url=f"https://raw.githubusercontent.com/gchq/CyberChef/refs/tags/{version}/src/web/static/images/cyberchef-512x512.png"
illus = get_zim_illustration(illus_url)
with (
Creator(filename=path, main_path="home")
.config_verbose(True)
.config_metadata(
std_metadata=StandardMetadataList(
Name=NameMetadata(name),
Language=LanguageMetadata(["eng"]),
Title=TitleMetadata("CyberChef"),
Creator=CreatorMetadata("GCHQ"),
Publisher=PublisherMetadata("openZIM"),
Date=DateMetadata(today),
Illustration_48x48_at_1=DefaultIllustrationMetadata(illus),
Description=DescriptionMetadata(
"The Swiss Army Knife for encryption, encoding, compression and data analysis"
),
)
) as creator
):
with zipfile.ZipFile(zip_path) as zip:
for fname in zip.namelist():
if fname.endswith("/"):
continue
with zip.open(fname) as file:
if fname == homepage:
creator.add_item_for(
path="home",
content=file.read(),
mimetype="text/html",
is_front=True,
)
else:
creator.add_item_for(
path=fname,
content=file.read(),
mimetype=mimetype_for(path=fname),
is_front=False,
)
if __name__ == "__main__":
entrypoint()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment