<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Omar Moustafa]]></title><description><![CDATA[Hiya! A passionate full-stack developer]]></description><link>https://omarcodes.io</link><generator>RSS for Node</generator><lastBuildDate>Wed, 15 Apr 2026 21:03:30 GMT</lastBuildDate><atom:link href="https://omarcodes.io/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Introducing recode: Your Personal Snippet Brain]]></title><description><![CDATA[Ever copy-paste the same snippet for the hundredth time, that you just hated it? We’ve all been there—digging through old projects, Slack threads, or random gists just to grab that one regex or API helper.
Meanwhile, sharing snippets with teammates? ...]]></description><link>https://omarcodes.io/recode</link><guid isPermaLink="true">https://omarcodes.io/recode</guid><category><![CDATA[Appwrite]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Fri, 24 Oct 2025 13:42:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761310827175/a7f4639e-61aa-4098-9d7a-0ffe3181df2e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Ever copy-paste the same snippet for the hundredth time, that you just hated it?</strong> We’ve all been there—digging through old projects, Slack threads, or random gists just to grab that one regex or API helper.</p>
<p><strong>Meanwhile, sharing snippets with teammates?</strong> Still a screenshot or a mess of copy-paste jobs.</p>
<p><strong>Meet recode.</strong> Your always-on snippet HQ built for busy developers.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/the-office-john-krasinski-jim-halpert-HABSzzvvRrDmU">https://giphy.com/gifs/the-office-john-krasinski-jim-halpert-HABSzzvvRrDmU</a></div>
<p> </p>
<h2 id="heading-how-i-got-the-idea">How I got the idea</h2>
<p><strong>A few weeks back</strong>, the idea hit us during yet another frantic search through terminal history:</p>
<p><strong><em>Why are we still treating snippets like disposable notes?</em></strong></p>
<p>What if we had a dedicated, beautiful space to <strong>save, search, tag, and reuse</strong> snippets instantly—without losing structure or syntax highlighting? <em>That’s how recode was born.</em> 🔥</p>
<h2 id="heading-how-recode-works">How recode Works</h2>
<p><strong>Drop in a snippet, give it a home, and reuse it everywhere.</strong> 🚀</p>
<p>Here’s how it all comes together:</p>
<ol>
<li><p><strong>Add</strong> – Paste your snippet, name it, pick a language, drop in tags.</p>
</li>
<li><p><strong>Save</strong> – recode stores it securely in Appwrite Databases with secure permissions.</p>
</li>
<li><p><strong>Find</strong> – Use tag filters, instant search, or command palette to surface snippets in milliseconds.</p>
</li>
<li><p><strong>Reuse</strong> – Copy, share, duplicate, or edit right from the dashboard.</p>
</li>
</ol>
<p>Need to see it in action? In just one session we migrated our crustiest clipboard history into a polished snippet library—and never looked back.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/hq8NHYI7J8c">https://youtu.be/hq8NHYI7J8c</a></div>
<p> </p>
<h3 id="heading-import-export-json">Import / Export (JSON)</h3>
<p>Export your snippet library as a single JSON file for backups, sharing, or migration. Importing validates and normalizes entries, lets you review changes, and preserves tags, languages, and timestamps. ❤️‍🩹</p>
<p>Quick UX</p>
<ul>
<li>Dashboard → Import/Export → Export JSON / Upload JSON → Done</li>
</ul>
<p>Example JSON (array of snippets):</p>
<pre><code class="lang-json">[
  {
    <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Readable snippet title"</span>,
    <span class="hljs-attr">"code"</span>: <span class="hljs-string">"// raw code as a single string"</span>,
    <span class="hljs-attr">"language"</span>: <span class="hljs-string">"typescript"</span>,
    <span class="hljs-attr">"tags"</span>: [<span class="hljs-string">"ui"</span>, <span class="hljs-string">"hooks"</span>]
  }
]
</code></pre>
<ul>
<li><code>title</code> (string) – required.</li>
<li><code>code</code> (string) – required.</li>
<li><code>language</code> (string) – optional; when omitted we auto-detect the language during import.</li>
<li><code>tags</code> (string array) – optional; defaults to an empty list when missing.</li>
</ul>
<p>Any invalid entries are skipped; you’ll get a toast with the number of imported snippets once processing completes.</p>
<h2 id="heading-challenges-along-the-way">Challenges Along the Way</h2>
<ul>
<li><p><strong>Real-time feel with server-first data.</strong><br />  Appwrite’s Tables API is powerful, but keeping the UX snappy meant carefully batching calls and normalizing responses for React state.</p>
</li>
<li><p><strong>Securing user data without slowing them down.</strong><br />  We leaned on Appwrite Auth for email flows but built custom guards to keep snippet access fast and private.</p>
</li>
<li><p><strong>Turning static content into an engaging workflow.</strong><br />  Snippets needed to feel “alive.” Animations powered by Framer Motion add just enough delight without slowing down productivity.</p>
</li>
</ul>
<h2 id="heading-why-appwrite-nextjs">Why Appwrite + Next.js?</h2>
<p>We wanted a serverless stack with solid auth, a modern UI pipeline, and rapid iteration:</p>
<ul>
<li><p><strong>Appwrite Cloud</strong> handles authentication, database (Tables), permissions, and storage.</p>
</li>
<li><p><strong>Next.js 15 App Router</strong> powers routing, streaming, and SEO.</p>
</li>
<li><p><strong>Appwrite SDK</strong> keeps client/server logic tightly integrated with typed responses.</p>
</li>
</ul>
<h2 id="heading-the-tech-stack-why-we-love-it">The Tech Stack (+ Why We Love It)</h2>
<ul>
<li><p><strong>Next.js 15</strong> – App Router, server components, route groups.</p>
</li>
<li><p><strong>TypeScript</strong> – End-to-end types, safer Appwrite SDK usage.</p>
</li>
<li><p><strong>Tailwind + shadcn/ui</strong> – Rapid iteration with polished, accessible components.</p>
</li>
<li><p><strong>Framer Motion</strong> – Page/page transitions, modals, subtle feedback.</p>
</li>
<li><p><strong>Appwrite</strong> – Auth, TablesDB, Realtime (coming soon for collaboration).</p>
</li>
<li><p><strong>Radix UI + Lucide</strong> – Accessible primitives and sharp iconography.</p>
</li>
<li><p><strong>Zod</strong> – Validation for snippet payloads and forms.</p>
</li>
</ul>
<h2 id="heading-coming-soon-recode-api-cli">🚀 Coming Soon: recode API + CLI</h2>
<p>We’re wrapping up a lightweight API so you can sync snippets directly from your editor or CI.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># prototype CLI flow</span>
recode login
recode snippet add ./handlers/fetchData.ts --tags utils fetch nextjs
recode snippet search auth --copy
</code></pre>
<p>Watch the repo—API keys and SDK docs are on deck.</p>
<h2 id="heading-quote-i-live-by"><strong>Quote I Live By</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1761313207195/bf5be339-0c4f-4271-a5be-82fef1eda084.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p><strong><em>Ship small, ship often.</em></strong><br /><em>You don’t need a 10x feature—just make the next commit undeniable.</em></p>
</blockquote>
<h2 id="heading-try-recode-yourself"><strong>Try recode Yourself</strong> ⚡️</h2>
<ul>
<li><p><a target="_blank" href="https://recode.appwrite.network/"><strong>recode Web App</strong></a></p>
</li>
<li><p><a target="_blank" href="https://github.com/Omar8345/recode"><strong>GitHub</strong></a></p>
</li>
</ul>
<p>Let recode handle the snippet chaos, so you can stay focused on building the future.</p>
]]></content:encoded></item><item><title><![CDATA[How Hashnode AI helped me to write better]]></title><description><![CDATA[Hey folks! Thanks for reading my article, today I'm going to talk about how using the Hashnode AI has helped me in writing articles and saving time.
So without further wasting time, let's start diving into the content! 🐋
How Hashnode AI affected my ...]]></description><link>https://omarcodes.io/how-hashnode-ai-helped-me-to-write-better</link><guid isPermaLink="true">https://omarcodes.io/how-hashnode-ai-helped-me-to-write-better</guid><category><![CDATA[WeMakeDevs]]></category><category><![CDATA[hashnode AI]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 28 May 2023 06:04:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1685253434700/edf9b674-69a7-40e6-b7bc-13b8414a46cb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey folks! Thanks for reading my article, today I'm going to talk about how using the Hashnode AI has helped me in writing articles and saving time.</p>
<p>So without further wasting time, let's start diving into the content! 🐋</p>
<h2 id="heading-how-hashnode-ai-affected-my-blog">How Hashnode AI affected my blog</h2>
<p>Hashnode AI can help in writing your article by providing SEO-friendly content/titles, it generates awesome introductions and outros since I started using Hashnode AI, I have noticed that the articles that I used Hashnode AI to write, got more views than other articles that have been written without using the Hashnode AI.</p>
<h2 id="heading-how-hashnode-ai-affected-me">How Hashnode AI affected me</h2>
<p>Hashnode AI has helped me to save time in writing articles, also I have been using Rix, it's an AI chatbot that can help me while coding JavaScript, TypeScript, and more!</p>
<p>Although it is still under development and it might provide misleading responses, sometimes it provides helpful responses, also Hashnode AI helped me to write articles, and it can write for me sections that Hashnode AI is capable of writing, for example, Hashnode AI might have written the section of <strong>Debugging Tools Based on AI</strong> in my article of <a target="_blank" href="https://omardevblog.toolsandapps4us.site/the-future-of-debugging-with-ai-and-machine-learning#heading-debugging-tools-based-on-ai"><strong>The Future of Debugging with AI and Machine Learning</strong></a>, the Hashnode AI might have written it, but I might have to double-check if the provided tools are available and providing the debugging experience with AI and Machine Learning or not.</p>
<h2 id="heading-is-paying-for-hashnode-ai-worth-it">Is paying for Hashnode AI worth it?</h2>
<p>Hashnode AI's pricing is pretty good for $7/month, although for students who just consider coding as a hobby and don't generate an income, it might be a barrier for some, if you write a lot and you care about your stats and your time, I recommend you really should subscribe, while Hashnode Pro doesn't provide access to Hashnode AI only, while it provides Priority Support from Hashnode and more!</p>
<h2 id="heading-thanks-for-reading">Thanks for reading!</h2>
<p>Thanks for reading my article, I hope you learned more about Hashnode AI, and have considered whether to subscribe or not, thanks for your time, and have a nice day!</p>
<p>Cheers! 🎉</p>
]]></content:encoded></item><item><title><![CDATA[Next-level Security: Passwordless Authentication with Prisma]]></title><description><![CDATA[Originally published on DevDojo

Authentication is the most thing that a user does on a website, logging in or out, and it's necessary to take your application's authentication to the next level with password-less authentication. 🚀
This article will...]]></description><link>https://omarcodes.io/next-level-security-passwordless-authentication-with-prisma</link><guid isPermaLink="true">https://omarcodes.io/next-level-security-passwordless-authentication-with-prisma</guid><category><![CDATA[Security]]></category><category><![CDATA[prisma]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[PlanetScale]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 19 Mar 2023 17:01:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/3GZNPBLImWc/upload/41b3c85aea69860877fc6e5c18074b41.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>Originally published on DevDojo</em></p>
</blockquote>
<p><strong>Authentication</strong> is the most thing that a user does on a website, logging in or out, and it's necessary to take your application's authentication to the next level with password-less authentication. 🚀</p>
<p>This article will be covering how to take your application's authentication to the next level using <strong>Prisma</strong> and building an API for authentication!</p>
<h2 id="heading-creating-the-api">Creating the API</h2>
<ul>
<li><p>Start by creating a new <strong>Next.js</strong> app:</p>
<pre><code class="lang-bash">  npx create-next-app passwordless-authentication
  <span class="hljs-built_in">cd</span> passwordless-authentication
