aboutsummaryrefslogtreecommitdiff

README for coupons

This project exists to make it easy to query the current sale papers for select grocery stores, including specifically Publix. Frontends include cli and a webapp (python flask).

Upstream

This project's upstream is at https://bgstack15.ddns.net/cgit/coupons.

Features

  • simple cli
  • simple wsgi web app with minimal javascript
  • caching of results for faster lookups during the same day

Alternatives

Visiting https://southernsavers.com manually, or each store's website.

I previously started using selenium (see aux/ads1.py in initial commit) but that was not necessary.

Reason for existence

To simplify and automate searching for items currently on sale.

Using

Command line interface

Basic usage is pretty simple. You need to specify a store at a minimum. When the script visits the webpage, it will cache the file to $XDG_CACHE_DIR/coupons/ to reduce the amount of work needed during the same day.

./coupons.py --store "publix" --search "candy"

To use standard input from a fully-cached javascript response from the website, you could run this.

<~/.cache/coupons/publix_2022-09-01.json ./coupons.py --stdin --clean --search "candy" --pretty

An already-cleaned json file would not need the --clean flag. But the cached values are the exact javascript+json payload from the server.

See also ./coupons.py --help.

Web app

Run a simple dev environment.

FLASK_APP=coupons_web.py FLASK_DEBUG=True flask run --host='0.0.0.0'

For a more robust production environment, drop the extra/wsgi-coupons.conf apache config into your apache httpd conf directory and configure it as documented in there.

Visiting the web app with curl

$ curl http://d2-03a/coupons/search/dog --header 'Accept: application/json' ; printf '\n'
[{"publix": {"Publix Weekly Ad: 9/7-9/13 or 9/8-9/14": {"Buy One Get Ones": ["Healthy Hide Good'n Fun Dog Treats Triple Flavor Ribs or Wings, 12 oz, at $11.99 <small>($5.99)</small>"]}, "Unadvertised Deals: 9/7-9/13": {"Pet Care": ["Blue Dry Dog Food, 5 lb, $14.99"]}, "Extra Savings Flyer: 8/27-9/9": {"Meat": ["Greenfield Natural Meat Co. Bratwurst 12 oz, Hot Dogs 13 oz or Lunchmeat, 7 oz, $4"]}}}, {"ingles": {"Ingles Ad & Coupons: 9/7-9/13": {"Meat": ["Gwaltney Hot Dogs, 12 oz, $1.48"]}}}, {"food lion": {"Food Lion Ad & Coupons: 9/7-9/13": {"Pet Care": ["Rachael Ray Nutrish Dry Dog Food, 5.5-6 lb, $10.99"]}}}]

$ curl -X POST http://d2-03a/coupons/search/ --data 'mayo' --header 'Accept: application/json' ; printf '\n'
[{"publix": {"Publix Weekly Ad: 9/7-9/13 or 9/8-9/14": {"Buy One Get Ones": ["Duke's Mayonnaise, 30-32 oz, at $5.23 <small>($3.11)</small>", "Hellmann's Mayonnaise, 15-20 oz, at $5.75 <small>($2.87)</small>"]}, "Extra Savings Flyer: 9/10-9/23": {"Grocery": ["Hellmann's Mayonnaise, 24-30 oz, $3.99", "Hellmann's Mayonnaise, Spicy Mayonnaise or Vegan Dressing & Spread, 11.5 oz, $3", "Primal Kitchen Mayonnaise, 12 oz, $8.99", "Sir Kensington's Special Sauce or Chipotle Mayonnaise, 12 oz, $4"]}}}]

The API accepts a few URL parameters, including &date=YYYY-MM-DD to use that day's cached results (it does not time travel for you) and ?nocache=1.

Improvements

  • Add flask-correct logger mechanisms?

Dependencies

For the web app:

  • apache with mod_wsgi
  • python3-flask

For AlmaLinux 8:

  • python3-flask
  • python3-mod_wsgi
  • httpd

Building or changing

Only a few stores are currently supported. The southernsavers.com website lists other stores that are probably drop-in capable. To learn the widgets.json path needed, use Developer Tools in a web browser to capture the full widgets.json path and add it to the stores_url dict.

References

bgstack15