<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Max Bridgland</title>
    <description>The latest articles on DEV Community by Max Bridgland (@m4cs).</description>
    <link>https://dev.to/m4cs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F265154%2F4a478351-3a84-4319-8d2f-adfacdc73a94.jpeg</url>
      <title>DEV Community: Max Bridgland</title>
      <link>https://dev.to/m4cs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/m4cs"/>
    <language>en</language>
    <item>
      <title>Creating a Cleaner MacOS Workspace</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Wed, 23 Dec 2020 23:13:31 +0000</pubDate>
      <link>https://dev.to/m4cs/creating-a-cleaner-macos-workspace-2e35</link>
      <guid>https://dev.to/m4cs/creating-a-cleaner-macos-workspace-2e35</guid>
      <description>&lt;p&gt;The default macOS window management and desktop environment is great don't get me wrong. However, after using alternative window management solutions on Linux distros, I've craved a better solution. I've enjoyed ricing my Linux desktops for the past couple of years, and in doing so I've looked for similar tools I can use on macOS. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffqr7iw1o79ig1v15wtl9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffqr7iw1o79ig1v15wtl9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article I'll be walking you through how to get a setup resembling the photo above. The tools in use you see are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;yabai (Window Management)&lt;/li&gt;
&lt;li&gt;skhd (Hotkeys for yabai, running commands, etc)&lt;/li&gt;
&lt;li&gt;iTerm2 (Terminal Emulator)&lt;/li&gt;
&lt;li&gt;pywal (Colorscheme Generator)&lt;/li&gt;
&lt;li&gt;Übersicht (JSX Widgets on the desktop)&lt;/li&gt;
&lt;li&gt;ncmpcpp and mopidy (Spotify music player on the command line)&lt;/li&gt;
&lt;li&gt;dmenu-mac (Alternative Spotlight launcher)&lt;/li&gt;
&lt;li&gt;gotop (htop alternative)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  yabai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpe6f82fjq7n3ulloa2wr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpe6f82fjq7n3ulloa2wr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yabai is a window manager that came from the creators older WM known as chunkwm. If you've ever used i3 or i3-gaps, it's extremely similar. Yabai works as a tiling window manager. There are a ton of customization options you can find on the GitHub Wiki.&lt;/p&gt;

&lt;p&gt;To install &lt;a href="https://github.com/koekeishiya/yabai/wiki/Installing-yabai-(latest-release)" rel="noopener noreferrer"&gt;follow the instructions found here.&lt;/a&gt; Make sure to disable SIP on your Mac!&lt;/p&gt;

&lt;p&gt;If you'd like a similar setup to what I have, you can use the &lt;code&gt;.yabairc&lt;/code&gt; file found &lt;a href="https://github.com/M4cs/yabai-skhd-configs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  skhd
&lt;/h3&gt;

&lt;p&gt;skhd (simple hotkey daemon) is a hotkey manager for macOS. It was created by the same person as yabai and works hand in hand with it. Using skhd you can create keybinds to edit your workspace, launch applications, change system values, and more.&lt;/p&gt;

&lt;p&gt;To install &lt;a href="https://github.com/koekeishiya/skhd#install" rel="noopener noreferrer"&gt;follow the instructions found here.&lt;/a&gt; If you'd like a config that already includes some yabai bindings, you can use the &lt;code&gt;.skhdrc&lt;/code&gt; file found &lt;a href="https://github.com/M4cs/yabai-skhd-configs" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  iTerm2
&lt;/h3&gt;

&lt;p&gt;iTerm2 is a great macOS terminal emulator. It offers a massive amount of customization for your setup and even works with pywal. Pywal is a tool that will generate colorschemes from images and set your wallpaper w/ said image.&lt;/p&gt;

&lt;p&gt;To install iTerm2, grab it &lt;a href=""&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;If you'd like to use my profile, simply open Profiles &amp;gt; Default &amp;gt; Colors: Under colorscheme select import &amp;gt; import &lt;a href="https://gist.github.com/M4cs/8333cba215acf7fffd04f1c3aa7900c1" rel="noopener noreferrer"&gt;this file&lt;/a&gt; and select it as your colorscheme.&lt;/p&gt;

&lt;p&gt;To install pywal, run &lt;code&gt;pip3 install pywal haishoku&lt;/code&gt;. I find that the haishoku backend generates the most favorable colorschemes. &lt;/p&gt;

&lt;h3&gt;
  
  
  ncmpcpp/mopidy
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F03kjzsud983wv6czjxeg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F03kjzsud983wv6czjxeg.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ncmpcpp is a command line based music player. You can see it in use in the two terminals on the top of the image. It has the ability to control mpd which I use mopidy to host. Mopidy is an mpd alternative that offers an MPD-like protocol and plugins. I use mopidy because it allows me to add Spotify to my mpd server! This means I get all spotify functionality through mpd.&lt;/p&gt;

&lt;p&gt;First install mopidy, mopidy-mpd, and mopidy-spotify. To do so you can follow the steps &lt;a href="https://docs.mopidy.com/en/latest/installation/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Next follow the steps &lt;a href="https://computingforgeeks.com/install-configure-mpd-ncmpcpp-macos/" rel="noopener noreferrer"&gt;here to install ncmpcpp. Ignore the steps for installing mpd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I haven't changed much to those configs from the default so feel free to experiment on your own!&lt;/p&gt;

&lt;h3&gt;
  
  
  gotop
&lt;/h3&gt;

&lt;p&gt;Gotop is an awesome go based process manager. It shows you a lot of information about your system and what processes are using what. You can install it by first installing Go and then running &lt;code&gt;go get -u github.com/cjbassi/gotop&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Customizations
&lt;/h3&gt;

&lt;p&gt;You can also use custom CSS for Firefox and theme that. &lt;a href="https://github.com/M4cs/foxify-cli" rel="noopener noreferrer"&gt;I made a tool to make the process easier. Read more about Foxify-CLI here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Compressing Videos Easily on Windows w/ FFMPEG and Registry Files</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Mon, 02 Nov 2020 23:59:53 +0000</pubDate>
      <link>https://dev.to/m4cs/compressing-videos-easily-on-windows-w-ffmpeg-and-registry-files-5fin</link>
      <guid>https://dev.to/m4cs/compressing-videos-easily-on-windows-w-ffmpeg-and-registry-files-5fin</guid>
      <description>&lt;p&gt;I am always sharing clips and videos with my friends and often times the file size is ridiculously large to send over most social media (Discord, Twitter, Telegram, etc). To get around these massive file sizes, I use ffmpeg to compress the video. FFMPEG is a super powerful tool for all your media processing. It has a ton of libraries for handling different tasks involving visual and audio media.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;Using ffmpeg we are able to compress videos down by ~10x. For example, if we have a 1 minute and 15 second clip that is 1080p 60fps @ 432Mb, we can use a simple one-line ffmpeg command to compress this video down to ~50Mb. This now allows us to send it on a lot of different platforms way easier. &lt;/p&gt;