</code></pre>
</li>
</ul>
<p>After creating your <strong>Next.js</strong> app, it's time to create a new database, in this article, you'll use the free <strong>MySQL</strong> database provided by <a target="_blank" href="https://planetscale.com/"><strong>PlanetScale</strong></a>! 🔥</p>
<p>After you have created your database on <strong>PlanetScale</strong>, click on <strong>Connect</strong> and choose <strong>Prisma</strong> in the dropdown menu, copy both your <code>.env</code> and <code>schema.prisma</code> files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1679063576200/b1408a29-268b-40ec-85f5-932d426d5aa6.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Now, let's install <strong>Prisma</strong> in our <strong>Next.js</strong> app:</p>
<pre><code class="lang-bash">  yarn add prisma @prisma/client
</code></pre>
</li>
<li><p>Once done, let's initialize <strong>Prisma</strong>:</p>
<pre><code class="lang-bash">  yarn prisma init
</code></pre>
</li>
</ul>
<p>Now, replace the <code>schema.prisma</code> file located in <code>prisma/schema.prisma</code> with the schema you copied from <strong>PlanetScale</strong>, create a file called <code>.env</code> in the app's root and paste the <code>.env</code> file you copied too.</p>
<p>Finally, we have set up <strong>Prisma</strong>, we can start coding the actual <strong>API</strong>. 💙</p>
<p>First, let's create our model/table which defines what the things required for the user, add the following code to your <code>schema.prisma</code>:</p>
<pre><code class="lang-javascript">model User {
  id        Int      @id @<span class="hljs-keyword">default</span>(autoincrement())
  email     <span class="hljs-built_in">String</span>   @unique
  code     Int
  status   <span class="hljs-built_in">String</span>
}
</code></pre>
<p>After that, run:</p>
<pre><code class="lang-bash">yarn prisma db push
</code></pre>
<p>Once your <code>User</code> table is ready, it's time to code our API, first, we have to create <code>pages/api/newAccount.js</code> file which will handle our new account creation:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
  <span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">"nodemailer"</span>);
  <span class="hljs-keyword">const</span> { email } = req.body;
  <span class="hljs-comment">// Check if the email is already in use</span>
  prisma.User.findUnique({
    <span class="hljs-attr">where</span>: {
      <span class="hljs-attr">email</span>: email,
    },
  }).then(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (user) {
      res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Email already in use"</span> });
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-comment">// Create reusable transporter object using the default SMTP transport</span>
      <span class="hljs-keyword">let</span> transporter = nodemailer.createTransport({
        <span class="hljs-attr">host</span>: <span class="hljs-string">"smtp.gmail.com"</span>,
        <span class="hljs-attr">port</span>: <span class="hljs-number">465</span>,
        <span class="hljs-attr">secure</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// Use SSL</span>
        <span class="hljs-attr">auth</span>: {
          <span class="hljs-attr">user</span>: <span class="hljs-string">"someone@gmail.com"</span>,
          <span class="hljs-attr">pass</span>: <span class="hljs-string">"xxxxxxxxxxxxxxxxxx"</span>,
        },
      });

      <span class="hljs-comment">// Generate a random 6 digit code</span>
      <span class="hljs-keyword">const</span> code = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-number">100000</span> + <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">900000</span>);
      <span class="hljs-comment">// setup email data with unicode symbols</span>
      <span class="hljs-keyword">let</span> mailOptions = {
        <span class="hljs-attr">from</span>: <span class="hljs-string">"someone@gmail.com"</span>,
        <span class="hljs-attr">to</span>: email,
        <span class="hljs-attr">subject</span>: <span class="hljs-string">"Passless Auth Demo"</span>,
        <span class="hljs-attr">text</span>: <span class="hljs-string">`Your verification code is <span class="hljs-subst">${code}</span>`</span>,
        <span class="hljs-attr">html</span>: <span class="hljs-string">`&lt;b&gt;Your verification code is &lt;strong&gt;<span class="hljs-subst">${code}</span>&lt;/strong&gt;&lt;/b&gt;`</span>,
      };
      <span class="hljs-comment">// Send the email</span>
      transporter.sendMail(mailOptions, <span class="hljs-function">(<span class="hljs-params">error, info</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (error) {
          <span class="hljs-built_in">console</span>.log(error);
          res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Internal server error"</span> });
        } <span class="hljs-keyword">else</span> {
          <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message sent: %s"</span>, info.messageId);
          <span class="hljs-comment">// Respond with a message code sent</span>
          res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Code sent"</span> });
        }
      });

      <span class="hljs-comment">// Save the user to the database on model User</span>
      prisma.user
        .create({
          <span class="hljs-attr">data</span>: {
            <span class="hljs-attr">email</span>: email,
            <span class="hljs-attr">code</span>: code,
            <span class="hljs-attr">status</span>: <span class="hljs-string">"UNVERIFIED"</span>,
          },
        })
        .then(<span class="hljs-function">(<span class="hljs-params">user</span>) =&gt;</span> {
          <span class="hljs-comment">// Respond with a message code sent</span>
          res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Code sent"</span> });
        })
        .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
          <span class="hljs-built_in">console</span>.log(e);
          res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Internal server error"</span> });
        });
    }
  });
}
</code></pre>
<p>First of all, we are importing the <strong>Prisma</strong> client and creating a new client and defining <code>nodemailer</code> which we will use with <strong>Gmail SMTP</strong> to send emails to our users with the verification codes.</p>
<p>After that, it will create a new random verification code and save the email and code into Prisma, we use the email provided in the <code>POST</code> request and check first if the email is already in use, if it is, we return an error to the user, if not, the code sends an email to the user, if sent, it responds with status <code>202</code> and if such error occurs, it logs the error in the console and responds with status <code>500</code> with <code>Internal server error</code>.</p>
<p>That's how the new account creation system works!</p>
<p>Now, we have to allow the user to login into their accounts, so we create a new file at <code>pages/api/loginAccount.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
  <span class="hljs-keyword">const</span> nodemailer = <span class="hljs-built_in">require</span>(<span class="hljs-string">"nodemailer"</span>);
  <span class="hljs-keyword">const</span> { email } = req.body;
  <span class="hljs-comment">// Check if there is a user with the email</span>
  prisma.user
    .findUnique({
      <span class="hljs-attr">where</span>: {
        <span class="hljs-attr">email</span>: email,
      },
    })
    .then(<span class="hljs-keyword">async</span> (user) =&gt; {
      <span class="hljs-comment">// If there is a user with the email</span>
      <span class="hljs-keyword">if</span> (user) {
        <span class="hljs-comment">// Send the user a verification code</span>
        <span class="hljs-comment">// Create reusable transporter object using the default SMTP transport</span>
        <span class="hljs-keyword">let</span> transporter = nodemailer.createTransport({
          <span class="hljs-attr">host</span>: <span class="hljs-string">"smtp.gmail.com"</span>,
          <span class="hljs-attr">port</span>: <span class="hljs-number">465</span>,
          <span class="hljs-attr">secure</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">// Use SSL</span>
          <span class="hljs-attr">auth</span>: {
            <span class="hljs-attr">user</span>: <span class="hljs-string">"someone@gmail.com"</span>,
            <span class="hljs-attr">pass</span>: <span class="hljs-string">"xxxxxxxxxxxxxxxxxx"</span>,
          },
        });
        <span class="hljs-comment">// Generate a random 6 digit code</span>
        <span class="hljs-keyword">const</span> code = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-number">100000</span> + <span class="hljs-built_in">Math</span>.random() * <span class="hljs-number">900000</span>);
        <span class="hljs-comment">// setup email data with unicode symbols</span>
        <span class="hljs-keyword">let</span> mailOptions = {
          <span class="hljs-attr">from</span>: <span class="hljs-string">"someone@gmail.com"</span>,
          <span class="hljs-attr">to</span>: email,
          <span class="hljs-attr">subject</span>: <span class="hljs-string">"Passless Auth Demo"</span>,
          <span class="hljs-attr">text</span>: <span class="hljs-string">`Your verification code is <span class="hljs-subst">${code}</span>`</span>,
          <span class="hljs-attr">html</span>: <span class="hljs-string">`&lt;b&gt;Your verification code is &lt;strong&gt;<span class="hljs-subst">${code}</span>&lt;/strong&gt;&lt;/b&gt;`</span>,
        };
        <span class="hljs-comment">// Send the email</span>
        transporter.sendMail(mailOptions, <span class="hljs-function">(<span class="hljs-params">error, info</span>) =&gt;</span> {
          <span class="hljs-keyword">if</span> (error) {
            <span class="hljs-built_in">console</span>.log(error);
            res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Internal server error"</span> });
          } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Message sent: %s"</span>, info.messageId);
            <span class="hljs-comment">// Respond with a message code sent</span>
            res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Code sent"</span> });
          }
        });
        <span class="hljs-comment">// Update the user code</span>
        <span class="hljs-keyword">await</span> prisma.user.update({
          <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">email</span>: email,
          },
          <span class="hljs-attr">data</span>: {
            <span class="hljs-attr">code</span>: code,
            <span class="hljs-attr">status</span>: <span class="hljs-string">"UNVERIFIED"</span>,
          },
        });
        res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Code sent"</span> });
      }
      <span class="hljs-comment">// If there is no user with the email</span>
      <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">// Return an error</span>
        res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Email not found"</span> });
      }
    });
}
</code></pre>
<p>First, we define our <strong>Prisma</strong> client and <code>nodemailer</code>, after that, we check if there is such a user with the email, if there is, we send the user an email with the verification code and update the database, if not, we return <code>Email not found</code>.</p>
<p>Finally, we have to allow the users to verify their accounts either to login in or create new accounts, so create a file called <code>verifyAccount.js</code>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
  <span class="hljs-keyword">const</span> { email, code } = req.body;
  <span class="hljs-comment">// Check the code</span>
  prisma.user
    .findUnique({
      <span class="hljs-attr">where</span>: {
        <span class="hljs-attr">email</span>: email,
      },
    })
    .then(<span class="hljs-keyword">async</span> (user) =&gt; {
      <span class="hljs-keyword">if</span> (user) {
        <span class="hljs-comment">// If the user is already verified</span>
        <span class="hljs-keyword">if</span> (user.status === <span class="hljs-string">"VERIFIED"</span>) {
          res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Account already verified"</span> });
        }
        <span class="hljs-comment">// If the code is correct</span>
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (user.code === code) {
          <span class="hljs-comment">// Update the user status to verified</span>
          <span class="hljs-keyword">await</span> prisma.user.update({
            <span class="hljs-attr">where</span>: {
              <span class="hljs-attr">email</span>: email,
            },
            <span class="hljs-attr">data</span>: {
              <span class="hljs-attr">status</span>: <span class="hljs-string">"VERIFIED"</span>,
            },
          });
          res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Account verified"</span> });
        }
        <span class="hljs-comment">// If the code is incorrect</span>
        <span class="hljs-keyword">else</span> {
          res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"Incorrect code"</span> });
        }
      } <span class="hljs-keyword">else</span> {
        res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">error</span>: <span class="hljs-string">"No user found"</span> });
      }
    });
}
</code></pre>
<p>Also, here we define only the <strong>Prisma</strong> client, and we check if the code is correct, so we get the user and check the code, if it is correct, we verify the account, if not we return <code>Incorrect code</code>, if there is no user, we return <code>No user found</code>.</p>
<p>Now, you are ready to run your <strong>API</strong>, but first, you have to install <code>nodemailer</code>:</p>
<pre><code class="lang-bash">yarn add nodemailer
yarn dev
</code></pre>
<h2 id="heading-outro-source-code">Outro + Source Code</h2>
<p>Finally, we are done with this project, we have used <strong>Next.js</strong> to create our API and used Prisma to interact with our <strong>MySQL</strong> database provided by <strong>PlanetScale</strong>.</p>
<p><strong>GitHub Repo</strong>: <a target="_blank" href="https://github.com/Omar8345/passwordless-authentication/"><strong>Omar8345/passwordless-authentication/</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[The Future of Debugging with AI and Machine Learning]]></title><description><![CDATA[Hiya 👋. Are you curious to find out more about how debugging will change as a result of artificial intelligence and machine learning? This subject is a hot one in the software development world, and for good reason. As a developer who was once enthu...]]></description><link>https://omarcodes.io/the-future-of-debugging-with-ai-and-machine-learning</link><guid isPermaLink="true">https://omarcodes.io/the-future-of-debugging-with-ai-and-machine-learning</guid><category><![CDATA[DebuggingFeb]]></category><category><![CDATA[AI]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[debugging]]></category><category><![CDATA[Artificial Intelligence]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Thu, 16 Feb 2023 12:26:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1676556378108/8d4ea68e-ce68-4af8-9219-e3369ce47efb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hiya 👋. Are you curious to find out more about how debugging will change as a result of artificial intelligence and machine learning? This subject is a hot one in the software development world, and for good reason. As a developer who was once enthusiastic about debugging, I'm eager to share what I've learned about this fascinating subject with you. Now grab a seat, and prepare for a detailed examination of how AI and machine learning will alter debugging in the future! 🤖⚛️</p>
<h2 id="heading-introduction">Introduction</h2>
<p>A time-consuming and difficult part of software development is debugging. The application of Machine Learning (ML) and Artificial Intelligence (AI) to debugging, on the other hand, is creating new opportunities for enhancing and speeding up the process. In this article, the current state, advantages, disadvantages, restrictions, and ethical issues of AI and ML in debugging are discussed.</p>
<h2 id="heading-current-debugging-situation">Current Debugging Situation</h2>
<p>The classic method of debugging entails checking code by hand for errors, identifying them, and fixing them. This can be time-consuming and difficult when working with large and complex codebases. Debugging frameworks and integrated development environments (IDEs) have recently made the process easier to manage, but they still have certain limits in terms of their capacity to quickly and precisely identify errors.</p>
<p>A study found that since debugging code consumes roughly 75% of engineers' time, software development is significantly hindered. Debugging may therefore be made more effective and efficient by integrating AI and ML into the process. As a result, less time and effort might be needed to find and fix problems.</p>
<h2 id="heading-the-use-of-machine-learning-and-artificial-intelligence-to-debugging">The Use of Machine Learning and Artificial Intelligence to Debugging</h2>
<p>By automating a number of tasks, AI and ML-based debugging can speed up and enhance productivity. By learning from vast datasets, AI systems, for instance, may find patterns in the code that could indicate flaws or issues. This helps to find issues that human developers might miss, improving the accuracy and dependability of debugging.</p>
<p>Automated debugging tools are one method that has potential for utilizing AI in debugging. These tools help developers solve issues more quickly and precisely by examining code and identifying potential weaknesses using machine learning approaches. Automated testing is another area where AI could be used for debugging. Developers may ensure their code works correctly and find any errors prior to release by utilizing ML algorithms to generate test scenarios.</p>
<p>Studies show that there are numerous ways that debugging can benefit from AI and ML. As an illustration, they could aid in accelerating and enhancing the precision, scope, and efficacy of debugging. Delegating the simpler debugging tasks to the machines while developers concentrate on the more challenging ones, such as developing new features and improving the user experience, allows developers to work more productively and effectively.</p>
<h2 id="heading-machine-learning-and-ai-applications-for-debugging">Machine learning and AI applications for debugging</h2>
<p>Applications for AI and machine learning that require debugging include the following:</p>
<ol>
<li><p><strong>Better and faster debugging</strong>: AI and machine learning may hasten and improve the efficiency of debugging by automating the process of identifying and detecting flaws. Instead of wasting time debugging, developers can now concentrate on integrating new features and enhancing current ones.</p>
</li>
<li><p><strong>Increased Precision</strong>: With machine learning approaches, it is possible to uncover bugs that human developers might miss, improving the accuracy and dependability of the debugging process. The overall quality of the software may rise if fewer issues are resolved before they enter the production stage.</p>
</li>
<li><p><strong>Increased adaptability</strong>: Conventional debugging methods become less efficient as software development projects grow larger and more complex. By enabling the quick and precise discovery of errors in even the most complex codebases, AI and machine learning can help broaden the debugging process to meet the needs of larger projects.</p>
</li>
<li><p><strong>More effective use of developer resources</strong>: AI and machine learning can increase developer productivity and efficiency by automating a number of troubleshooting activities. This lets the machines handle the more tedious aspects of debugging while people concentrate on higher-level tasks like creating new features and enhancing the user experience.</p>
</li>
<li><p><strong>Continuous improvement</strong>: The debugging process can teach AI and machine learning by seeing trends and anomalies that can be used to improve upcoming software releases. This could result in a constructive feedback loop of ongoing improvement where the program gradually becomes more dependable and stable.</p>
</li>
</ol>
<p>Debugging is often an appealing area of research and development for software development teams because to the advantages that AI and machine learning offer. These technologies allow developers to work more efficiently, write better code, and deliver better software to their clients.</p>
<h2 id="heading-difficulties-and-limitations">Difficulties and Limitations</h2>
<p>Despite the potential advantages of utilizing AI and ML in debugging, there are still a number of obstacles to be solved. The need for a huge volume of high-quality data to train ML systems is a big problem. This implies that vast datasets of bug reports, test cases, and other pertinent information from developers are required for AI systems to have access to when debugging.</p>
<p>Another disadvantage is that AI systems may make mistakes or fail to catch serious faults. Developers must be able to comprehend and interpret the data, even though AI algorithms might produce highly precise results.</p>
<h2 id="heading-ethical-considerations">Ethical Considerations</h2>
<p>As more businesses and organizations adopt AI, it is imperative that ethical considerations be included in its development. AI has the ability to significantly improve efficiency and accuracy, but it also has the potential to have unanticipated side effects. For instance, AI has the ability to breach privacy regulations, exacerbate preexisting biases, and remove human decision-making from the equation.</p>
<p>Studies have demonstrated that facial recognition algorithms are less accurate at detecting people with darker skin tones, and when AI-driven assessments are used, there is a <em>risk of bias</em> in hiring and employment decisions. Automatic decision-making technologies may potentially make errors with grave consequences, such as incorrectly convicting someone or denying them access to essential resources.</p>
<p>It is essential to think about the potential drawbacks and take safety procedures to lessen any risks in order to allay these ethical concerns. Algorithms that have been trained on a variety of datasets should be inclusive and equal, according to developers. Companies must also make sure that the data used in AI systems is collected in a way that respects people's privacy and security and is open and honest.</p>
<p>To direct the creation and use of AI technologies, clear legal frameworks are also required. This means ensuring that ethical considerations are taken into account right from the beginning of the development process and that accountability structures are in place to handle any unintended consequences of AI decision-making.</p>
<p>Ultimately, as artificial intelligence continues to change our reality, designers and associations must take into account any potential moral issues. We can make sure that AI is used in a way that is advantageous to everyone by including justice, inclusion, transparency, and accountability into the construction of AI.</p>
<h2 id="heading-concerns-about-safety-and-security">Concerns about safety and security</h2>
<p>While using AI and computer-based intelligence for problem solving, developers must consider sane safety and security worries. Sensitive data, login credentials, and proprietary code are all commonly handled and stored using these technologies. Data leaks and breaches are more likely since hackers can take advantage of any system flaw.</p>
<p>Automating particular stages of the debugging process is one way to expand the attack surface when employing AI and machine learning. As a result, these systems might develop new weaknesses that hackers could use. These systems' algorithms can potentially be exploited or changed, especially if they were developed using a corrupted dataset.</p>
<p>Another major cause for concern is the potential for data breaches or leaks. Data is handled and stored by these systems, making it more susceptible to theft or unauthorized access. This might compromise the integrity of the debugged software or expose private information.</p>
<p>Strong security measures like encryption, access controls, and intrusion detection systems must be incorporated by developers to guarantee that the processed data is properly protected. Developers may also be required to anonymize sensitive data or limit the amount of data processed in order to lower the risk of data breaches or leaks. Developers can safeguard user privacy and foster trust in the system by being open and honest about how data is used during debugging.</p>
<p>When using AI and machine learning for debugging, developers must be aware of the risks and take the necessary procedures to address privacy and security concerns. Developers can protect important data and increase user confidence with this technique.</p>
<h2 id="heading-debugging-tools-based-on-ai">Debugging Tools Based on AI</h2>
<p>Recently, the development of AI-based debugging tools has begun. These instruments make use of machine learning techniques to find and fix coding faults. Three such resources are available right now:</p>
<ul>
<li><p><strong>Kodezi</strong>: A code intelligence platform powered by AI in the cloud. Code completion, syntax highlighting, and automatic formatting are just a few of the features the platform offers to help developers find and fix bugs in their code. Kodezi is currently available for beta testing, and developers are already using it for debugging.</p>
</li>
<li><p><strong>Snyk</strong>: Snyk is a cloud-based program that aids programmers in identifying and resolving security flaws in their code. The program utilizes artificial intelligence to find open-source library issues and then automatically releases fixes for them. Snyk can be used to find and fix security-related bugs in programs even though it wasn't designed with debugging in mind.</p>
</li>
<li><p><strong>Rookout</strong>: Rookout is an AI-based debugging tool that assists developers in finding and resolving production-related errors fast and without the need for code alterations or redeployment. Developers can collect data from running applications, analyze the data, and get deeper understanding of how the program is operating thanks to Rookout's real-time debugging features.</p>
</li>
</ul>
<p>These are just a handful of the AI-based debugging tools that are currently accessible to developers. These tools can speed up the process of discovering and repairing errors, which results in better code overall, but they cannot totally replace human testing and analysis.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In conclusion, the development of faster, more precise, and more potent debugging tools is one of the possible benefits of artificial intelligence and machine learning. These technologies' advantages in debugging make them a promising area for research and development despite a number of issues and constraints that need to be addressed. AI and machine learning can aid developers in writing better code and providing better software to their consumers by analyzing large datasets, identifying trends and anomalies, and continuously improving the product.</p>
<p>But it's also important to understand the ethical issues that arise when AI and machine learning are used to software development. Protective measures and moral concerns must be incorporated throughout the design and development process as one way for developers to lessen potential risks.</p>
<p>We should anticipate much larger developments in software development's debugging and other areas as AI and machine learning continue to improve. We can fully exploit AI and machine learning in the development of the software of the future if we accept these technologies and appropriately use them. 🚀</p>
]]></content:encoded></item><item><title><![CDATA[How to use ChatGPT-3 into Python]]></title><description><![CDATA[ChatGPT is a state-of-the-art language model developed by OpenAI. It is a deep learning model trained on a vast amount of text data, allowing it to generate human-like text and respond to text-based inputs. It is considered one of the most advanced l...]]></description><link>https://omarcodes.io/how-to-use-chatgpt-3-into-python</link><guid isPermaLink="true">https://omarcodes.io/how-to-use-chatgpt-3-into-python</guid><category><![CDATA[chatgpt]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 05 Feb 2023 14:32:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/N8AYH8R2rWQ/upload/924b6d98d9e74fa1a2e60600c0337388.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>ChatGPT is a state-of-the-art language model developed by OpenAI. It is a deep learning model trained on a vast amount of text data, allowing it to generate human-like text and respond to text-based inputs. It is considered one of the most advanced language models currently available, with a vast knowledge base and the ability to generate coherent and coherently formatted text.</p>
<p>In this article, we will explain how to use ChatGPT-3 in Python. We will cover the steps necessary to obtain an API key for OpenAI's GPT-3 and how to integrate the language model into a Python application.</p>
<h2 id="heading-using-chatgpt-with-python">Using ChatGPT with Python</h2>
<p>To use ChatGPT, there are 2 ways:</p>
<ul>
<li><p>Using the OpenAI library</p>
</li>
<li><p>Using the OpenAI's API</p>
</li>
</ul>
<h3 id="heading-using-the-openai-library">Using the OpenAI library</h3>
<p>To get started, you will need to obtain an API key for OpenAI's GPT-3. This can be done by creating an account on the OpenAI website and applying for access to the GPT-3 API.</p>
<p>Once you have obtained an API key, you will need to install the <code>openai</code> library in Python. You can install this library using <code>pip</code> by running the following command in your terminal or command prompt:</p>
<pre><code class="lang-bash">pip install openai
</code></pre>
<p>After the <code>openai</code> library has been installed, you can use the following code to initialize the GPT-3 model and generate text:</p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># initialize the OpenAI API key</span>
openai.api_key = <span class="hljs-string">"your_api_key_here"</span>

<span class="hljs-comment"># generate text using the GPT-3 model</span>
model_engine = <span class="hljs-string">"text-davinci-002"</span>
prompt = <span class="hljs-string">"What is the capital of France?"</span>

completions = openai.Completion.create(
    engine=model_engine,
    prompt=prompt,
    max_tokens=<span class="hljs-number">1024</span>,
    n=<span class="hljs-number">1</span>,
    stop=<span class="hljs-literal">None</span>,
    temperature=<span class="hljs-number">0.5</span>,
)

message = completions.choices[<span class="hljs-number">0</span>].text
print(message)
</code></pre>
<p>This code will generate a text response to the prompt "What is the capital of France?" using the <code>text-davinci-002</code> model engine. The response will be printed to the console.</p>
<h3 id="heading-using-the-openais-api">Using the OpenAI's API</h3>
<p>OpenAI's API is a cloud-based platform that allows developers to access GPT-3 and other AI models developed by OpenAI. It is a convenient way to incorporate state-of-the-art language processing capabilities into your applications without having to train the models yourself.</p>
<p>To use the OpenAI API, you'll need to sign up for an API key, which will give you access to a limited number of requests per month. With the API key, you can send a request to the API with some input text, and the API will respond with the generated text. You can control the length and content of the generated text by specifying various parameters in the API request.</p>
<ol>
<li><p>Sign up for an OpenAI API key: Go to the OpenAI website and sign up for an API key. You'll need to provide some information and agree to the terms and conditions.</p>
</li>
<li><p>Install the requests library: The requests library is a popular Python library for making HTTP requests. You can install it using pip by running the following command in your terminal:</p>
</li>
</ol>
<pre><code class="lang-bash">pip install requests
</code></pre>
<ol>
<li>Send a request to the OpenAI API: Use the requests library to send an HTTP POST request to the OpenAI API endpoint. You'll need to specify the API key, the model to use (GPT-3), the input text, and any other parameters you want to control. Here's an example:</li>
</ol>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> requests

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_text</span>(<span class="hljs-params">prompt</span>):</span>
    api_key = <span class="hljs-string">"your_api_key_here"</span>
    model = <span class="hljs-string">"text-davinci-002"</span>
    endpoint = <span class="hljs-string">f"https://api.openai.com/v1/engines/<span class="hljs-subst">{model}</span>/jobs"</span>
    headers = {
        <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
        <span class="hljs-string">"Authorization"</span>: <span class="hljs-string">f"Bearer <span class="hljs-subst">{api_key}</span>"</span>
    }
    data = {
        <span class="hljs-string">"prompt"</span>: prompt,
        <span class="hljs-string">"max_tokens"</span>: <span class="hljs-number">100</span>,
        <span class="hljs-string">"n"</span>: <span class="hljs-number">1</span>,
        <span class="hljs-string">"stop"</span>: <span class="hljs-literal">None</span>,
        <span class="hljs-string">"temperature"</span>: <span class="hljs-number">0.5</span>,
    }
    response = requests.post(endpoint, headers=headers, json=data)
    <span class="hljs-keyword">if</span> response.status_code == <span class="hljs-number">200</span>:
        response_json = response.json()
        <span class="hljs-keyword">return</span> response_json[<span class="hljs-string">'choices'</span>][<span class="hljs-number">0</span>][<span class="hljs-string">'text'</span>]
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-literal">None</span>

generated_text = generate_text(<span class="hljs-string">"Hello, how are you?"</span>)
print(generated_text)
</code></pre>
<ol>
<li>Parse the response: The OpenAI API will respond with a JSON object that contains the generated text. You can parse the response and extract the text to use it in your application.</li>
</ol>
<p>That's it! With these steps, you can use the OpenAI API to generate text using GPT-3 in Python. Of course, you can modify the parameters and customize the code to fit your specific needs.</p>
<h2 id="heading-outro">Outro 🎉</h2>
<p>In conclusion, OpenAI offers two ways for developers to leverage its cutting-edge technology: through the OpenAI API and the OpenAI Library. Both methods provide access to state-of-the-art AI models, allowing for a wide range of use cases, from natural language processing to computer vision. Whether you're a seasoned developer or just starting out, OpenAI has something to offer to bring your AI projects to life.</p>
]]></content:encoded></item><item><title><![CDATA[Streamlining Content Management with Gatsby and Cockpit CMS]]></title><description><![CDATA[Gatsby is a modern, blazing fast, and static site generator built using React. It is a great tool for building fast and secure websites with a smooth and dynamic user experience. The reason why Gatsby is so popular among web developers is that it all...]]></description><link>https://omarcodes.io/streamlining-content-management-with-gatsby-and-cockpit-cms</link><guid isPermaLink="true">https://omarcodes.io/streamlining-content-management-with-gatsby-and-cockpit-cms</guid><category><![CDATA[Gatsby]]></category><category><![CDATA[cms]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sat, 04 Feb 2023 11:00:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/-zRNvl3EUdw/upload/4b908cdbc7eb219b55d546f89f513f44.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a target="_blank" href="https://www.gatsbyjs.com/"><strong>Gatsby</strong></a> is a modern, blazing fast, and static site generator built using React. It is a great tool for building fast and secure websites with a smooth and dynamic user experience. The reason why Gatsby is so popular among web developers is that it allows you to build a website without the need for a traditional CMS.</p>
<p>In this article, we will be exploring how to integrate Cockpit CMS, a headless CMS, with Gatsby to streamline the content management process.</p>
<p><a target="_blank" href="https://getcockpit.com/">Cockpit</a> is a flexible and user-friendly headless CMS that can be used to manage your website's content. It offers a clean and intuitive interface that makes it easy to manage your website's content and data.</p>
<h2 id="heading-setup">Setup</h2>
<p>Before we dive into integrating Cockpit with Gatsby, we need to set up a Gatsby project. If you already have a Gatsby project, you can skip this section.</p>
<p>To create a new Gatsby project, run the following command in your terminal:</p>
<pre><code class="lang-bash">npx gatsby new my-gatsby-project
</code></pre>
<p>This command will create a new Gatsby project in a directory named <code>my-gatsby-site</code>.</p>
<h2 id="heading-integrate-cockpit-cms">Integrate Cockpit CMS:</h2>
<p>To integrate Cockpit with Gatsby, we need to install the <code>gatsby-source-cockpit</code> plugin. This plugin will allow us to fetch data from Cockpit and use it in our Gatsby site.</p>
<p>To install the plugin, run the following command in your terminal:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-gatsby-site
npm install gatsby-source-cockpit
</code></pre>
<p>Once the plugin is installed, we need to configure it to connect to our Cockpit instance (get an account from <a target="_blank" href="https://getcockpit.com/">here</a>). To do this, add the following code to your <code>gatsby-config.js</code> file:</p>
<pre><code class="lang-javascript"><span class="hljs-built_in">module</span>.exports = {
  <span class="hljs-attr">plugins</span>: [
    {
      <span class="hljs-attr">resolve</span>: <span class="hljs-string">`gatsby-source-cockpit`</span>,
      <span class="hljs-attr">options</span>: {
        <span class="hljs-attr">cockpitConfig</span>: {
          <span class="hljs-attr">baseURL</span>: <span class="hljs-string">`https://YOUR_COCKPIT_URL`</span>,
          <span class="hljs-attr">accessToken</span>: <span class="hljs-string">`YOUR_ACCESS_TOKEN`</span>,
        },
      },
    },
  ],
};
</code></pre>
<p>Replace <code>YOUR_COCKPIT_URL</code> with the URL of your Cockpit instance and <code>YOUR_ACCESS_TOKEN</code> with the access token you generated in Cockpit.</p>
<p>Next, we need to create a GraphQL query to fetch data from Cockpit. In your <code>src/pages/index.js</code> file, add the following code:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
<span class="hljs-keyword">import</span> { graphql } <span class="hljs-keyword">from</span> <span class="hljs-string">"gatsby"</span>;

<span class="hljs-keyword">const</span> IndexPage = <span class="hljs-function">(<span class="hljs-params">{ data }</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> { allCockpitPages } = data;
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      {allCockpitPages.edges.map(({ node }) =&gt; (
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{node.id}</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{node.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{node.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      ))}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> query = graphql<span class="hljs-string">`
  query {
    allCockpitPages {
      edges {
        node {
          id
          title
          content
        }
      }
    }
  }
`</span>;
</code></pre>
<p>This query will retrieve all the data from the <code>Article</code> collection in Cockpit. You can access the data in your components by using the <code>data</code> prop provided by Gatsby. In your <code>src/pages/index.js</code> file, you can use the following code to display the title and content of each article:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> ({ data }) =&gt; (
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    {data.allCockpitArticle.edges.map(({ node }, index) =&gt; (
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{index}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{node.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{node.content}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    ))}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
)
</code></pre>
<p>This code loops through the <code>edges</code> array in the <code>data.allCockpitArticle</code> object and displays the title and content of each article using a React component.</p>
<p>Finally, you can run <code>gatsby develop</code> in your terminal to start the development server and see the data from Cockpit being displayed on your website.</p>
<p>Now, you have successfully integrated Cockpit CMS with Gatsby 🎉!</p>
<h2 id="heading-outro">Outro</h2>
<p>In conclusion, combining Gatsby with Cockpit CMS is a powerful way to streamline the process of managing your website's content. With Gatsby's fast performance and Cockpit's flexible and user-friendly content management system, you can easily create a dynamic website that can handle large amounts of traffic.</p>
]]></content:encoded></item><item><title><![CDATA[Build a Telegram Bot for Medusa E-Commerce Store]]></title><description><![CDATA[Hey ya, e-commerce enthusiasts! Are you ready to take your Medusa store to the next level? Well, buckle up because we're about to show you how to build a Telegram bot that will blow your customers' minds! But before we dive into the exciting stuff, l...]]></description><link>https://omarcodes.io/build-a-telegram-bot-for-medusa-e-commerce-store</link><guid isPermaLink="true">https://omarcodes.io/build-a-telegram-bot-for-medusa-e-commerce-store</guid><category><![CDATA[medusa]]></category><category><![CDATA[Python]]></category><category><![CDATA[telegram]]></category><category><![CDATA[telegram bot]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Mon, 30 Jan 2023 11:58:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/SDgX8iC-kEU/upload/e4c3aad4beb7de32a3db2ab1b17af720.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey ya, e-commerce enthusiasts! Are you ready to take your Medusa store to the next level? Well, buckle up because we're about to show you how to build a Telegram bot that will blow your customers' minds! But before we dive into the exciting stuff, let's catch up. I've been on vacation for a while, so sorry for my absence in the writing world. But now, I'm back and ready to share some amazing projects with you.</p>
<p>In this article, we'll go through the process of building a Telegram bot that allows users to purchase products from your <a target="_blank" href="https://medusajs.com/">Medusa</a>-powered e-commerce store. We'll be using Python and Flask for the backend and the <code>python-telegram-bot</code> library to interact with the Telegram API.</p>
<h2 id="heading-step-1-setting-up-a-telegram-bot">Step 1: Setting up a Telegram bot</h2>
<p>To get started, you'll need to <em>create</em> a <strong>Telegram bot</strong>. You can do this by talking to the <a target="_blank" href="https://t.me/BotFather">BotFather</a> on Telegram and following the instructions provided. Once you've set up your bot, make a note of the API key that you're given.</p>
<h2 id="heading-step-2-building-the-backend">Step 2: Building the backend</h2>
<p>The backend of the bot will <em>handle</em> all the <strong>interactions between the bot and your Medusa store</strong>. We'll be using Python and Flask for the backend. You'll need to make sure that the backend can handle requests from Telegram and make calls to the Medusa API to retrieve product information and process orders.</p>
<p>First, let's start by creating a new <code>Flask</code> project and installing the required libraries:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># create a new Flask project</span>
$ mkdir medusa-telegram-bot &amp;&amp; <span class="hljs-built_in">cd</span> medusa-telegram-bot
$ python3 -m venv venv
$ <span class="hljs-built_in">source</span> venv/bin/activate
(venv) $ pip install flask python-telegram-bot
</code></pre>
<p>Next, let's create a new file called <code>app.py</code> and set up a basic Flask application:</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, request
<span class="hljs-keyword">from</span> telegram <span class="hljs-keyword">import</span> Bot
app = Flask(__name__)

<span class="hljs-meta">@app.route('/', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_update</span>():</span>
    <span class="hljs-comment"># handle the incoming update from Telegram</span>
    <span class="hljs-keyword">pass</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>Now we need to initialize the bot:</p>
<pre><code class="lang-py">bot = Bot(token=<span class="hljs-string">'YOUR_TELEGRAM_BOT_TOKEN'</span>)
</code></pre>
<h2 id="heading-step-3-connecting-the-backend-to-telegram">Step 3: Connecting the backend to Telegram</h2>
<p>Once the backend is set up, we'll need to connect it to Telegram. This is done by configuring a webhook that points to the URL of the backend. Once this is done, Telegram will send all incoming messages to the backend for processing.</p>
<p>To set up a webhook, we can use the <code>setWebhook</code> method provided by the python-telegram-bot library:</p>
<pre><code class="lang-py">bot.setWebhook(url=<span class="hljs-string">'https://your-server-url.com/'</span> + bot.token)
</code></pre>
<h2 id="heading-step-4-connecting-medusa-to-the-telegram-bot">Step 4: Connecting Medusa to the Telegram bot</h2>
<p>In this step, we'll integrate Medusa into our Telegram bot by using the Medusa Python library. This library provides a simple interface for interacting with the Medusa API and allows us to easily fetch and update products, orders, and other data from our storefront.</p>
<p>Here's an example of how we can use the Medusa library to fetch a list of products from our storefront and send them to the user through Telegram:</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> medusa <span class="hljs-keyword">import</span> Medusa

medusa = Medusa(api_key=<span class="hljs-string">'YOUR_MEDUSA_API_KEY'</span>)

<span class="hljs-meta">@app.route('/handle_message', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">handle_message</span>():</span>
    <span class="hljs-comment"># Get the incoming message from Telegram</span>
    message = request.get_json()
    text = message[<span class="hljs-string">'message'</span>][<span class="hljs-string">'text'</span>]

    <span class="hljs-comment"># Determine the user's intent</span>
    <span class="hljs-keyword">if</span> <span class="hljs-string">'/products'</span> <span class="hljs-keyword">in</span> text:
        products = medusa.products.list()
        product_list = <span class="hljs-string">''</span>
        <span class="hljs-keyword">for</span> product <span class="hljs-keyword">in</span> products:
            product_list += product[<span class="hljs-string">'title'</span>] + <span class="hljs-string">'\n'</span>
        reply_text = <span class="hljs-string">'Here are a list of products in our store: \n'</span> + product_list
    <span class="hljs-keyword">else</span>:
        reply_text = <span class="hljs-string">'I am sorry, I do not understand what you want me to do.'</span>

    <span class="hljs-comment"># Send the reply</span>
    reply_to_message(reply_text, message[<span class="hljs-string">'chat'</span>][<span class="hljs-string">'id'</span>])

    <span class="hljs-keyword">return</span> <span class="hljs-string">'ok'</span>
</code></pre>
<p>In this example, the function checks if the message contains '/products' and then fetch products from Medusa, and sends a list of products to the user through Telegram. You can customize this to fit your needs and you can also add other functionalities like creating a new order, or updating an existing order. Please note that this is just an example and may require further modification to work in your specific use case.</p>
<h2 id="heading-step-5-creating-the-medusa-module-for-telegram-bot-integration">Step 5: Creating the Medusa Module for Telegram Bot Integration</h2>
<p>Create a new file called <code>medusa.py</code> in your project directory. In this file, you can define the Medusa class and any other necessary functions or classes:</p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> requests

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Medusa</span>:</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, base_url, api_key</span>):</span>
        self.base_url = base_url
        self.api_key = api_key

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_product</span>(<span class="hljs-params">self, product_data</span>):</span>
        headers = {<span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer {}'</span>.format(self.api_key)}
        response = requests.post(self.base_url + <span class="hljs-string">'/products'</span>, json=product_data, headers=headers)
        <span class="hljs-keyword">return</span> response.json()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_product</span>(<span class="hljs-params">self, product_id, updates</span>):</span>
        headers = {<span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer {}'</span>.format(self.api_key)}
        response = requests.patch(self.base_url + <span class="hljs-string">'/products/{}'</span>.format(product_id), json=updates, headers=headers)
        <span class="hljs-keyword">return</span> response.json()

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_products</span>(<span class="hljs-params">self</span>):</span>
        headers = {<span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'Bearer {}'</span>.format(self.api_key)}
        response = requests.get(self.base_url + <span class="hljs-string">'/products'</span>, headers=headers)
        <span class="hljs-keyword">return</span> response.json()
</code></pre>
<p>This is an example of how you can define the Medusa class in <code>medusa.py</code>. The class has three methods: <code>create_product</code>, <code>update_product</code>, and <code>get_products</code>. Each method makes a request to the Medusa API using the requests library, passing in the necessary data and headers.</p>
<p>You will need to replace the <code>base_url</code> and <code>api_key</code> with the actual values for your Medusa instance. Additionally, you may need to modify the methods to match the specific API endpoint and request format for the Medusa API.</p>
<p>Once the medusa module is defined and imported in the telegram bot script, you can call the class methods to interact with the Medusa instance.</p>
<p>Please note that this is just an example and you should check the Medusa API documentation for the correct endpoints and request format.</p>
<h2 id="heading-step-6-running-the-telegram-bot-with-medusa-integration">Step 6: Running the Telegram Bot with Medusa Integration</h2>
<p>Now that the Telegram bot and Medusa module have been set up, it's time to run the bot and test the integration.</p>
<ol>
<li><p><strong>Open</strong> a terminal or command prompt and navigate to the root directory of your bot project.</p>
</li>
<li><p><strong>Start</strong> the bot by running the command <code>python3 bot.py</code> (assuming your main bot file is named <code>bot.py</code>).</p>
</li>
<li><p><strong>Open</strong> Telegram and search for your bot's username.</p>
</li>
<li><p><strong>Send</strong> a message to the bot and see if the Medusa integration is working as expected.</p>
</li>
<li><p><strong>Stop</strong> the bot, simply close the terminal/command prompt or use the CTRL+C command.</p>
</li>
</ol>
<blockquote>
<p>Note: Make sure that all the required packages installed and the token is correct.</p>
</blockquote>
<p>You can now continue to add more functionality and features to your Telegram bot and Medusa integration, and use it in your e-commerce website.</p>
<p><strong>Congratulations</strong> 🎉, you have successfully created a Telegram bot that integrates with Medusa, an open-source alternative to Shopify. With this bot, you can now easily manage your e-commerce store and communicate with your customers through Telegram.</p>
<p>It's always a good idea to keep testing and improving your bot, and you can also add new features and functionality as per your requirement. With Medusa and Telegram, the possibilities are endless.</p>
<p>Don't forget to take a break, I went on vacation and that's why I discontinued writing articles. But now I'm back and ready to share more exciting projects and ideas with you. Thanks for reading!</p>
]]></content:encoded></item><item><title><![CDATA[Connect MetaMask Wallet with Flask and Discord.py]]></title><description><![CDATA[Introduction
Today we will build a Discord.py and use Flask to allow to integrate the Ethereum wallet addresses with the wallet, you use the Flask frontend to connect the wallet while it's logged in the Flask system and when you want to check if sync...]]></description><link>https://omarcodes.io/metamask-discord</link><guid isPermaLink="true">https://omarcodes.io/metamask-discord</guid><category><![CDATA[Python]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[HTML5]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 02 Oct 2022 11:46:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1664711029707/4pQg3Qo6z.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Today we will build a <code>Discord.py</code> and use <code>Flask</code> to allow to integrate the Ethereum wallet addresses with the wallet, you use the <code>Flask</code> frontend to connect the wallet while it's logged in the <code>Flask</code> system and when you want to check if synced, the <code>Discord.py</code> bot sends a <code>JSON POST</code> request to read.</p>
<p><strong>SO LET'S GOOOOO 🔥🔥🔥</strong></p>
<h2 id="heading-setup-the-flask-page">Setup the Flask Page</h2>
<p>Start by creating a new directory, and in that directory, create a folder for the Flask page:</p>
<pre><code class="lang-bash">mkdir metamask-flask-discord
<span class="hljs-built_in">cd</span> metamask-flask-discord
mkdir flask
<span class="hljs-built_in">cd</span> flask
</code></pre>
<p>Now, create an <code>app.py</code> file and a <code>log.txt</code> and paste this into the <code>app.py</code>:</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template, Response, request
app = Flask(__name__)

<span class="hljs-meta">@app.route('/&lt;discord_id&gt;')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">index</span>(<span class="hljs-params">discord_id</span>):</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'index.html'</span>, discordId = discord_id)

<span class="hljs-meta">@app.route('/sync', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sync</span>():</span>
    discord_id = request.json[<span class="hljs-string">'discordId'</span>]
    wallet_address = request.json[<span class="hljs-string">'walletAddress'</span>]
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'log.txt'</span>, <span class="hljs-string">'r+'</span>) <span class="hljs-keyword">as</span> f:
        file = f.read()
        <span class="hljs-keyword">if</span> discord_id <span class="hljs-keyword">in</span> file:
            <span class="hljs-keyword">if</span> wallet_address <span class="hljs-keyword">in</span> file:
                Pass
            <span class="hljs-keyword">else</span>:
                f.write(<span class="hljs-string">' '</span> + wallet_address)
        <span class="hljs-keyword">else</span>:
            f.write(<span class="hljs-string">'\n'</span> + discord_id + <span class="hljs-string">' '</span> + wallet_address)
    f.close()

<span class="hljs-meta">@app.route('/read', methods=['POST'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read</span>():</span>
    discord_id = request.json[<span class="hljs-string">'discordId'</span>]
    <span class="hljs-keyword">with</span> open(<span class="hljs-string">'log.txt'</span>, <span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        file = f.read()
        <span class="hljs-keyword">if</span> discord_id <span class="hljs-keyword">in</span> file:
            wallet_addresses = file.split(discord_id)[<span class="hljs-number">1</span>].split(<span class="hljs-string">' '</span>)
            wallet_addresses.pop(<span class="hljs-number">0</span>)
            <span class="hljs-keyword">return</span> Response(str(wallet_addresses), mimetype=<span class="hljs-string">'application/json'</span>)
        <span class="hljs-keyword">else</span>:
            <span class="hljs-keyword">return</span> Response(<span class="hljs-string">'No wallet address found'</span>, mimetype=<span class="hljs-string">'application/json'</span>)
</code></pre>
<p>This is our main <code>flask</code> file, what we are doing here, we are setting <code>3</code> routes:</p>
<ul>
<li><code>/</code> (main)</li>
<li><code>sync</code> (to sync with the logs which also syncs with the bot)</li>
<li><code>read</code> (provides wallet addresses for a specific user)</li>
</ul>
<p>And for <code>sync</code> and <code>read</code> we will receive a <code>JSON POST</code> request, <code>POST</code> is more safer, that's why I personally prefer it. </p>
<p>Also, in both <code>sync</code> and <code>read</code> we open up the <code>log.txt</code> either to read wallet addresses for a specific user, or write new wallet addresses for a new user.</p>
<p>Now, let's create the landing page where you can connect your <code>MetaMask</code> wallet:</p>
<pre><code class="lang-bash">mkdir templates
touch index.html
</code></pre>
<p>Now in your <code>index.html</code>, paste this:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>MetaMask Connection<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">center</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Connect Your MetaMask Wallet Here To Connect With Discord!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"connectWallet"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">""</span>&gt;</span>Connect Wallet<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"syncDiscord"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">""</span>&gt;</span>Sync Discord<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"walletAddress"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/javascript"</span>&gt;</span><span class="javascript">
            <span class="hljs-keyword">var</span> discordId = <span class="hljs-string">"{{ discordId }}"</span>;
            <span class="hljs-built_in">window</span>.walletAddress = <span class="hljs-literal">null</span>
            <span class="hljs-keyword">const</span> syncDiscord = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'syncDiscord'</span>);
            <span class="hljs-keyword">const</span> connectWallet = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'connectWallet'</span>)
            <span class="hljs-keyword">const</span> walletAddress = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'walletAddress'</span>)


            <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">checkInstalled</span>(<span class="hljs-params"></span>) </span>{
                <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span>.ethereum == <span class="hljs-string">'undefined'</span>) {
                    walletAddress.innerText = <span class="hljs-string">'Please install MetaMask to continue.'</span>
                    <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
                }
                connectWallet.addEventListener(<span class="hljs-string">'click'</span>, connectWalletwithMetaMask)
            }

            <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">connectWalletwithMetaMask</span>(<span class="hljs-params"></span>) </span>{
                <span class="hljs-keyword">const</span> accounts = <span class="hljs-keyword">await</span> <span class="hljs-built_in">window</span>.ethereum.request({ <span class="hljs-attr">method</span>: <span class="hljs-string">'eth_requestAccounts'</span> })
                .catch(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
                    <span class="hljs-built_in">console</span>.error(e.message)
                    <span class="hljs-keyword">return</span>
                })
                <span class="hljs-keyword">if</span> (!accounts) { <span class="hljs-keyword">return</span> }

                <span class="hljs-built_in">window</span>.walletAddress = accounts[<span class="hljs-number">0</span>]
                walletAddress.innerText = <span class="hljs-built_in">window</span>.walletAddress


                connectWallet.innerText = <span class="hljs-string">'Sign Out'</span>
                connectWallet.removeEventListener(<span class="hljs-string">'click'</span>, connectWalletwithMetaMask)
                <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
                    connectWallet.addEventListener(<span class="hljs-string">'click'</span>, signOutOfMetaMask)
                    syncDiscord.addEventListener(<span class="hljs-string">'click'</span>, syncDiscordWithWallet)
                }, <span class="hljs-number">200</span> )
            }

            <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">signOutOfMetaMask</span>(<span class="hljs-params"></span>) </span>{
                <span class="hljs-built_in">window</span>.walletAddress = <span class="hljs-literal">null</span>
                walletAddress.innerText = <span class="hljs-string">''</span>
                connectWallet.innerText = <span class="hljs-string">'Connect Wallet'</span>

                connectWallet.removeEventListener(<span class="hljs-string">'click'</span>, signOutOfMetaMask)
                syncDiscord.removeEventListener(<span class="hljs-string">'click'</span>, syncDiscordWithWallet)

                <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
                    connectWallet.addEventListener(<span class="hljs-string">'click'</span>, connectWalletwithMetaMask)
                }, <span class="hljs-number">200</span> )
            }

            <span class="hljs-built_in">window</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function">() =&gt;</span> {
                checkInstalled()
            })

            <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">syncDiscordWithWallet</span>(<span class="hljs-params"></span>) </span>{
                alert(<span class="hljs-string">"If the wallet is already in the system, nothing would happen, if not, it would add it to the bot system."</span>)
                <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/sync'</span>, {
                    <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
                    <span class="hljs-attr">headers</span>: {
                        <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span>
                    },
                    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
                        <span class="hljs-attr">walletAddress</span>: <span class="hljs-built_in">window</span>.walletAddress,
                        <span class="hljs-attr">discordId</span>: discordId
                    })
                })
            }

        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">center</span>&gt;</span>   
    <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>So here we make few buttons, and make a few event listeners which run certain functions, and for example, when the wallet is connected, we replace the event listener to listen to the sign out function, why would the user sign in again if he is already signed in, hahah!</p>
<p>And for syncing here, we send a <code>JSON POST</code> request with <code>walletAddress</code> and <code>discordId</code> to <code>/sync</code> to save it!</p>
<h2 id="heading-working-on-our-discordpy-bot">Working on our Discord.py bot</h2>
<p>Start by creating a directory and creating a <code>.env</code> &amp; <code>bot.py</code>:</p>
<pre><code class="lang-bash">mkdir discordbot
<span class="hljs-built_in">cd</span> discordbot
touch .env
touch bot.py
</code></pre>
<p>Now, open up your <code>.env</code> file where you save your token just like this:</p>
<pre><code class="lang-env">TOKEN=&lt;your-discord-bot-token-here&gt;
</code></pre>
<p>Let's work on the actual bot now:</p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> discord
<span class="hljs-keyword">from</span> discord.ext <span class="hljs-keyword">import</span> commands
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> dotenv <span class="hljs-keyword">import</span> load_dotenv
load_dotenv()
token = os.getenv(<span class="hljs-string">'TOKEN'</span>)


intents = discord.Intents.all()
bot = commands.Bot(command_prefix=<span class="hljs-string">'$'</span>, intents=intents)

<span class="hljs-meta">@bot.event</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">on_ready</span>():</span>
    print(<span class="hljs-string">"Bot is ready"</span>)
    print(<span class="hljs-string">"Username: {}"</span>.format(bot.user.name))
    print(<span class="hljs-string">"ID: {}"</span>.format(bot.user.id))
    print(<span class="hljs-string">"Discord.py Version: {}"</span>.format(discord.__version__))
    print(<span class="hljs-string">"------"</span>)

<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">linkwallet</span>(<span class="hljs-params">ctx</span>):</span>
    <span class="hljs-keyword">await</span> ctx.author.send(<span class="hljs-string">"Click on this link to connect your MetaMask Wallet"</span>)
    <span class="hljs-keyword">await</span> ctx.author.send(<span class="hljs-string">"Link your wallet here: http://127.0.0.1:5000/{}"</span>.format(ctx.author.id))

<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">readuser</span>(<span class="hljs-params">ctx, userid: str</span>):</span>
    r = requests.post(<span class="hljs-string">'http://127.0.0.1:5000/read'</span>, json={<span class="hljs-string">'discordId'</span>: userid})
    <span class="hljs-keyword">await</span> ctx.send(r.text)




bot.run(token)
</code></pre>
<p>So what we are doing is simple, first <code>linkwallet</code> command which actually sending a DM with a link like this to connect: <code>http://127.0.0.1:5000/&lt;discord-id&gt;</code></p>
<p>And <code>readuser</code> gets a <code>userid</code> and send a JSON request to read and returns the <code>JSON</code> response back to the user!</p>
<h2 id="heading-try-it-out">Try it out!</h2>
<p>Let's run the <code>flask</code> app:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> flask
flask run
</code></pre>
<p>And let's run the bot:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> discordbot
python bot.py
</code></pre>
<h2 id="heading-video-demo">Video Demo:</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=3NBCYG2rbjc">https://www.youtube.com/watch?v=3NBCYG2rbjc</a></div>
<h2 id="heading-important-links">Important Links 🔗</h2>
<ul>
<li><a href="https://github.com/Omar8345/metamask-discord">GitHub Repo</a></li>
</ul>
<h2 id="heading-thanks-for-reading">Thanks for reading!!!</h2>
<p>Thanks for reading this article 🚀</p>
<p>Hope you learned something <strong>useful !!!</strong></p>
]]></content:encoded></item><item><title><![CDATA[Manage Prisma records from Discord]]></title><description><![CDATA[Hello buddy😊! Today we will use a Discord bot powered by Discord.py to manage our Prisma records, but in this article, we will pretend that we got a shop and we use the Discord.py bot to manage the sale records, which is the example we'll work with ...]]></description><link>https://omarcodes.io/manage-prisma-records-from-discord</link><guid isPermaLink="true">https://omarcodes.io/manage-prisma-records-from-discord</guid><category><![CDATA[prisma]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Discord.py]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[PlanetScale]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 18 Sep 2022 06:07:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1663481184752/LWqTRrFQd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello buddy😊! Today we will use a <strong>Discord</strong> bot powered by <em>Discord.py</em> to manage our <strong>Prisma</strong> records, but in this article, we will pretend that we got a shop and we use the <strong>Discord.py</strong> bot to manage the sale records, which is the example we'll work with today. So let's go🚀!</p>
<p><iframe src="https://giphy.com/embed/2eJy3doMRJIuxRdedh" width="480" height="270" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/2eJy3doMRJIuxRdedh">via GIPHY</a></p><p></p>
<h2 id="heading-working-on-our-prismanextjs-api">Working on our Prisma/Next.js API</h2>
<p>Start by creating a <strong>Next.js</strong> project:</p>
<pre><code class="lang-bash">npx create-next-app
</code></pre>
<p>Now, move into the directory and install <em>Prisma</em> into the project:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> prisma-with-discord
yarn add prisma @prisma/client
</code></pre>
<p>Now, let's get Prisma ready, go to <strong><a target="_blank" href="https://planetscale.com">PlanetScale.com</a></strong> which is a free <em>MySQL</em> database provider, sign up and create a database, once the database is ready, click <strong>Connect</strong> and get the credentials:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663403519179/oL93ZXI7B.png" alt="image.png" /></p>
<p>Now run:</p>
<pre><code class="lang-bash">yarn prisma init
</code></pre>
<p>Now paste the <code>.env</code> file you copied from PlanetScale and the same for the <code>prisma/schema.prisma</code>.</p>
<p>So what we are doing that the Discord bot is able to manage records in a <strong>Prisma</strong> table/model like adding or deleting a record! Which means we need probably 3 API files, <code>add_record</code>, <code>delete_record</code>, <code>view_records</code>, and <code>edit_record</code>.</p>
<p>So now we will make a model in <code>schema.prisma</code> to use it for our testing:</p>
<pre><code class="lang-prisma">model Sale {
  id Int @id @default(autoincrement())
  item String
  price Float
  currency String
  buyer String
}
</code></pre>
<p>Now this is an example of a store sale where we store the sale <code>id</code>, the item sold, the price, and currency of the price, and the buyer who bought the item.</p>
<p>Let's sync in our database:</p>
<pre><code class="lang-bash">yarn prisma db push
</code></pre>
<p>Here comes the fun part! We will work on the 4 <em>API</em> files, so first let's start with <code>pages/api/add_record.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()

    <span class="hljs-keyword">const</span> { item, price, currency, buyer } = req.body
    <span class="hljs-keyword">if</span> (!item || !price || !currency || !buyer) {
        res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing `item`, `price`, `currency` or `buyer`'</span> })
        <span class="hljs-keyword">return</span>
    }
    prisma.sale.create({
        <span class="hljs-attr">data</span>: {
            <span class="hljs-attr">item</span>: item,
            <span class="hljs-attr">price</span>: price,
            <span class="hljs-attr">currency</span>: currency,
            <span class="hljs-attr">buyer</span>: buyer
        }
    }).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
        res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Sale/record created successfully'</span> })
    }
    ).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Error occured while creating the sale record'</span> })
    }
    ).finally(<span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">await</span> prisma.$disconnect()
    }
    )
}
</code></pre>
<p>So what we are doing here is storing the <code>item</code>, <code>price</code>, <code>currency</code>, and <code>buyer</code> by getting their values from <code>req.body</code>, after that, if one of the 4 parameters are missing, we return an error and we won't proceed into the next step, if we got the 4 parameters, we create the sale record with the data provided and either return a success message or a error message.</p>
<p>Now, let's be able to edit records, so create a file <code>pages/api/edit_record.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()

    <span class="hljs-keyword">const</span> { sale_id, what_to_update, new_value } = req.body
    <span class="hljs-keyword">if</span> (!sale_id || !what_to_update || !new_value) {
        res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing `sale_id`, `what_to_update` or `new_value`'</span> })
        <span class="hljs-keyword">return</span>
    }
    prisma.sale.update({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">id</span>: sale_id
        },
        <span class="hljs-attr">data</span>: {
            [what_to_update]: new_value
        }
    }).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
        res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Sale/record updated successfully'</span> })
    }
    ).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
      res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Error occured while updating the sale record, what you can update is `item`, `price`, `currency` or `buyer`'</span> })
    }
    ).finally(<span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">await</span> prisma.$disconnect()
    }
    )
}
</code></pre>
<p>So what we are doing here as always we are looking for the <code>id</code> of the sale/record, <code>what_to_update</code> which can be for example <code>currency</code> or <code>buyer</code>, with <code>new_value</code> which is the new value for that thing to update.</p>
<p>Also, <em>I might want to be able to delete a record</em>, so create a file <code>pages/api/delete_record.js</code> and paste the following code below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()

    <span class="hljs-keyword">const</span> { sale_id } = req.body
    <span class="hljs-keyword">if</span> (!sale_id) {
        res.status(<span class="hljs-number">400</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing `sale_id`'</span> })
        <span class="hljs-keyword">return</span>
    }
    prisma.sale.delete({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">id</span>: sale_id
        }
    }).then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
        res.status(<span class="hljs-number">200</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Sale/record deleted successfully'</span> })
    }
    ).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
        res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Error occured while deleting the sale record'</span> })
    }
    ).finally(<span class="hljs-keyword">async</span> () =&gt; {
        <span class="hljs-keyword">await</span> prisma.$disconnect()
    }
    )
}
</code></pre>
<p>Now, simply here we are looking for the sale (record in the model/table) using the <code>id</code> because it's unique, so it's impossible to get 2 or more results for a query, and then if we found it, we delete it, if not, we return an error.</p>
<p>Last but not least, let's be able to view records/sales, create a file in <code>pages/api</code> called <code>view_records.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">"@prisma/client"</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()

  prisma.sale.findMany().then(<span class="hljs-function">(<span class="hljs-params">result</span>) =&gt;</span> {
    res.status(<span class="hljs-number">200</span>).json(result)
  }
  ).catch(<span class="hljs-function">(<span class="hljs-params">error</span>) =&gt;</span> {
    res.status(<span class="hljs-number">500</span>).json({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Error occured while listing all sales'</span> })
  }
  ).finally(<span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">await</span> prisma.$disconnect()
  }
  )
}
</code></pre>
<p>So it's very simple what we are doing here, we are just not waiting for any parameters, just listing all the sale records and sending in <strong>JSON</strong>!</p>
<h2 id="heading-creating-the-discord-bot-using-discordpy">Creating the Discord bot using Discord.py</h2>
<p>First go to https://discord.com/developers/applications and create an application:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663418771080/L2hAluWsL.png" alt="image.png" /></p>
<p>(<em>the reason why I didn't write "Discord", but instead "Disc0rd" because it won't allow including "Discord" in the bot's name for security purposes, but this is just for educational purposes and we aren't trying to hack anyone</em>)</p>
<p>Click on <em>Bot</em> and <strong>Build a bot</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1663418619546/Zs6Y-tV7P.png" alt="image.png" /></p>
<p>Click reset token and carefully copy the token!</p>
<p>Now, let's run these 3 commands to get setup!</p>
<pre><code class="lang-bash">mkdir discord_bot
touch .env
touch main.py
</code></pre>
<p>Now open your <code>.env</code> file and put in your <code>TOKEN</code> just like this:</p>
<pre><code class="lang-env">TOKEN=ABC123
</code></pre>
<p>After the <code>TOKEN</code> is ready to use, let's start working on the main code for the bot:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> discord
<span class="hljs-keyword">from</span> discord.ext <span class="hljs-keyword">import</span> commands
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> dotenv

dotenv.load_dotenv()
intents = discord.Intents.all()
bot = commands.Bot(command_prefix=<span class="hljs-string">'!'</span>, description=<span class="hljs-string">"A bot allows you to manage your Prisma records"</span>, intents=intents)


<span class="hljs-meta">@bot.event</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">on_ready</span>():</span>
    print(<span class="hljs-string">f'Logged in as <span class="hljs-subst">{bot.user}</span> (ID: <span class="hljs-subst">{bot.user.id}</span>)'</span>)
    print(<span class="hljs-string">'------'</span>)


<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span>(<span class="hljs-params">ctx, item: str, price: float, currency: str, buyer: str</span>):</span>
    r = requests.post(<span class="hljs-string">'http://localhost:3000/api/add_record'</span>, json={<span class="hljs-string">"item"</span>: item, <span class="hljs-string">"price"</span>: price, <span class="hljs-string">"currency"</span>: currency, <span class="hljs-string">"buyer"</span>: buyer})
    <span class="hljs-keyword">await</span> ctx.send(r.json()[<span class="hljs-string">"message"</span>])

<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">delete</span>(<span class="hljs-params">ctx, sale_id: int</span>):</span>
    r = requests.post(<span class="hljs-string">'http://localhost:3000/api/delete_record'</span>, json={<span class="hljs-string">"sale_id"</span>: sale_id})
    <span class="hljs-keyword">await</span> ctx.send(r.json()[<span class="hljs-string">"message"</span>])

<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">edit</span>(<span class="hljs-params">ctx, sale_id: int, what_to_update: str, new_value: str</span>):</span>
    <span class="hljs-keyword">if</span> what_to_update == <span class="hljs-string">"price"</span>:
        new_value = float(new_value)
    r = requests.post(<span class="hljs-string">'http://localhost:3000/api/edit_record'</span>, json={<span class="hljs-string">"sale_id"</span>: sale_id, <span class="hljs-string">"what_to_update"</span>: what_to_update, <span class="hljs-string">"new_value"</span>: new_value})
    <span class="hljs-keyword">await</span> ctx.send(r.json()[<span class="hljs-string">"message"</span>])

<span class="hljs-meta">@bot.command()</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">view</span>(<span class="hljs-params">ctx</span>):</span>
    r = requests.get(<span class="hljs-string">'http://localhost:3000/api/view_records'</span>, json={})
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> r.json():
        <span class="hljs-keyword">await</span> ctx.send(<span class="hljs-string">f"Sale ID: `<span class="hljs-subst">{item[<span class="hljs-string">'id'</span>]}</span>` - Item: `<span class="hljs-subst">{item[<span class="hljs-string">'item'</span>]}</span>` - Price: `<span class="hljs-subst">{item[<span class="hljs-string">'price'</span>]}</span>` - Currency: `<span class="hljs-subst">{item[<span class="hljs-string">'currency'</span>]}</span>` - Buyer: `<span class="hljs-subst">{item[<span class="hljs-string">'buyer'</span>]}</span>`"</span>)

bot.run(os.getenv(<span class="hljs-string">"TOKEN"</span>))
</code></pre>
<p>So we are first making some imports for some libraries/modules at the top and then we are creating the <strong>Discord Bot Client</strong> with using all the <code>intents</code>, it's not recommended to always use all <code>intents</code> but just for testing in this case!</p>
<p>After that we set the bot <code>description</code>, <code>intents</code>, and <code>command_prefix</code>.</p>
<p>Now we start by <code>on_ready</code> to print in the console that the bot is <strong>ready</strong> to use, after that we start creating commands with <code>@bot.command()</code> and using:</p>
<pre><code class="lang-py"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> &lt;<span class="hljs-title">command</span>&gt;(<span class="hljs-params">ctx, &lt;arguments ...&gt;</span>):</span>
</code></pre>
<p>Here we use this way to create a command, for example I would make the edit command, so I will replace <code>&lt;command&gt;</code> with <code>edit</code>, and in the parentheses we would always start with <code>ctx</code> after that we will put our arguments we need in order with their value type, like this:</p>
<pre><code class="lang-py">(ctx, sale_id: int, what_to_update: str, new_value: str)
</code></pre>
<p>And then we send a <code>JSON</code> <em>GET/POST (one of them, both would work)</em> and then return the response.</p>
<p>So let's test it together! Here is a quick 3-minute video for you!</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/flLhX0RTpEI">https://youtu.be/flLhX0RTpEI</a></div>
<h2 id="heading-the-end">The End!</h2>
<p>Thanks for reading this article, I hope you learned new things because I also invested my time writing this :)</p>
]]></content:encoded></item><item><title><![CDATA[Convert Figma components to React (Next.js) components]]></title><description><![CDATA[Hallo! Wie geht's? ("Hello, how are you?" in German)
Hoping you are having a fruitful day, today we'll convert Figma components to React (Next.js) components! Which is a super time-saver ✨.
Let's go!
1 - Creating an Amplify project
Go to the AWS Ampl...]]></description><link>https://omarcodes.io/convert-figma-components-to-react-nextjs-components</link><guid isPermaLink="true">https://omarcodes.io/convert-figma-components-to-react-nextjs-components</guid><category><![CDATA[Next.js]]></category><category><![CDATA[figma]]></category><category><![CDATA[Figma to Code]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 11 Sep 2022 07:36:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662881585329/4I3r3aAsg.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hallo! Wie geht's? ("Hello, how are you?" in German)</p>
<p>Hoping you are having a fruitful day, today we'll convert <strong><a target="_blank" href="https://figma.com">Figma</a></strong> components to <em>React</em> (<strong>Next.js</strong>) components! Which is a super time-saver ✨.</p>
<p>Let's go!</p>
<h2 id="heading-1-creating-an-amplify-project">1 - Creating an Amplify project</h2>
<p>Go to the <a target="_blank" href="https://aws.amazon.com/pm/amplify/"><strong>AWS Amplify</strong> page</a> and click on <strong>Build an app with AWS Amplify</strong>. If required, sign in/sign up for an <strong>AWS</strong> account, after that, set the app name to your preferred name and click <strong>Confirm Deployment</strong>.</p>
<h2 id="heading-2-creating-our-figma">2 - Creating our Figma</h2>
<p>Open the <a target="_blank" href="https://figma.com/community"><strong>Figma Community Site</strong></a> and search for <em>AWS Amplify UI Kit</em> and use the original one made by <strong>AWS Amplify</strong>, or use this direct link:</p>
<p><a target="_blank" href="https://www.figma.com/community/file/1047600760128127424">AWS Amplify UI Kit - On Figma</a></p>
<p>Click the <strong>Duplicate</strong> button and edit the sample components as your needs.</p>
<h2 id="heading-3-import-figma-components-to-aws-amplify-studio">3 - Import Figma components to AWS Amplify Studio</h2>
<p>On the sidebar in the studio, click <strong>UI Library</strong> and click on <strong>Get Started</strong> and paste the <strong>Figma file you duplicated</strong> and continue.</p>
<p>Then you will get all the components, where you can accept/reject every component alone, or only accept all.</p>
<h2 id="heading-4-setup-nextjs-with-the-amplify-dependencies">4 - Setup Next.js with the Amplify dependencies</h2>
<p>In your terminal, run:</p>
<pre><code class="lang-bash">npx create-next-app figma-to-next
</code></pre>
<p>Now, just to make sure the app is working, run:</p>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>And check <code>localhost:3000</code>, now, the app is working, let's install a few things before importing the components from Amplify:</p>
<pre><code class="lang-bash">npm i aws-amplify @aws-amplify/ui-react
</code></pre>
<p>Now, also a requirement, be sure that you got Amplify CLI installed on your system, to verify that, run:</p>
<pre><code class="lang-bash">amplify -v
</code></pre>
<h2 id="heading-5-import-the-components-from-amplify-to-nextjs">5 - Import the components from Amplify to Next.js</h2>
<p>Open the studio and click <strong>Local Setup Instructions</strong> and copy the command, and run it in your Next.js project's root folder, now let's check if the components have been imported by running the following simple command:</p>
<pre><code class="lang-bash">ls -la ui-components
</code></pre>
<p>Now, you're all done! You can now use your components which are made using Figma in React/Next.js! </p>
<p>Have a nice day ✨! See you!</p>
]]></content:encoded></item><item><title><![CDATA[Build a to-do Node.js CLI with Prisma and Next.js]]></title><description><![CDATA[Yo! What's up? Remember the last article where we used Prisma with Next.js and made a CLI and added an authentication feature? I noticed many of you learned a lot! So here?! You will learn even more, including making a to-do list app as a CLI with Pr...]]></description><link>https://omarcodes.io/build-a-to-do-nodejs-cli-with-prisma-and-nextjs</link><guid isPermaLink="true">https://omarcodes.io/build-a-to-do-nodejs-cli-with-prisma-and-nextjs</guid><category><![CDATA[Next.js]]></category><category><![CDATA[PlanetScale]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[prisma]]></category><category><![CDATA[MySQL]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 04 Sep 2022 14:17:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1662300993804/Pup31GZbD.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Yo! What's up? Remember the last article where we used Prisma with Next.js and made a CLI and added an authentication feature? I noticed many of you learned a lot! So here?! You will learn even more, including making a to-do list app as a CLI with Prisma and Next.js API powering the application to give it the best functionality!</p>
<p>Hold on, Omar? <strong>Why</strong> do we need Prisma/Next.js? The reason why buddy is because this application allows you to sync your tasks from anywhere in the world!</p>
<p>Without further time wasting, let's get started.</p>
<h2 id="heading-creating-our-api">Creating our API</h2>
<p>First of all, we need a database, so let's use PlanetScale for this! Head over to <a target="_blank" href="https://planetscale.com">planetscale.com</a> and click <strong>Get Started</strong>, create your database, and wait for it to get ready for work!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1662274213691/vBI6L8cM7.png?auto=compress" alt="PlanetScale Database Creation" /></p>
<p>Now, launch your terminal and start a new <strong>Next.js</strong> project using <code>npx</code> after that change directory:</p>
<pre><code class="lang-bash">npx create-next-app
<span class="hljs-built_in">cd</span> to-do-list-app
</code></pre>
<p>Now after we created our project, let's add Prisma and get it ready so run the following command in the terminal:</p>
<pre><code class="lang-bash">yarn add prisma @prisma/client
yarn prisma init
</code></pre>
<p>After that we will get a <code>schema.prisma</code> file in the <code>prisma</code> folder, replace the file with the following:</p>
<pre><code class="lang-prisma">generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider = "mysql"
  url = env("DATABASE_URL")
  referentialIntegrity = "prisma"
}
</code></pre>
<p>So, what we just most importantly changed the database provider to <code>mysql</code> because we are using a <strong>MySQL</strong> database.</p>
<p>Now on the <strong>PlanetScale</strong> dashboard, click on <em>Connect</em> and choose <strong>Prisma</strong> as the option to connect with, copy the <code>.env</code> file provided and create a <code>.env</code> file in your project and paste what you just copied.</p>
<p>Now we will make 2 models, a <code>User</code> and a <code>Task</code>, so add these 2 models to your Prisma schema file:</p>
<pre><code class="lang-prisma">model User {
  id Int @id @default(autoincrement())
  username String @unique
  password String
  token String @unique
}

model Task {
  id Int @id @default(autoincrement())
  title String
  userToken String
}
</code></pre>
<p>Now, your schema file should look like this:</p>
<pre><code class="lang-prisma">generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider = "mysql"
  url = env("DATABASE_URL")
  referentialIntegrity = "prisma"
}

model User {
  id Int @id @default(autoincrement())
  username String @unique
  password String
  token String @unique
}

model Task {
  id Int @id @default(autoincrement())
  title String
  userToken String
}
</code></pre>
<p>Now run <code>yarn prisma db push</code> to sync your <strong>MySQL PlanetScale Database</strong>.</p>
<p>We have to now create our API files, first remove <code>pages/api/hello.js</code> file and create a file called <code>register.js</code> in <code>pages/api</code> folder and paste the following code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { username, password, token } = req.body;
    <span class="hljs-keyword">if</span> (!username || !password || !token) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing username, password or token'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">username</span>: username
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'Username already taken'</span>
            });
        } <span class="hljs-keyword">else</span> {
            prisma.user.findUnique({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">token</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
                <span class="hljs-keyword">if</span> (user) {
                    res.status(<span class="hljs-number">400</span>).json({
                        <span class="hljs-attr">message</span>: <span class="hljs-string">'Token already taken'</span>
                    });
                } <span class="hljs-keyword">else</span> {
                    prisma.user.create({
                        <span class="hljs-attr">data</span>: {
                            <span class="hljs-attr">username</span>: username,
                            <span class="hljs-attr">password</span>: password,
                            <span class="hljs-attr">token</span>: token
                        }
                    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
                        res.json({
                            <span class="hljs-attr">message</span>: <span class="hljs-string">"User created successfully"</span>,
                            <span class="hljs-attr">user</span>: user
                        });
                    });
                }
            }
            );
        }
    });

}
</code></pre>
<p>What we are doing here is defining a <strong>Prisma</strong> client and making variables for <code>username</code>, <code>password</code>, and <code>token</code>. If one of the parameters isn't provided, we return an error:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { username, password, token } = req.body;
    <span class="hljs-keyword">if</span> (!username || !password || !token) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing username, password or token'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
</code></pre>
<p>And for registration we first check if username is used, if yes, we return an error, if not, we check if the token is used, if yes, returns an error as usual, if not, we will proceed to registration:</p>
<pre><code class="lang-js">    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">username</span>: username
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'Username already taken'</span>
            });
        } <span class="hljs-keyword">else</span> {
            prisma.user.findUnique({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">token</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
                <span class="hljs-keyword">if</span> (user) {
                    res.status(<span class="hljs-number">400</span>).json({
                        <span class="hljs-attr">message</span>: <span class="hljs-string">'Token already taken'</span>
                    });
                } <span class="hljs-keyword">else</span> {
                    prisma.user.create({
                        <span class="hljs-attr">data</span>: {
                            <span class="hljs-attr">username</span>: username,
                            <span class="hljs-attr">password</span>: password,
                            <span class="hljs-attr">token</span>: token
                        }
                    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
                        res.json({
                            <span class="hljs-attr">message</span>: <span class="hljs-string">"User created successfully"</span>,
                            <span class="hljs-attr">user</span>: user
                        });
                    });
                }
            }
            );
        }
    });
</code></pre>
<p>Now, we have the user to be able to authenticate/login, create <code>login.js</code> file and paste the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { username, password } = req.body;
    <span class="hljs-keyword">if</span> (!username || !password) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing username or password'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">username</span>: username
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            <span class="hljs-keyword">if</span> (user.password === password) {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'User authenticated successfully'</span>,
                    <span class="hljs-attr">userToken</span>: user.token,
                    <span class="hljs-attr">user</span>: username
                });
            } <span class="hljs-keyword">else</span> {
                res.status(<span class="hljs-number">400</span>).json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Incorrect password'</span>
                });
            }
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );

}
</code></pre>
<p>So as always we are defining the <em>Prisma</em> client and checking if one of the parameters (<code>username</code> or <code>password</code>) are missing, and if so, we will return an error:</p>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { username, password } = req.body;
    <span class="hljs-keyword">if</span> (!username || !password) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing username or password'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
</code></pre>
<p>Then we use the <code>findUnique</code> feature to use the <code>username</code> which is unique to find a record/user in the table, so if we haven't found a user, we return a error, if we found one with the matching username, we check if the password provided matches along with the username, if the password is correct, we return a token which is something like a random piece of characters &amp; numbers which is hard to guess which allows you to do anything including with the API itself (when sending requests manually), if not, we return an error that the password is incorrect:</p>
<pre><code class="lang-js">prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">username</span>: username
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            <span class="hljs-keyword">if</span> (user.password === password) {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'User authenticated successfully'</span>,
                    <span class="hljs-attr">userToken</span>: user.token,
                    <span class="hljs-attr">user</span>: username
                });
            } <span class="hljs-keyword">else</span> {
                res.status(<span class="hljs-number">400</span>).json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Incorrect password'</span>
                });
            }
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
</code></pre>
<p>Now, let's make the fun..... start! Create a new file called <code>create.js</code> which will allow the user to create new tasks! Paste the following code into the file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { token, taskTitle } = req.body;
    <span class="hljs-keyword">if</span> (!token || !taskTitle) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing token or task title'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.create({
                <span class="hljs-attr">data</span>: {
                    <span class="hljs-attr">title</span>: taskTitle,
                    <span class="hljs-attr">userToken</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Task created successfully'</span>,
                });
            });
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
}
</code></pre>
<p>Simply skipping defining the <strong><em>Prisma client</em></strong>, so we use <code>findUnique</code> to check the user token if valid or not, if it's not, we pass an error saying that there is no such user, if the user exists, we create a task with the title given and with that token, and then we return a success message:</p>
<pre><code class="lang-js">    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.create({
                <span class="hljs-attr">data</span>: {
                    <span class="hljs-attr">title</span>: taskTitle,
                    <span class="hljs-attr">userToken</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Task created successfully'</span>,
                });
            });
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
</code></pre>
<p>Now if we assume someone wants to delete a task? Create <code>delete.js</code> and paste the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { token, taskId } = req.body;
    <span class="hljs-keyword">if</span> (!token || !taskId) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing token or task id'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.findUnique({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">id</span>: taskId
                }
            }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                <span class="hljs-keyword">if</span> (task.userToken === token) {
                    prisma.task.delete({
                        <span class="hljs-attr">where</span>: {
                            <span class="hljs-attr">id</span>: taskId
                        }
                    }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                        res.json({
                            <span class="hljs-attr">message</span>: <span class="hljs-string">'Task deleted successfully'</span>,
                        });
                    });
                } <span class="hljs-keyword">else</span> {
                    res.status(<span class="hljs-number">400</span>).json({
                        <span class="hljs-attr">message</span>: <span class="hljs-string">'Task does not belong to the user'</span>
                    });
                }
            }
            );
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
}
</code></pre>
<p>So what we do is find the user using the token, if we didn't find the user, we return an error, if we found the user, we find the task using the ID, we check if the owner is matching, if so we delete it, if not, we return an error:</p>
<pre><code class="lang-js">    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.findUnique({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">id</span>: taskId
                }
            }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                <span class="hljs-keyword">if</span> (task.userToken === token) {
                    prisma.task.delete({
                        <span class="hljs-attr">where</span>: {
                            <span class="hljs-attr">id</span>: taskId
                        }
                    }).then(<span class="hljs-function"><span class="hljs-params">task</span> =&gt;</span> {
                        res.json({
                            <span class="hljs-attr">message</span>: <span class="hljs-string">'Task deleted successfully'</span>,
                        });
                    });
                } <span class="hljs-keyword">else</span> {
                    res.status(<span class="hljs-number">400</span>).json({
                        <span class="hljs-attr">message</span>: <span class="hljs-string">'Task does not belong to the user'</span>
                    });
                }
            }
            );
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
</code></pre>
<p>Last but not least the <code>view.js</code> file which allows the user to view the tasks:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient();
    <span class="hljs-keyword">const</span> { token } = req.body;
    <span class="hljs-keyword">if</span> (!token) {
        res.status(<span class="hljs-number">400</span>).json({
            <span class="hljs-attr">message</span>: <span class="hljs-string">'Missing token'</span>
        });
        <span class="hljs-keyword">return</span>;
    }
    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.findMany({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">userToken</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">tasks</span> =&gt;</span> {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Tasks retrieved successfully'</span>,
                    <span class="hljs-attr">tasks</span>: tasks
                });
            });
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
}
</code></pre>
<p>So what we do here is find the user, if not found, we return an error, if we found the user, we return all the tasks corresponding to the user:</p>
<pre><code class="lang-js">    prisma.user.findUnique({
        <span class="hljs-attr">where</span>: {
            <span class="hljs-attr">token</span>: token
        }
    }).then(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> {
        <span class="hljs-keyword">if</span> (user) {
            prisma.task.findMany({
                <span class="hljs-attr">where</span>: {
                    <span class="hljs-attr">userToken</span>: token
                }
            }).then(<span class="hljs-function"><span class="hljs-params">tasks</span> =&gt;</span> {
                res.json({
                    <span class="hljs-attr">message</span>: <span class="hljs-string">'Tasks retrieved successfully'</span>,
                    <span class="hljs-attr">tasks</span>: tasks
                });
            });
        } <span class="hljs-keyword">else</span> {
            res.status(<span class="hljs-number">400</span>).json({
                <span class="hljs-attr">message</span>: <span class="hljs-string">'No user found'</span>
            });
        }
    }
    );
</code></pre>
<p>Now, we got our <strong>API</strong> ready after hard work 🥳!</p>
<h2 id="heading-creating-our-cli">Creating our CLI</h2>
<p>Run the following commands to get started:</p>
<pre><code class="lang-bash">mkdir todocli
<span class="hljs-built_in">cd</span> todocli
npm init -y
</code></pre>
<p>Now create a <code>index.js</code> file and paste the following:</p>
<pre><code class="lang-js"><span class="hljs-meta">#!/usr/bin/env node</span>

<span class="hljs-keyword">var</span> args = process.argv.slice(<span class="hljs-number">2</span>);
<span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-keyword">var</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">'request'</span>);
command = args[<span class="hljs-number">0</span>];

<span class="hljs-keyword">if</span> (command == <span class="hljs-string">'login'</span>) {
    options = {
        <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/login'</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">json</span>: {
            <span class="hljs-attr">username</span>: args[<span class="hljs-number">1</span>],
            <span class="hljs-attr">password</span>: args[<span class="hljs-number">2</span>]
        }
    };
    request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
        <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-built_in">console</span>.log(body.message);
            fs.writeFile(<span class="hljs-string">'./token.txt'</span>, body.userToken, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
                <span class="hljs-keyword">if</span> (err) {
                    <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(err);
                }
                <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Token saved successfully!"</span>);
            }
            );
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(body.message);
        }
    });
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (command == <span class="hljs-string">'register'</span>) {
    options = {
        <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/register'</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">json</span>: {
            <span class="hljs-attr">username</span>: args[<span class="hljs-number">1</span>],
            <span class="hljs-attr">password</span>: args[<span class="hljs-number">2</span>],
            <span class="hljs-attr">token</span>: <span class="hljs-built_in">Math</span>.random().toString(<span class="hljs-number">36</span>).substring(<span class="hljs-number">2</span>, <span class="hljs-number">15</span>) + <span class="hljs-built_in">Math</span>.random().toString(<span class="hljs-number">36</span>).substring(<span class="hljs-number">2</span>, <span class="hljs-number">15</span>)
        }
    };
    request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
        <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-built_in">console</span>.log(body.message);
            <span class="hljs-comment">// save token</span>
            fs.writeFile(<span class="hljs-string">'./token.txt'</span>, body.user.token, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err</span>) </span>{
                <span class="hljs-keyword">if</span> (err) {
                    <span class="hljs-keyword">return</span> <span class="hljs-built_in">console</span>.log(err);
                }
                <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Token saved successfully!"</span>);
            }
            );
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (body.message==<span class="hljs-string">"Token already taken"</span>) {
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Please try registering again!"</span>)
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(body.message);
        }
    });
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (command == <span class="hljs-string">'create'</span>) {
    options = {
        <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/create'</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">json</span>: {
            <span class="hljs-attr">taskTitle</span>: args.slice(<span class="hljs-number">1</span>).join(<span class="hljs-string">' '</span>),
            <span class="hljs-attr">token</span>: fs.readFileSync(<span class="hljs-string">'./token.txt'</span>, <span class="hljs-string">'utf8'</span>)
        }
    };
    request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
        <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-built_in">console</span>.log(body.message);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(body.message);
        }
    });
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (command == <span class="hljs-string">'view'</span>) {
    options = {
        <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/view'</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">json</span>: {
            <span class="hljs-attr">token</span>: fs.readFileSync(<span class="hljs-string">'./token.txt'</span>, <span class="hljs-string">'utf8'</span>)
        }
    };
    request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
        <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-comment">// save the title and id of each task in an array</span>
            <span class="hljs-keyword">var</span> tasks = [];
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; body.tasks.length; i++) {
                tasks.push({
                    <span class="hljs-attr">id</span>: body.tasks[i].id,
                    <span class="hljs-attr">title</span>: body.tasks[i].title
                });
            }
            <span class="hljs-comment">// print the tasks along with their ids</span>
            <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Your tasks are:"</span>);
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; tasks.length; i++) {
                <span class="hljs-built_in">console</span>.log(tasks[i].id + <span class="hljs-string">": "</span> + tasks[i].title);
            }

        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(body.message);
        }
    });
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (command == <span class="hljs-string">'delete'</span>) {
    options = {
        <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/delete'</span>,
        <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
        <span class="hljs-attr">json</span>: {
            <span class="hljs-attr">taskId</span>: args[<span class="hljs-number">1</span>],
            <span class="hljs-attr">token</span>: fs.readFileSync(<span class="hljs-string">'./token.txt'</span>, <span class="hljs-string">'utf8'</span>)
        }
    };
    request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
        <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
            <span class="hljs-built_in">console</span>.log(body.message);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.log(body.message);
        }
    });
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (command == <span class="hljs-string">'help'</span>) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Usage: todocli &lt;command&gt; &lt;arguments&gt;"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Commands:"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"login &lt;username&gt; &lt;password&gt;"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"register &lt;username&gt; &lt;password&gt;"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"create &lt;task title&gt;"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"view"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"delete &lt;task id&gt;"</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"help"</span>);
}
</code></pre>
<p>Simply what we are mainly doing is getting the parameters and depending on the API, and the token is saved into a <code>txt</code> file locally. </p>
<p>Now install a required package using <code>npm install request</code></p>
<p>Now edit your <code>package.json</code> and replace your <code>scripts</code>, paste the following:</p>
<pre><code class="lang-json">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-string">"bin"</span>: {
    <span class="hljs-attr">"todocli"</span>: <span class="hljs-string">"index.js"</span>
  }
</code></pre>
<p>Your <code>package.json</code> should now look like this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"todocli"</span>,
  <span class="hljs-attr">"version"</span>: <span class="hljs-string">"1.0.0"</span>,
  <span class="hljs-attr">"description"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"main"</span>: <span class="hljs-string">"index.js"</span>,
  <span class="hljs-attr">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  },
  <span class="hljs-attr">"bin"</span>: {
    <span class="hljs-attr">"todocli"</span>: <span class="hljs-string">"index.js"</span>
  },
  <span class="hljs-attr">"keywords"</span>: [],
  <span class="hljs-attr">"author"</span>: <span class="hljs-string">""</span>,
  <span class="hljs-attr">"license"</span>: <span class="hljs-string">"ISC"</span>,
  <span class="hljs-attr">"dependencies"</span>: {
    <span class="hljs-attr">"request"</span>: <span class="hljs-string">"^2.88.2"</span>
  }
}
</code></pre>
<p>Now we are done, do <code>npm install . -g</code> and start using the app!</p>
<h2 id="heading-test-it-out-no-setup-needed">Test it out - No setup needed</h2>
<p>Just install <code>to-do-cli-prisma</code> with the command:</p>
<pre><code class="lang-bash">npm i to-do-cli-prisma
</code></pre>
<p>And check how to use it with the command: <code>todocli help</code></p>
<h2 id="heading-important-links">Important links 🔗</h2>
<ul>
<li><strong>GitHub Repo</strong> - <a target="_blank" href="https://github.com/Omar8345/to-do-list-app-cli">Omar8345/to-do-list-app-cli</a></li>
<li><strong>npm Package</strong> - <a target="_blank" href="https://www.npmjs.com/package/to-do-cli-prisma">to-do-cli-prisma</a></li>
</ul>
<p>Thanks for reading this article and hope you learned something useful!</p>
]]></content:encoded></item><item><title><![CDATA[How to setup authentication with Node.js CLI and Prisma]]></title><description><![CDATA[Originally published on DevDojo

Hello there! Today we will be integrating user authentication with your Node.js CLI, we will also cover how to create one, and we will make an API to authenticate user details! Without wasting much more time, let's go...]]></description><link>https://omarcodes.io/how-to-setup-authentication-with-nodejs-cli-and-prisma</link><guid isPermaLink="true">https://omarcodes.io/how-to-setup-authentication-with-nodejs-cli-and-prisma</guid><category><![CDATA[prisma]]></category><category><![CDATA[PlanetScale]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[MySQL]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 07 Aug 2022 14:07:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/imgCpfIMoRw/upload/v1659881090947/qalqBRY55.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><em>Originally published on <a target="_blank" href="https://devdojo.com/omarthedev/how-to-setup-authentication-with-nodejs-cli"><strong>DevDojo</strong></a></em></p>
</blockquote>
<p>Hello there! Today we will be integrating <strong>user authentication</strong> with your <em>Node.js CLI</em>, we will also cover how to create one, and we will make an <em>API</em> to authenticate user details! Without wasting much more time, let's go!</p>
<h2 id="heading-creating-our-cli">Creating our CLI</h2>
<p>Start by creating a folder and initializing our project 🎉:</p>
<pre><code class="lang-bash">mkdir mycli
<span class="hljs-built_in">cd</span> mycli
npm init -y
</code></pre>
<p>Now, let's make a test command like <code>mycli-help</code>, so to do that, create an <code>index.js</code> file and paste the following code:</p>
<pre><code class="lang-js"><span class="hljs-meta">#!/usr/bin/env node</span>

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello World!"</span>);
</code></pre>
<p>Simply, what we are doing here is adding the <strong>shebang</strong> which serves as a way for your operating system program loader to locate and use toe parse the correct interpreter for your executable file. This only works in Unix Systems though.</p>
<blockquote>
<p>In computing, a shebang is the character sequence consisting of the character's number sign and exclamation mark (#!) at the beginning of a script.</p>
<p>From: <strong>Wikipedia</strong>: https://en.wikipedia.org/wiki/Shebang_(Unix)</p>
</blockquote>
<p>And we are simply printing in the console <code>Hello World!</code>, so let's edit our <code>package.json</code>, so add this <code>scripts</code> JSON keypair:</p>
<pre><code class="lang-json">  <span class="hljs-string">"scripts"</span>: {
    <span class="hljs-attr">"start"</span>: <span class="hljs-string">"node index.js"</span>
  }
</code></pre>
<p>And add this <code>bin</code> which tells the app which file should be run once this command is executed:</p>
<pre><code class="lang-json">  <span class="hljs-string">"bin"</span>: {
    <span class="hljs-attr">"mycli-help"</span>: <span class="hljs-string">"index.js"</span>
  }
</code></pre>
<p>Now, let's install the <strong>CLI</strong> and give it a try:</p>
<pre><code class="lang-bash">npm i . -g
mycli-help
</code></pre>
<p>You should get <code>Hello World!</code>, now let's uninstall it and work on our <em>API</em> 🚀:</p>
<pre><code class="lang-bash">npm uninstall mycli -g
</code></pre>
<h2 id="heading-setting-up-our-api-prisma">Setting up our API + Prisma</h2>
<p>Start by creating a new <strong>Next.js</strong> app using <code>npx</code>:</p>
<pre><code class="lang-bash">npx create-next-app
<span class="hljs-built_in">cd</span> my-auth-api
</code></pre>
<p>After that, let's set up our <strong>Prisma</strong> schema and our <em>MySQL</em> database, so first of all let's get the database, for this guide, we will use <a target="_blank" href="https://planetscale.com"><strong>PlanetScale</strong></a> or generally a <em>MySQL</em> database, it should be the same process, just update your <strong>Schema configs</strong>.</p>
<p>So, head over to <em>PlanetScale</em> and create a new <em>database</em> if you don't have one yet, it will take a few minutes to get ready, just be patient, once done, click on <strong>Connect</strong>, choose <em>Prisma</em> from the dropdown menu and copy the <code>.env</code> file content:</p>
<p><img src="https://i.postimg.cc/R0p449L9/image.png" alt /></p>
<p>Now, let's create a <code>.env</code> file and paste the environment variables you just copied from <strong>PlanetScale</strong>. Now, let's setup <em>Prisma</em> 🚀:</p>
<pre><code class="lang-bash">yarn add prisma @prisma/client
</code></pre>
<p>Now, let's check out our <code>prisma/schema.prisma</code> and update the configs, etc. to the following:</p>
<pre><code class="lang-prisma">generator client {
  provider = "prisma-client-js"
  previewFeatures = ["referentialIntegrity"]
}

datasource db {
  provider = "mysql"
  url = env("DATABASE_URL")
  referentialIntegrity = "prisma"
}
</code></pre>
<p>Now, let's define our <code>Account</code> Model, like this:</p>
<pre><code class="lang-prisma">model Account {
  id Int @default(autoincrement()) @id
  username String @unique
  password String
}
</code></pre>
<p>Now, let's sync our <strong>database</strong> 🚀:</p>
<pre><code class="lang-bash">npx prisma db push
</code></pre>
<p>Now, your <strong>database</strong> is in <em>sync</em> with your schema, now let's work on our <strong>API</strong>.</p>
<p>Now, remove the <code>pages/api/hello.js</code> file, and let's create a file in <code>pages/api/</code> called <code>auth.js</code>, so it should be <code>pages/api/auth.js</code></p>
<p>Now, place this code in the <code>auth.js</code> file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">handler</span>(<span class="hljs-params">req, res</span>) </span>{
  <span class="hljs-keyword">if</span> (!req.body.username || !req.body.password) {
    res.status(<span class="hljs-number">400</span>).json({
      <span class="hljs-attr">error</span>: <span class="hljs-string">'Please provide username and password'</span>
    })
  }
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()
  <span class="hljs-keyword">const</span> findAccount = <span class="hljs-keyword">async</span> (username, password) =&gt; {
    <span class="hljs-keyword">const</span> account = <span class="hljs-keyword">await</span> prisma.account.findFirst({
      <span class="hljs-attr">where</span>: {
        username,
        <span class="hljs-attr">password</span>: password,
      },
    })
    <span class="hljs-keyword">if</span> (!account) {
      <span class="hljs-keyword">return</span> res.json({
        <span class="hljs-attr">status</span>: <span class="hljs-string">'error authentication failed'</span>
      })
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> res.json({
        <span class="hljs-attr">status</span>: <span class="hljs-string">'authorized'</span>,
        <span class="hljs-attr">accountAuthorized</span>: username
      })
    }
  }
  findAccount(req.body.username, req.body.password)
}
</code></pre>
<p>Simply, what we are doing here, first of all, we are importing the <code>PrismaClient</code> to use <strong>Prisma</strong>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { PrismaClient } <span class="hljs-keyword">from</span> <span class="hljs-string">'@prisma/client'</span>
</code></pre>
<p>And after that, we are making the <strong>API</strong> and defining the <em>Prisma Client</em> so that we can use <strong>Prisma</strong> in the <em>API</em>, also we are checking if the username and password are provided in JSON:</p>
<pre><code class="lang-js">  <span class="hljs-keyword">if</span> (!req.body.username || !req.body.password) {
    res.status(<span class="hljs-number">400</span>).json({
      <span class="hljs-attr">error</span>: <span class="hljs-string">'Please provide username and password'</span>
    })
  }
  <span class="hljs-keyword">const</span> prisma = <span class="hljs-keyword">new</span> PrismaClient()
</code></pre>
<p>After creating the <em>Prisma</em> client, let's use it to check if a record in our <strong>model</strong> matches with the credentials sent in a JSON request which will be sent from our <em>CLI</em>, so we use <code>findFirst</code> to check for a matching record and don't worry, as long as the username is unique with the help of <code>@unique</code>, same passwords but for different accounts won't effect, so after checking for a matching record, we either get <code>null</code> for the value of <code>account</code> because there is no such record matching, so we use a condition to return a response in JSON telling that there is an error authenticating the user, and otherwise, we will get the record details including <code>id</code>, <code>username</code>, <code>password</code> in <code>account</code>, but we don't need all of this, so we return a response in JSON with a message telling that authentication was successful and we provide the <code>username</code> which has been successfully authorized for confirmation:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> findAccount = <span class="hljs-keyword">async</span> (username, password) =&gt; {
    <span class="hljs-keyword">const</span> account = <span class="hljs-keyword">await</span> prisma.account.findFirst({
      <span class="hljs-attr">where</span>: {
        username,
        <span class="hljs-attr">password</span>: password,
      },
    })
    <span class="hljs-keyword">if</span> (!account) {
      <span class="hljs-keyword">return</span> res.json({
        <span class="hljs-attr">status</span>: <span class="hljs-string">'error authentication failed'</span>
      })
    } <span class="hljs-keyword">else</span> {
      <span class="hljs-keyword">return</span> res.json({
        <span class="hljs-attr">status</span>: <span class="hljs-string">'authorized'</span>,
        <span class="hljs-attr">accountAuthorized</span>: username
      })
    }
  }
</code></pre>
<p>Now, we will run the function and provide <code>username</code> and <code>password</code>, which are in <code>res.body</code>:</p>
<pre><code class="lang-js">  findAccount(req.body.username, req.body.password)
</code></pre>
<p>Now, the <strong>API</strong> is good to go! Just run:</p>
<pre><code class="lang-bash">yarn dev
</code></pre>
<h2 id="heading-authenticating-the-user-from-cli">Authenticating the user from CLI</h2>
<p>Now, we got an <em>API</em> running and waiting for someone to call! We have to get 2 things from the user, a (username) and a (password), so let's code it inside our <code>index.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-meta">#!/usr/bin/env node</span>

<span class="hljs-keyword">var</span> args = process.argv.slice(<span class="hljs-number">2</span>);
<span class="hljs-keyword">var</span> username = args[<span class="hljs-number">0</span>];
<span class="hljs-keyword">var</span> password = args[<span class="hljs-number">1</span>];

<span class="hljs-keyword">if</span> (!username || !password) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Please provide username and password'</span>);
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Usage: mycli-auth &lt;username&gt; &lt;password&gt;'</span>);
    process.exit(<span class="hljs-number">1</span>);
}

