diff --git a/scripts/bulk-email/.gitignore b/scripts/bulk-email/.gitignore index 40a82cc2..a9aa0ee8 100644 --- a/scripts/bulk-email/.gitignore +++ b/scripts/bulk-email/.gitignore @@ -1,2 +1,3 @@ .env *.csv +uv.lock diff --git a/scripts/bulk-email/uv.lock b/scripts/bulk-email/uv.lock deleted file mode 100644 index cb4b9d21..00000000 --- a/scripts/bulk-email/uv.lock +++ /dev/null @@ -1,106 +0,0 @@ -version = 1 -revision = 3 -requires-python = ">=3.13" - -[[package]] -name = "boto3" -version = "1.40.55" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "botocore" }, - { name = "jmespath" }, - { name = "s3transfer" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/50/d8/a279c054e0c9731172f05b3d118f3ffc9d74806657f84fc0c93c42d1bb5d/boto3-1.40.55.tar.gz", hash = "sha256:27e35b4fa9edd414ce06c1a748bf57cacd8203271847d93fc1053e4a4ec6e1a9", size = 111590, upload-time = "2025-10-17T19:34:56.753Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/42/8c/559c6145d857ed953536a83f3a94915bbd5d3d2d406db1abf8bf40be7645/boto3-1.40.55-py3-none-any.whl", hash = "sha256:2e30f5a0d49e107b8a5c0c487891afd300bfa410e1d918bf187ae45ac3839332", size = 139322, upload-time = "2025-10-17T19:34:55.028Z" }, -] - -[[package]] -name = "botocore" -version = "1.40.55" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "jmespath" }, - { name = "python-dateutil" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a4/92/dce4842b2e215d213d34b064fcdd13c6a782c43344e77336bcde586e9229/botocore-1.40.55.tar.gz", hash = "sha256:79b6472e2de92b3519d44fc1eec8c5feced7f99a0d10fdea6dc93133426057c1", size = 14446917, upload-time = "2025-10-17T19:34:47.44Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/21/30/f13bbc36e83b78777ff1abf50a084efcc3336b808e76560d8c5a0c9219e0/botocore-1.40.55-py3-none-any.whl", hash = "sha256:cdc38f7a4ddb30a2cd1cdd4fabde2a5a16e41b5a642292e1c30de5c4e46f5d44", size = 14116107, upload-time = "2025-10-17T19:34:44.398Z" }, -] - -[[package]] -name = "bulk-email" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "boto3" }, - { name = "python-dotenv" }, -] - -[package.metadata] -requires-dist = [ - { name = "boto3", specifier = ">=1.40.55" }, - { name = "python-dotenv", specifier = ">=1.1.1" }, -] - -[[package]] -name = "jmespath" -version = "1.0.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/00/2a/e867e8531cf3e36b41201936b7fa7ba7b5702dbef42922193f05c8976cd6/jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe", size = 25843, upload-time = "2022-06-17T18:00:12.224Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/b4/b9b800c45527aadd64d5b442f9b932b00648617eb5d63d2c7a6587b7cafc/jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", size = 20256, upload-time = "2022-06-17T18:00:10.251Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "python-dotenv" -version = "1.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" }, -] - -[[package]] -name = "s3transfer" -version = "0.14.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "botocore" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/62/74/8d69dcb7a9efe8baa2046891735e5dfe433ad558ae23d9e3c14c633d1d58/s3transfer-0.14.0.tar.gz", hash = "sha256:eff12264e7c8b4985074ccce27a3b38a485bb7f7422cc8046fee9be4983e4125", size = 151547, upload-time = "2025-09-09T19:23:31.089Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/48/f0/ae7ca09223a81a1d890b2557186ea015f6e0502e9b8cb8e1813f1d8cfa4e/s3transfer-0.14.0-py3-none-any.whl", hash = "sha256:ea3b790c7077558ed1f02a3072fb3cb992bbbd253392f4b6e9e8976941c7d456", size = 85712, upload-time = "2025-09-09T19:23:30.041Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "urllib3" -version = "2.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, -] diff --git a/scripts/resume-downloader/.env.example b/scripts/resume-downloader/.env.example new file mode 100644 index 00000000..992f3aaf --- /dev/null +++ b/scripts/resume-downloader/.env.example @@ -0,0 +1,10 @@ +ACCOUNT_ID= +ACCESS_KEY_ID= +ACCESS_KEY= +CF= +BUCKET_NAME= +DOWNLOAD_PATH=./resumes +CSV_PATH=./users.csv +EVENT_ID= + + diff --git a/scripts/resume-downloader/.gitignore b/scripts/resume-downloader/.gitignore new file mode 100644 index 00000000..c60ca23c --- /dev/null +++ b/scripts/resume-downloader/.gitignore @@ -0,0 +1,2 @@ +uv.lock +users.csv diff --git a/scripts/resume-downloader/README.md b/scripts/resume-downloader/README.md new file mode 100644 index 00000000..9d83d4b1 --- /dev/null +++ b/scripts/resume-downloader/README.md @@ -0,0 +1,23 @@ +# Resume Downloader + +Simple tool used for gathering all resumes from Cloudflare R2 and saving the file as the user's name. + +## Setup + +1. Clone the repository if you haven't +2. Install dependencies through uv (install uv first) +Run the following: +``` + uv sync +``` + +3. Create a .env file. Copy the environment variables from .env.example + +4. Get a csv file with a structure matching users.csv.example + +## Usage + +### Download all resumes corresponding to csv + +uv run main.py + diff --git a/scripts/resume-downloader/main.py b/scripts/resume-downloader/main.py new file mode 100644 index 00000000..2fb016d0 --- /dev/null +++ b/scripts/resume-downloader/main.py @@ -0,0 +1,53 @@ +import boto3 +import os +import csv +from dotenv import load_dotenv + +load_dotenv() + +ACCOUNT_ID: str = os.getenv("ACCOUNT_ID", "") +ACCESS_KEY_ID: str = os.getenv("ACCESS_KEY_ID", "") +ACCESS_KEY: str = os.getenv("ACCESS_KEY", "") +BUCKET_NAME: str = os.getenv("BUCKET_NAME", "") +DOWNLOAD_PATH: str= os.getenv("DOWNLOAD_PATH", "") +CSV_PATH: str = os.getenv("CSV_PATH", "") +EVENT_ID: str = os.getenv("EVENT_ID", "") + +def download_file_from_r2(client, bucket, key, download_path): + try: + client.download_file(bucket, key, download_path) + except Exception as e: + print(f"Error downloading '{bucket}/{key}': {e}") + return False + +def main(): + try: + s3 = boto3.client( + service_name="s3", + endpoint_url=f"https://{ACCOUNT_ID}.r2.cloudflarestorage.com", + aws_access_key_id=ACCESS_KEY_ID, + aws_secret_access_key=ACCESS_KEY, + # aws_account_id=ACCOUNT_ID, + region_name="auto", + ) + print("R2 client initialized successfully.") + + os.makedirs(os.path.dirname(DOWNLOAD_PATH), exist_ok=True) + + with open(CSV_PATH, mode='r', newline='', encoding='utf-8') as csvfile: + reader = csv.DictReader(csvfile) + folder = EVENT_ID + for row in reader: + id = row['id'].strip() + name = row['name'].strip() + key = f"{folder}/{id}" + filename= f"{DOWNLOAD_PATH}/{name}.pdf" + download_file_from_r2(s3, BUCKET_NAME, key, filename) + print(f"Saved {BUCKET_NAME}/{key}' to {filename}") + + except Exception as e: + print(f"Failed to initialize R2 client or process files: {e}") + +if __name__ == "__main__": + main() + diff --git a/scripts/resume-downloader/pyproject.toml b/scripts/resume-downloader/pyproject.toml new file mode 100644 index 00000000..a0f6ae8a --- /dev/null +++ b/scripts/resume-downloader/pyproject.toml @@ -0,0 +1,10 @@ +[project] +name = "bulk-email" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "python-dotenv>=1.1.1", + "boto3>=1.40.55", +] diff --git a/scripts/resume-downloader/users.csv.example b/scripts/resume-downloader/users.csv.example new file mode 100644 index 00000000..76e6b717 --- /dev/null +++ b/scripts/resume-downloader/users.csv.example @@ -0,0 +1,3 @@ +"id","name", +"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","FirstName_LastName", +