&lt;h4&gt;
  
  
  Before Compression:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy820l09icakjhqrbrucw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy820l09icakjhqrbrucw.png" alt="Before"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  After Compression:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3hzennnekr489w7d6ytm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3hzennnekr489w7d6ytm.png" alt="After"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the while, we lose little to no quality in the video. This is a great solution but it can be a serious hassle to have to open your terminal every time you want to compress these videos. I thought it would be easier to simply make a right-click menu item to quickly compress videos. I've tested it with m4v, mkv, and mp4 videos and it works flawlessly.&lt;/p&gt;

&lt;p&gt;Normally you could just run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

ffmpeg -i INPUT_FILE.mp4 -vcodec h264 -acodec aac OUTPUT.mp4


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;but nobody wants to have to type this out every time. Since I already had an FFMPEG python compression script laying around I used that as the main program to be run.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Setup
&lt;/h2&gt;

&lt;p&gt;You need a couple of tools to start. First, get Python 3 (preferably above 3.5). &lt;strong&gt;Make sure you have Python3 installed to your PATH as well.&lt;/strong&gt; &lt;a href="https://phoenixnap.com/kb/how-to-install-python-3-windows#htoc-step-5-add-python-path-to-environment-variables-optional" rel="noopener noreferrer"&gt;See how here.&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, install &lt;code&gt;ffmpeg&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

scoop install ffmpeg


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Make sure your scoop shims are in your PATH! (C:\Users&amp;lt;YOU&amp;gt;&lt;br&gt;
scoop\shims is the default path)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you're ready to start compressing!&lt;/p&gt;
&lt;h2&gt;
  
  
  Making our script and right-click registry file
&lt;/h2&gt;
&lt;h3&gt;
  
  
  compress.py
&lt;/h3&gt;

&lt;p&gt;Starting out you can make a &lt;code&gt;compress.py&lt;/code&gt; file and place it any where. I placed it in &lt;code&gt;C:\Users\Max\ffmpeg-compress\compress.py&lt;/code&gt;. The contents of that file are as follows:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PIPE&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pathlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;

&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;span class="n"&gt;video_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ffmpeg&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-i&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-vcodec&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;h264&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-acodec&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;aac&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;-compressed.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;video_file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])])&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Going line by line:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1-3: Importing our modules. &lt;code&gt;sys&lt;/code&gt; to get our arguments, &lt;code&gt;run&lt;/code&gt; and &lt;code&gt;PIPE&lt;/code&gt; from &lt;code&gt;subprocess&lt;/code&gt; in order to call our command and get the output, and &lt;code&gt;Path&lt;/code&gt; from &lt;code&gt;pathlib&lt;/code&gt; to parse and clean up our path strings.&lt;/p&gt;

&lt;p&gt;4: &lt;code&gt;args&lt;/code&gt; is a list of arguments passed when calling the executable (this will be our filename)&lt;/p&gt;

&lt;p&gt;5: &lt;code&gt;video_file&lt;/code&gt; is a Path object with the args passed joined as a string&lt;/p&gt;

&lt;p&gt;6: &lt;code&gt;run([...])&lt;/code&gt; is where we call the &lt;code&gt;ffmpeg&lt;/code&gt; executable from Python and run our command to compress.&lt;/p&gt;
&lt;h3&gt;
  
  
  compress.bat
&lt;/h3&gt;

&lt;p&gt;Next, you need to make a &lt;code&gt;.bat&lt;/code&gt; file anywhere on your computer. I placed mine @ &lt;code&gt;C:\Users\Max\compress.bat&lt;/code&gt;. The contents of that file are:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;

@echo &lt;span class="kd"&gt;OFF&lt;/span&gt;
&lt;span class="kd"&gt;SET&lt;/span&gt; &lt;span class="kd"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="vm"&gt;%%a&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="o"&gt;*)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="kd"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;%%a&lt;/span&gt;
&lt;span class="kd"&gt;python&lt;/span&gt; &lt;span class="kd"&gt;C&lt;/span&gt;:\\Users\\Max\\ffmpeg&lt;span class="na"&gt;-compress&lt;/span&gt;\\compress.py &lt;span class="nv"&gt;%subject%&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Going line by line:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1: &lt;code&gt;@echo OFF&lt;/code&gt; disables the printing of each line in the batch script to the terminal. A standard in batch scripts.&lt;/p&gt;

&lt;p&gt;2-3: Will set all of our arguments to a variable &lt;code&gt;subject&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4: Calls our python script with the video as our argument.&lt;/p&gt;
&lt;h3&gt;
  
  
  ffmpeg-compress.reg
&lt;/h3&gt;

&lt;p&gt;Finally, we need to make a file called &lt;code&gt;ffmpeg-compress.reg&lt;/code&gt; anywhere. We can use Notepad to do so. In this file, paste the following but replace the filepath for &lt;code&gt;compress.bat&lt;/code&gt; with yours.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\*\shell\ffmpeg-compress]
@="Compress File w/ FFMPEG"

[HKEY_CLASSES_ROOT\*\shell\ffmpeg-compress\command]
@="\"C:\\Users\\Max\\compress.bat\" \"%1\""


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Going section by section:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;[HKEY_CLASSES_ROOT\*\shell\ffmpeg-compress]&lt;/code&gt;, we are setting the title of our right-click menu button.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;[HKEY_CLASSES_ROOT\*\shell\ffmpeg-compress\command]&lt;/code&gt;, we are setting the actual command string we want the button to run when clicked.&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Now when we right-click on a file, we have the option to &lt;code&gt;Compress w/ FFMPEG&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FGwqdC8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FGwqdC8c.png" alt="Preview"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will now allows us to easily compress videos without having to open the terminal.&lt;/p&gt;

&lt;p&gt;A gist is available with the files used in this here:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  Why are you using Python? Couldn't you do this in pure batch?
&lt;/h3&gt;

