Automate or Perish: My Python Scripts Do the Dishes While I Nap
Sweating the Small Stuff? Let Python Be Your Sweatshop Overseer
Look, I’ve got news for you, champ: if you’re still doing repetitive tasks with your meat fingers, you’re basically volunteering at the human treadmill factory. And trust me, that factory pays in blisters and existential dread. Python isn’t just some overhyped snake language for data scientists in hoodies—it’s your personal digital slave army. I’ve got scripts that brew my coffee (metaphorically… mostly), stalk my ex’s Instagram (kidding! …mostly), and even negotiates with my ISP when my internet drops. Let’s rip off the band-aid and dive into the gloriously automated chaos of my digital life. Buckle up, buttercup—we’re going deep.
Desktop Wallpaper Rotation: Because Your Eye Balls Deserve a Vacation
Ever stare at the same bland wallpaper for 8 hours a day? Congrats, you’re slowly morphing into a beige office drone. I fixed this with an Unsplash-powered wallpaper assassin that refreshes my desktop hourly. But Wong Edan doesn’t do half-measures. This isn’t just os.system("wget unsplash.jpg") and call it a day. Oh no. We’re talking surgical precision with API key management, geotag filtering, and fail-safes so your screen doesn’t turn into a goat rodeo.
Here’s how this beauty works under the hood:
- Step 1: Authenticate Like a Spy – Unsplash’s API requires OAuth, but Wong Edan hates storing tokens in plaintext. So my script uses
keyringto stash credentials in the system’s secure vault. On Windows? It’s the Credential Manager. On macOS? Keychain Access. Linux? *whispers* I uselibsecretand pray. The first-run setup guides you through Unsplash’s developer portal like a patient therapist. - Step 2: Query with Surgical Precision – Blindly grabbing “nature” photos is amateur hour. My query builder uses location bias. Live in Oslo?
query_params = {"query": "fjord, northern lights", "orientation": "landscape", "location": "oslo"}. But what if you’re on a train? GPS spoofing viageocoderlibrary injects your last known location from Google Maps history (with user consent, obviously… mostly). - Step 3: The Holy Trinity of Wallpaper Handling – This is where most scripts faceplant:
def set_wallpaper(image_path): if sys.platform == "win32": SPI_SETDESKWALLPAPER = 0x0014 ctypes.windll.user32.SystemParametersInfoW( SPI_SETDESKWALLPAPER, 0, image_path, 0x0001 | 0x0002 # SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE ) elif sys.platform == "darwin": osascript = ( 'tell application "System Events" to ' 'set picture of every desktop to POSIX file "{}"' ).format(image_path) subprocess.run(["osascript", "-e", osascript]) else: # Linux (GNOME) subprocess.run([ "gsettings", "set", "org.gnome.desktop.background", "picture-uri", f"file://{image_path}" ])Notice the
SPIF_SENDWININICHANGEflag? Skip that and Windows won’t refresh the wallpaper. Linux users? If you’re using KDE, this breaks—hence thetry/exceptblock that falls back toplasmashell -e "loadDesktopScript 'Desktop')" .... Perfection is non-negotiable. - Step 4: The “What If Unsplash Catches Fire?” Protocol – My
main()loop has layers like an onion dipped in failure sauce:
while True: try: download_and_set_wallpaper() time.sleep(3600) # Hourly except requests.exceptions.RequestException as e: # Failed API call? Retry in 5 mins log_error(e) time.sleep(300) continue except OSError as e: # File error? Purge cache and use fallback shutil.rmtree(CACHE_DIR) set_wallpaper(FALLBACK_IMAGE) raise # Still alert me! except Exception as e: # Nuclear option: Use motivational cat image set_wallpaper(os.path.join(ASSETS, "angry_cat.jpg")) send_sms_alert("WALLPAPER APOCALYPSE")Yes, it SMSes me if everything fails. Because Wong Edan treats automation like air traffic control—there is no acceptable downtime.
I’ve got 14 cron jobs running this (because I rotate through 14 monitors in my cave-of-doom office). But here’s the secret most tutorials skip: cache management. Unsplash’s API is rate-limited to 50 requests/hour. My script stores every downloaded image in a timestamped SQLite database, cross-referencing Unsplash IDs to avoid duplicates. It also scrubs the cache weekly using APScheduler to delete images older than 30 days. This isn’t automation—it’s digital real estate management.
Cocktail Wizardry: Because Regret Should Be Algorithmically Optimized
Ever stare into your liquor cabinet thinking, “What unholy concoction can I birth tonight?” Me too. So I built cocktail_watcher.py—a cocktail robot that cross-references your sad pantry with 3,000+ recipes. But Wong Edan doesn’t just say “Hey, you have vodka!” It calculates regret minimization scores based on your tolerance for shame.
Let’s dissect this beautiful monster:
Database Design: Where Mixology Meets Relational Algebra
I scrapped JSON. Why? Because querying “recipes using exactly what I have” with JSON is like defusing a bomb blindfolded. I built a proper SQLite schema:
- Table: ingredients
CREATE TABLE ingredients ( id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL, -- 'vodka', 'lemon juice' category TEXT NOT NULL, -- 'spirit', 'citrus', 'sweetener' in_stock BOOLEAN DEFAULT 0 -- CRUCIAL: tracks pantry ); - Table: recipes
CREATE TABLE recipes ( id INTEGER PRIMARY KEY, name TEXT NOT NULL, -- 'Espresso Martini' difficulty INTEGER, -- 1-5 scale (my pain tolerance) description TEXT ); - Table: recipe_ingredients (Junction Table)
CREATE TABLE recipe_ingredients ( recipe_id INTEGER, ingredient_id INTEGER, quantity TEXT, -- '30ml', '2 dashes' FOREIGN KEY(recipe_id) REFERENCES recipes(id), FOREIGN KEY(ingredient_id) REFERENCES ingredients(id) );
This lets me run surgical queries like:
-- Fetch cocktails using ONLY what I have in stock
SELECT r.name, COUNT(*) AS matched_ingredients
FROM recipes r
JOIN recipe_ingredients ri ON r.id = ri.recipe_id
JOIN ingredients i ON ri.ingredient_id = i.id
WHERE i.in_stock = 1
GROUP BY r.id
HAVING COUNT(*) = (
SELECT COUNT(*)
FROM recipe_ingredients
WHERE recipe_id = r.id
)
ORDER BY r.difficulty ASC;
Translation: “Show me drinks I can make right now without begging my neighbor for bitters.”
The “Pantry Scanner” Interface (Or: Wong Edan Hates Typing)
Manually updating in_stock? In this economy? My script syncs with my grocery app via requests library. But the real magic is voice control:
import speech_recognition as sr
def listen_for_pantry_updates():
r = sr.Recognizer()
with sr.Microphone() as source:
print("Say 'I bought [ingredient]' or 'I ran out of [ingredient]'")
audio = r.listen(source)
try:
text = r.recognize_google(audio).lower()
if "bought" in text:
ingredient = text.split("bought ")[-1]
mark_ingredient_in_stock(ingredient, True)
elif "out" in text:
ingredient = text.split("out of ")[-1]
mark_ingredient_in_stock(ingredient, False)
except sr.UnknownValueError:
print("Wong Edan’s ears are stuffed with wax. Try again.")
But wait—Google Speech Recognition fails if my room is noisy. Solution? Custom wake words with Porcupine (Picovoice’s open-source tool). I trained it to trigger only on “Cocktail Oracle” so my script doesn’t activate when I yell “TEQUILA!” at 2 AM.
The “Regret Score” Algorithm (Patent Pending)
Not all cocktails are created equal when you’re hangry. My script analyzes:
- Ingredient Complexity – A Manhattan (3 ingredients) scores 1.0. A Last Word (4 ingredients + egg white) scores 3.7. Threshold: >2.5 requires “sobriety verification” via Google Authenticator.
- Historical Failure Rate – Did you burn the rim last time you made a Margarita? The script weights that heavily. Data pulled from my “regret_log.csv” (yes, it’s a thing).
- Current Blood Sugar – Syncs with my Dexcom glucose monitor via Bluetooth LE. Low blood sugar? Blocks all drinks with “simple syrup” in ingredients.
The output isn’t just a list—it’s a prioritized cocktail menu with Wong Edan’s scathing commentary:
✅ YOU CAN MAKE: Moscow Mule (Regret Score: 0.8/5.0) Why: You have vodka, ginger beer, lime. Hard pass on the copper mug drama. ❌ SKIP: French 75 (Regret Score: 4.3/5.0) Why: No champagne (again). Also, your last attempt caused a champagne geyser. 💡 PRO TIP: Just eat the lime. You're already crying.
Financial Watchdog: Because Banks Love It When You Ignore $0.50 Fees
Bank fees are like cockroaches: small, annoying, and multiplying when you’re not looking. My finance_watcher.py scans 7 accounts hourly to catch bullshit charges. But Wong Edan doesn’t just email you about a $35 overdraft fee—it declares war.
Bank Statement Parsing: Regex on Steroids
PDFs? CSVs? OFX? Wong Edan eats them for breakfast. Here’s how I handle a Chase CSV:
def parse_chase_csv(file_path):
with open(file_path, 'r') as f:
reader = csv.reader(f)
next(reader) # Skip header
for row in reader:
date = datetime.strptime(row[0], '%m/%d/%Y')
amount = float(row[4].replace('$', ''))
description = row[3]
# Flag suspicious patterns with REGEX NINJAS
if re.search(r'(OVERDRAFT|NSF|ATM FEE)', description, re.I):
trigger_alert(f"RED ALERT: {description} - ${amount}")
# Detect "stealth fees" like 'Account Maintenance'
elif re.search(r'account maintenance', description, re.I) and amount > 5:
log_and_dispute(row) # More on this soon
The real art? Handling international transactions. When my wife bought “café” in Paris, Chase listed it as “CAFE 2673 PARIS FR”. Solution:
# Map common merchant codes to readable names
MERCHANT_CODES = {
r"CAFE \d+": "Local Cafe",
r"AMAZON MKTPLACE": "Amazon (But Why?)",
r"NETFLIX": "Brain Rot Subscription"
}
for pattern, name in MERCHANT_CODES.items():
if re.search(pattern, description, re.I):
description = name
break
The Automated Dispute Machine (Where Wong Edan Gets Scary)
Catching a fee is half the battle. Fighting it is where Wong Edan shines. When a $12 “paper statement fee” hits, my script:
- Screenshots the transaction via
pyautogui(logged into Chase) - Generates a dispute letter template using
jinja2filled with regulatory citations (Regulation E) - Auto-fills Chase’s online dispute form using
Selenium - Sends a “pre-dispute” email to the VP of customer experience with
smtplib, cc’ing the CEO’s public contact form
Here’s the dispute_fee() function’s dirty secrets:
def dispute_fee(transaction):
# Step 1: Grab evidence (this is the scary part)
driver = get_logged_in_chase_driver()
driver.get(f"https://chase.com/transactions/{transaction.id}")
screenshot = take_screenshot(driver)
# Step 2: Generate legal-sounding gibberish
template = env.get_template('dispute_letter.j2')
letter = template.render(
date=datetime.now().strftime("%B %d, %Y"),
account=transaction.account,
amount=transaction.amount,
regulation_cite="12 CFR § 1005.11(c)(1)(i)"
)
# Step 3: Auto-submit via Chase's flaky web form
form = driver.find_element(By.ID, "disputeForm")
form.find_element(By.NAME, "amount").send_keys(str(transaction.amount))
form.find_element(By.NAME, "reason").send_keys("Unauthorized charge per Reg E")
form.find_element(By.NAME, "evidence").send_keys(screenshot)
form.submit()
# Step 4: Nuclear option (email VP)
if transaction.amount > 10:
send_targeted_email(
to="[email protected]",
subject=f"URGENT: Dispute #{transaction.id} - Escalation Required",
body=f"Per Reg E, this {transaction.amount} fee is invalid. ... [Wong Edan's Threatening Tone]"
)
Results? Over $400 in disputed fees refunded in 6 months. But the real win? Chase’s system now auto-approves my disputes because their AI recognizes “Wong Edan” as a “high-friction customer”.
Why This Isn’t About Python—It’s About Your Soul
You could write these scripts in PowerShell or Bash. But Wong Edan chooses Python for three unholy reasons:
- The “I’m Not a Robot” Illusion – Python reads like English.
if not has_enough_vodka: panic()is self-documenting. Try that in PowerShell whereif (-not $hasVodka) { throw "WINE NOT FOUND" }looks like a ransom note. - Ecosystem Domination – Need to talk to Google Sheets?
gspread. Scrape a site?BeautifulSoup. Send SMS?twilio. Python’s PyPI is a cheat code. That cocktail script uses 12 libraries. Rewriting it in PowerShell would require duct-taping 5 different APIs while crying. - It’s Forgiving (Unlike Wong Edan) – Miss a semicolon in JavaScript? Everything explodes. In Python? The interpreter gently suggests, “Did you forget indentation, sweetie?” That’s why beginners survive. That’s why automation scales.
Here’s the hard truth no one admits: Automation isn’t about saving time—it’s about saving your sanity. When my wallpaper rotator catches an Unsplash outage before I even blink, that’s not “efficiency”. That’s preserving brain cells for actual human things—like remembering my wife’s birthday (which, yes, my birthday_tracker.py also handles). Every script I’ve written is a tiny rebellion against the tyranny of tedium.
Start Small, Dream Big, Automate Relentlessly
Don’t try to clone Skynet on day one. Wong Edan’s first script was a rename_photos.py that fixed his “DSC_0001.jpg” disaster. Here’s your battle plan:
- Week 1: The “Hell No” List – Track every task you do twice that makes you grunt. Is it renaming files? Copy-pasting data? Checking flight prices? These are your targets.
- Week 2: Weaponize the Standard Library – Forget fancy APIs. Master:
os.rename()(batch file renaming),smtplib(email alerts),shutil(folder ops). These alone automate 60% of desktop drudgery. - Week 3: Steal Like an Artist – Found a Reddit script for Gmail cleanup? Paste it into
gmail_slayer.py. But Wong Edan’s rule: break it, fix it, own it. Add error logging. Make it send you memes when it works.
Remember: If your script saves 2 minutes a day but breaks once a month, it’s still worth it. Why? Because those 2 minutes compound into 12 hours yearly—and that’s 12 hours you spent laughing instead of weeping over spreadsheets. Automation isn’t magic. It’s just Python, your stubbornness, and Wong Edan’s unshakable belief that you deserve better than manual labor.
Now go forth. Automate your way to enlightenment. Or at least to a cocktail that doesn’t require begging your neighbor for bitters.