<span class="hljs-keyword">var</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">'request'</span>);
<span class="hljs-keyword">var</span> options = {
    <span class="hljs-attr">url</span>: <span class="hljs-string">'http://localhost:3000/api/auth'</span>,
    <span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
    <span class="hljs-attr">json</span>: {
        <span class="hljs-attr">username</span>: username,
        <span class="hljs-attr">password</span>: password
    }
}
request(options, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, response, body</span>) </span>{
    <span class="hljs-keyword">if</span> (!error &amp;&amp; response.statusCode == <span class="hljs-number">200</span>) {
        <span class="hljs-built_in">console</span>.log(body);
    }
}
);
</code></pre>
<p>So what we are doing is that we are checking if username and password are provided when executing the command, so if both or one of the credentials aren't provided, we will log an error with expected usage and exit.</p>
<p>If they are both provided, we import <code>request</code> and set options where the API is running accepting JSON requests, setting the method to <code>POST</code>, and in the JSON which we will send, we provide <code>username</code> and <code>password</code>, and then if we get a JSON back with status code <code>200</code> which means <strong>OK</strong>, we return the JSON to the user in the console, which is fine, as long as our JSON response is human readable and understandable, you may configure this if you wish 😉.</p>
<p>Now, before trying it, just install <code>request</code>:</p>
<pre><code class="lang-bash">npm install request
</code></pre>
<p>Now, just edit <code>mycli-help</code> to <code>mycli-auth</code> in <code>bin</code> in the <code>package.json</code> file, it should be like this:</p>
<pre><code class="lang-json">  <span class="hljs-string">"bin"</span>: {
    <span class="hljs-attr">"mycli-auth"</span>: <span class="hljs-string">"index.js"</span>
  }
</code></pre>
<p>Now, test it out! But first, run <code>npx prisma studio</code> and go to http://localhost:5000 and check the <code>Account</code> model, add a user record which you will be using to authenticate, done? Now:</p>
<pre><code class="lang-bash">npm i . -g
mycli-auth &lt;username&gt; &lt;password&gt;
</code></pre>
<p>And.... congrats 🎉, you have successfully made your authentication feature!</p>
<h2 id="heading-try-it-no-setup">Try it - No setup!</h2>
<p>Just install from NPM:</p>
<pre><code class="lang-bash">npm i nodejs-cli-prisma-auth -g
</code></pre>
<p>And try authorizing with the sample admin user:</p>
<pre><code class="lang-bash">mycli-auth admin supersecret123
</code></pre>
<p>And kaboom 💥! Even here is the GitHub Repo: <a target="_blank" href="https://github.com/Omar8345/nodejs-prisma-auth/">Omar8345/nodejs-prisma-auth</a>!</p>
<p>Thanks for reading this article ✨, hope you learned something useful today!</p>
]]></content:encoded></item><item><title><![CDATA[How to Add Advanced Analytics to Medusa with Next.js and Matomo]]></title><description><![CDATA[Medusa is an open source headless commerce, it makes it easy for developers to create awesome online commerce shops in no time! Medusa aims to provide developers with a great experience and limitless customization capabilities. Well, Medusa is well k...]]></description><link>https://omarcodes.io/how-to-add-advanced-analytics-to-medusa-with-nextjs-and-matomo</link><guid isPermaLink="true">https://omarcodes.io/how-to-add-advanced-analytics-to-medusa-with-nextjs-and-matomo</guid><category><![CDATA[Next.js]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Fri, 29 Jul 2022 07:28:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1659079558774/sgLmZqT6Z.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong><a target="_blank" href="https://medusajs.com/">Medusa</a></strong> is an open source headless commerce, it makes it easy for developers to create awesome online commerce shops in no time! <strong>Medusa</strong> aims to provide developers with a great experience and limitless customization capabilities. Well, <strong>Medusa</strong> is well known for being a <strong>Shopify</strong> open source alternative.</p>
<p>In this <strong>guide</strong>, you will be integrating <strong>Matomo</strong> which allows you to get your website (store) analytics, such as <strong>average session time</strong> (how long a user stays on the page), etc. </p>
<p>You will be integrating <strong>Matomo</strong> with a <strong>Next.js</strong> app, where it’s the same if you use <strong>Next.js</strong> to build and create your <strong>Medusa</strong> store.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along with this guide, the following requirements are required:</p>
<ul>
<li>A <strong>Matomo</strong> account - Get an account from <a target="_blank" href="https://matomo.org/start-free-analytics-trial/">here</a></li>
<li><strong>Node</strong> V14.0 or higher - Download from <a target="_blank" href="https://nodejs.org/en/download/">here</a></li>
<li><strong><a target="_blank" href="https://www.sqlite.org/download.html">SQLite</a></strong> or <strong><a target="_blank" href="https://www.postgresql.org/download/">PostgreSQL</a></strong> (<em>SQLite</em> is only for getting started; <em>PostgreSQL</em> is recommended)</li>
<li><strong><a target="_blank" href="https://redis.io/download/">Redis</a></strong> server up and running</li>
</ul>
<p>More information can be found here on <a target="_blank" href="https://docs.medusajs.com/tutorial/set-up-your-development-environment/"><strong><em>How-to</em> Set up your development environment</strong></a>.</p>
<h2 id="heading-setting-up-your-medusa-store">Setting up your Medusa Store</h2>
<p>This section is separated into 3 parts as follows:</p>
<ul>
<li><em>Setting up the</em> <strong>Medusa Server</strong></li>
<li><em>Setting up the</em> <strong>Medusa Store</strong></li>
<li><em>Setting up the</em> <strong>Medusa Admin Dashboard</strong></li>
</ul>
<h3 id="heading-1-setting-up-the-medusa-server">1. Setting up the Medusa Server</h3>
<ul>
<li>Start by creating a new <strong>Medusa</strong> project and seeding it:</li>
</ul>
<pre><code class="lang-bash">medusa new my-medusa-store --seed
</code></pre>
<ul>
<li>Move into the project’s directory and start the <strong>server</strong>:</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> my-medusa-store
medusa develop
</code></pre>
<p>Now, your <strong>Medusa</strong> server is running on port <strong>9000</strong>.</p>
<p>To test it out, use your browser and go to <a target="_blank" href="http://localhost:9000/store/products"><code>localhost:9000/store/products</code></a> and you should get a <strong>JSON</strong> response like this:</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084184-5d53af0f-669e-4887-a706-868ad513713c.png" alt /></p>
<h3 id="heading-2-setting-up-the-medusa-store">2. Setting up the Medusa Store</h3>
<ul>
<li>Start by creating the <strong>Next.js Medusa Storefront</strong> and changing the directory:</li>
</ul>
<pre><code class="lang-bash">npx create-next-app -e https://github.com/medusajs/nextjs-starter-medusa my-medusa-storefront
<span class="hljs-built_in">cd</span> my-medusa-storefront
</code></pre>
<ul>
<li>Next, get your <strong>environment</strong> <strong>variables</strong> ready:</li>
</ul>
<pre><code class="lang-bash">mv .env.template .env.local
</code></pre>
<ul>
<li>Finally, start your <strong>Next.js</strong> <strong>Medusa</strong> store:</li>
</ul>
<pre><code class="lang-bash">npm run dev
</code></pre>
<p>Now, your <strong>Next.js Medusa Store</strong> is running 🎉 on port <code>8000</code></p>
<p>You can test it out by checking one of the sample products in <a target="_blank" href="http://localhost:8000/products/t-shirt"><code>/products/t-shirt</code></a> and you can see the sample <strong>Medusa T-Shirt</strong> for <strong>€19.50</strong>.</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084306-e85487cf-89d9-4200-a286-62eac55636c3.png" alt /></p>
<h3 id="heading-3-setting-up-the-medusa-admin-dashboard-and-making-some-things">3. Setting up the Medusa Admin Dashboard and making some things</h3>
<ul>
<li>Start by cloning the <a target="_blank" href="https://github.com/medusajs/admin">Admin GitHub repository</a> and changing the directory:</li>
</ul>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/medusajs/admin medusa-admin
<span class="hljs-built_in">cd</span> medusa-admin
</code></pre>
<ul>
<li>Next, install the required packages:</li>
</ul>
<pre><code class="lang-bash">npm install
</code></pre>
<ul>
<li>Finally, start the <strong>admin dashboard</strong>:</li>
</ul>
<pre><code class="lang-bash">npm run start
</code></pre>
<p>Now the <strong>Medusa Admin Dashboard</strong> is running on port <code>7000</code>, head over to <a target="_blank" href="http://localhost:7000"><code>localhost:7000</code></a> and log in with the user details:</p>
<pre><code><span class="hljs-attribute">email</span>: admin<span class="hljs-variable">@medusa-test</span>.com
<span class="hljs-attribute">password</span>: supersecret
</code></pre><p><img src="https://user-images.githubusercontent.com/68811721/181084380-b135db35-8418-4707-a789-1392fee64c32.png" alt /></p>
<p>Once you are logged in, get started by creating some products.</p>
<p>So head over to <strong>Products</strong> and create a <strong>new product</strong>:</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084550-6ceef02e-d1ae-43b7-b507-ee6209b56401.png" alt /></p>
<p>After creating your products, let’s create some <strong>collections</strong>, go to <strong>Collections</strong> and click <strong>New Collection</strong>.</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084632-5a3b7d3c-a23e-47b6-83bc-d7429e3a969d.png" alt /></p>
<p>Now, head back over to <strong>Products</strong> and assign a collection to each product like this:</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084702-eab47e75-fc13-4127-a76a-8d404fe00a38.png" alt /></p>
<p>Now, your products can be <strong>viewed</strong> and <strong>filtered</strong> by your users.</p>
<p>You can test it out by going to <a target="_blank" href="http://localhost:8000/store"><code>localhost:8000/store</code></a> and you can see the products you created and filter them.</p>
<h2 id="heading-integrating-matomo-to-get-analytics">Integrating Matomo to get Analytics</h2>
<p>Open your <strong>Matomo</strong> Dashboard, if you haven’t used <strong>Matomo</strong> before, you would be given 4 options to setup <strong>Matomo</strong>, choose <strong>Tracking Code</strong> and copy the <strong>JS code</strong> inside the <code>&lt;script&gt;</code> tag like this:</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084762-50272506-11c9-44b6-a9e6-d1aa1d1af970.png" alt /></p>
<p>Or, if you can’t find the setup instructions for <strong>Matomo</strong> on login, head over to <strong>Settings</strong> &gt; <strong>Websites</strong> &gt; <strong>Tracking Code</strong> and scroll a little down until you find the <strong>JS tracking code</strong>, copy the <strong>JS</strong> code inside the <code>&lt;script&gt;</code> tag.</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181084834-fc7758bf-783a-46f2-826d-21843f942d64.png" alt /></p>
<p>Now, let’s integrate <strong>Matomo</strong>, open your <strong>Next.js Medusa Store</strong> using your favorite <strong>IDE</strong> (Visual Studio Code, Atom, etc.) and head over to <code>src/pages</code>, and start by editing the <code>_app.tsx</code> file.</p>
<p>First of all, you will use <code>Script</code> to run the <strong>JS code</strong>, so use this line of code to import <code>Script</code>:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">import</span> Script <span class="hljs-keyword">from</span> <span class="hljs-string">"next/script"</span>;
</code></pre>
<p>And now, inside your <code>return()</code> include a <code>&lt;Script&gt;</code> tag with the <code>strategy</code> set as <code>afterInteractive</code> and optionally the <code>id</code> to <code>matomoAnalytics</code> so that you can refer to this later. Be sure to add 1 angle brackets (<code>&lt;&gt;</code>) and mention an <code>&lt;/&gt;</code> at the end of <code>return()</code>, final code should be like this:</p>
<pre><code class="lang-ts">&lt;&gt;
    &lt;Script strategy=<span class="hljs-string">"afterInteractive"</span> id=<span class="hljs-string">"matomoAnalytics"</span>&gt;
        {<span class="hljs-string">`
        // your code here
        `</span>}
    &lt;/Script&gt;