&lt;p&gt;I suck with batch and I really don't like having to deal with weirdness passing args and parsing them. Python is just a more comfortable language for me. I'm also able to do string replacing and what not easier, and I already had the Python file&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
      <category>python</category>
      <category>batch</category>
    </item>
    <item>
      <title>Getting Started with winfetch, A neofetch Alternative for Windows</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Fri, 22 May 2020 22:37:50 +0000</pubDate>
      <link>https://dev.to/m4cs/getting-started-with-winfetch-a-neofetch-alternative-for-windows-ce5</link>
      <guid>https://dev.to/m4cs/getting-started-with-winfetch-a-neofetch-alternative-for-windows-ce5</guid>
      <description>&lt;p&gt;Today I released a new tool called winfetch. I decided to make this as an excuse to learn the language Go and also because screenfetch/neofetch solutions on Windows in the past were extremely unreliable. I knew I would be limited as far as what I could display since we don't get as many cool libraries Unix systems get. I found a great module called &lt;code&gt;ghw&lt;/code&gt; which allows you to query and obtain system/hardware information. &lt;/p&gt;

&lt;p&gt;I thought it would be a great way to share it by writing a blog post about it. Winfetch is extremely simple to use thanks to how awesome Go is as a language and distribution platform. I was easily able to make my module distributed through GitHub so all you have to do to install it is run:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

go get github.com/M4cs/winfetch


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once you do this you can add &lt;code&gt;winfetch&lt;/code&gt; as a command to your &lt;code&gt;$PROFILE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You are able to customize what information you want displayed with the tool along with which colors and ASCII art is displayed. Below you can see two examples of configuration setups using winfetch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FM4cs%2Fwinfetch%2Fmaster%2Fgitimages%2Fpreview1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FM4cs%2Fwinfetch%2Fmaster%2Fgitimages%2Fpreview1.png" alt="im"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FM4cs%2Fwinfetch%2Fmaster%2Fgitimages%2Fpreview.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FM4cs%2Fwinfetch%2Fmaster%2Fgitimages%2Fpreview.png" alt="im2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see you can easily add custom ASCII art. There is more information on the GitHub page which is available below:&lt;/p&gt;

&lt;p&gt;GitHub Source and Readme - &lt;a href="https://github.com/M4cs/winfetch" rel="noopener noreferrer"&gt;https://github.com/M4cs/winfetch&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>github</category>
      <category>productivity</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Simplifying "Login With Twitter" using Python and Flask.</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Fri, 24 Apr 2020 20:39:16 +0000</pubDate>
      <link>https://dev.to/m4cs/simplifying-login-with-twitter-using-python-and-flask-48io</link>
      <guid>https://dev.to/m4cs/simplifying-login-with-twitter-using-python-and-flask-48io</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NvfhvXTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2560/1%2AvvoZyeIdTr31jHsv8s3WQg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NvfhvXTe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2560/1%2AvvoZyeIdTr31jHsv8s3WQg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recently while working on a project I came across an issue with trying to implement Twitter Integrations into my Flask app. All of the guides on Google were breaking or just didn’t fit in with my application. I wanted a simple way to interface with Twitter’s OAuth1 API but everything was giving me errors.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: This guide assumes you have setup a Twitter Application and have your consumer keys and callback URLs set. If you do not know how to do this please refer to &lt;a href="https://docs.inboundnow.com/guide/create-twitter-application/"&gt;this guide.&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Finally, I decided to try something myself, I looked into requests_oauthlib and realized it would be much easier to just use their Client class to generate signatures and implement with my Flask app. I couldn’t find any examples that were easy to understand or read as far as the code went so I wanted to share how I ended up implementing this into my application.&lt;/p&gt;

&lt;p&gt;First the libraries I used in my implementation. flask is the library I’m using in order to create my main webserver and viewable routes. We don’t use much apart from the redirect function from it in this. flask_restful is the REST library I’m using in order to easily create a JSON based API. The endpoints we create in this are RESTful API Endpoints that inherit the Resource class from flask_restful. requests_oauthlib is the OAuth library I use in order to generate the OAuth headers to authenticate with Twitter’s API. We will also be using the requests library in order to make requests server side to Twitter.&lt;/p&gt;

&lt;p&gt;First you need to setup a flask app. Lets make a folder called app first:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir ./app
cd ./app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now from within the app/ directory we will create a file called &lt;strong&gt;init&lt;/strong&gt;.py :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Let's import the Flask class from the flask library
from flask import Flask

# Let's import the Api class from the flask_restful library
from flask_restful import Api

# Let's import our OAuth library to setup
from requests_oauthlib.oauth1_auth import Client

# Create A Config To Store Values
config = {
    'twitter_consumer_key': 'ENTER TWITTER CONSUMER KEY',
    'twitter_consumer_secret': 'ENTER TWITTER CONSUMER SECRET'
}

# Initialize Our Flask App
app = Flask(__name__)

# Initialize Our RESTful API
api = Api(app)

# Initialize Our OAuth Client
oauth = Client(config['twitter_consumer_key'], client_secret=config['twitter_consumer_secret'])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is all we need to do for now in the &lt;strong&gt;init&lt;/strong&gt;.py file. Next we will start to create our endpoints for Twitter. This assumes you have setup a Twitter Application and you have your consumer keys.&lt;/p&gt;

&lt;p&gt;Next we create our endpoint. For this we can just create a file called twitter.py or really whatever you’d like. Next we add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Import our functions and Resource class from flask_restful
from flask_restful import Resource, reqparse

# Import our functions from Flask
from flask import redirect

# Import our oauth object from our app
from app import oauth

# Import requests in order to make server sided requests
import requests

# We have to create our initial endpoint to login with twitter
class TwitterAuthenticate(Resource):
    # Here we are making it so this endpoint accepts GET requests
    def get(self):
        # We must generate our signed OAuth Headers
        uri, headers, body = oauth.sign('https://twitter.com/oauth/request_token')
        # We need to make a request to twitter with the OAuth parameters we just created
        res = requests.get(uri, headers=headers, data=body)
        # This returns a string with OAuth variables we need to parse
        res_split = res.text.split('&amp;amp;') # Splitting between the two params sent back
        oauth_token = res_split[0].split('=')[1] # Pulling our APPS OAuth token from the response.
        # Now we have to redirect to the login URL using our OAuth Token
        return redirect('https://api.twitter.com/oauth/authenticate?oauth_token=' + oauth_token, 302)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is our authentication endpoint, when somebody attempts to hit this it will redirect them to the Twitter login page which will then send them to our Callback URL which you should have setup in your Twitter App’s dashboard.&lt;/p&gt;

