Skip to content

xcode88/campaign_automation

Repository files navigation

Hashbun Campaign Tool

Turn a landing-page PDF (the two-column Canva format, page 1) into a campaign in the Hashbun system, in two monitored steps:

STEP 1  extract   ->   you add dropdown options   ->   STEP 2  review & push

Images are not pushed (you add the logo/hero in the UI afterwards); they are still saved locally for reference.


One-time setup in PyCharm

  1. Open this folder in PyCharm.
  2. Accept the offer to create a virtual environment from requirements.txt (manual: python -m venv .venv, activate, pip install -r requirements.txt).
  3. Copy config.example.py to config.py and paste your Bearer token. config.py is gitignored.

Step 1 — extract

  1. Drop your landing-page PDFs into pdfs/.
  2. Run step1_extract.py.

For each PDF you get output/<uri>/ containing:

  • <uri>.txt — everything extracted, human-readable
  • logo.png, hero.png — the two images (manual upload)
  • _extraction.json — machine state for step 2 (don't edit)
  • one empty options file per detected dropdown, e.g. pays.json

The console lists exactly which dropdown files to fill, with their paths.


Between the steps — country list + other dropdowns

Country (global — set once per batch)

Maintain one file at the project root, countries.json, with your country list:

[
  { "code": 1, "value": "United States" },
  { "code": 2, "value": "France" }
]

Any country field (Pays / Country / Land / 国 …) in any campaign uses this list automatically — you do not create a per-campaign country file. Update it once per batch when the country list changes. (countries.example.json shows the format.)

If a country field is found but countries.json is empty or missing, the push stops with a warning for that campaign, so it can never silently become a text box.

Other dropdowns (per campaign)

For non-country dropdowns, step 1 drops an empty <field>.json in the campaign folder and tells you its name. Paste options in the same format. Leave it empty ([]) and that field stays a text box.


Step 2 — review & push

Run step2_push.py. For each extracted campaign it:

  1. Builds the uri from the title (lower-cased, spaces -> hyphens).
  2. Checks your live system for that uri. If it already exists, it appends the current month and year, e.g. apples-oranges -> apples-oranges-jun-26 (and -2, -3, ... if that is taken too).
  3. Shows the field mapping, the images/styles that will be attached, and the full payload.
  4. On y, it uploads the images, then POSTs the campaign live and prints the new id and URL.

Images

If hero.png / logo.png are present in the campaign folder, they are uploaded to your backend (POST /image/) on push:

  • hero is uploaded with altText = <uri> (so the Cloudinary file is unique).
  • logo is uploaded with altText = logo-<6 random chars>.

The returned ids are attached to the campaign's image / logo. If an image is missing or the upload fails, the campaign is still created without it.

Styles

Every campaign gets the CSS in default_styles.css (project root) in its styles field. Edit that one file to change the default for all future pushes.


How fields are typed

Field Becomes
label with an options file DropDown (options from the file)
label that looks like email Email
consent checkbox CheckBox, name = consent HTML with <a target="_blank">
everything else TextBox

All fields are marked required (from the * on the label).


Project layout

hashbun_campaign_tool/
    step1_extract.py        run first
    step2_push.py           run after filling dropdown files
    config.example.py       copy to config.py and add your token
    requirements.txt
    pdfs/                   <- input PDFs
    output/                 <- per-campaign folders land here
    hashbun/
        extract.py          page-1 PDF -> txt/images/state + dropdown templates
        mapping.py          state + option files -> campaign payload
        api.py              uri uniqueness check + POST
        util.py             uri slug + month/year suffix
        cli.py              the two-step flow

Notes

  • Image export needs PyMuPDF (in requirements); if missing, the tool still runs and skips images.
  • Text extraction uses pdfplumber — no external binaries.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors