<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mohamed Adel</title>
    <description>The latest articles on DEV Community by Mohamed Adel (@mohamedation).</description>
    <link>https://dev.to/mohamedation</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F752009%2F24c3e347-392c-40b7-96f4-88cf38b492f5.jpeg</url>
      <title>DEV Community: Mohamed Adel</title>
      <link>https://dev.to/mohamedation</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohamedation"/>
    <language>en</language>
    <item>
      <title>Sassy Chef - local Gemma plans meals &amp; shopping list so We stay lazy</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Fri, 23 Oct 2026 13:45:18 +0000</pubDate>
      <link>https://dev.to/mohamedation/sassy-chef-local-gemma-plans-meals-shopping-list-so-we-stay-lazy-48f2</link>
      <guid>https://dev.to/mohamedation/sassy-chef-local-gemma-plans-meals-shopping-list-so-we-stay-lazy-48f2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;Sassy Chef&lt;/strong&gt; as a tiny local meal planner that does the morning brainwork I keep skipping.&lt;/p&gt;

&lt;p&gt;Every day the same loop: what do I cook, what am I missing from the fridge, do I need to go buy something. I usually lose that fight and order food. This week’s theme is literally “reward laziness,” so I made the thing that should have existed already:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One command in the morning&lt;/li&gt;
&lt;li&gt;Local &lt;strong&gt;Gemma 3&lt;/strong&gt; (&lt;code&gt;gemma3:4b&lt;/code&gt; via Ollama) plans breakfast → lunch → dinner&lt;/li&gt;
&lt;li&gt;It looks at what’s already in my pantry JSON before inventing a shopping list&lt;/li&gt;
&lt;li&gt;It dumps a markdown plan + a &lt;strong&gt;1–2 page PDF&lt;/strong&gt; I can print and take to the kitchen / store&lt;/li&gt;
&lt;li&gt;Personality is a sassy chef that roasts my procrastination, not my life choices&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The lazy trick I’m happiest about: &lt;strong&gt;the shopping list is assumed bought after &lt;code&gt;plan&lt;/code&gt;.&lt;/strong&gt; I don’t have to check boxes into a CLI every evening. If I actually skipped spinach, that’s the only day I type anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; sassy_chef missed spinach
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That pulls it out of the pantry and parks it for tomorrow’s list. Normal days = zero extra work. That felt more “sloth” than a fancy UI.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/-KDyUCu9hJM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mohamedation" rel="noopener noreferrer"&gt;
        mohamedation
      &lt;/a&gt; / &lt;a href="https://github.com/mohamedation/sassy-chef" rel="noopener noreferrer"&gt;
        sassy-chef
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local AI that plans your day of cooking so you don't have to think before coffee.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Sassy Chef&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;Local AI that plans your day of cooking so you don't have to think before coffee.&lt;/p&gt;

&lt;p&gt;Every morning it writes &lt;strong&gt;breakfast → shopping list → lunch → dinner&lt;/strong&gt;, keeps a rolling pantry + shopping list on disk, and dumps everything as markdown you can paste into email, Google Keep, or Tasks.&lt;/p&gt;

