Skip to content

Instantly share code, notes, and snippets.

@0x9900
Last active December 26, 2023 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0x9900/d8b8282c270f2a6910e1cc6e878553d5 to your computer and use it in GitHub Desktop.
Save 0x9900/d8b8282c270f2a6910e1cc6e878553d5 to your computer and use it in GitHub Desktop.
Automatically send QSL cards by calling eqsl
#!/usr/bin/env python
#
# BSD 3-Clause License
# Copyright (c) 2023 Fred W6BSD All rights reserved.
#
"""
`sendcard` is a companion program for e-qsl (https://pypi.org/project/e-qsl/)
This program monitors a directory for an ADIF file and then calls `eqsl`
with the file as an argument.
"""
import logging
import os
import shutil
import sys
from argparse import ArgumentParser
from subprocess import call
from watchfiles import Change, DefaultFilter, watch
DEFAULT_ADIF = 'MacLoggerDX_Export.adi'
DEFAULT_DIR = '/Users/fred/Downloads'
SHOW_CARD = False
KEEP_CARD = False
logging.basicConfig(
format="%(asctime)s %(name)s:%(lineno)d %(levelname)s - %(message)s",
level=logging.INFO
)
wf_log = logging.getLogger('watchfiles.main')
wf_log.setLevel(logging.CRITICAL)
def send_cards(filename: str, show_card: bool, keep_card: bool) -> None:
eqsl:str|None = shutil.which('eqsl')
args:list[str] = [eqsl, '-a', filename]
if eqsl is None:
raise FileNotFoundError('eqsl not found')
if not os.path.exists(filename):
return
if show_card:
args.append('-s')
if keep_card:
args.append('-k')
logging.info('Command: %s', ' '.join(args))
call(args)
class ADIFilter(DefaultFilter):
def __init__(self, directory: str, name: str) -> None:
super().__init__()
self.full_name = os.path.join(directory, name)
def __call__(self, change: Change, path: str) -> bool:
return super().__call__(change, path) and path == self.full_name
def main() -> None:
parser = ArgumentParser(description="DXCC entities lookup")
parser.add_argument("-s", "--show", action="store_true", default=False,
help="Show the card")
parser.add_argument("-k", "--keep", action="store_true", default=False,
help="Keep the card in the temporary directory")
parser.add_argument("-p", "--path", default=DEFAULT_DIR,
help="Path [default: %(default)s]")
parser.add_argument("-a", "--adif", default=DEFAULT_ADIF,
help="ADIF file to watch [default: %(default)s]")
opts = parser.parse_args()
full_name = os.path.join(opts.path, opts.adif)
if os.path.exists(full_name):
logging.info('The ADIF file already exists. Sending cards.')
send_cards(full_name, opts.show, opts.keep)
watch_filter = ADIFilter(opts.path, opts.adif)
logging.info('Sendcards watching %s for %s', opts.path, opts.adif)
for changes in watch(opts.path, watch_filter=watch_filter, debounce=3200, recursive=False):
if Change.deleted in [c for c, _ in changes]:
continue
for _, filename in changes:
logging.info('Calling send_cards with %s', filename)
send_cards(full_name, opts.show, opts.keep)
if __name__ == "__main__":
try:
main()
except (FileNotFoundError, KeyboardInterrupt) as err:
logging.info(err)
sys.exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment