Created
December 9, 2025 10:45
-
-
Save rgaudin/99bb6a0f5663e77d566447732e67968a to your computer and use it in GitHub Desktop.
Quick and dirty script to gen a ZIM of a CyberChef release
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ 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