&lt;p&gt;Built for &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19" rel="nofollow"&gt;Hacktoberfest 2026 Week 3 — Slow and Steady&lt;/a&gt;: open-weight AI that rewards laziness. Runs entirely offline with &lt;strong&gt;Gemma 3 via Ollama&lt;/strong&gt; (default &lt;code&gt;gemma3:4b&lt;/code&gt;).&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why open / local&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Your fridge and habits never leave your machine&lt;/li&gt;
&lt;li&gt;No API bill for a daily habit&lt;/li&gt;
&lt;li&gt;Swap models in one config line (&lt;code&gt;gemma3:4b&lt;/code&gt; → &lt;code&gt;gemma3:12b&lt;/code&gt;, etc.)&lt;/li&gt;
&lt;li&gt;Works when the internet doesn't&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;
&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.11+&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ollama.com" rel="nofollow noopener noreferrer"&gt;Ollama&lt;/a&gt; running locally&lt;/li&gt;
&lt;li&gt;A pulled model (default Gemma):&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;ollama serve          &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; if not already running&lt;/span&gt;
ollama pull gemma3:4b&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;PDF day sheets need one package (&lt;code&gt;fpdf2&lt;/code&gt;). The meal planner…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mohamedation/sassy-chef" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma3:4b
python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt   &lt;span class="c"&gt;# only fpdf2 for the PDF sheet&lt;/span&gt;
python &lt;span class="nt"&gt;-m&lt;/span&gt; sassy_chef doctor
python &lt;span class="nt"&gt;-m&lt;/span&gt; sassy_chef plan
&lt;span class="c"&gt;# open output/today-day.pdf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stack on purpose: &lt;strong&gt;Python stdlib + Ollama HTTP + optional fpdf2.&lt;/strong&gt; No web app, no cloud key, no “agent framework” for a problem that is one JSON chat and a JSON file.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The loop
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pantry.json + missed leftovers + recent meals
        → Ollama chat (gemma3:4b, format=json, sassy system prompt)
        → breakfast / lunch / dinner + shopping_to_buy_today
        → write cooking.md + shopping.md + day.pdf
        → assume list bought → pantry updated, shopping cleared
        → (only if needed) missed &amp;lt;item&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gemma does the creative part: titles, steps, “what am I missing,” the roast. Python owns the boring part: files, PDF layout, “did you actually buy it or are we lying to tomorrow.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Design choices that mattered
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimistic shopping.&lt;/strong&gt; First version had a &lt;code&gt;bought&lt;/code&gt; command. That’s daily chores. Flipped it: assume success, &lt;code&gt;missed&lt;/code&gt; only on failure. Fits the theme harder than another checkbox UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Printable PDF.&lt;/strong&gt; Markdown is great for email/Keep. Standing in a kitchen I want one A4 page with checkboxes, not three files and a phone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pantry is a JSON file.&lt;/strong&gt; Deliberately dumb. Easy to edit by hand when the model’s quantity guesses are wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sassy, not mean.&lt;/strong&gt; Prompt rules: roast laziness, leave bodies/culture alone. The model still occasionally invents “Rice and Chicken (Almost)” when there’s no chicken, which is why the prompt now says: if it’s in the title, it has to be in pantry or on the shopping list.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Gemma / Ollama
&lt;/h3&gt;

&lt;p&gt;I already run Ollama. &lt;code&gt;gemma3:4b&lt;/code&gt; is small enough for a morning habit and good enough at structured JSON if you ask clearly and validate the three meal slots. Config is one line if I want &lt;code&gt;gemma3:12b&lt;/code&gt; later. Same code path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Privacy.&lt;/strong&gt; My fridge contents and “I skipped spinach again” habits are not a product telemetry event. They stay in &lt;code&gt;data/pantry.json&lt;/code&gt; on disk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Offline.&lt;/strong&gt; Breakfast planning should not fail because the API is rate-limited. Laptop + Ollama is enough.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost.&lt;/strong&gt; A daily meal plan against a paid API is a subscription I would cancel in week two. Local weights = free after the hardware I already own.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swapability.&lt;/strong&gt; Open weights mean I can change the model without rewriting the app or begging a vendor. That matters more for a habit tool than for a one-off demo.&lt;/p&gt;

