Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Search Gists
Sign in Sign up

Instantly share code, notes, and snippets.

@grisha765
CreatedJuly 18, 2025 15:03
    • Star(1)You must be signed in to star a gist
    • Fork(0)You must be signed in to fork a gist
    Save grisha765/0197d0b1fcbcc591e74539a9309845df to your computer and use it in GitHub Desktop.
    A script for automatically sending photos from a camera via FTP, created for cameras that send photos to an FTP server.
    #!/usr/bin/env -S uv run --script
    # /// script
    # dependencies = ["httpx", "pyftpdlib"]
    # ///
    importos
    importmimetypes
    importtempfile
    importlogging
    logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    )
    importhttpx
    frompyftpdlib.authorizersimportDummyAuthorizer
    frompyftpdlib.handlersimportFTPHandler
    frompyftpdlib.serversimportFTPServer
    topic=os.getenv("FTP_PASSWORD")
    ftp_port=int(os.getenv("FTP_PORT",2121))
    passive_ports=os.getenv("PASSIVE_PORTS")
    masquerade_address=os.getenv("MASQUERADE_ADDRESS")
    ntfy_url=os.getenv("NTFY_URL","https://ntfy.sh")
    classImageForwardHandler(FTPHandler):
    defon_file_received(self,file_path):
    ext=os.path.splitext(file_path)[1].lower()
    ifextnotin {".png",".jpg",".jpeg"}:
    logging.info("Ignoring non‑image file: %s",file_path)
    os.remove(file_path)
    return
    content_type= (
    mimetypes.guess_type(file_path)[0]or"application/octet-stream"
    )
    filename=os.path.basename(file_path)
    url=f"{ntfy_url.rstrip('/')}/{topic}"
    try:
    withopen(file_path,"rb")asfh:
    payload=fh.read()
    headers= {
    "Title":"The camera detect movement!",
    "Filename":filename,
    "Content-Type":content_type,
    "Priority":"max"
    }
    logging.info("Forwarding %s to %s",filename,url)
    response=httpx.put(
    url,
    content=payload,
    headers=headers,
    timeout=10,
    )
    response.raise_for_status()
    logging.info("ntfy response: %s",response.status_code)
    exceptExceptionasexc:
    logging.exception("Failed to forward %s: %s",filename,exc)
    finally:
    os.remove(file_path)
    defmain():
    ifnottopic:
    raiseRuntimeError("Set FTP_PASSWORD environment variable")
    homedir=tempfile.gettempdir()
    authorizer=DummyAuthorizer()
    authorizer.add_user(
    "user",
    topic,
    homedir=homedir,
    perm="elradfmw",
    )
    handler=ImageForwardHandler
    handler.authorizer=authorizer
    handler.banner="FTP to ntfy bridge ready."
    ifpassive_ports:
    try:
    start,end=map(int,passive_ports.split("-"))
    handler.passive_ports=range(start,end+1)
    logging.info("Passive port range: %d-%d",start,end)
    exceptValueError:
    raiseRuntimeError("Invalid PASSIVE_PORTS format, expected START-END")
    ifmasquerade_address:
    handler.masquerade_address=masquerade_address
    logging.info("Masquerade address: %s",masquerade_address)
    address= ("0.0.0.0",ftp_port)
    server=FTPServer(address,handler)
    logging.info("Starting FTP server on %s:%s",*address)
    logging.info("ntfy topic URL: %s/%s",ntfy_url.rstrip("/"),topic)
    server.serve_forever()
    if__name__=="__main__":
    main()
    Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

    [8]ページ先頭

    ©2009-2025 Movatter.jp