&lt;/&gt;
</code></pre>
<p>Now, let’s test it out, so just refresh the app, and you can see that if you go to the <strong>Matomo</strong> dashboard you can see the analytics start showing!</p>
<h2 id="heading-testing">Testing</h2>
<p>Now, try visiting the Medusa Store, you will find active sessions with country, etc.</p>
<p>Try visiting <a target="_blank" href="http://localhost:8000/"><code>/</code></a> and then <a target="_blank" href="http://localhost:8000/store"><code>/store</code></a> and then head over to the <strong>Matomo</strong> Dashboard, click on <strong>Visitors</strong> &gt; <strong>Visits Log</strong> and you will find some information, including <strong>OS</strong>, <strong>browser</strong>, <strong>region</strong>, <strong>IP address</strong>, <strong>pages visited</strong>, etc.</p>
<p><img src="https://user-images.githubusercontent.com/68811721/181085036-567f79b1-94f7-446f-b627-132c5d85cd20.png" alt /></p>
<p>Also, you can head over to <strong>Real-time</strong> and check visits in <strong>real-time</strong>, you can check <strong>Devices</strong> and <strong>Software</strong> to analyze user data, and you can do <strong>even more</strong> with <strong>Matomo</strong>!</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Now, you have <strong>successfully</strong> integrated <strong>Matomo</strong> Analytics with your <strong>Medusa Store</strong>. Now you can get Analytics data such as average session time and more from the <strong>Matomo</strong> Dashboard! Where <strong>Next.js</strong> with <strong>TypeScript</strong> was used to build and create the storefront and the <code>&lt;Script&gt;</code> tag was used to run the <strong>Matomo</strong> tracking <strong>JS</strong> code to get analytics.</p>
]]></content:encoded></item><item><title><![CDATA[Introducing OnePass - The encrypted safe password manager!]]></title><description><![CDATA[Worried about memorizing many passwords? And instead using the same password for all your accounts? We have got the solution, introducing OnePass, the encrypted safe password manager!
How does it work?
OnePass uses NextAuth.js to authenticate users l...]]></description><link>https://omarcodes.io/onepass</link><guid isPermaLink="true">https://omarcodes.io/onepass</guid><category><![CDATA[PlanetScale]]></category><category><![CDATA[PlanetScaleHackathon]]></category><category><![CDATA[prisma]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Tue, 26 Jul 2022 10:08:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658829520241/TqslxBerl.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Worried about memorizing many passwords? And instead using the same password for all your accounts? We have got the solution, introducing <strong>OnePass</strong>, the encrypted safe password manager!</p>
<h3 id="heading-how-does-it-work">How does it work?</h3>
<p><strong>OnePass</strong> uses <strong>NextAuth.js</strong> to authenticate users <em>like you</em>. As soon as you add a password, it will be <strong>encrypted</strong> by a <em>secret key</em>, and once you try to view the password, it's <em>decrypted</em>.</p>
<p>For making sure who owns the <strong>email/password</strong> object, we link it to a user account on <em>OnePass</em>.</p>
<p><img src="https://media4.giphy.com/media/yl9M9EtQ81pQJMBhT0/giphy.gif?cid=790b76112730b0e0a06f30c87918d4ed2d93135c543bc734&amp;rid=giphy.gif&amp;ct=g" alt /></p>
<h3 id="heading-what-is-my-tech-stack">What is my tech-stack?</h3>
<p>For this project, I used:</p>
<ul>
<li><strong>Next.js</strong> - Building the website</li>
<li><strong>TypeScript</strong> - Used with <em>Next.js</em> to give functionality to the website</li>
<li><strong>TailwindCSS</strong> - Used to give styling</li>
<li><strong>Prisma</strong> - To interact with the database (<em>PlanetScale</em>)</li>
<li><strong>tRPC</strong> - For making the <em>TypeScript <strong>API</strong></em></li>
<li><strong>NextAuth</strong> - For authenticating users</li>
</ul>
<h3 id="heading-how-planetscale-was-helpful">How PlanetScale was helpful</h3>
<p><strong>PlanetScale</strong> provided me a free <strong>database</strong> where I can store 2 important things with the help of <em>Prisma</em>, which are the <strong>user</strong> object (<em>credentials used to sign in to OnePass</em>) and the <strong>external credentials</strong> object (<em>where a username/email and password is saved for an external website like Google</em>), where it's the first time using <strong>Prisma</strong>, I learned a lot about <em>MySQL</em> 💖.</p>
<h3 id="heading-important-links">Important Links 🔗</h3>
<ul>
<li><strong>GitHub</strong> - <em><a target="_blank" href="https://github.com/Omar8345/OnePass">Omar8345/OnePass</a></em></li>
<li><strong>Live Demo</strong> - <em><a target="_blank" href="https://one-pass.vercel.app/">one-pass.vercel.app</a></em></li>
</ul>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>Special thanks to <strong>PlanetScale</strong> and <strong>Hashnode</strong> for organizing this <em>awesome</em> Hackathon!</p>
]]></content:encoded></item><item><title><![CDATA[Will NFT Ticketing be the future?]]></title><description><![CDATA[NFTs is a great way to prove ownership on the internet, even digitally. An interesting use case of NFTs is the NFT-powered ticketing system. Today, we will talk about:

What is the NFT Ticketing System?
How does the NFT Ticketing System work?
My opin...]]></description><link>https://omarcodes.io/nft-ticketing</link><guid isPermaLink="true">https://omarcodes.io/nft-ticketing</guid><category><![CDATA[NFT]]></category><category><![CDATA[crypto]]></category><category><![CDATA[Ethereum]]></category><category><![CDATA[Blockchain]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Thu, 21 Jul 2022 11:52:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1658404271039/BJKZ4DqAk.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>NFT</strong>s is a great way to prove ownership on the <strong>internet</strong>, even <em>digitally</em>. An <strong>interesting use case of NFTs</strong> is the <em>NFT-powered ticketing system</em>. Today, we will talk about:</p>
<ul>
<li>What is the <strong>NFT Ticketing System</strong>?</li>
<li>How does the <strong>NFT Ticketing System</strong> work?</li>
<li>My opinion:- Will <strong>NFT Ticketing</strong> will be the future of <em>tickets</em>?</li>
</ul>
<h2 id="heading-what-is-the-nft-ticketing-system">What is the NFT Ticketing System?</h2>
<p><strong>NFT</strong>s, short for a <em>non-fungible token</em> which <strong>non-fungible</strong> means that thing is <strong>not exchangeable</strong>, and where token here means <strong>any digital asset, a video, a GIF/picture, whatever you can expect</strong> which says that an <strong>NFT</strong>s is a digital asset/file and it's non-exchangeable.</p>
<p><strong>NFT tickets</strong> are <em>digital assets</em> that hold your access credentials to a particular event. They can also offer ticket holders some special perks such as exclusive merchandise and more. On top of helping establish a closer relationship with fans, NFT tickets can provide ongoing royalties for artists, event organizers, and stakeholders.</p>
<h2 id="heading-how-does-nft-ticketing-work">How Does NFT Ticketing work?</h2>
<p>If you think about the way <strong>NFT</strong> works, it seems to fit well with event tickets. Physical tickets are usually a one-off piece of paper and <strong>only</strong> valid for one event admission or seat. In both ways, those tickets <strong>are non-fungible, if physical, digital, or even considered as an NFT</strong>.</p>
<p>However, the downside of traditional ticketing is that tickets go through a few distribution channels with limited regulation or control. For example, resellers in the secondary ticket market can inflate prices, and ticket scalpers can buy up most tickets online to resell at a higher price. With NFT tickets, anyone can track the transactions on a <a target="_blank" href="https://academy.binance.com/en/articles/what-is-blockchain-technology-a-comprehensive-guide-for-beginners">blockchain ledger</a>, making it easier for everyone to see when and where the ticket was bought and sold – while event organizers are afforded more control over primary and secondary ticket sales. </p>
<p>An NFT ticketing system can also help limit resale value and fees with the help of a <a target="_blank" href="https://academy.binance.com/en/articles/what-are-smart-contracts">smart contract</a>, a program that runs on the blockchain. A smart contract is a deterministic program that self-executes particular tasks when and if certain conditions are satisfied. Organizers can determine how royalties are split on secondary ticket sales by setting up a rule that can trigger a royalty payment whenever the ticket is sold to a new owner. </p>
<p>Additionally, event organizers can forgo third-party distribution by minting the amount of NFT tickets they need on their preferred blockchain network as part of the ticketing system. Once they set the sale or auction price, payment from a buyer will trigger a smart contract. The NFT ticket will then be sent to the buyer's digital wallet, allowing them to access it anytime via their phone. Because the NFT ticket is stored on a blockchain network, you can also choose to resell your ticket on the NFT marketplace designated by the event organizer. Once someone buys your ticket, a smart contract is triggered, and you'll receive payment while the buyer gets the ticket.  </p>
<p>Artists can also use NFT tickets to reward long-time fans with exclusive airdrops or other perks to elevate their experience. A real-world example of NFT tickets in action was Binance's partnership with Southern Europe's largest music festival: Primavera Sound. </p>
<h3 id="heading-ok-omar-but-why-nfts">Ok Omar, but why NFTs?</h3>
<p>NFT ticketing can potentially disrupt the traditional ticketing industry by solving the inefficiencies faced by the current ticketing system. </p>
<h3 id="heading-preventing-forgery">Preventing forgery</h3>
<p>One of the major downsides of paper tickets and QR Codes is that they can be easily forged, creating a gap in security for event venues and disappointment for fans who unknowingly bought a fake ticket. 
But since NFT ticket transactions are recorded on a blockchain ledger, event organizers and attendees can validate the authenticity of every ticket on the chain and track the history of ownership. Making it near impossible for bad actors to falsify a ticket. </p>
<h3 id="heading-reduce-costs-and-faster-production">Reduce costs and faster production</h3>
<p>The costs associated with selling and minting NFT tickets can be potentially lower than the cost needed to produce and distribute traditional tickets. 
NFT tickets can often require much less production lead time than physical tickets, allowing organizers to mint and distribute tickets within a few hours. </p>
<h3 id="heading-ongoing-revenue-opportunities">Ongoing revenue opportunities</h3>
<p>The blockchain technology behind NFTs opens up the potential opportunity to generate tangible value for all involved. NFT tickets can provide ongoing royalties to the artist and event organizer via smart contract technology. If a ticket holder sells their ticket on a secondary marketplace, a percentage of the resale revenue may also be redirected to the artist. Ticket holders can also resell NFT airdrops they are gifted as a part of the ticket’s built-in rewards.  </p>
<h3 id="heading-lowers-chances-of-loss-or-damage">Lowers chances of loss or damage</h3>
<p>Traditional paper-based tickets can be easily lost or damaged. Since NFT tickets are stored in a digital wallet that can be accessed via a mobile phone, the risk of losing or damaging your ticket is exponentially lower.  </p>
<h2 id="heading-my-opinion-are-physicaldigital-ticketing-systems-going-to-stay">My Opinion: Are physical/digital ticketing systems going to stay?</h2>
<p>Most probably we cannot still stop using <strong>digital tickets</strong> while who uses <em>physical tickets now?</em> No one! So maybe in the soon future <strong>NFT-powered tickets</strong> are going to start being used by many users and then more people will start using the <strong>NFT-powered ticketing system</strong> and then we can stop using the <em>traditional digital ticketing system with traditional QR codes</em>.</p>
<h2 id="heading-outro-the-quote-of-the-day">Outro (The quote of the day)</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1658403900120/6xob9cA2o.jpg?auto=compress" alt="quote" /></p>
]]></content:encoded></item><item><title><![CDATA[My review for the Craft Conference 2022]]></title><description><![CDATA[My review for the Craft Conference 2022
I am Omar. A certified software developer and a designer.  I have taken many programming courses and I am experienced in many popular programming languages including Python, Java, and JavaScript.
Craft Conferen...]]></description><link>https://omarcodes.io/my-review-for-the-craft-conference-2022</link><guid isPermaLink="true">https://omarcodes.io/my-review-for-the-craft-conference-2022</guid><category><![CDATA[conference]]></category><category><![CDATA[Developer]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Mon, 27 Jun 2022 10:59:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1656327541870/diTXLpgbQ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-my-review-for-the-craft-conference-2022">My review for the Craft Conference 2022</h2>
<p>I am Omar. A certified software developer and a designer.  I have taken many programming courses and I am experienced in many popular programming languages including <strong>Python, Java, and JavaScript</strong>.</p>
<p>Craft Conference 2022 was one of the conferences I enjoyed where I learned many things, one of my favourite talks was from Debbie O'Brien, who works [at] Microsoft as a Senior Program Manager where she talked about Testing Web Applications with Playwright and how to make automatic easy tests in no time without making it hard on you, taking a long time even to learn how and build, and so much on, so that's Playwright.</p>
<h2 id="heading-testing-web-applications-with-playwright-debbie-obrien-microsoft">Testing Web Applications with Playwright - Debbie O'Brien, Microsoft</h2>
<p>Debbie O'Brien from Microsoft spoke about Java, Dot Net and Python. Testing is hard, testing takes time to learn and to write, and time is money. As developers, we want to test. We know we should but we don't have time. So how can we get more developers to do testing? We can create better tools. Let me introduce you to Playwright - Reliable end-to-end cross-browser testing for modern web apps, by Microsoft and fully open source. Playwright's Codegen generates tests for you in JavaScript, TypeScript, Dot Net, Java or Python. Now you have no excuses. It's time to use Playwright.</p>
<p>I didn't know anything about Playwright. I learned that it's okay not to test your application because it's hard, takes time to build and learn, and takes a long time. So that's why Playwright is the solution to test the web applications. It's easy with Playwright to test web applications, it is an end-to-end testing tool and it runs on almost all browsers, Chromium, and more.</p>
<p>I learned Playwright it's better because it works with any browser, any platform, one API, fast execution and more.</p>
<p>How I can get started with Playwright is simple is just as follows:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Run from your project's root directory</span>
npm init playwright@latest
<span class="hljs-comment"># Or create a new project</span>
npm init playwright@latest new-project
</code></pre>
<p>Also, the thing that I liked is that there is a <strong>VS Code</strong> extension for Playwright which has a UI so it would be easy to use 😎. </p>
<p>I will be also writing a summary of how to make your first test. After the installation in your browser, just by clicking <code>F1</code>, you will get a <code>package.json</code>, <code>playwright.config.ts</code>, and <code>Tests</code> folder with an example test file. If you don't have an existing project, you can use the To-Do template!</p>
<p>What's also great is Codegen which generates tests by recording your actions. You can run it using <code>npx playwright codegen</code> which then will open 2 windows with a browser window and the tests, also the tests support multiple languages, including Java, JavaScript, Python, and C#.</p>
<p>What about running tests? You can run all tests, a set of tests, or a single test. Or you can even make tests run in parallel and it's super fast 🚀! </p>
<p>You can run tests in <strong>Headless</strong> or <strong>Headed</strong>:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># headless</span>
npx playwright <span class="hljs-built_in">test</span>
<span class="hljs-comment"># headed</span>
npx playwright <span class="hljs-built_in">test</span> --headed
</code></pre>
<p>What about breaking tests? It's recommended to break tests to check if they are working. As an example, I was using a <strong>locator</strong> in a t-shirt online store, there is (Women, Men, and Children) if you try to locate <code>Men</code>, Playwright isn't sure what you want to exactly approach, because also the word <code>Men</code> is in <code>Women</code> because it's so strict, so we need to mention <strong>exactly <code>Men</code>, no any letter missing and no any letter is extra</strong>!</p>
<p>Locators are a way to find element(s) on the page at any moment with built-in auto-waiting and retry-ability, they are like the pins on a map. Here is how to make/use a locator:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656055107266/FJV95_mQL.png" alt="image.png" /></p>
<p>Running debug mode:</p>
<pre><code class="lang-bash">npx playwright <span class="hljs-built_in">test</span> --debug
</code></pre>
<p>If you would like to have better errors details, this is for the terminal, if you are using the extension in <strong>VS Code, it's as follows</strong>:</p>
<p>Just make a breakpoint where you want to stop your code and click on the green check mark and click <strong>Debug Test</strong>.</p>
<p>We can show reports using the command:</p>
<pre><code class="lang-bash">npx playwright show-report
</code></pre>
<p>This is an report example in <strong>Chromium</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656055687150/7YOyhCrIh.png" alt="image.png" /></p>
<p>Let's talk about tracing files, if you want to record a trace for each test, normally it's on if it's a broken test, but you can manually turn it on by mentioning the following:</p>
<pre><code class="lang-js">trace: <span class="hljs-string">'on'</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656055817258/kL2saIRQX.png" alt="image.png" /></p>
<p>What it does is if you go to your report, at the bottom you will get an image, a trace <code>.zip</code> file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656055889978/w6pLzAFtG.png" alt="image.png" /></p>
<p>Or you can just click and it'll open it up.</p>
<h2 id="heading-my-reviews-summary">My review's summary</h2>
<p>To pack up, <strong>Playwright</strong> is an amazing way to test your applications in no time seamlessly as it supports many programming languages including <strong>Java, JavaScript, Python, and C#</strong>. Also, there is a <strong>Visual Studio Code extension for Playwright!</strong> You can make a breakpoint and run your test in <strong>debug mode</strong>.</p>
<p>I also tried to use it with <strong><a target="_blank" href="https://omardevblog.toolsandapps4us.site/codeguard">CodeGuard</a></strong> which is my submission for the <strong>Hashnode X Linode Hackathon</strong> and I found some bugs, errors, etc. which I fixed in <strong>release version 1.1</strong> which has been just released yesterday, and announced today on the submission article. Since then, my project <strong>CodeGuard</strong> for the Hashnode X Linode Hackathon got better because I used <strong>Playwright</strong> to test my application/project <strong>CodeGuard</strong> and find errors which sometimes are "<strong>behind the scenes</strong>" which is called the back-end!</p>
<p>I also benefited a lot from breaking my tests by making breakpoints and running in debug mode. And I had been using <strong>Playwright</strong> since then in all my projects, even if it's a personal one, but why not if it's all automated 🚀😎. You can use <strong>Playwright</strong> with any browser which is great and even get a trace in a <code>.zip</code> file!</p>
<p>I learned a lot and it was really useful I hope to continue using <strong>Playwright</strong>!</p>
<h2 id="heading-special-thanks">Special thanks 🚀</h2>
<p>Special thanks to Craft Conf for providing me with this complimentary ticket to attend the conference, I learned a lot!</p>
<p>Also thanks to you <a class="user-mention" href="https://hashnode.com/@mszeles">Miki Szeles</a> for providing me with this awesome opportunity!</p>
]]></content:encoded></item><item><title><![CDATA[Introducing CodeGuard: The open-source tool to obfuscate your JavaScript or Python code]]></title><description><![CDATA[Please note we NO LONGER support codeguard.tech domain - the current owner is unknown, we are not responsible for any damages.

Probably most of us know that copying and pasting from GitHub, Stack Overflow, etc. doesn't make you a programmer.
Also, i...]]></description><link>https://omarcodes.io/codeguard</link><guid isPermaLink="true">https://omarcodes.io/codeguard</guid><category><![CDATA[Linode]]></category><category><![CDATA[Linode Hackathon]]></category><category><![CDATA[Python]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Tue, 21 Jun 2022 18:35:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1655797654681/UqOK9nL3e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p><strong>Please note we NO LONGER support</strong> <code>codeguard.tech</code> <strong>domain - the current owner is unknown, we are not responsible for any damages.</strong></p>
</blockquote>
<p><strong>P</strong>robably most of us know that <strong>copying and pasting from GitHub, Stack Overflow, etc.</strong> <em>doesn't</em> make you a <strong>programmer</strong>.</p>
<p>Also, <strong>it's not great for</strong> <em>someone to steal your code</em> and <strong>use it pretending that he made that code/script</strong>, right?</p>
<p><strong>Here CodeGuard comes!</strong> <em>The open-source tool to obfuscate your JavaScript or Python code in no time!</em></p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/abcnetwork-marvel-agents-of-shield-agentsofshield-UQJmx6TG578HeyuT0V">https://giphy.com/gifs/abcnetwork-marvel-agents-of-shield-agentsofshield-UQJmx6TG578HeyuT0V</a></div>
<p> </p>
<h2 id="heading-how-i-got-this-inspiration">How I got this inspiration?</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://giphy.com/gifs/sesamestreet-Zd5ZVGn3ZvYKl7U6MW">https://giphy.com/gifs/sesamestreet-Zd5ZVGn3ZvYKl7U6MW</a></div>
<p> </p>
<p><strong>Once upon a time</strong>, I was creating an <strong>project which does really great thing including making meetings, etc.</strong> and this idea came in my mind:</p>
<p><strong><em>Why would I allow someone steal my code pretending that he wrote that script/code?</em></strong></p>
<p>So, I though why don't I make a code obfuscator to make my code hard to read and nearly impossible to understand? So, that's the beginning of <a target="_blank" href="https://codeguard.tech"><strong>CodeGuard</strong></a>.</p>
<h2 id="heading-how-did-i-make-it-project-workflow">How did I make it? (Project workflow)</h2>
<p><strong>Once a user provides a link to the file, we recommend using</strong> <a target="_blank" href="https://gist.github.com"><strong><em>GitHub Gist</em></strong></a> <strong>because the project was made to be used with Gist, but it will work also if you give a direct link to the file like</strong> <code>https://example.com/myproject/main.py</code></p>
<p><strong>The user will be selecting either Python or JavaScript:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655798332965/e4aP95m-u.png" alt="image.png" /></p>
<p>Upon the user selection, it will call the API (<strong>no longer available</strong>) providing 2 parameters, the code link in <code>link</code> and the programming language in <code>lang</code>, of course you would like to try to use the <strong>API</strong> yourself, we will leave a guide below!</p>
<p>As soon as the <strong>API has been called</strong>, it will start getting the file and obfuscating it, as soon as the <strong>obfuscated file is ready, it will be automatically downloaded at the user side</strong>.</p>
<p>Note: <strong>For Python code, change the obfuscated code extension to</strong> <code>.pyo</code> and use <code>python -O &lt;file-name&gt;.pyo</code> to run the file!</p>
<h2 id="heading-what-problems-did-i-experience">What problems did I experience</h2>
<ul>
<li><strong>Making the back-end</strong></li>
</ul>
<p>As <strong>I need to use JS/PY</strong> to obfuscate, although they run at the client side, I am unable to run the script to obfuscate from client-side</p>
<ul>
<li><strong>How will I host and make the API</strong></li>
</ul>
<p>With the help of Flask, I can make a API with pretty good functionalities which can help me in the project, and with the existence of Linode, I can host my API on a Linux server in the cloud!</p>
<h2 id="heading-use-of-linode">Use of Linode</h2>
<p>Use of Linode... Linode provided us with one of the best tools to setup terminals / servers to host and deploy the core feature, our <strong>API</strong>. Apart from that in the development phase we used Linode to host the project and collaborate on it, until it was in build phase and we could use Vercel to deploy it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656056240791/A4Ii0xhqT.png" alt="image.png" /></p>
<blockquote>
<p>The amount of storage and network bandwidth given is more than enough for an open-source and fully scalable project team to get started with!</p>
</blockquote>
<h2 id="heading-the-tech-stack-i-used-why-did-i-use-it">The tech-stack I used + Why did I use it?</h2>
<ul>
<li><p><a target="_blank" href="https://nextjs.org/"><strong>Next.js</strong></a> - <em>The entirety of the webpage!</em></p>
</li>
<li><p><strong>HTML/CSS</strong> - <em>Touches of HTML and CSS were used to add extra detailed styling and div functionality (Forms)</em></p>
</li>
<li><p><a target="_blank" href="https://javascript.com"><strong>JavaScript</strong></a> - <em>Was used to allow transitions and smooth navigation along the webpage and validation of user input on client side itself</em></p>
</li>
<li><p><a target="_blank" href="https://linux.org"><strong>Linux</strong></a> <a target="_blank" href="https://ubuntu.com"><strong>Ubuntu</strong></a> <strong>(</strong><a target="_blank" href="https://linode.com"><strong>Linode</strong></a><strong>)</strong> - <em>Host the API</em></p>
</li>
<li><p><a target="_blank" href="https://vercel.com"><strong>Vercel</strong></a> - <em>Host the website!</em></p>
</li>
<li><p><a target="_blank" href="https://python.org"><strong>Python</strong></a> <strong>(</strong><a target="_blank" href="https://flask.palletsprojects.com/"><strong>Flask</strong></a><strong>)</strong> - <em>Used to make the API</em></p>
</li>
</ul>
<h2 id="heading-api">API</h2>
<h3 id="heading-use-the-api-hosted-by-us">Use the API (hosted by us)</h3>
<p>It's really simple to use our API, in JavaScript, it only requires one line of code!</p>
<pre><code class="lang-js"><span class="hljs-built_in">window</span>.location = <span class="hljs-string">"https://NO_LONGER_AVAILABLE/?link=&lt;code link here&gt;&amp;lang=&lt;js or py&gt;"</span>
</code></pre>
<p>For example:</p>
<pre><code class="lang-js"><span class="hljs-built_in">window</span>.location = <span class="hljs-string">"https://NO_LONGER_AVAILABLE/?link=https://gist.githubusercontent.com/Omar8345/1038a82e7db5f81d0722a4f2ab701924/raw/b213490f419b1d67de6a6a1647557934b97fc1ef/nicecode.js&amp;lang=js"</span>
</code></pre>
<h3 id="heading-hosting-the-api-on-your-machine">Hosting the API on your machine</h3>
<ul>
<li>Clone the repository on your local machine:</li>
</ul>
<p><code>git clone https://github.com/Omar8345/CodeGuard</code></p>
<ul>
<li>Next, head into <code>CodeGuard/API</code> and open your favorite IDE, if you use <strong>Visual Studio Code</strong>, just enter:</li>
</ul>
<p><code>code .</code></p>
<ul>
<li>And it will open up <strong>VSC</strong> in the folder, just run in the terminal the following command:</li>
</ul>
<p><code>$env:FLASK_APP="__init__.py" &amp;&amp; flask run</code></p>
<p>You should see a local link, head into it or <a target="_blank" href="http://127.0.0.1:5000/">http://127.0.0.1:5000/</a> and you should find some kind of error, just simply ignore it, now add the <code>link</code> and <code>lang</code> parameters value and you should be good to go!</p>
<p><strong>Made using</strong> <a target="_blank" href="https://vercel.com"><strong>Vercel</strong></a> <strong>and</strong> <a target="_blank" href="https://linode.com"><strong>Linode</strong></a> <strong>for the</strong> <a target="_blank" href="https://hashnode.com"><strong>Hashnode</strong></a> <strong>X</strong> <a target="_blank" href="https://linode.com"><strong>Linode</strong></a> <strong><em>Hackathon</em>!</strong></p>
<h2 id="heading-live-demo">Live Demo!</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.loom.com/share/b9f9be56ec6040f3a653354c78d58caa">https://www.loom.com/share/b9f9be56ec6040f3a653354c78d58caa</a></div>
<p> </p>
<h2 id="heading-my-quote">My quote</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655800348645/6a-GYYsTT.png" alt="image.png" /></p>
<blockquote>
<p><strong>Take your time - But don't mess up!</strong></p>
</blockquote>
<p><strong>Take your time</strong> in studying, even <strong>study like 72 hours</strong>, but <strong><em>take the full mark!</em></strong></p>
<h2 id="heading-important-links-try-codeguard">Important Links 🔗 - Try CodeGuard!</h2>
<ul>
<li><p><a target="_blank" href="https://github.com/Omar8345/CodeGuard"><strong>GitHub Repo</strong></a></p>
</li>
<li><p><a target="_blank" href="https://nextjs.org"><strong>Next.js</strong></a></p>
</li>
<li><p><a target="_blank" href="https://codeguard.tech"><strong>CodeGuard</strong></a></p>
</li>
</ul>
<h3 id="heading-special-thanks-to-vedant-singhal">Special thanks to Vedant Singhal</h3>
<p><strong>Vedant</strong> a developer in high school from <strong>India</strong>! <strong>Vedant</strong> helped me a lot in this project, so I would like to thank him here!</p>
<p><strong>Thank you Vedant!</strong></p>
<p>Check out Vedant on Social Media:</p>
<ul>
<li><p><a target="_blank" href="https://github.com/Ved235"><strong>GitHub - Ved235</strong></a></p>
</li>
<li><p><a target="_blank" href="https://www.buymeacoffee.com/ved235"><strong>Buymeacoffee - Ved235</strong></a></p>
</li>
<li><p><a target="_blank" href="https://learnwithved.hashnode.dev/"><strong>Vedant's Blog</strong></a></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1656056348747/nxBXhpeP6.png" alt="image.png" /></p>
<h3 id="heading-we-would-like-to-hear-your-feedback-and-suggestions-in-the-comments-below">We would like to hear your feedback and suggestions in the comments below!</h3>
<hr />
<p><strong>Edit on 24/06/2022</strong>:</p>
<p><strong>It's version 1.1 release!</strong></p>
<p>Added some improvements and fixed some bugs in the website and API</p>
<p>Website:</p>
<ul>
<li><p><strong>Error on wrong language selection</strong></p>
</li>
<li><p><strong>Errors with better details</strong></p>
</li>
</ul>
<p>API:</p>
<ul>
<li><p><strong>No need now to mention</strong> <code>lang</code> while using the API</p>
</li>
<li><p><strong>Landing page instead of error</strong></p>
</li>
<li><p><code>redirect</code> has been made if you don't want to redirect to the API host domain if you are using this with your website especially using <code>window.location</code></p>
</li>
</ul>
<p>Extra: <strong>In</strong> <code>__init__.py</code> in <code>API</code>, if it's <code>JS</code> code, it runs the things which obfuscates Python code, the code has been updated with the correct code, sorry for that! (the code in the repo)</p>
<p><strong>Did you find any bugs?</strong></p>
<p>Tell us in the comments!</p>
<hr />
<p><strong>Edit on 30/06/2022 (few hours before the deadline time):</strong></p>
<p>Hey everyone!!!</p>
<p>I just released (announced) the CodeGuard V1.2 release!!!</p>
<p>What's new? 🎉</p>
<p>FIRST OF ALL - You can now provide a GitHub Repo, all the JavaScript and Python code in the Repo will be obfuscated and renamed with the old (non-obfuscated) file name and any other files won't be effected, it's awesome!</p>
<p>What you will even love more 💌 - Here is dark mode! You can switch to dark mode by clicking the button in the footer! (now, it's in the bottom right)</p>
<p>Check out the GitHub Repo: <a target="_blank" href="https://github.com/Omar8345/CodeGuard">Omar8345/CodeGuard</a></p>
<p>Stay tuned with the future updates</p>
<p>Also, we launched a Ko-fi page to support us! Check it out!</p>
<p>Let's support CodeGuard! <a target="_blank" href="https://ko-fi.com/CodeGuard">ko-fi.com/CodeGuard</a></p>
]]></content:encoded></item><item><title><![CDATA[Cloud platforms - Why choose AWS?]]></title><description><![CDATA[Hey there, wherever whom you are and where you are, welcome to this article.
As you had stepped into here, you should be interested about what cloud platform to choose and why especially choose AWS! Doesn't matter you are a business owner, developer,...]]></description><link>https://omarcodes.io/aws</link><guid isPermaLink="true">https://omarcodes.io/aws</guid><category><![CDATA[THW Cloud Computing]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Azure]]></category><category><![CDATA[google cloud]]></category><category><![CDATA[DigitalOcean]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Wed, 18 May 2022 06:10:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652854194673/ONexDK6mS.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey there, wherever whom you are and where you are, welcome to this article.</p>
<p>As you had stepped into here, you should be interested about what cloud platform to choose and why especially choose <strong>AWS</strong>! Doesn't matter you are a business owner, developer, or just a student, this article is guaranteed to help 😀.</p>
<p>So, without wasting my time and yours's too, let's start!</p>
<h2 id="heading-cloud-platform">Cloud platform</h2>
<h3 id="heading-what-is-a-cloud-platform">What is a cloud platform</h3>
<p>A cloud platform refers to "<strong><em>the operating system and hardware of a server in an Internet-based data center</em></strong>". They are like a large place which contains many computers used by personal and enterprise users.</p>
<h3 id="heading-types-of-a-cloud-platform">Types of a cloud platform</h3>
<p>There are several types of cloud platforms which fits for different purposes. Which includes:</p>
<ul>
<li><p><strong>Public Cloud:</strong> Public cloud platforms are third-party service providers that provide computing resources and more over the internet. Examples are like Google Cloud, Amazon Web Services (AWS), Microsoft Azure, and DigitalOcean.</p>
</li>
<li><p><strong>Private Cloud:</strong> A private cloud platform is made exclusively for a single organization, or maybe a single person, which no one other uses it except you or your organization. It's usually hosted (on-site | at your org) or sometimes hosted by a third-party service provider.</p>
</li>
<li><p><strong>Hybrid Cloud:</strong> Hybrid Cloud is a combination between a <strong>Private</strong> and <strong>Public</strong> cloud platforms. Both data and applications seamlessly pass between the two (private and public), which gives the organization more flexibility.</p>
</li>
</ul>
<h3 id="heading-uses-of-cloud-platforms">Uses of cloud platforms</h3>
<p>Here, we'll just pass an example, and you can seamlessly understand the rest. We are talking about that I have a company/shop website which I would like to host it on the internet. Let's say I own resources which are enough to host the website and make it fast and such on, and I don't want to use them, or you can also say that you don't have enough resources to host the website and need to buy the needed resources with someone who should maintain them and keep them up-to-date.</p>
<p>Here comes the work of a cloud platform, there are many cloud platforms, such as AWS, Azure, Google Cloud, and last but not least DigitalOcean, I recommend AWS, we'll know why later on. AWS has a data center, with many computers (large computers which can do things that a normal computer couldn't do), you can rent a resources from AWS or the cloud platform you prefer by using 2 common plans:</p>
<ul>
<li><ol>
<li>Pay-as-you-go is a common plan which you can pay as you use the resources, will never stop unless reaches the limit of money you set or when you manually set it.</li>
</ol>
</li>
<li><ol>
<li>And another way to pay is to buy limited use of the resources, which means you will buy a resources and use it like for example host a website, and your bandwidth will be let's say 10 GB, when your bandwidth reaches 0, the resources will stop.</li>
</ol>
</li>
</ul>
<p>Now we are done of cloud platforms story, let's get on why choose AWS.</p>
<h2 id="heading-why-choose-aws">Why choose AWS?</h2>
<p><strong>AWS</strong> is a cloud platform, and it is the best cloud platform in the market with the most highest growth.</p>
<p>AWS certifications are also well-trusted by big tech companies.</p>
<p>We will talk about the most best 7 reasons to choose AWS:</p>
<h3 id="heading-1-location">1. Location</h3>
<p>One of the biggest AWS advantages is that it is available in 44 different zones in 16 geographical locations. You can access the servers from any country you want to. By hiring an AWS developer, you can access all the features from wherever you are.</p>
<h3 id="heading-2-recovery-system">2. Recovery System</h3>
<p>Another of the most valuable AWS benefits is its disaster recovery system. Custom software development companies offer a solution to recover lost data so that your day-to-day-to-day operations aren't affected.</p>
<h3 id="heading-3-better-security">3. Better Security</h3>
<p>AWS, as a cloud service, offers enchanted security to protect your virtual org. The data centers and servers have multiple layers of operational security. The Amazon detective makes security monitoring faster and more reliable.</p>
<h3 id="heading-4-multi-region-backups">4. Multi-region Backups</h3>
<blockquote>
<p>Since the AWS cloud management system is decentralized, you can backup your important data in multiple regions. The platform offers AMIs and EBS snapshots mode of backing up. So even when your primary operational environment goes offline, your backup will not have any impact. You can also schedule backups across different regions.</p>
</blockquote>
<h3 id="heading-5-scalability-factor">5. Scalability Factor</h3>
<blockquote>
<p>Auto Scaling and Elastic Load Balancing are two AWS tools that make scaling easier while delivering high performance. You can scale up or down based on your requirements. Amazon Web Services has a massive infrastructure that can provide computing resources as and when you need them.</p>
</blockquote>
<h3 id="heading-6-pricing-model">6. Pricing Model</h3>
<p>One of the top AWS advantages is its pricing model. AWS platform works on the pay-as-you-go pricing model. You don’t have to pay heavy subscription fees for resources that you won’t even use. The flexible pricing structure drastically improves the organizational bottom line, keeping cloud computing affordable for you.</p>
<h3 id="heading-7-flexibility">7. Flexibility</h3>
<p>Finally, one of the most important AWS benefits is its flexibility. It enables you to select your operating system, programming language, web application platform, database, and other services that you may need. AWS offers a virtual environment to load all the services that your application may require. It also simplifies the data migration process.</p>
<h2 id="heading-amazon-cloud-business-is-the-future">Amazon Cloud Business is the Future</h2>
<p>All the big tech giants and software development companies use AWS services for their cloud computing needs. You can hire a professional for AWS cloud consulting to identify your computing requirements and how you can integrate your enterprise’s infrastructure with the cloud platform. </p>
<h2 id="heading-thanks-for-reading">Thanks for reading!</h2>
<p>Hope you enjoyed the article and I hope it didn't waste your time by either learning something new or choosing what cloud platform to choose.</p>
<p>Have a great day 😁</p>
]]></content:encoded></item><item><title><![CDATA[Introducing Supabase: The new open-source Firebase alternative]]></title><description><![CDATA[Supabase? The open-source Firebase alternative?!
This is an Extra Ordinary Claim because it requires Extra Ordinary Evidence
"Supabase VS Firebase"
Supabase VS Firebase
1. Features




SupabaseFirebase



DatabaseDatabase

AuthenticationAuthenticatio...]]></description><link>https://omarcodes.io/supabase</link><guid isPermaLink="true">https://omarcodes.io/supabase</guid><category><![CDATA[Databases]]></category><category><![CDATA[Firebase]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[THW Web Apps]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 15 May 2022 03:19:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1652584681684/beWraLWPk.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Supabase?</strong> The open-source <strong>Firebase</strong> alternative?!</p>
<p>This is an <strong>Extra Ordinary Claim because it requires Extra Ordinary Evidence</strong></p>
<p>"Supabase VS Firebase"</p>
<h2 id="heading-supabase-vs-firebase">Supabase VS Firebase</h2>
<h3 id="heading-1-features">1. Features</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Supabase</td><td>Firebase</td></tr>
</thead>
<tbody>
<tr>
<td>Database</td><td>Database</td></tr>
<tr>
<td>Authentication</td><td>Authentication</td></tr>
<tr>
<td>Storage</td><td>Storage</td></tr>
<tr>
<td>Functions</td><td>Functions</td></tr>
<tr>
<td></td><td>Hosting</td></tr>
<tr>
<td></td><td>Analytics</td></tr>
<tr>
<td></td><td>Crashlytics</td></tr>
<tr>
<td></td><td>ML</td></tr>
<tr>
<td></td><td>Push notifications</td></tr>
<tr>
<td></td><td>Remote config</td></tr>
</tbody>
</table>
</div><p>This isn't completely a fair comparison because <strong>Supabase</strong> is still new, but <strong>Firebase</strong> has been here for a long time!</p>
<p>There is one <strong>great</strong> fact which is about <strong>Supabase</strong>. What's it?</p>
<p><strong>Supabase</strong> uses open-source technologies for it's platform, what does it mean?</p>
<p>It means that you can <strong>run Supabase with Docker, and you can <em>host your own Firebase alternative on AWS (recommended) or any other cloud platform.</em></strong></p>
<h3 id="heading-2-policies">2. Policies</h3>
<p>When you use <strong>Firebase</strong>, you are locked in with <strong>Google</strong>, as you are signing a contract with the <strong>Alphabet</strong> cooperation by giving them the power to destroy your business at any moment if they decide that's what should happen. Proof as in the following picture:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652526710954/NwYSWMEFl.png" alt="image.png" /></p>
<p>Source: <a target="_blank" href="https://firebase.google.com/terms/billing"><strong>Firebase Paid Services Terms of Service</strong></a></p>
<p>Let's look now to <strong>S</strong>upabase features to see how they stack-up in front of <strong>F</strong>irebase...</p>
<h3 id="heading-user-authentication">User Authentication</h3>
<p>Before we start, <strong>S</strong>upabase isn't a 1-to-1 mapping of <strong>F</strong>irebase. It just provides the tools which approximately do the same thing. I have made a demo using <strong>S</strong>upabase and I would like to tell you that the developer experience is similar to <strong>F</strong>irebase. The only thing <strong>S</strong>upabase is missing is phone authentication. Now, in the actual code, you can get a user logged in with one or two lines of code like <strong>F</strong>irebase, I do like that <strong>S</strong>upabase returns an error as an object, because in <strong>F</strong>irebase you should wrap it in a try catch block to catch errors.</p>
<h3 id="heading-security">Security</h3>
<p>One thing cool that <strong>S</strong>upabase does but <strong>F</strong>irebase doesn't is that automatically create a database record for the user.</p>
<h3 id="heading-database">Database</h3>
<p>We haven't talked about database yet. In <strong>F</strong>irebase we have 2 different database options but we'll be focusing on <strong>F</strong>irestore which is very similar to <strong>MongoDB</strong> and it is a <strong>NoSQL</strong> document database. It is very easy to work with scales automatically and it automatically handles relational data fairly well. However, it's not ideal for graphs and full-text search.</p>
<p><strong>S</strong>upabase uses <strong>PostgreSQL</strong> as it's database, a relational SQL database that has been around forever. But SQL databases are expensive, hard to use, and difficult to scale. <strong>S</strong>upabase offers you handling the scaling for you automatically and also by providing a dashboard and SDK to make working with the database much easier.</p>
<h3 id="heading-realtime">Realtime</h3>
<p>If you are building a realtime app, you can do so with one line of code with very little configuration with <strong>F</strong>irebase. The client-side SDKs are very sophisticated and do thing like optimistic updates where it updates the UI before the actual changes is committed to the back-end. It also supports offline mode.</p>
<p>In <strong>S</strong>upabase you can subscribe to real time updates that's pretty much it. Another issue that security policies will not work with real time data.</p>
<h2 id="heading-pricing">Pricing</h2>
<p>Both products has a free tier:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Supabase</strong></td><td><strong>Firebase</strong></td></tr>
</thead>
<tbody>
<tr>
<td>10K users</td><td>Unlimited users</td></tr>
<tr>
<td>500 MB data</td><td>1 GB data</td></tr>
<tr>
<td>FREE</td><td>FREE</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Supabase</strong></td><td><strong>Firebase</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>$25</strong> per month for 7</td><td><strong>$0.18</strong> per GB</td></tr>
<tr>
<td><strong><em>Unlimited API calls?!</em></strong></td><td><strong>$0.06</strong> per 100K reads</td></tr>
<tr>
<td></td><td><strong>$0.18</strong> per 100K writes</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Supabase</strong></td><td><strong>Firebase</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>$25</strong> per month</td><td><strong>$0.18</strong> per GB</td></tr>
<tr>
<td><strong>$0.125</strong> per GB (<em>over 8 GB</em>)</td></tr>
</tbody>
</table>
</div><h3 id="heading-the-end">The end 🎉</h3>
<p>Hope the comparison was useful for you! Good bye!</p>
]]></content:encoded></item><item><title><![CDATA[Introducing Linky - Best link shortener for developers]]></title><description><![CDATA[Want to make your own unique short-link generator?
We will be making that today!!! Stay with us!
We will be making the project from A to Z, the whole work will be covered!!!
The project is a simple website which you enter the long link then it conver...]]></description><link>https://omarcodes.io/linky</link><guid isPermaLink="true">https://omarcodes.io/linky</guid><category><![CDATA[THW Web Apps]]></category><category><![CDATA[Python]]></category><category><![CDATA[Flask Framework]]></category><category><![CDATA[Heroku]]></category><category><![CDATA[HTML5]]></category><dc:creator><![CDATA[Omar Moustafa]]></dc:creator><pubDate>Sun, 08 May 2022 12:42:47 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/sxiSod0tyYQ/upload/v1652013719475/JV_DG-0zK.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-want-to-make-your-own-unique-short-link-generator">Want to make your own unique short-link generator?</h1>
<p>We will be making that today!!! Stay with us!</p>
<p>We will be making the project from A to Z, the whole work will be covered!!!</p>
<p>The project is a simple website which you enter the long link then it converts it to a fancy short link!</p>
<p>Without further time wasted, let's start <strong>coding</strong>...</p>
<h2 id="heading-coding">Coding</h2>
<ul>
<li><em>Tech-stack which will be used:</em><ul>
<li><strong>Flask</strong></li>
<li><strong>Python</strong></li>
<li><strong>Heroku</strong></li>
</ul>
</li>
</ul>
<p>Before we start, be sure to install <code>Flask</code>, use the command </p>
<p><code>pip3 install Flask Flask-SQLAlchemy</code></p>
<p>Be sure the <code>A</code> should be capital.</p>
<p>Start by making your project folder, we will start by coding <code>app.py</code> which is the main code for our app. Create in addition to a directory called <code>templates</code> which will be having HTML to view our Flask App.</p>
<p>Let's start creating the basic Flask App.</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask

app = Flask(__name__)

<span class="hljs-meta">@app.route('/')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello_world</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"HELLO WORLD"</span>

<span class="hljs-meta">@app.route('/omar')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello_omar</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"HI OMAR"</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(port=<span class="hljs-number">5000</span>, debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>In the beginning, we are ending up importing Flask and initialize our Flask App. After initializing, we have a decorator function, if you don't know what is a decorator it is basically a super function which wraps around the functions inside it. For example <code>@app.route('/')</code> is a decorator,  which tells us whenever we go to whatever website/URL is it it like <code>https://example.com/</code> will return <strong>HELLO WORLD</strong>, but for example if we go to <code>https://example.com/omar</code> which decorator <code>@app.route('/omar')</code> is responsible for, it will be returning <strong>HI OMAR</strong>.</p>
<p>By default, Flask runs on port <code>5000</code> but we will just be specifying it anyways. It's better to set <code>debug</code> to on which will gives us extra information which will really help us when we experience issues.</p>
<p>Let's test the script by running it. The highlighted link is where the Flask app is running, go to it to test it, note it only works on your local pc.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651998275987/MB8TyD1Nc.png" alt="image.png" /></p>
<p>As we are on the main page, it should return <strong>HELLO WORLD</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651998322920/mPePwe7As.png" alt="image.png" /></p>
<p>Let's try going to <code>/omar</code>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651998356829/6HeM_qkdS.png" alt="image.png" /></p>
<p>Make a new file in <code>templates</code> called <code>base.html</code> and copy the following template:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>{% block title %}{% endblock %}<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Linky<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>&gt;</span>
        {% block content%}
        {% endblock %}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://code.jquery.com/jquery-3.5.1.slim.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>I added <code>bootstrap</code> which is basically it is a CSS library which has tons of pre-defined rules and a code written for us which we can instantly use. This is a basic HTML code except the <code>&lt;title&gt;</code> block,  the <code>&lt;title&gt;</code> block won't be same for each page we go to, so instead of writing the <code>&lt;title&gt;</code> block every time inside of our new HTML page, we will just give a block title, which allows us being directly accessing the block and changing only the elements which goes in this block instead of writing everything.</p>
<p>As we are in a <code>body</code>, we put everything in <code>div</code> to make everything look more better. As we see the 2 lines in the body which as follows:</p>
<pre><code class="lang-html">        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Linky<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">hr</span>&gt;</span>
</code></pre>
<p>will be same in all our web pages, so all of our web pages will have these 2 lines... The only difference will be what goes over here:</p>
<pre><code class="lang-html">        {% block content%}
        {% endblock %}
</code></pre>
<p>instead of writing all bootstrap stuff again, we can directly write whatever goes in here. So how to extend the information we have from <code>base.html</code>, make a file <code>home.html</code> and copy the following template:</p>
<pre><code class="lang-html">{% extends "base.html" %}
{% block title %}Shorten URL{% endblock %}

{% block content %}
<span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span>, <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"url"</span>&gt;</span>Enter an https:// URL:<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"url"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"nm"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"url"</span>
       <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"https://example.com"</span>
       <span class="hljs-attr">pattern</span>=<span class="hljs-string">"https://.*"</span> <span class="hljs-attr">size</span>=<span class="hljs-string">"50"</span>
       <span class="hljs-attr">required</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
{% endblock %}
</code></pre>
<p>This is the HTML page which will be displayed at our home page. Let's take a look:</p>
<p>First, we are going to extend <code>base.html</code> which actually means like the <code>base.html</code> is already in <code>home.html</code>. And here we have <code>{% block title %}</code> in <code>home.html</code> which refers to the block in <code>base.html</code> since it was called the name block title. As you can see, we are giving it a title of <strong>Shorten URL</strong>. So instead of writing all of this again, we just changed what is the title in <code>base.html</code> which whatever the title in <code>base.html</code> is, it will appear in ALL pages. As we have block content in <code>base.html</code>, everything in block content in <code>home.html</code> is as it is in <code>base.html</code>, imagine it as a variable.</p>
<p>Second, in <code>home.html</code> we have a form, which has 2 inputs, first we have a label which says "<strong>Enter an https:// URL:</strong>", next an input type which is set to type <strong>URL</strong> so it will only accept a URL and it's name is nm which we will be referring to it later on, the user will provide the long URL, and finally an input which is for submit the URL to get the short URL.</p>
<p>Let's link all the HTML we have to our app, return to <code>app.py</code></p>
<p>One thing we have to import from Flask is <code>render_template</code>.</p>
<p>In decorator <code>@app.route('/')</code>, instead of returning HELLO WORLD, return <code>render_template("home.html")</code>, in this case we would like to display <code>home.html</code>.</p>
<p>New code:</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template

app = Flask(__name__)

<span class="hljs-meta">@app.route('/')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello_world</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">"home.html"</span>)

<span class="hljs-meta">@app.route('/omar')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">hello_omar</span>():</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">"HI OMAR"</span>

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(port=<span class="hljs-number">5000</span>, debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>Let's try running our Flask App. As we are on the main page, it should display <code>home.html</code></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652000855526/XQ74rFiUn.png" alt="image.png" /></p>
<p>Now, let's cleanup our code and make changes.</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template, request

app = Flask(__name__)

<span class="hljs-meta">@app.route('/', methods=['POST', 'GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>():</span>
    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">"POST"</span>:
        url_received = request.form[<span class="hljs-string">"nm"</span>]
        <span class="hljs-keyword">return</span> url_received
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'home.html'</span>)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    app.run(port=<span class="hljs-number">5000</span>, debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>As you notice, we imported <code>request</code> from Flask, and what will it help us is to get the information from the website. Before, we were only using by default GET methods, but now we will define the 2 methods, GET and POST. What does this actually mean?</p>
<p>POST and GET are 2 different methods to transfer data for using HTML inside a web browser, the only difference that POST is more secure method when compared to GET, why? Because in a POST method, you can't see the information in the URL, but for GET, the info can be found in the URL. For example when we where going to <code>http://127.0.0.1:5000/omar</code>, we can see the information in the URL, so it is a GET method, but for POST, for example when we put a link in main page and submit, the data is actually being transferred but they cannot be found in the URL, so it is a POST.</p>
<p>So if the request method is POST, it means we got a link from the form for further processing, the URL will be stored in <code>url_received</code>, as you see, I used <code>return url_received</code> for now to test if it does work or not... For example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652003381798/zXe9niH6y.gif" alt="ezgif-3-a7aa5c7255.gif" /></p>
<p>If it's not a POST method, we will stay on the same page until another thing is submitted which will be processed to see what's next.</p>
<p>We will be using Database, let me introduce you to the idea.</p>
<p>The database we are using is called SQL Alchemy, so SQL Alchemy is specific for Python. The reason using the database is that you can kind of treat each of our items as a Python object, which makes it a lot easier to interact with and another point to put into consideration that is by using SQL Alchemy is that we can do everything by Python code. So if you don't know how to code SQL queries, don't worry you can code most of them in Python and also the lines of code to make a query is a lot less so a lot easier.</p>
<p>Copy the following code and let's work on some configurations:</p>
<pre><code class="lang-py"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask, render_template, request, redirect, url_for
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy
<span class="hljs-keyword">import</span> random
<span class="hljs-keyword">import</span> string
<span class="hljs-keyword">import</span> os

app = Flask(__name__)
app.config[<span class="hljs-string">'SQLALCHEMY_DATABASE_URI'</span>] = os.environ.get(<span class="hljs-string">'DATABASE_URL'</span>)
app.config[<span class="hljs-string">'SQLALCHEMY_TRACK_MODIFICATIONS'</span>] = <span class="hljs-literal">False</span>

db = SQLAlchemy(app)

<span class="hljs-meta">@app.before_first_request</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_tables</span>():</span>
    db.create_all()

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Urls</span>(<span class="hljs-params">db.Model</span>):</span>
    id_ = db.Column(<span class="hljs-string">"id_"</span>, db.Integer, primary_key=<span class="hljs-literal">True</span>)
    long = db.Column(<span class="hljs-string">"long"</span>, db.String())
    short = db.Column(<span class="hljs-string">"short"</span>, db.String(<span class="hljs-number">10</span>))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, long, short</span>):</span>
        self.long = long
        self.short = short

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">shorten_url</span>():</span>
    letters = string.ascii_lowercase + string.ascii_uppercase
    <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:
        rand_letters = random.choices(letters, k=<span class="hljs-number">3</span>)
        rand_letters = <span class="hljs-string">""</span>.join(rand_letters)
        short_url = Urls.query.filter_by(short=rand_letters).first()
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> short_url:
            <span class="hljs-keyword">return</span> rand_letters


<span class="hljs-meta">@app.route('/', methods=['POST', 'GET'])</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>():</span>
    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">"POST"</span>:
        url_received = request.form[<span class="hljs-string">"nm"</span>]
        found_url = Urls.query.filter_by(long=url_received).first()

        <span class="hljs-keyword">if</span> found_url:
            <span class="hljs-keyword">return</span> redirect(url_for(<span class="hljs-string">"display_short_url"</span>, url=found_url.short))
        <span class="hljs-keyword">else</span>:
            short_url = shorten_url()
            print(short_url)
            new_url = Urls(url_received, short_url)
            db.session.add(new_url)
            db.session.commit()
            <span class="hljs-keyword">return</span> redirect(url_for(<span class="hljs-string">"display_short_url"</span>, url=short_url))
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'url_page.html'</span>)

<span class="hljs-meta">@app.route('/&lt;short_url&gt;')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">redirection</span>(<span class="hljs-params">short_url</span>):</span>
    long_url = Urls.query.filter_by(short=short_url).first()
    <span class="hljs-keyword">if</span> long_url:
        <span class="hljs-keyword">return</span> redirect(long_url.long)
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-string">f'&lt;h1&gt;Url doesnt exist&lt;/h1&gt;'</span>

<span class="hljs-meta">@app.route('/display/&lt;url&gt;')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_short_url</span>(<span class="hljs-params">url</span>):</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'shorturl.html'</span>, short_url_display=url)

<span class="hljs-meta">@app.route('/all_urls')</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_all</span>():</span>
    <span class="hljs-keyword">return</span> render_template(<span class="hljs-string">'all_urls.html'</span>, vals=Urls.query.all())

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>:
    app.run(port=<span class="hljs-number">5000</span>, debug=<span class="hljs-literal">True</span>)
</code></pre>
<p>Change <code>os.environ.get('DATABASE_URL')</code> to <code>'sqlite:///urls.db'</code>. We are done, just go to the GitHub Repo, and get the HTML files inside templates, be sure to rename the files or change there names to your own unique name in the Python code.</p>
<h2 id="heading-the-end">The End!</h2>
<p>Thanks for reading this blog, hope you like it and learnt something helpful!!!</p>
<ul>
<li><strong>Live Demo:</strong> linky-web.herokuapp.com</li>
<li><strong>GitHub Repo:</strong> <a target="_blank" href="https://github.com/omardev100/linky">OmarDev100/linky</a></li>
</ul>
]]></content:encoded></item></channel></rss>