&lt;p&gt;Closed APIs are fine when you need the absolute best model and you’re okay shipping your life to someone else’s GPU. For “what do I cook from this sad pantry,” open + local won on privacy and “set it once.”&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; daily plans run through Gemma via Ollama (&lt;code&gt;gemma3:4b&lt;/code&gt; default, model override in &lt;code&gt;config.toml&lt;/code&gt; / &lt;code&gt;--model&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Small models still hallucinate a missing ingredient into a meal title if you don’t constrain them&lt;/li&gt;
&lt;li&gt;Pantry quantities are approximate (“4 eggs left”) so not a real inventory system with barcodes&lt;/li&gt;
&lt;li&gt;PDF is English / Latin-friendly via DejaVu when available; other scripts may need a font tweak&lt;/li&gt;
&lt;li&gt;No nutrition tracking, no fancy UI for this demo&lt;/li&gt;
&lt;li&gt;Cron is on you; the tool doesn’t install a daemon&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you also open the fridge, stare for thirty seconds, and then order something, this might save you that stare.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Wed, 14 Oct 2026 15:33:41 +0000</pubDate>
      <link>https://dev.to/mohamedation/-2kgh</link>
      <guid>https://dev.to/mohamedation/-2kgh</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1" class="crayons-story__hidden-navigation-link"&gt;Invoico - yet another invoice and receipts assistant&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mohamedation" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F752009%2F24c3e347-392c-40b7-96f4-88cf38b492f5.jpeg" alt="mohamedation profile" class="crayons-avatar__image" width="460" height="460"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mohamedation" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mohamed Adel
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mohamed Adel
                
                
              
              &lt;div id="story-author-preview-content-4848725" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mohamedation" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F752009%2F24c3e347-392c-40b7-96f4-88cf38b492f5.jpeg" class="crayons-avatar__image" alt="" width="460" height="460"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mohamed Adel&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1" id="article-link-4848725"&gt;
          Invoico - yet another invoice and receipts assistant
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>showdev</category>
      <category>softwaredevelopment</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Invoico - yet another invoice and receipts assistant</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Wed, 14 Oct 2026 09:35:48 +0000</pubDate>
      <link>https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1</link>
      <guid>https://dev.to/mohamedation/invoico-yet-another-invoice-and-receipts-assistant-5go1</guid>
      <description>&lt;p&gt;This is my participation in the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest 2026 Open-Source AI Challenge — Week 2 (Side Hustle)&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;I'm mohamedation, and I built &lt;strong&gt;Invoico&lt;/strong&gt; for the challenge: a local invoice and receipt helper (another one, yes i know). The theme this week is side hustle, so the project had to be something you could imagine turning into a small product — with open weights in the loop, and some real measurement to back it up.&lt;/p&gt;

&lt;p&gt;The problem I invisioned is pretty ordinary and common. Every few months there is a folder of invoice PDFs and phone photos of receipts, and then someone has to type vendor, date, net, VAT, gross into a spreadsheet. Those files are private. Pushing them through a closed vision API just to skip a boring afternoon of data entry never sat right with me. So for this challenge I built something that stays local. It can be turned into a self hosted or a packaged software and with minor automations, it can work as just taking a photo of the reciept and it automatically extract the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You drop in a PDF, JPG, or PNG. A local open-weight vision model through Ollama (Gemma) reads the page and pulls out the fields — including line items, cash tendered, and change, because till slips love to print a big Cash number that is &lt;em&gt;not&lt;/em&gt; the bill. Plain Python then checks whether net + VAT roughly equals gross, whether the line items add up, and whether someone mixed up cash with the total. You review, confirm (notes stick around if you confirm a mismatch as-is), edit or delete later, and export a CSV.&lt;/p&gt;

&lt;p&gt;There is also an Overview with charts, and an Analyze step where the same local model looks at the spend snapshot and writes a short briefing. Mixed currencies get an EUR estimate from a static ECB rate file (demo only — more on that below).&lt;/p&gt;

&lt;p&gt;Nothing goes out to a cloud API for inference. That was the design from the start for the challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the side hustle angle fits the challenge
&lt;/h2&gt;

&lt;p&gt;Week 2 asks you to think about the product shape, not only the demo. Here is the path I would take if this ever left the challenge folder.&lt;/p&gt;

&lt;p&gt;Not SaaS. User accounts and a shared database would put invoices on someone else's servers, which fights the whole local-first idea.&lt;/p&gt;

&lt;p&gt;Not a heavy self-hosted enterprise thing either. The compose file is in the repo if you want to run it that way, but that is not the story.&lt;/p&gt;

&lt;p&gt;For a side hustle, packaged software fits better: install it (or one compose up), Ollama locally, SQLite locally. One-time license, or yearly if updates matter when models change. Inference stays on the user's hardware, so there is no per-document cloud bill to pass on. The repo is MIT either way — this challenge entry is open source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Cl_LL_XIZYI" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In the video I walk through uploading a clean invoice, the intentional bad-math sample, confirming a mismatch so the note stays, a real till receipt where Total ≠ Cash, then Overview and Analyze.&lt;/p&gt;

&lt;p&gt;A few screenshots:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu47nbt2v7z7yxx3q1w3t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu47nbt2v7z7yxx3q1w3t.jpg" alt="Overview — spend at a glance" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj8p4rvhgus6yn42ewdfx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj8p4rvhgus6yn42ewdfx.jpg" alt="Invoices — filter, edit, CSV export" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb4lv6k3n4k8um6jusm6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpb4lv6k3n4k8um6jusm6.jpg" alt="Analyze — local model briefing" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/mohamedation" rel="noopener noreferrer"&gt;
        mohamedation
      &lt;/a&gt; / &lt;a href="https://github.com/mohamedation/invoico" rel="noopener noreferrer"&gt;
        invoico
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local invoices. local AI
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Invoico&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Local invoice &amp;amp; receipt assistant. Drop in a PDF or a phone photo, a vision model on your machine pulls out the fields, Python checks the math, you confirm, and you get a CSV for the accountant.&lt;/p&gt;
&lt;p&gt;Nothing is sent to a cloud API. That is the product.&lt;/p&gt;
&lt;p&gt;I built this for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12" rel="nofollow"&gt;Hacktoberfest 2026 Open-Source AI Challenge — Week 2 (Side Hustle)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://youtu.be/Cl_LL_XIZYI" rel="nofollow noopener noreferrer"&gt;https://youtu.be/Cl_LL_XIZYI&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mohamedation/invoico/docs/screenshots/overview.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmohamedation%2Finvoico%2FHEAD%2Fdocs%2Fscreenshots%2Foverview.jpg" alt="Overview"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mohamedation/invoico/docs/screenshots/invoices.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmohamedation%2Finvoico%2FHEAD%2Fdocs%2Fscreenshots%2Finvoices.jpg" alt="Invoices"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/mohamedation/invoico/docs/screenshots/analyze.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmohamedation%2Finvoico%2FHEAD%2Fdocs%2Fscreenshots%2Fanalyze.jpg" alt="Analyze"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Side hustle (where this actually goes)&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This is &lt;strong&gt;not&lt;/strong&gt; a SaaS. I am not spinning up user accounts and a shared database so your invoices sit on my servers — that would throw away the whole privacy angle.&lt;/p&gt;
&lt;p&gt;It is also not an enterprise self-hosted platform. Freelancers do not want to babysit Postgres for a receipt folder.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The real product shape is packaged software:&lt;/strong&gt; you install it (or &lt;code&gt;docker compose up&lt;/code&gt;), Ollama runs on your machine, SQLite stays local. Pay once for…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/mohamedation/invoico" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama pull gemma3:4b
docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;span class="c"&gt;# or uvicorn + streamlit — see the README&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stack is FastAPI + Streamlit + Ollama + SQLite. Compose runs the API and UI; Ollama stays on the host. &lt;code&gt;pytest -q&lt;/code&gt; is green (15 tests).&lt;/p&gt;

&lt;h2&gt;
  
  
  How it came together
&lt;/h2&gt;

&lt;p&gt;The flow looks roughly like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Upload a receipt or invoice (PDF or image)
       - Prepare the file for processing
       - Use Ollama Vision to extract invoice details and line items
       - Check and correct totals, change, and item sums when needed
       - Validate net amount, VAT, line items, and gross total
       - Save to SQLite, updating existing records with the same hash or invoice number
       - Review everything in the Invoices section
       - Optionally, generate an analysis summary
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few things that i noticed:&lt;/p&gt;

&lt;p&gt;Dumping the full Pydantic JSON Schema into Ollama's &lt;code&gt;format&lt;/code&gt; made the small model just… drop fields. A hand-written (and AI cleaned) compact schema fixed that.&lt;/p&gt;

&lt;p&gt;Gemma 4's "thinking" mode burned the token budget on chain-of-thought and came back with empty &lt;code&gt;content&lt;/code&gt; so i used &lt;code&gt;think=False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On real till receipts from the data set &lt;a href="https://huggingface.co/datasets/jsdnrs/ICDAR2019-SROIE" rel="noopener noreferrer"&gt;https://huggingface.co/datasets/jsdnrs/ICDAR2019-SROIE&lt;/a&gt; small models kept putting Cash tendered or even a store ID like &lt;code&gt;1950&lt;/code&gt; into the gross amount. I ended up with three layers: clearer prompt, extract cash / change / line items as their own fields, then Python recovery (&lt;code&gt;cash − change&lt;/code&gt; or sum of product lines).&lt;/p&gt;

&lt;p&gt;Extraction was the obvious model call. Analyze is the second one it builds a spend snapshot. Felt more useful and somewht unique instead of just another sorter or AI OCR."&lt;/p&gt;

&lt;h2&gt;
  
  
  Numbers
&lt;/h2&gt;

&lt;p&gt;I labelled a small set under &lt;code&gt;eval/ground_truth.csv&lt;/code&gt;: four synthetic invoices in &lt;code&gt;samples/&lt;/code&gt; plus three real scanned till slips (Malaysian cash bills from the huggingface dataset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nb"&gt;eval&lt;/span&gt;/run_eval.py &lt;span class="nt"&gt;--compare&lt;/span&gt; gemma4:e2b gemma3:4b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Head-to-head (same images, same prompt)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Core exact*&lt;/th&gt;
&lt;th&gt;Gross accuracy&lt;/th&gt;
&lt;th&gt;Cash vs total correct†&lt;/th&gt;
&lt;th&gt;Avg s/doc&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;gemma3:4b&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0.857&lt;/strong&gt; (6/7)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3/3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gemma4:e2b&lt;/td&gt;
&lt;td&gt;0.571 (4/7)&lt;/td&gt;
&lt;td&gt;0.571&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0/3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1.22&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*Core exact = vendor + gross + currency all right on the same document.&lt;br&gt;&lt;br&gt;
†On the three real slips that print both a bill total and a cash/change block.&lt;/p&gt;

&lt;h3&gt;
  
  
  Field accuracy (gemma3:4b)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Accuracy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;currency&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gross_amount&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cash_tendered&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;change_amount&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net_amount&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vat_amount&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vat_rate&lt;/td&gt;
&lt;td&gt;1.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;issue_date&lt;/td&gt;
&lt;td&gt;0.86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invoice_no&lt;/td&gt;
&lt;td&gt;0.86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vendor&lt;/td&gt;
&lt;td&gt;0.86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;doc_type&lt;/td&gt;
&lt;td&gt;0.71&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Per document (gemma3:4b)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;th&gt;Gross pred&lt;/th&gt;
&lt;th&gt;Cash pred&lt;/th&gt;
&lt;th&gt;Core&lt;/th&gt;
&lt;th&gt;Seconds&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;invoice_cloudtools.png&lt;/td&gt;
&lt;td&gt;synthetic&lt;/td&gt;
&lt;td&gt;119.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;2.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invoice_us_hosting.png&lt;/td&gt;
&lt;td&gt;synthetic&lt;/td&gt;
&lt;td&gt;49.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;1.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invoice_bad_math.png&lt;/td&gt;
&lt;td&gt;synthetic&lt;/td&gt;
&lt;td&gt;250.00&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;2.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;receipt_cafe.png&lt;/td&gt;
&lt;td&gt;synthetic&lt;/td&gt;
&lt;td&gt;15.41&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;2.93&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image.jpg (BOOK TALK)&lt;/td&gt;
&lt;td&gt;real scan&lt;/td&gt;
&lt;td&gt;9.00&lt;/td&gt;
&lt;td&gt;10.00&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;2.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image (1).jpg (McD)&lt;/td&gt;
&lt;td&gt;real scan&lt;/td&gt;
&lt;td&gt;26.60&lt;/td&gt;
&lt;td&gt;100.00&lt;/td&gt;
&lt;td&gt;no‡&lt;/td&gt;
&lt;td&gt;3.73&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image (3).jpg (Bar Wang)&lt;/td&gt;
&lt;td&gt;real scan&lt;/td&gt;
&lt;td&gt;8.20&lt;/td&gt;
&lt;td&gt;8.20&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;3.17&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;‡Amounts are right (total 26.60, cash 100.00, change 73.40). Core failed because the vendor came back as the legal entity (&lt;code&gt;Gerbang Alaf Restaurants Sdn Bhd&lt;/code&gt;) plus a store number, not the short name &lt;code&gt;McDonald&lt;/code&gt; I had in the labels. Wrong label match, not a wrong total.&lt;/p&gt;

&lt;h3&gt;
  
  
  Same real slips on gemma4:e2b
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Truth gross&lt;/th&gt;
&lt;th&gt;e2b gross&lt;/th&gt;
&lt;th&gt;e2b cash&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BOOK TALK&lt;/td&gt;
&lt;td&gt;9.00&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;18.00&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;10.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;McDonald's&lt;/td&gt;
&lt;td&gt;26.60&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;53.20&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;(wrong / missing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bar Wang Rice&lt;/td&gt;
&lt;td&gt;8.20&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3.30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Faster, sure (about 1.2s per doc), but on till receipts it was a mess. So the default in the repo is &lt;code&gt;gemma3:4b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Line items are a useful second opinion when the model grabs a store ID or doubles something. And validation still matters; the synthetic bad-math invoice (&lt;code&gt;net 200 + VAT 40 ≠ gross 250&lt;/code&gt;) is supposed to stay in review.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open weights
&lt;/h2&gt;

&lt;p&gt;Privacy first — invoices do not need a cloud vision hop.&lt;/p&gt;

&lt;p&gt;Cost is next after you have the hardware, another document is basically free which i think the future will lean more towards this.&lt;/p&gt;

&lt;p&gt;And control: could swap &lt;code&gt;gemma4:e2b&lt;/code&gt; for &lt;code&gt;gemma3:4b&lt;/code&gt;, re-run the same labelled set or improve your review time and so on.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — extraction and analyze both go through Gemma via Ollama (&lt;code&gt;gemma3:4b&lt;/code&gt; by default; e2b still around for comparison) and i might test more open weights models later.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick FX note
&lt;/h3&gt;

&lt;p&gt;Overview and Analyze convert mixed currencies to EUR using &lt;code&gt;fx/eurofxref.csv&lt;/code&gt; which is a static ECB snapshot (demo, dated &lt;strong&gt;13 October 2026&lt;/strong&gt;). Not live FX, not auto-updated, not for real bookkeeping or tax. Native currency totals stay visible next to the estimate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still rough
&lt;/h2&gt;

&lt;p&gt;The labelled set is small, and real phone photos will keep being messier than the clean samples.&lt;/p&gt;




&lt;p&gt;That is my Week 2 entry. Repo and demo are linked above. As always, any feedback is much appreciated.&lt;/p&gt;

</description>
      <category>hf26challenge</category>
      <category>devchallenge</category>
    </item>
    <item>
      <title>Twitter Replying Bot that generates color grids</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Wed, 02 Nov 2022 14:30:01 +0000</pubDate>
      <link>https://dev.to/mohamedation/twitter-replying-bot-that-generates-color-grids-9m8</link>
      <guid>https://dev.to/mohamedation/twitter-replying-bot-that-generates-color-grids-9m8</guid>
      <description>&lt;p&gt;Yet another tweepy tutorial, but we are not complaining.&lt;/p&gt;

&lt;p&gt;a little background: i like to create random fractals art (NFT anyone) I can just can spend hours staring at one and seeing all different things. so what's a better way to share my creations? a twitter bot of course, but lets also make it do something else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fehslh96x6o1bwxrzio.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0fehslh96x6o1bwxrzio.gif" alt="Preview" width="572" height="900"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you can try it your self by tweeting 'make grid' to @machineation on twitter. the bot will hash your username then use it as a seed to generate a unique color grid based on the username. lets start.&lt;/p&gt;

&lt;p&gt;requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;python &amp;gt;= 3.10&lt;/li&gt;
&lt;li&gt;twitter developer account (not covered in the tutorial)&lt;/li&gt;
&lt;li&gt;tweepy&lt;/li&gt;
&lt;li&gt;numpy&lt;/li&gt;
&lt;li&gt;pillow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;if your not familiar with twitter developer account, please &lt;a href="https://developer.twitter.com/en/support/twitter-api/developer-account" rel="noopener noreferrer"&gt;Check this&lt;/a&gt; because creating the developer account, app, and getting the authentication are not covered in this tutorial.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;lets start by installing  the required packages..feel free to use virtual environment or pip3 if you have both version of python.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install tweepy numpy pillow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after everything is installed, lets create a file called "bot.py" but you can name yours anything you like, and then lets import what we will need.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after that, we need to add the authentication and create the API object using tweepy. you can read about the tweepy authentication in the &lt;a href="https://docs.tweepy.org/en/stable/authentication.html" rel="noopener noreferrer"&gt;docs&lt;/a&gt; but essientially, you need the API Key, API Key Secret, Access Token and Access Token Secret  &lt;/p&gt;

&lt;p&gt;&lt;em&gt;your keys are secret. don't include them in the script and upload them to to any publicly visible cloud. use .env or some other method to keep secrets. for simplicity, the tutorial doesn't cover that&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OAuthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#create API object
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_on_rate_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;wait_on_rate_limit – Whether or not to automatically wait for rate limits to replenish&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order not to reply to the same tweet multiple times and also to get only the mentions that the bot haven't seen yet, we will make sure to save the last mention tweet id. We will save it to a file so that even if we stopped the bot and then resumed, we will start from the mentions we haven't seen yet, not from the beginning.&lt;br&gt;
Let's create 2 functions. One for reading the id from file and one to store the id.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;file_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;last_seen_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;file_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;last_seen_id&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_seen_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_seen_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the first function for reading the id takes one parameter which is the file name, and the function to store the id takes 2 parameters, the file name and the id. in the future, if you want to have more functions that store and read different things, you can call the same functions and changing the parameters and we would change "last_seen_id" with "data" for example.&lt;/p&gt;

&lt;p&gt;Now, Lets create the function to create the colors grid from the username. I opted to code it as a separate function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate 100x100 grid of random colours
&lt;/span&gt;    &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;im&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;resample&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NEAREST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grids/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;"handle": the parameter that will be the username that we will pass to the function.&lt;/li&gt;
&lt;li&gt;"hash": we will hash the username using sha256 to use it as a random seed for numpy.&lt;/li&gt;
&lt;li&gt;"grid": using numpy, we create a grid with random colors (seeded with the username hash). you can make it any size you want.&lt;/li&gt;
&lt;li&gt;"im": using pillow to create the 1600x1600 image from the data. you can use any size you want.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;we then save the png image in a folder in the same directory called "grids" with the username as the file name.&lt;/p&gt;

&lt;p&gt;Next step, let's create the function that will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch the mentions since last stored tweet id.&lt;/li&gt;
&lt;li&gt;Loop over the mentions.&lt;/li&gt;
&lt;li&gt;Store the tweet id.&lt;/li&gt;
&lt;li&gt;Check if the tweet is not by our bot.&lt;/li&gt;
&lt;li&gt;Check if tweet contains specific words.&lt;/li&gt;
&lt;li&gt;Check if the tweet doesn't contain extra words and reply with a message if so.&lt;/li&gt;
&lt;li&gt;Reply to tweet depending on the matched word.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;this means you can expand the bot to do other things based on the tweet content (command). But first, we need to set some variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;grid_tweet&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;bot_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xxxxxxxxxxxx&lt;/span&gt;
    &lt;span class="n"&gt;FILE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grid_last_seen.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Here is your unique color grid, @{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;grid_unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@{} If you want a grid, You just need to tweet &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; to Me without any other words and I will create and send You one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;let's go over them:&lt;/p&gt;

&lt;h3&gt;
  
  
  bot_id
&lt;/h3&gt;

&lt;p&gt;we set this variable so that we can check if the tweet author is not our bot. this way we make sure that if our bot tweeted the same words we are looking for, the bot doesn't reply to itself. you can get the bot id through different ways, but here is a simple one&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Through the Browser&lt;br&gt;
you can go to the bot page on twitter, right click anywhere inside the page and click "Inspect" then search for "identifier" in the elements which will look something like this&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"identifier": "1572580999673831426"
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  FILE_NAME
&lt;/h3&gt;

&lt;p&gt;this is the file we will use to read and store the last mention tweet id. This will be used to call the functions we already created and pass the variable to them. We can then have different files for different functions if we want.&lt;/p&gt;

&lt;h3&gt;
  
  
  words
&lt;/h3&gt;

&lt;p&gt;The list of words we are looking for. you can add more separated with a comma. For our example we are only using "make grid".&lt;/p&gt;

&lt;h3&gt;
  
  
  message
&lt;/h3&gt;

&lt;p&gt;the message we are going to include in our reply. we are using {} at the end to format it later and add the username to it.&lt;/p&gt;

&lt;h3&gt;
  
  
  grid_unknown
&lt;/h3&gt;

&lt;p&gt;Another message if the tweet has extra words in addition to "make grid". also using {} to be formatted later with the username.&lt;/p&gt;

&lt;p&gt;now let's create the rest of the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Finding tweets that mention our bot
&lt;/span&gt;        &lt;span class="n"&gt;mentions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mentions_timeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;read_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="c1"&gt;# Iterating through each mention tweet
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mentions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Save the tweet id in the file
&lt;/span&gt;            &lt;span class="nf"&gt;store_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Check to see if the tweet author is not our bot
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;bot_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Check if the tweet has any of the words we defined in our list after converting the tweet to lower case
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Removes the first part of the mention which is our bot username like so @username
&lt;/span&gt;                    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="c1"&gt;# Act based on the matched word/command. can later be used to add more functionality.
&lt;/span&gt;                    &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="c1"&gt;# Prints the username and tweet
&lt;/span&gt;                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Creating Grid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Calls our make_grid function and passing the username.
&lt;/span&gt;                                &lt;span class="nf"&gt;make_grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Set the media to the image created by our function
&lt;/span&gt;                                &lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grids/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attempting to reply...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Reply with the message after formatting to include username and the media
&lt;/span&gt;                                &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_status_with_media&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_reply_to_status_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully replied :)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="c1"&gt;# Error handling. for now it just prints the error.
&lt;/span&gt;                            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;# If the tweet contains extra words in addition to our command
&lt;/span&gt;                        &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tweet contains other words&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Reply with the grid_unknown message
&lt;/span&gt;                                &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid_unknown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;in_reply_to_status_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully replied with explaination :)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Sleep for 2 minutes
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so at the end, our file will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;

&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OAuthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_access_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xxxx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#create API object
&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;wait_on_rate_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;read_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;file_read&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;last_seen_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="n"&gt;file_read&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;last_seen_id&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last_seen_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;w&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;last_seen_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;file_write&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt;    

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;make_grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sha256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;
    &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Generate 100x100 grid of random colours
&lt;/span&gt;    &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uint8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;im&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromarray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1600&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;resample&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resampling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NEAREST&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grids/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;grid_tweet&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;bot_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;xxxxxxxxxxxx&lt;/span&gt;
    &lt;span class="n"&gt;FILE_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grid_last_seen.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Here is your unique color grid, @{}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;grid_unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@{} If you want a grid, You just need to tweet &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; to Me without any other words and I will create and send You one.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Finding tweets that mention our bot
&lt;/span&gt;        &lt;span class="n"&gt;mentions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mentions_timeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;since_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;read_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; 
        &lt;span class="c1"&gt;# Iterating through each mention tweet
&lt;/span&gt;        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mentions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Save the tweet id in the file
&lt;/span&gt;            &lt;span class="nf"&gt;store_last_seen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FILE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# Check to see if the tweet author is not our bot
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;bot_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Check if the tweet has any of the words we defined in our list after converting the tweet to lower case
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Removes the first part of the mention which is our bot username like so @username
&lt;/span&gt;                    &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                    &lt;span class="c1"&gt;# Act based on the matched word/command. can later be used to add more functionality.
&lt;/span&gt;                    &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;make grid&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="c1"&gt;# Prints the username and tweet
&lt;/span&gt;                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; - &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Creating Grid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Calls our make_grid function and passing the username.
&lt;/span&gt;                                &lt;span class="nf"&gt;make_grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Set the media to the image created by our function
&lt;/span&gt;                                &lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grids/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attempting to reply...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Reply with the message after formatting to include username and the media
&lt;/span&gt;                                &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_status_with_media&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;in_reply_to_status_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully replied :)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="c1"&gt;# Error handling. for now it just prints the error.
&lt;/span&gt;                            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="c1"&gt;# If the tweet contains extra words in addition to our command
&lt;/span&gt;                        &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tweet contains other words&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="c1"&gt;# Reply with the grid_unknown message
&lt;/span&gt;                                &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grid_unknown&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;screen_name&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;in_reply_to_status_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mention&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully replied with explaination :)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                                &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Sleep for 2 minutes
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The mighty Machineation is starting...&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;grid_tweet&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that's it..now all you have to do is start it with:&lt;br&gt;
&lt;code&gt;pyhton bot.py&lt;/code&gt;&lt;br&gt;
and tweet from a different account to your bot saying "make grid" and it should reply in a couple of minutes with the color grid.&lt;/p&gt;