&lt;p&gt;Next we need to add the logic for handling our callback URL. We can add this to the same file as the TwitterAuthenticate class.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# We need to create a parser for that callback URL
def callback_parser():
    parser = reqparse.RequestParser()
    parser.add_argument('oauth_token')
    parser.add_argument('oauth_verifier')
    return parser

# Now we setup the Resource for the callback
class TwitterCallback(Resource):
    def get(self):
        parser = callback_parser()
        args = parser.parse_args() # Parse our args into a dict
        # We need to make a request to twitter with this callback OAuth token
        res = requests.post('https://api.twitter.com/oauth/access_token?oauth_token=' + args['oauth_token'] + '&amp;amp;oauth_verifier=' + args['oauth_verfier']])
        res_split = res.text.split('&amp;amp;')
        # Now we need to parse our oauth token and secret from the response
        oauth_token = res_split[0].split('=')[1]
        oauth_secret = res_split[1].split('=')[1]
        userid = res_split[2].split('=')[1]
        username = res_split[3].split('=')[1]
        # We now have access to the oauth token, oauth secret, userID, and username of the person who logged in. 
        # .... Do more code here
        # ....
        return redirect('http://somwhere.com", 302)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This TwitterCallback class will parse and handle the OAuth tokens in order to access the user’s account info. You can do whatever you want with this info whether that be storing it into a DB User Model or making requests with Tweepy!&lt;/p&gt;

&lt;p&gt;The last step is adding these endpoints to your &lt;strong&gt;init&lt;/strong&gt;.py file we created at the beginning! At the bottom of the file add this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from app.twitter import TwitterAuthenticate, TwitterCallback

api.add_resource(TwitterAuthenticate, '/authenticate/twitter')
api.add_resource(TwitterCallback, '/callback/twitter') # This MUST match your Callback URL you set in the Twitter App Dashboard!!!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Our final twitter.py should look like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask_restful import Resource, reqparse
from flask import redirect
from app import oauth
import requests
class TwitterAuthenticate(Resource):
    def get(self):
        uri, headers, body = oauth.sign('[https://twitter.com/oauth/request_token'](https://twitter.com/oauth/request_token'))
        res = requests.get(uri, headers=headers, data=body)
        res_split = res.text.split('&amp;amp;') # Splitting between the two params sent back
        oauth_token = res_split[0].split('=')[1] # Pulling our APPS OAuth token from the response.
        return redirect('[https://api.twitter.com/oauth/authenticate?oauth_token='](https://api.twitter.com/oauth/authenticate?oauth_token=') + oauth_token, 302)

def callback_parser():
    parser = reqparse.RequestParser()
    parser.add_argument('oauth_token')
    parser.add_argument('oauth_verifier')
    return parser

class TwitterCallback(Resource):
    def get(self):
        parser = callback_parser()
        args = parser.parse_args() # Parse our args into a dict
        res = requests.post('[https://api.twitter.com/oauth/access_token?oauth_token='](https://api.twitter.com/oauth/access_token?oauth_token=') + args['oauth_token'] + '&amp;amp;oauth_verifier=' + args['oauth_verfier']])
        res_split = res.text.split('&amp;amp;')
        oauth_token = res_split[0].split('=')[1]
        oauth_secret = res_split[1].split('=')[1]
        userid = res_split[2].split('=')[1]
        username = res_split[3].split('=')[1]
        # ... Do Code Here
        return redirect('[http://somwhere.com](http://somwhere.com)", 302)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Our final &lt;strong&gt;init&lt;/strong&gt;.py should look something like:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask
from flask_restful import Api
from requests_oauthlib.oauth1_auth import Client

config = {
    'twitter_consumer_key': 'ENTER TWITTER CONSUMER KEY',
    'twitter_consumer_secret': 'ENTER TWITTER CONSUMER SECRET'
}

app = Flask(__name__)
api = Api(app)
oauth = Client(config['twitter_consumer_key'], client_secret=config['twitter_consumer_secret'])

from app.twitter import TwitterAuthenticate, TwitterCallback

api.add_resource(TwitterAuthenticate, '/authenticate/twitter')
api.add_resource(TwitterCallback, '/callback/twitter')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope you find this guide helpful and have a fun time integrating with Twitter’s User API!&lt;/p&gt;

&lt;p&gt;You can find a GitHub Gist &lt;a href="https://gist.github.com/M4cs/0ea99c84f181876bfc81caecbe39e7f4"&gt;here with the files shown above.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Follow me on &lt;a href="https://twitter.com/maxbridgland"&gt;Twitter &lt;/a&gt;and &lt;a href="https://github.com/M4cs"&gt;GitHub&lt;/a&gt; for more interesting programming stuff!&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Making Slack More Fun with Slacky</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Sat, 11 Jan 2020 11:54:02 +0000</pubDate>
      <link>https://dev.to/m4cs/making-slack-more-fun-4j6b</link>
      <guid>https://dev.to/m4cs/making-slack-more-fun-4j6b</guid>
      <description>&lt;p&gt;Imagine being able to automate tasks, add custom notifications, custom commands, and add more fun things to do in Slack with your coworkers. Well I made it possible since there were no other Python selfbots Open Sourced on GitHub for Slack. I had always enjoyed using selfbots on Discord but since they were against ToS I had stopped. Slack on the other hand has no issues with these "custom integrations" and if anything, enable it. So today I present to you, Slacky.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vrb6ayi0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c51etepow34q2ewhjrr6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vrb6ayi0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/c51etepow34q2ewhjrr6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Slacky is a personal token based approach to the common Slack bot. It allows for all RTM functionality a normal Slack bot would, but it uses your account to do it. It reads messages from your user in order to automate and make your messages more fun. It comes with a load of commands off the bat but also allows for easily adding plugin packs or your own custom Python commands.&lt;/p&gt;

&lt;p&gt;Below you can see a preview of the tool:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---BMCFO87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/M4cs/Slacky/raw/master/slacky.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---BMCFO87--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/M4cs/Slacky/raw/master/slacky.gif" alt="Client"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's also really easy to add your own plugins. A simple example plugin takes less than 30 lines! Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;slacky&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Prefixes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;check_user&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;slack.errors&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SlackApiError&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;custom_example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Get Data from Payload
&lt;/span&gt;    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'data'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'channel'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Get Channel ID
&lt;/span&gt;    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Get User
&lt;/span&gt;    &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'ts'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;# Get msg Timestamp
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;check_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# Check if User == You
&lt;/span&gt;        &lt;span class="n"&gt;web_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="c1"&gt;# Init Client
&lt;/span&gt;        &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Get Text
&lt;/span&gt;        &lt;span class="c1"&gt;# Check for Command Here
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;text_split&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_split&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'prefix'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'example'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Command has been triggered
&lt;/span&gt;                &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Prefixes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'Ran Command: example'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="c1"&gt;# Do your logic here and then update the message at the end below.
&lt;/span&gt;                &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;web_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat_update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;ts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"This command is an example custom command."&lt;/span&gt;
                    &lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;SlackApiError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Prefixes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a bunch of default commands as of the first release already. Below is a table of said commands:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;heartbeat&lt;/td&gt;
&lt;td&gt;Check if bot is up or not&lt;/td&gt;
&lt;td&gt;~heartbeat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;info&lt;/td&gt;
&lt;td&gt;Get info about the bot&lt;/td&gt;
&lt;td&gt;~info&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ascii&lt;/td&gt;
&lt;td&gt;Generate ASCII art from a phrase&lt;/td&gt;
&lt;td&gt;~ascii msg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shift&lt;/td&gt;
&lt;td&gt;CrEaTe ShIfT tExT lIkE tHiS&lt;/td&gt;
&lt;td&gt;~shift phrase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;subspace&lt;/td&gt;
&lt;td&gt;Replace spaces with emojis&lt;/td&gt;
&lt;td&gt;~subspace :emoji: msg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setprefix&lt;/td&gt;
&lt;td&gt;Sets bot command prefix&lt;/td&gt;
&lt;td&gt;~setprefix prefix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xkcd&lt;/td&gt;
&lt;td&gt;Get Daily xkcd comic&lt;/td&gt;
&lt;td&gt;~xkcd&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete&lt;/td&gt;
&lt;td&gt;Delete X num of your msgs&lt;/td&gt;
&lt;td&gt;~delete num_of_msgs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;react&lt;/td&gt;
&lt;td&gt;React to last sent message&lt;/td&gt;
&lt;td&gt;~react :emoji:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reactrand&lt;/td&gt;
&lt;td&gt;React to with random emoji&lt;/td&gt;
&lt;td&gt;~reactrand&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reactspam&lt;/td&gt;
&lt;td&gt;Spam 23 Reactions (Notification Spam)&lt;/td&gt;
&lt;td&gt;~randspam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;howdoi&lt;/td&gt;
&lt;td&gt;Find code snippets from stack overflow&lt;/td&gt;
&lt;td&gt;~howdoi loop over list python&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;listener&lt;/td&gt;
&lt;td&gt;Add or remove listeners&lt;/td&gt;
&lt;td&gt;~listener add/delete phrase&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;listener list&lt;/td&gt;
&lt;td&gt;List all listener words&lt;/td&gt;
&lt;td&gt;~listener list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;help&lt;/td&gt;
&lt;td&gt;Display this message&lt;/td&gt;
&lt;td&gt;~help&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can run this locally or with Docker to have it run in the background! &lt;a href="https://github.com/M4cs/Slacky"&gt;The source code is available here&lt;/a&gt; and any plugin packs would be greatly appreciated! You will be featured in the README just make a Pull Request with any plugin packs you make.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
    <item>
      <title>JSONsty - Creating a Secure Cloud Storage Solution for JSON</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Thu, 19 Dec 2019 04:14:53 +0000</pubDate>
      <link>https://dev.to/m4cs/jsonsty-creating-a-secure-cloud-storage-solution-for-json-1g31</link>
      <guid>https://dev.to/m4cs/jsonsty-creating-a-secure-cloud-storage-solution-for-json-1g31</guid>
      <description>&lt;p&gt;One day I was sitting at work and my friend contacted me on Discord. He wanted an easy solution to host JSON data remotely for a Raspberry Pi project. He had used my service &lt;a href="https://psty.io" rel="noopener noreferrer"&gt;psty.io&lt;/a&gt; for a while and brought the idea to implement it into the service myself. I thought it was a great idea and hopped on it that night.&lt;/p&gt;

&lt;p&gt;I decided I would write it in Python with Flask and using mongoDB as the main database. I wanted this to be secure, fast, and able to handle a lot of connections at once. I have been able to do so with this stack in the past and I was most comfortable with it so I gave it a shot. &lt;/p&gt;

&lt;p&gt;The first part I wrote was the RESTful API. I knew it would be easiest with Flask since it's just JSON and that means no need to write a web front-end. This was done in a night and I had a very basic API for users. It simply allowed you to create JSON stores, edit them, delete them, and grab them. By the time this was done I showed a couple friends and they were concerned with the fact I was able to see all the data on the database. I wanted to look for a solution.&lt;/p&gt;

&lt;p&gt;After that I decided it would be better to offer a panel to users so I decided I would just write an entire web front-end. These are very simple Jinja2 templated, server side rendered pages. I plan on making a React app once I get better with Javascript but since the main idea of this is the API I am not too worried since the frontend gets the job done. You can edit Account Settings, create stores, edit stores, and delete stores. The API is extremely simple and you are given an API key immediately when you signup!&lt;/p&gt;

&lt;p&gt;I have been working with another developer the past couple weeks on an encryption/steganography technology called &lt;a href="https://github.com/Pixcryption" rel="noopener noreferrer"&gt;Pixcryption&lt;/a&gt;. We were working on adding the AES layer of security to it and I brought up JSONsty to him. He has been wanting to learn as much as possible so he took it as an opportunity to study Flask, MongoDB, Unit Testing, and more about AES. &lt;/p&gt;

&lt;p&gt;We spent the past couple days working together on securing the system with AES OCB and Base64. Now it encrypts all the JSON data in the database and decrypts when the user requests their store. Each user has an object on the db and that controls which stores belong to them through ObjectIds which map a relationship between the collections.&lt;/p&gt;

&lt;p&gt;Now JSONsty is ready for the public to start using in my eyes and I plan to make it even better over time. Psty.io has been doing well and I want to build it out into a family of software that provides tools for developers to make sharing and developing easier. Below you can find the source to JSONsty and you can also signup now &lt;a href="https://json.psty.io" rel="noopener noreferrer"&gt;here!&lt;/a&gt; We also would love any contributors who would like to harden the security or just make it a better service. &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/M4cs" rel="noopener noreferrer"&gt;
        M4cs
      &lt;/a&gt; / &lt;a href="https://github.com/M4cs/jsonsty" rel="noopener noreferrer"&gt;
        jsonsty
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ☁️ Free Cloud JSON Storage Written in Python 🐍
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
    &lt;a rel="noopener noreferrer" href="https://github.com/M4cs/jsonsty/blob/master/examples/banner.png?raw=true"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FM4cs%2Fjsonsty%2Fraw%2Fmaster%2Fexamples%2Fbanner.png%3Fraw%3Dtrue"&gt;&lt;/a&gt;
    &lt;br&gt;
    &lt;b&gt;Made with Python and Flask&lt;/b&gt;
    &lt;br&gt;
    &lt;a href="https://github.com/M4cs/jsonsty/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/6ddc2458fe77d20946f8dab3adc945959a5e0e63bd3931f44b29c8e60506dca8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f4d3463732f6a736f6e737479"&gt;&lt;/a&gt;
    &lt;a href="https://github.com/M4cs/jsonsty/issues" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8ec806f9dca6d976d32d6a61c7f59949ac97f20828ca08a8fd26cde97d892a30/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f4d3463732f6a736f6e737479"&gt;&lt;/a&gt;
    &lt;a href="https://github.com/M4cs/jsonsty/forks" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2a21969ea7bc5926749b8ff5d43744626375f5d555a7cef56107f969c684b718/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f4d3463732f6a736f6e737479"&gt;&lt;/a&gt;
    &lt;a href="https://github.com/M4cs/jsonsty" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8a4d2e16bc383812c65b10a1461ca8e2a6104a05c4af9fda4ac713d5bd64fddb/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f4d3463732f6a736f6e737479"&gt;&lt;/a&gt;
    &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/edee42645c940d08c5e8cc0a9f7605a16c18e1a5c52523e1af95cc0351d97f80/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f707974686f6e2d332e362532422d677265656e"&gt;&lt;img src="https://camo.githubusercontent.com/edee42645c940d08c5e8cc0a9f7605a16c18e1a5c52523e1af95cc0351d97f80/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f707974686f6e2d332e362532422d677265656e"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;JSONsty&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;What is JSONsty? JSONsty is a service provided by &lt;a href="https://psty.io" rel="nofollow noopener noreferrer"&gt;psty.io&lt;/a&gt; that allows you to store JSON data in the cloud for free using an extremely simple API or web panel frontend. The source code here includes everything running on the &lt;a href="https://json.psty.io" rel="nofollow noopener noreferrer"&gt;website&lt;/a&gt; as we speak. It should always be 1:1 up-to-date on the &lt;code&gt;master&lt;/code&gt; branch compared to the website.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;How Does It Work?&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;JSONsty is a Flask application that includes a REST API and dynamically rendered Website using the Jinja2 module. It interfaces and stores all data on a remote mongoDB cluster that acts as the master database. Users have an account which links the data, known as &lt;code&gt;stores&lt;/code&gt;, on the database, and then link said store to the user.&lt;/p&gt;

&lt;p&gt;When you create an account you receive an API Key which allows you to communicate with our API. The API allows you to create…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/M4cs/jsonsty" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>security</category>
      <category>python</category>
      <category>mongodb</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Creating A Jailed Shell Webpage with Repl.it and an iFrame</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Fri, 13 Dec 2019 16:01:08 +0000</pubDate>
      <link>https://dev.to/m4cs/creating-a-jailed-shell-webpage-with-repl-it-and-an-iframe-1jfd</link>
      <guid>https://dev.to/m4cs/creating-a-jailed-shell-webpage-with-repl-it-and-an-iframe-1jfd</guid>
      <description>&lt;h1&gt;
  
  
  How I Made A Jailed Shell Webpage with Repl.it
&lt;/h1&gt;

&lt;p&gt;Recently I was inspired by &lt;a href="https://repl.it"&gt;repl.it&lt;/a&gt;'s Jobs page. It uses their runtime to host an iframe of their shell that runs in the browser. This inspired me to make my own website follow suite and have a shell that users could use and navigate with commands rather than your traditional elemental webpage and UX. Big shoutout to Kognise for the help with everything!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bWCMKUhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.googleapis.com/replit/images/1576210146664_588105403f64ec1a755f3130159b3c27.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bWCMKUhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://storage.googleapis.com/replit/images/1576210146664_588105403f64ec1a755f3130159b3c27.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really liked this style since it made me think of all the fun I've had with CTFs and it gave me a perfect excuse to put one in my own website for fun. Repl.it makes this &lt;strong&gt;extremely&lt;/strong&gt; easy by offering a bash environment off the bat which also includes a basic 18.04 Ubuntu bootstrap meaning it allows for Python and other stock scripting languages to be run. This means I can have a termporary Ubuntu environment running on my website without worrying about it being persistent or breaking a VPS that it's hosted on. Repl.it handles all of this with unlimited temporary containers for my website to be running concurrently. Meaning multiple people can be logged in and their changes won't effect one another!&lt;/p&gt;

&lt;p&gt;It also just gives your website a certain hacky vibe which can be cool. The Repl project linked to this talk post has my bootstrap for a Jailed environment but I'll walk you through what I'm doing in it! The files that don't have logic just contain text which can be displayed using the &lt;code&gt;cat&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;main.sh&lt;/code&gt; we have the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x .pipes
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; ./main.sh
bash &lt;span class="nt"&gt;--rcfile&lt;/span&gt; .bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I'm doing here is giving a script permissions to run so people can run the command &lt;code&gt;pipes&lt;/code&gt; on my webpage which produces an XP-alike pipes screensaver but in your terminal! Next we are removing the &lt;code&gt;main.sh&lt;/code&gt; script to clean up the jailed environment. A lot of the custom files I use inside my jailed environment are hidden from the normal &lt;code&gt;ls&lt;/code&gt; command which makes it less cluttered for the person visiting my site. Afterwards we run &lt;code&gt;bash --rcfile .bashrc&lt;/code&gt; which runs a bash shell but with the file &lt;code&gt;.bashrc&lt;/code&gt; as the source to load from, meaning it will run all of the commands inside &lt;code&gt;.bashrc&lt;/code&gt; before allowing input from the user.&lt;/p&gt;

&lt;p&gt;That brings us to &lt;code&gt;.bashrc&lt;/code&gt;. I won't show you the entire file since most of it is already there by default you can pull the &lt;code&gt;.bashrc&lt;/code&gt; script I have already inside the Repl. The custom parts of it are at the bottom as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[91m'&lt;/span&gt;
&lt;span class="nv"&gt;GREEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[92m'&lt;/span&gt;
&lt;span class="nv"&gt;BROWN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[93m'&lt;/span&gt;
&lt;span class="nv"&gt;BLUE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[94m'&lt;/span&gt;
&lt;span class="nv"&gt;PURPLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[95m'&lt;/span&gt;
&lt;span class="nv"&gt;CYAN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[96m'&lt;/span&gt;
&lt;span class="nv"&gt;GRAY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\e[97m'&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;TERM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;xterm-256color

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;PS1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;BLUE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;guest&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GRAY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;@&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PURPLE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;maxbridgland.com&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GRAY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PURPLE&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]\w\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GRAY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="se"&gt;\[&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GRAY&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\]&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;pipes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'./.pipes'&lt;/span&gt;
&lt;span class="nb"&gt;alias source&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias exit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo "Ah! Ah! Ah!"'&lt;/span&gt;
&lt;span class="nb"&gt;alias mkdir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias touch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias rm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias cp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias mv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;alias cd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo "Use ls instead!"'&lt;/span&gt;
&lt;span class="nb"&gt;alias help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo "Commands: ls, pipes, cat, motd"'&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;motd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'cat .art'&lt;/span&gt;
&lt;span class="nb"&gt;alias alias&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo "Ah! Ah! Ah!"'&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;bash&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'echo ""'&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; .art
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first variables being set are for colors codes in ANSI. This gives the PS1 which is the prompt before your input it's color. As you can see I set my user as guest and the host to maxbridgland.com to reflect my website. Setting TERM is to set the terminal base to render your colors in the terminal. This xterm-256 gives you all 256 R, G, and B values for colors.  You would probably want to change this. What these commands are doing is removing the ability to run certain commands from the user. This gives it more of a jailed environment which goes along with the CTF I have included on my site. &lt;code&gt;alias&lt;/code&gt; sets the variable afterwards to run whatever it is set to run. For most of these it just echo's nothing so it has no power, but to troll a bit you can see I've removed the exit command and replaced it with &lt;code&gt;Ah! Ah! Ah!&lt;/code&gt; meaning you can stay as long as you wan't but you can never leave..&lt;/p&gt;

&lt;p&gt;The last command is just displaying my &lt;code&gt;.art&lt;/code&gt; file which holds the &lt;code&gt;motd&lt;/code&gt; command's output. It has some ASCII art which was generated using &lt;a href="http://patorjk.com/software/taag/#p=display&amp;amp;f=Graffiti&amp;amp;t=Type%20Something%20"&gt;THE BEST ASCII Text Generator Around&lt;/a&gt;. Here is what the &lt;code&gt;.art&lt;/code&gt; file looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 █     █░▓█████  ██▓     ▄████▄   ▒█████   ███▄ ▄███▓▓█████ 
▓█░ █ ░█░▓█   ▀ ▓██▒    ▒██▀ ▀█  ▒██▒  ██▒▓██▒▀█▀ ██▒▓█   ▀ 
▒█░ █ ░█ ▒███   ▒██░    ▒▓█    ▄ ▒██░  ██▒▓██    ▓██░▒███   
░█░ █ ░█ ▒▓█  ▄ ▒██░    ▒▓▓▄ ▄██▒▒██   ██░▒██    ▒██ ▒▓█  ▄ 
░░██▒██▓ ░▒████▒░██████▒▒ ▓███▀ ░░ ████▓▒░▒██▒   ░██▒░▒████▒
░ ▓░▒ ▒  ░░ ▒░ ░░ ▒░▓  ░░ ░▒ ▒  ░░ ▒░▒░▒░ ░ ▒░   ░  ░░░ ▒░ ░
  ▒ ░ ░   ░ ░  ░░ ░ ▒  ░  ░  ▒     ░ ▒ ▒░ ░  ░      ░ ░ ░  ░
  ░   ░     ░     ░ ░   ░        ░ ░ ░ ▒  ░      ░      ░   
    ░       ░  ░    ░  ░░ ░          ░ ░         ░      ░  ░
                        ░                                    

Take a look around, or head to https://n.maxbridgland.com

There may or may not also be a CTF somewhere here, but you have
to know me pretty well in order to get it ;)

Don't like my new site? Let me know on twitter! @maxbridgland

Run help to see some available commands... although it's not all of them

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just a simple message and some pretty ASCII text.&lt;/p&gt;

&lt;p&gt;To host this I have a VPS that I've setup with my domain and an extremely simple HTML file and stylesheet. The setup for that can be found &lt;a href="https://repl.it/@M4cs/Shell"&gt;here&lt;/a&gt;. The &lt;code&gt;index.html&lt;/code&gt; file is simple with just this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;'utf-8'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;'viewport'&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;'width=device-width'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;'stylesheet'&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;'style.css'&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text/css'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;MySite&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;iframe&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;'https://bashrepl.m4cs.repl.run'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An iFrame pointing to my repl.run instance and filled up in the webpage by my stylesheet here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;iframe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Super simple!&lt;/p&gt;

&lt;p&gt;As you can see, setting up a Repl.it Runtime Environment and Customizing it to make your own website-thats-a-shell is easy! It's also a great way to learn your way around repl and see the capabilities of what they offer. The fact we get free containers like this is crazy! &lt;/p&gt;

&lt;p&gt;The CTF is in my website currently and only one person has got it with some hints. If you can get it, you'll know what to do! Good luck!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>replit</category>
      <category>design</category>
      <category>bash</category>
    </item>
    <item>
      <title>Creating a REST API with MongoDB and the Falcon Framework Python</title>
      <dc:creator>Max Bridgland</dc:creator>
      <pubDate>Tue, 05 Nov 2019 05:05:03 +0000</pubDate>
      <link>https://dev.to/m4cs/creating-a-rest-api-with-mongodb-and-the-falcon-framework-python-5i6</link>
      <guid>https://dev.to/m4cs/creating-a-rest-api-with-mongodb-and-the-falcon-framework-python-5i6</guid>
      <description>&lt;p&gt;Recently I started working with the Falcon Framework to make an API for a URL shortening site. A friend of mine showed me the framework and I decided to give it a try. It's a bit of a learning curve from other common frameworks like Django or Flask, but once you get the hang of it, it's super easy to work with.&lt;br&gt;
In this article I'll go over the basic setup of a Falcon REST API with MongoDB support. This is the first part to a multipart series on how to build a complete Dart, Falcon, MongoDB webapp.&lt;/p&gt;

&lt;p&gt;To start, we will want a file structure like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- app/
|- controllers/
|- resources/
|- models/
|- __init__.py
|- settings.py
- app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All of our logic will live inside of the app/ folder. Inside this app folder we have a controllers/ folder which will hold the helper functions and logic for communicating with our database and performing internal functions, theresources/ folder which will hold all of our routes, and themodels/ folder will hold the logic for setting up our models in our database. The settings.py file contains our configuration for the application where we will store our variables for credentials and what not. Make sure you include an &lt;strong&gt;init&lt;/strong&gt;.py file in every folder insideapp/. The top level &lt;strong&gt;init&lt;/strong&gt;.py file will include our base setup and definition of our application. Let's start with getting the dependencies needed to run our application.&lt;/p&gt;

&lt;p&gt;Make sure you have mongoDB installed on your system, or have a database hosted on a server. If you have it hosted on your server then the HOST constant in our settings.py folder will be the IP of that address. If you have the database hosted locally for development purposes you will use localhost as the HOST constant.&lt;/p&gt;

&lt;p&gt;You can check if you have mongoDB installed by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mongod &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@mainbox:~# mongod &lt;span class="nt"&gt;--version&lt;/span&gt;
db version v3.2.22
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then you should be set. There will probably be more information about your environment but the first line is all that matters. For this I'll be using mongoDB version 3.2.22.&lt;/p&gt;

&lt;p&gt;To get setup with our python dependencies we will start by creating a virtualenv:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;virtualenv
virtualenv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate &lt;span class="c"&gt;# or .venv/Scripts/activate on Windows&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;falcon falcon-jsonify mongoengine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are on Unix or Linux you will also need to install a webserver to run the application. You can use uwsgi or gunicorn. If you are on Windows you will want to use the waitress module.&lt;/p&gt;

&lt;p&gt;To install uwsgi or gunicorn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;uwsgi
pip &lt;span class="nb"&gt;install &lt;/span&gt;gunicorn
To &lt;span class="nb"&gt;install &lt;/span&gt;waitress and hupper &lt;span class="k"&gt;for &lt;/span&gt;hot reloads:
pip &lt;span class="nb"&gt;install &lt;/span&gt;waitress hupper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Waitress doesn't include a hot-reload option by default like uwsgi or gunicorn so you must use hupper in order to have this feature (it makes development a lot easier but it is not necessary).&lt;br&gt;
Now that we have all of our dependencies installed we can start configuring our application. Open up our settings.py file inside app/. Set it up like the following snippet replacing your information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;flask_jsonfiy&lt;/span&gt;
&lt;span class="n"&gt;dbcfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'localhost'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# or external server address
&lt;/span&gt;    &lt;span class="s"&gt;'port'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'MONGO_USER'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="s"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'MONGO_PASS'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;middleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;falcon_jsonify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;help_messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is all we need for now. If you end up using middleware or need to configure other options do it inside this file and import it from your other modules.&lt;br&gt;
Now we can setup our core &lt;strong&gt;init&lt;/strong&gt;.py file inside the app/ folder. Set it up like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;falcon&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mongoengine&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;mongo&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app.settings&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;middleware&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;falcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mongo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;'development'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# This will be the name of your database
&lt;/span&gt;    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbcfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'host'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbcfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'port'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbcfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'username'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dbcfg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'password'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For now this all we need until we add an endpoint in resources/. Now we can setup our basic User model for the website. This is the only model we will be working in this part of the tutorial. To start create a file inside models/ called notes_model.py. You should setup your file like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;mongoengine&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;datetime&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NoteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Document&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;StringField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There isn't much to the model for now but you'll add to this later. Now we can move onto setting up our basic register endpoint. Open up the resources/ folder and add a file named notes.py. Inside of this file we will add the logic to setup our handlers and responses. You should also make a file named notes.py inside the controllers/ folder. These files will work together. Setup the resources/notes.py file up like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;falcon&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app.controllers.notes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NotesController&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;app.models.notes_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NoteModel&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetNotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;falcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_200&lt;/span&gt;
        &lt;span class="n"&gt;notes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;notes_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NoteModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;objects&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;notes_obj&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'notes'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;notes&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UploadNotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'body'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;notes_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NoteModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;notes_obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;falcon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTP_201&lt;/span&gt;
        &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Your Note Has Been Posted!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;'status'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;'successful'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our resource setup we can open our core &lt;strong&gt;init&lt;/strong&gt;.py file in the app/ folder. You will want to add these lines to the bottom:&lt;br&gt;
from app.resources.notes import *&lt;br&gt;
app.add_route('/notes/', UploadNotes)&lt;br&gt;
app.add_route('/notes/{}', GetNotes)&lt;br&gt;
Unlike other frameworks you aren't going to be returning anything. This is all we need for a basic REST API. We can now communicate with our mongoDB database by sending requests to our server.&lt;/p&gt;

&lt;p&gt;Now we can start our webapp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# With Gunicorn:&lt;/span&gt;
gunicorn &lt;span class="nt"&gt;-p&lt;/span&gt; 8000 &lt;span class="nt"&gt;--reload&lt;/span&gt; app:app
&lt;span class="c"&gt;# With uWSGI:&lt;/span&gt;
uwsgi &lt;span class="nt"&gt;--http&lt;/span&gt; :9090 &lt;span class="nt"&gt;--wsgi-file&lt;/span&gt; app.py
With Waitress and Hupper:
hupper &lt;span class="nt"&gt;-m&lt;/span&gt; waitress &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8000 app:app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your server should be running on &lt;a href="http://localhost:8000/"&gt;http://localhost:8000/&lt;/a&gt; now. You should try to post something to the /notes/ endpoint which will allow you to add a note.&lt;/p&gt;

</description>
      <category>python</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
