{"id":13866057,"url":"https://github.com/dapperfu/python_Meijer","last_synced_at":"2025-07-15T02:31:24.375Z","repository":{"id":40507158,"uuid":"139483807","full_name":"dapperfu/python_Meijer","owner":"dapperfu","description":"Reverse engineered API for Meijer's Shopping List.","archived":false,"fork":false,"pushed_at":"2022-11-27T23:23:43.000Z","size":1386,"stargazers_count":18,"open_issues_count":0,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-23T06:31:10.755Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dapperfu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"security.png","support":null}},"created_at":"2018-07-02T19:11:54.000Z","updated_at":"2024-11-20T18:38:11.000Z","dependencies_parsed_at":"2023-01-21T06:02:04.940Z","dependency_job_id":null,"html_url":"https://github.com/dapperfu/python_Meijer","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dapperfu/python_Meijer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperfu%2Fpython_Meijer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperfu%2Fpython_Meijer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperfu%2Fpython_Meijer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperfu%2Fpython_Meijer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dapperfu","download_url":"https://codeload.github.com/dapperfu/python_Meijer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperfu%2Fpython_Meijer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265390866,"owners_count":23757605,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-05T12:00:50.726Z","updated_at":"2025-07-15T02:31:24.042Z","avatar_url":"https://github.com/dapperfu.png","language":"Jupyter Notebook","funding_links":[],"categories":["Python"],"sub_categories":[],"readme":"# ```python-meijer```\n\n- What: Reverse engineered API for Meijer shopping list.\n- Why: I can't actually get in contact with a Meijer Engineer. Their Facebook team just \"takes feedback.\"\n  On n'est jamais servi si bien que par soi-même.\n- How: [mitmproxy](https://mitmproxy.org/), Python with [requests](http://docs.python-requests.org/en/master/)\n\n## Installation \n\npip install -e \"git+https://github.com/dapperfu/python_Meijer.git#subdirectory=meijer\u0026#egg=meijer\" \n\n## Development Installation\n\n```\ngit clone https://github.com/dapperfu/python_Meijer.git\ncd python_Meijer\n# Create \u0026 Activate virtual environment\npython3 -mvenv venv\nsource venv/bin/activate\n# Install development li\npip install -U pip wheel setuptools\npip install -r requirements.txt\n```\n\n## Usage\n\nMeijer login information is stored in the environmental variable `MEIJER_API_KEY`.\n\n```export MEIJER_API_KEY=\"user|pass\"```\n\n1. *Don't use the same login for Meijer's shopping list as your Bank, 'k?*\n2. If you use a `|` in your password, you can edit the delimiter in `Meijer.py`\n\n### Shell completion.\n\nShell completion through [click](https://click.palletsprojects.com/en/8.1.x/shell-completion/)\n\nAdd `meijer` Bash completion to the terminal:\n\n```\n_meijer_COMPLETE=bash_source meijer \u003e ~/.meijer-complete.bash\necho \". ~/.meijer-complete.bash\" \u003e\u003e ~/.bashrc\n```\n\n### Shopping list.\n\n\n\n```\n$ meijer list\nUsage: meijer list [OPTIONS] COMMAND [ARGS]...\n\n  Meijer list manipulation.\n\nOptions:\n  -p, --prompt  Prompt for mPerks username \u0026 password\n  --help        Show this message and exit.\n\nCommands:\n  add    Add items to shopping list.\n  clear  Clear current shopping list.\n  show   Show current shopping list.\n```\n\nShow the list, add something, show the list again.\n```\n$ meijer list show\n[ ] Check the box to mark complete\n[ ] Click/Tap here to edit an item\n[ ] Press and hold to drag and drop an item\n$ meijer list add\nEnter your shopping list. Complete with a blank line.\n- Tacos\n-\n$ meijer list show\n[ ] Tacos\n[ ] Check the box to mark complete\n[ ] Click/Tap here to edit an item\n[ ] Press and hold to drag and drop an item\n```\n\nClear the list:\n\n```shell\nmeijer list clear\nmeijer list show\n```\n\nFancy:\n\n```\ncat examples/list\n\n$ meijer list add \u003c examples/list\nEnter your shopping list. Complete with a blank line.\n- - - - - %\n\n$ meijer list show\n[ ] 8% Milk\n[ ] 4% Milk\n[ ] 2% Milk\n[ ] 1% Milk\n```\n\n## Development Tools.\n\n- [HTC One M7](https://www.htc.com/us/smartphones/htc-one-m7/).\n- Android 6. [Android 7.0+ makes it very difficult to use self signed certs](https://github.com/mitmproxy/mitmproxy/issues/2054#issuecomment-281836486). It's just easier to have an old device laying around for MITM proxy. It is still possible but requires root and more steps than \"Install Cert\".\n- [Meijer Mobile App apk](https://apkpure.com/meijer/com.meijer.mobile.meijer) [[Google Play Link](https://play.google.com/store/apps/details?id=com.meijer.mobile.meijer\u0026hl=en_US)]\n- apk decompiler:\n  - [Online Android Apk decompiler](http://www.javadecompilers.com/apk)\n  - [apktool](https://ibotpeaches.github.io/Apktool/)\n- Jupyter Notebook as a development environment.\n\nUse ```shop_n_scan_faker.py``` with mitmproxy to fake any meijer store's location.\n\nhttps://docs.mitmproxy.org/stable/addons-scripting/\n\n```\n# mitmproxy\nmitmproxy -s shop_n_scan_faker.py\n\n# mitmweb\nmitmweb -s shop_n_scan_faker.py\n```\n\n##\n\n## Motivation\n\nThe Meijer \"[Shop \u0026 Scan](https://www.meijer.com/content/content.jsp?pageName=shopandscan\u0026icid=HP:OLA:062418:MoreWays:ShopandScan)\" feature is pretty cool, however it has a lot of room for improvement.\n\n- The software barcode scanner is in software and slow. It also misreads the barcode often.\n- Hand held barcode scanners [are cheap, fast and accurate](https://www.amazon.com/TaoTronics-Bluetooth-Portable-Processor-Compatible/dp/B06VV65V89/ref=sr_1_4?ie=UTF8\u0026qid=1542388719\u0026sr=8-4\u0026keywords=bluetooth+barcode).\n- ~~It's hard to flip between your shopping list and the app.~~\n- You can't \"parallel\" shop with kids or SO. If you both start a shop and scan and try to checkout it'll only import the last one. (We found this one out the hardway).\n\nDecompiling the Meijer.apk it looks like it's mostly just a REST app. So I setup a mitmproxy to watch for traffic.\n\n## Lessons Learned\n\n### Misc.\n\n- Shopping lists doesn't support Unicode, no emoji's for you.\n\n### You can't trick the Meijer App with mock locations.\n\nTests for Mock Location, in:\n\n5.1.2:\n\n```mobile/meijer/com/meijergo/utils/location/LocationHelper.java```:\n\n\n```\npublic void onLocationChanged(Location location) {\n    if (location != null) {\n        if (location.hasAccuracy()) {\n            if (this.sessionEnv == SessionEnvironment.PRODUCTION \u0026\u0026 location.isFromMockProvider()) {\n                this.listener.onLocationReceived(0.0d, 0.0d, 0.0f);\n            } else {\n                this.listener.onLocationReceived(location.getLatitude(), location.getLongitude(), location.getAccuracy());\n            }\n        }\n    }\n}\n```\n\n5.3.0:\n\nThey updated it to give you a warning that Mock Locations are not allowed.\n\n```\npublic void onLocationChanged(Location location) {\n    if (location == null) {\n        requestLocation();\n        return;\n    }\n    LocationHelperListener locationHelperListener = this.listener;\n    if (locationHelperListener != null) {\n        locationHelperListener.onLocationReceived(location.getLatitude(), location.getLongitude(), location.isFromMockProvider());\n    }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapperfu%2Fpython_Meijer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdapperfu%2Fpython_Meijer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapperfu%2Fpython_Meijer/lists"}