</description>
      <category>python</category>
      <category>twitter</category>
      <category>tutorial</category>
      <category>tweepy</category>
    </item>
    <item>
      <title>Twitter Bot that is generating unique color grids</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Thu, 27 Oct 2022 15:18:51 +0000</pubDate>
      <link>https://dev.to/mohamedation/twitter-bot-that-is-generating-unique-color-grids-3735</link>
      <guid>https://dev.to/mohamedation/twitter-bot-that-is-generating-unique-color-grids-3735</guid>
      <description>&lt;p&gt;The NFT craze came and went and whether you believe in them or not, no one can deny the possibilities and the coding behind the technology.&lt;br&gt;
I have always been amazed by Fractals and random computer generated art.so what is better than creating a twitter bot that shares the Fractals I generate with the world? a bot that responds to mentions and generate something.&lt;/p&gt;

&lt;p&gt;The basic and simple idea behind it is by using tweepy and creating a bot that fetches mentions and check if certain words (command) and then creates something and send it back to the user who tweeted at the bot. that is exactly what I did..just for fun.&lt;/p&gt;

&lt;p&gt;if you mention @machineation on twitter with "make grid" then the bot will take your twitter username, hash it, then create a random color grid seeded by the username.&lt;/p&gt;

&lt;p&gt;I don't know if that would be an interesting post/tutorial to show how to code such a bot. If anyone is interested, then i will invest some time in it for sure.&lt;/p&gt;

