Create instagram-automation-session-notes.md via n8n

This commit is contained in:
herbygitea 2026-03-29 23:54:01 +00:00
parent dfbabd73ed
commit 6f81771dd8

View File

@ -0,0 +1,165 @@
---
project: instagram-automation-session-notes
type: session-notes
status: active
tags:
- pbs
- n8n
- instagram
- mysql
- wordpress
- automation
- docker
created: 2026-03-16
updated: 2026-03-16
path: PBS/Tech/Sessions/
---
# Session Notes — MySQL Schema, Error Checking & The Great Lockout of 2026
## ✅ Accomplished This Session
### Error Checking — Instagram Reply Workflow
All four error checks are now wired to Notify Travis → Google Chat:
- ✅ Subscribe check notification
- ✅ Hash verification failure notification (with ⛔ alert level)
- ✅ Empty table lookup notification (includes Reel ID, commenter, comment text)
- ✅ Keyword not matched notification
**Key learnings:**
- n8n "Always Output Data" needed on MySQL node so IF node can evaluate empty results
- When "Always Output Data" is on, check `$('node').first().json.id` exists instead of `length > 0` (length returns 1 for empty item)
- Google Chat HTTP Request node must use "Using Fields Below" mode, not raw JSON — literal newlines from expressions break JSON
- Build message strings as single `={{ }}` expression using `+` concatenation to keep `\n` as escaped characters
- `$now.toFormat('MMM dd, HH:mm:ss')` works in both test and live contexts (unlike `$execution.startedAt`)
- Timestamp and title passed from calling workflow, Notify Travis just passes them through
---
### MySQL Schema — New Tables Created
**`pbs_recipes`:**
```sql
CREATE TABLE IF NOT EXISTS pbs_recipes (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
post_id BIGINT UNSIGNED NOT NULL,
title VARCHAR(500) NOT NULL,
url VARCHAR(500) NOT NULL,
keyword VARCHAR(100) NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY (post_id)
);
```
**`instagram_posts`:**
```sql
CREATE TABLE IF NOT EXISTS instagram_posts (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
reel_id VARCHAR(50) NOT NULL,
post_id BIGINT UNSIGNED NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY (reel_id),
FOREIGN KEY (post_id) REFERENCES pbs_recipes(post_id)
);
```
**Key decisions:**
- `post_id` is nullable in `instagram_posts` — NULL means unmatched reel, not an error
- `reel_id` stored as VARCHAR not BIGINT (Instagram ID integer overflow issue)
- Normalized schema — keyword and URL live in `pbs_recipes` only, JOIN at query time
- Staying on shared MySQL instance — at current scale (2k/month, 10-20 replies) separate instance is overkill
- phpMyAdmin added back to Docker Compose for direct MySQL access
---
### WordPress Publish Webhook — Proof of Concept Complete
- WPCode Lite snippet fires on post publish (admin only)
- Payload: post_id, title, url, tags, categories
- HMAC signature verification via X-PBS-Signature header
- Raw body passed via X-PBS-Body header (base64 encoded) for exact signature verification
- n8n Code node verifies signature before processing
- Ready to wire into `pbs_recipes` table insert workflow
---
### Architecture Decision — Reply Workflow Refactor
Current two-table lookup + merge is being replaced with:
- Single `instagram_posts` lookup only
- URL stored directly in `instagram_posts` (populated at reel insert time from `pbs_recipes`)
- Simpler, faster, fewer failure points
---
## 🔧 The Great WordPress Lockout of 2026
**What happened:** Wordfence locked out staging WP admin. Unlock email never arrived.
**What we tried (none of it worked):**
- WP-CLI wf:unblock-ip command (not a registered command)
- Clearing wp_options Wordfence entries in MySQL
- Disabling Wordfence plugin
- Restarting WordPress container
- Deleting wflogs directory
**Root cause discovered:**
Wordfence WAF runs as a PHP auto_prepend_file — completely independent of the plugin being active. Found in .htaccess and wordfence-waf.php in WordPress root.
**Actual fix:** Wrong email address on the admin account. Changed it, logged right in. 🤦
**Real lesson learned:** Read the error message carefully before spending an hour troubleshooting! 😄
**Lockout duration if we hadn't figured it out:** 1 MONTH
---
## 📋 Runbook Addition — WordPress Lockout Recovery
```bash
# Get into WordPress container
docker exec -it wordpress bash
cd /var/www/html
# List all users
wp --allow-root user list
# Reset password by username
wp --allow-root user update admin --user_pass=newpassword
# Reset password by email
wp --allow-root user update user@email.com --user_pass=newpassword
# If WAF is blocking login page independently of plugin:
# 1. Remove Wordfence WAF block from .htaccess
# 2. Rename wordfence-waf.php to wordfence-waf.php.disabled
# 3. docker restart wordpress
```
---
## 🔜 Next Steps
- [ ] Wire WordPress publish webhook → n8n workflow → insert into `pbs_recipes`
- [ ] Build one-time migration workflow — n8n datatables → MySQL
- [ ] Finish reply workflow refactor — remove Merge node, single `instagram_posts` lookup
- [ ] Fix production WordPress admin email (same issue exists there!)
- [ ] Deploy all changes to production once staging is verified
---
## 📝 Notes
- All development on staging (staging.plantbasedsoutherner.com)
- n8n datatables to be retired once MySQL migration complete
- Foreign key constraint requires `pbs_recipes` record to exist before `instagram_posts` insert
- Use `WHERE post_id IS NULL` query to find unmatched reels for Content Hub dashboard
---
*Last Updated: March 16, 2026*
*Maintained by: Travis*
*Project: Plant Based Southerner — Instagram Automation*