</description>
      <category>python</category>
      <category>twitter</category>
      <category>art</category>
      <category>bot</category>
    </item>
    <item>
      <title>Personal Website</title>
      <dc:creator>Mohamed Adel</dc:creator>
      <pubDate>Tue, 31 May 2022 18:28:03 +0000</pubDate>
      <link>https://dev.to/mohamedation/by-developer-for-developers-45gg</link>
      <guid>https://dev.to/mohamedation/by-developer-for-developers-45gg</guid>
      <description>&lt;p&gt;i have been playing with computers all my life. i am from the late dial-up internet era. the modem dialing sounds still feel like the beginning of an adventure to me.&lt;/p&gt;

&lt;p&gt;i had the opportunity to shift careers in the last couple of years and got a nice deal freelancing remotely for a abroad company, doing web developments. i manage the server side of things and do what every full stack developer does..breaks things, then fix them.&lt;/p&gt;

&lt;p&gt;the idea was to get my freelancing career started and have some extra job on the side, so where does that begins? a website of course.&lt;/p&gt;

&lt;p&gt;easier said than done. life happens and i find myself stuck between completing tasks, fighting through life, or just napping..with the occasional gaming now and then (eve online, csgo anyone?) &lt;/p&gt;

&lt;p&gt;i still don't know what i can show in my portfolio and what not, so i just wanted to get one going. so i worked on something that has a tribute to couple of things that a like, and an Easter egg...all would be kinda appreciated by fellow developers and geeks, but not so much for any potential clients. its a lot of fun doing stuff like that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mohamedation.com" rel="noopener noreferrer"&gt;mohamedation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>portfolio</category>
      <category>html</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
