<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[The Baivaru Blog]]></title><description><![CDATA[Rants, ramblings and weird tutorials]]></description><link>https://blog.baivaru.net/</link><image><url>https://blog.baivaru.net/favicon.png</url><title>The Baivaru Blog</title><link>https://blog.baivaru.net/</link></image><generator>Ghost 3.0</generator><lastBuildDate>Tue, 28 Apr 2026 14:09:30 GMT</lastBuildDate><atom:link href="https://blog.baivaru.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Here is what I learnt about Clubhouse]]></title><description><![CDATA[Clubhouse]]></description><link>https://blog.baivaru.net/mummy-i-wrote-a-clubhouse-bot/</link><guid isPermaLink="false">61d5e9196e796a0841957320</guid><category><![CDATA[Python]]></category><category><![CDATA[Guide]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[API]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Wed, 05 Jan 2022 19:06:58 GMT</pubDate><media:content url="https://blog.baivaru.net/content/images/2022/01/shutterstock_1903690942-1080x675.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baivaru.net/content/images/2022/01/shutterstock_1903690942-1080x675.jpg" alt="Here is what I learnt about Clubhouse"><p>A Guide by: @<a href="https://t.me/eyaadh">eyaadh</a></p><p>It has been a while since I have done a post like this or even done a YouTube tutorial. Let me start the new year post not by throwing off a technical project or some source code, but by explaining the concept of how mighty Clubhouse works.</p><p>Say what? You do not know what Clubhouse is? You must be living under a rock! Either way Clubhouse (“Clubhouse”) is an audio chat-type social networking app developed by Alpha Exploration Co in 2020. Recently among Maldivians, it has become the morning Coffee, lunch, tea, and even the sleeping pill. Politicians, single mothers, single boys, single men, double men, boyfriends, girlfriends, self-claimed scientists like me spend awful long hours on the application. Why should I spare it when celebrities like Elon Musk and Noh Hong-cheol are on it. Do not ask me who Noh Hong-cheol, nor do I know other than that he is a well-known celebrity a lot of people follow. The impact that Clubhouse can cause among Maldivians was seen on Dec17, 2021 when it went down/was not accessible for almost 24hrs. The opposition party went on to Twitter claiming the poor ISPs had banned it in the Maldives. Those political puppets did not bother me until a tech-know-who accused the same and that would have been the funniest joke of 2021.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2022/01/image-3.png" class="kg-image" alt="Here is what I learnt about Clubhouse"></figure><p>What Clubhouse brought to the table is not something new, audio-chatting has been available on social networking for the longest I can remember in the form of applications such as Skype, Line and, etc. Also as a sub-feature on many other social platforms like Facebook, WhatsApp, Telegram, etc. In my opinion, Clubhouse seems to be special because it allows you to talk and discuss without any flaws outside the present life with a lot of people from various backgrounds in various public rooms across the platform as well as an intuitive UI/UX. That being said let's look at the basic structure/flow of the Clubhouse.</p><h2 id="structure-flow">Structure / Flow</h2><p>As of today, the clubhouse is mainly composed of four components:</p><ol><li>Clubhouse App</li><li>Clubhouse API Server</li><li>Agora RTC Server</li><li>PubNub Server</li></ol><p>And here is a small flow chart I took from a Korean blog explaining how things on this flow chart get along with each other.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2022/01/image-4.png" class="kg-image" alt="Here is what I learnt about Clubhouse"></figure><p>It is important to highlight that unlike many other applications that we see around - those cheeky developers and founders at Clubhouse did find a way to effectively utilize existing platforms in the market rather than implementing all the functions on the application by themselves. Probably having access to developer documentation of these said applications is how and a dumb person like me could easily reverse engineer and study the workflow of the application.</p><p>To get into more specifics; except for user authentication and club management, core functionalities such as voice chat and real-time status change processing actively use 3rd-party PaaS. To be more specific: RTC -  real-time voice conversation technology utilizes Agora.io service. And PubNub is used for notifications while being in a conversation.</p><p>Too much to process? Ok, no problem let us put this brief in normal human terms: The Clubhouse mobile application acts as a client and provides UI/UX of social network functions to users. Basically, it provides functions such as membership registration and login, user/club search, user invitation, channel (room) list display, schedule management, follower/following management, room creation, alerts, etc. The Application uses HTTP requests to communicate with the Clubhouse API server, which is responsible for updating the state by actually communicating with the server-side functions.</p><p>When you send a request to join a room and after this information - exchange to establish an RTC session through Agora server is completed, everything related to voice conversation is managed by Agora RTC SDK. And for real-time <strong><u>UPDATES</u></strong> about joining a particular room, promoting a listener to a speaker or moderator is handled by PubNub.</p><h2 id="what-did-i-do-with-these-findings">What did I do with these findings?</h2><p>It is so nice of you that you had asked. Well, I created a bot that calls out a welcome message to every new speaker within a room, want to see it in action? Come join the club <a href="https://www.clubhouse.com/club/%DE%84%DE%8E%DE%97">Bageecha</a>, visit the active room and raise your hand, unlike any other room you will find among Maldivian ones they always accept and welcome anyone who ever visits the room (a friendly bunch of very good people), and on top of all that - you will also see a “LaaluParee Kamana” saying a lovely welcome message to you. Such a nice gesture right?</p><p>As usual just like any of my other projects, this whole project is also built based on python, I used aiohttp to communicate with the REST API. And there is a library called agora-python-sdk that can be used within your python projects to communicate with agora.io. And to generate the welcome voice messages which the bot calls out I used our old friend gTTS. And that is not enough information to build one of your own?. What else do you need? The endpoints for REST API? Listen, as I mentioned earlier I am not here to spoon-feed you but explain the concept. So within this post, I do not intend to share any source codes, but I could tell you how I started with it if that would help you.</p><p>I used Burp Suite (if you prefer Frida feel free to use that) and intercepted the traffic and bingo! it showed me all that I needed, including the endpoints. What you need to note down here is almost all of the clubhouse's endpoints, including the API server, are located behind Cloudflare. So, most requests to the Clubhouse API have a <em>__cfduid</em> cookie attached. For this cookie - within your source simply use the secrets library and generate a hex token with 24 nbytes and to the end of this token add a random integer between 1-9. Additionally, requests sent to the API server have Clubhouse-specific HTTP headers such as language, unique user ID, app version, or device-specific values which you could simply collect from the intercepted traffic. The User-Agent is also set and sent as a custom UA including the app build number. Lastly, in the header of each HTTP request, you must also include the token provided by the server at the time of signup/login Authorizationis and this one is important. For both Android and iOS this token is returned with two different mechanisms that resolve captchas – iOS uses rc_token and Android uses SafetyNet. How you sail through this is up to you.</p><p>And in regards to the unique ID that is required by agora.io, you can collect this from the Info.plist of the Clubhouse app. It is stored as AGORA_KEY. Also, while joining a room, to be able to voice communicate you would also require an RTC Token. This token will be returned as a response to the endpoint join_channel. That should be enough information for you to start with. And let me tell you a secret. I am no hacker, I am just a simple developer who happens to know a bit of python.</p><p>Either way, the idea of the welcome bot is from my very good fellow friend Sunny who happens to be the founder of the club Bageecha, and for me as usual this was a fun experiment. And why not? It is first of its kind at least among Maldivian Clubhouse-rs. Not everyone in Bageecha Club was very fond of the project when we started with it, and that is ok, I do understand that not everyone is as technically literate and find what excites a geek like me exciting. And there is a say which says 5 fingers are not of the same size 😉</p>]]></content:encoded></item><item><title><![CDATA[HC-SR04 Ultrasonic Range Sensor with Raspberry Pi]]></title><description><![CDATA[Raspberry Pi Series]]></description><link>https://blog.baivaru.net/hc-sr04-ultrasonic-range-sensor-on-the-raspberry-pi/</link><guid isPermaLink="false">601eef4e6e796a084195726b</guid><category><![CDATA[Python]]></category><category><![CDATA[Guide]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[Electronics]]></category><category><![CDATA[Sensors]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Sun, 07 Feb 2021 10:29:21 GMT</pubDate><media:content url="https://blog.baivaru.net/content/images/2021/02/izmerenie-fon-makro.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baivaru.net/content/images/2021/02/izmerenie-fon-makro.jpg" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"><p>A Guide by: @<a href="https://t.me/eyaadh">eyaadh</a> </p><p>On our last post we looked at how to light a led using GPIO, and that was output. This time let's use a sensor and do some input. For this experiment I used a HC-SRO4 Ultrasonic Range Sensor and the sensor outputs 5V which needs to be dropped/converted to 3V3 so that it could be connected/used with GPIO without damaging our Raspberry Pi! Keeping all that in mind let’s go back to primary school Physics class along with Electronics in this experiment in order to explain each step in achieving today's goal!</p><h2 id="accessories-required-for-this-project-">Accessories required for this project:</h2><ol><li>HC-SR04<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=63">http://gadgets.mv/index.php?route=product/product&amp;product_id=63</a></li><li>1kΩ Resistor &amp; 2kΩ Resistor<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=104">http://gadgets.mv/index.php?route=product/product&amp;product_id=104</a></li><li>Jumper Wires<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=152">http://gadgets.mv/index.php?route=product/product&amp;product_id=152</a></li></ol><h3 id="ultrasonic-distance-sensor-">Ultrasonic Distance Sensor:</h3><p>As the name indicates, ultrasonic sensors measure distance by sending a sound wave at a frequency above the range of human hearing. A basic ultrasonic sensor consists of one or more ultrasonic transmitters, a receiver and a control circuit.</p><p>The transmitter emits an ultrasonic wave which bounces off any nearby object and the receiver receives the wave reflected back from the target. The distance to the target is measured using the time lapses between sending and receiving of the ultrasonic pulse also known as the width of the pulse. This is possible because we know the sound’s velocity in the air. We will look into how we put all this in a formula later within the tutorial.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2021/02/image.png" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>HC-SR04 has four pins that you need to worry about: VCC (Power), Trig (Trigger), Echo (Receive), and GND (Ground).</p><h4 id="how-does-hc-sr04-work">How does HC-SR04 work</h4><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/-891K3JMf-oS_XhqmbE3Lo65cW7z5jQVItcscj_2k4w9nw3mWwB0pUB7Bvo0ovz0PFX8yWk3v4tx6EfEx2FN1oSIdjPTDpzBfR4LRRuiOsCTjW6Q6clh9eQto37DeQgfyk8yhg51" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>VCC is the power supply for HC-SR04 Ultrasonic distance sensor which we will connect to one of the 5V pins from GPIO header of raspberry pi, ground it using GND, and we are going to use one of the GPIO pins to send an input signal to TRIG, which triggers the sensor to send pulse of at least 10 µS (10 microseconds). In response to that the sensor transmits a sonic burst of eight pulses at 40 KHz. This 8-pulse pattern makes the “ultrasonic signature” from the device unique, allowing the receiver to differentiate the transmitted pattern from the ambient ultrasonic noise.</p><p>The eight ultrasonic pulses travel through the air away from the transmitter. Meanwhile the Echo pin goes High (5V) to start forming the beginning of the echo-back signal. In case, If those pulses are not reflected back then the Echo signal will timeout after 38 mS (38 milliseconds) and return Low (0V). Thus a 38 mS pulse indicates no obstruction within the range of the sensor. If those pulses are reflected back the Echo pin goes low as soon as the signal is received. This produces a pulse whose width varies between 150 µS to 25 mS - depending upon the time it took for the signal to be received. The width of the received pulse is then used to calculate the distance to the reflected object. Lost me there? Even I do get lost with it, trying to explain this same scenario while struggling to put it in words. To keep it simple and for the ease of understanding let's look at a simple example.</p><p>Suppose we have an object in front of the sensor at an unknown distance and we received a pulse of width 300 µS on the Echo pin. We will use the good old formulae "<em><strong>distance = speed x time"</strong></em> from our physics book to calculate the distance of the object from the sensor.</p><p>Here, we have the value of Time i.e. 300 µs and we know the speed is 340 m/s. We have to convert the speed of sound into cm/µs in order to calculate the distance and that is 0.034 cm/µs.</p><!--kg-card-begin: markdown--><pre><code>Distance = 0.034 cm/µs x 300 µs
</code></pre>
<!--kg-card-end: markdown--><p>But this is not done! Remember that the pulse indicates the time it took for the signal to be sent out and reflected back so to get the distance we need to divide our result in half.</p><!--kg-card-begin: markdown--><pre><code>Distance = (0.034 cm/µs x 300 µs) / 2
Distance = 5.1 cm
</code></pre>
<!--kg-card-end: markdown--><p>So, now we know that the object is 8.5 centimeters away from the sensor. Well all that is fine and now we have a great knowledge of how the sensor works, but there is a concern. Remember I said Echo remains low (0V) until a pulse is triggered and it goes High (5V). Also if you remember, in my previous post I even told you that once we introduce anything higher than 3V3 to GPIO it will harm the Raspberry Pi. To avoid this we will need to use a small voltage divider circuit, consisting of two resistors, to lower the sensor output voltage to something our Raspberry Pi can handle.</p><h3 id="voltage-dividers">Voltage Dividers</h3><p>A voltage divider is a simple circuit that can reduce voltage. It distributes the input voltage among the components of the circuit. That being said, the best example of a voltage divider is two resistors (R1 and R2)  connected in series, with the input voltage (Vin) applied across the resistor pair and the output voltage (Vout) taken from a point between them. It is used to produce different voltage levels from a common voltage source but with the same current for all components in the series circuit. In our circuit, Vin will be ECHO, which needs to be decreased from 5V to our Vout of 3.3V.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/Df1a4MDx7EGjy_JLyF07ATovO2w7Q6QcgcUlfEjgCsByOJx6tsWWo-JucBhbOWKnIlQwp6sX8X7gOcrYsPXrBkssTT1gc7bkSjrzYk7fb-VLM8HiLfxdNk6Dl8BbMsEmzi1Pt5ty" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>The above circuit and the simple equation from Kirchhoff’s Voltage Law that we studied at Physics class from primary school - can be applied in our calculations.</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/3OfloU-P2_WfJ2OTtDnOwDb0h_PxZ7FIaMzLMFf1OKA4rW_0oAbui4cfLiCvOsIEyTxTEsp1V1b7a3YUK4786SWW0k59whWZe_bTMbTP31vP2aom6IaC7msdtCvBcMtIxha5-RFa" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>Without getting too deep into the math side, we only actually need to calculate one resistor value, as it’s the dividing ratio that’s important. We already know our input voltage which is 5V, and our required output voltage that is 3.3V, and we can use any combination of resistors to achieve the reduction. I happen to have a bunch of extra 1kΩ resistors laying around my table - meanwhile I wait for <a href="http://gadget.mv">gadget.mv</a> to send me their shipment “of stuff”, so I decided to use one of these in the circuit as R1. So my calculations were as bellow:</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/deb2h0jCmP7k_CcGnOE0d_z5VOaxBOdnIsbZjEbPFJnvL8BTw0bugXJsrJ8yRbuKW5vMVmDVYG7sLgEDW5yAujBTE1YTtfGtRFy2YtLC10bfRAnxWgLixQRQfG82ctNIEQdoRypK" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>I definitely am not going to get a resistor of 1941Ω from Maldives on a normal day when it sunshine's or rains therefore I do need to tweak a bit here to get all this working, well isn't that a problem? If you remember from my last post I did also mention that in a case like this we can use the nearest higher available resistor, therefore we will be using a 1kΩ for R1 and a 2kΩ resistor as R2! Problem solved!!!</p><h2 id="assemble-the-circuit">Assemble the Circuit</h2><p>As mentioned earlier we will be using 4 pins from our GPIO header of Raspberry Pi for this circuit. Go ahead and connect the Vcc of your sensor into the positive rail of your breadboard, and plug GND of the sensor into your negative rail. Respectively from the GPIO header plug GPIO 5V (Pin 2) into the positive rail, and GPIO GND (Pin 6) into the negative rail.</p><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/PLP5bZfZCimP66EY2eTlgKodw9MN_Dau5D06j7JaZKoIHvTobyta4Z_QzHdCIxgnLHtXqxnytFwzFdMqwbadAhgl3I4kOk8StlS6DwPaZuyZCRftz4sHTt3SVZf_0NbkspUXmygD" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>And now connect TRIG into a blank rail, and plug that rail into GPIO 23 (Pin 16).</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/HEqqOzVR61w3h1aGgsjet2AYwrBxLRISF-Ror_nv_SQU9p4fw9VYBtK9oO8qLUnWShP-h72cfMwstfKVUrraFaWndHPKLkrWgbCeqKXo2PIis_T2XJk5cQ3NsdUwdYI0wC3GHlrU" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>And then plug ECHO of the sensor into a blank rail, link another blank rail using R1 (1kΩ resistor). Link your R1 rail with the GND rail using R2 (2kΩ resistor). Leave a space between the two resistors. And finally Add GPIO 24 (Pin 18) to the rail with your R1 (1kΩ resistor). This GPIO pin needs to sit between R1 and R2</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/4do2VM3ge5LmqiXR3lIqo-OKRdsmrauIPx6Q-wNl43EvIiX4bA5L6YECtbFUoxzpSDbEurIsYHbwz-Crvcs8ekIwgiqF2m-At_vbt9UBZvJ9QRpR88CJHJsXFLll2o5K5aI-ttLv" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>Well that is it! Our HC-SRO4 sensor is connected to Raspberry Pi. For a better understanding of the circuit refer to the schematic given below.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/LQHC6VaQSk1iU9gI9uVrmOtkUMJeRVyU6h4Q5jK69pf8dlFY-fKaEELwPIMq_APT0qpDJfZc41fYPBkXLO-RqOip2N3IAVqB2p2ILL4l5yoKyZUjFlNxTXZmLnUKliePTvIOzltx" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><h2 id="the-code">The Code</h2><!--kg-card-begin: markdown--><pre><code>from gpiozero import DistanceSensor
from time import sleep

sensor = DistanceSensor(echo=24, trigger=23)
while True:
    print('Distance to nearest object is', sensor.distance * 100 , 'cm')
    sleep(1)
</code></pre>
<!--kg-card-end: markdown--><p>Well wait is that all? Don’t we have to do all those calculations using the distance formula and everything else that we had talked about earlier. Actually the library gpiozero handles all that for us at the backend, and this code gives great justification of what I also mentioned in my last post that gpiozero “requires minimal boilerplate code”. On the other hand if we had used RPi.GPIO we would have required to deal with all of those calculations manually. Ah! I just love using gpiozero so much, it keeps everything so clean and simple :-)</p><p>Now let's also look at what this code does. We started by importing DistanceSensor from gpiozero library and sleep from time.</p><!--kg-card-begin: markdown--><pre><code>sensor = DistanceSensor(echo=24, trigger=23)
</code></pre>
<!--kg-card-end: markdown--><p>And then we assign a variable (sensor) for the DistanceSensor - mentioning its echo and trigger pins. Even though on my source I have just only defined the parameters echo and trigger for the DistanceSensor it accepts a few more and below are the details for your perusal.</p><!--kg-card-begin: markdown--><ul>
<li><strong>echo (int or str)</strong> - The GPIO pin which the ECHO pin is connected to. See Pin Numbering for valid pin numbers. If this is None a GPIODeviceError will be raised.</li>
<li><strong>trigger (int or str)</strong> - The GPIO pin which the TRIG pin is connected to. See Pin Numbering for valid pin numbers. If this is None a GPIODeviceError will be raised.</li>
<li><strong>queue_len (int)</strong> - The length of the queue used to store values read from the sensor. This defaults to 30.</li>
<li><strong>max_distance (float)</strong> - The value attribute reports a normalized value between 0 (too close to measure) and 1 (maximum distance). This parameter specifies the maximum distance expected in meters. This defaults to 1.</li>
<li><strong>threshold_distance (float)</strong> - Defaults to 0.3. This is the distance (in meters) that will trigger the in_range and out_of_range events when crossed.</li>
<li><strong>partial (bool)</strong> - When False (the default), the object will not return a value for is_active until the internal queue has filled with values. Only set this to True if you require values immediately after object construction.</li>
<li><strong>pin_factory (Factory or None)</strong> - See API - Pins for more information (this is an advanced feature which most users can ignore).</li>
</ul>
<!--kg-card-end: markdown--><p>After this we have an indefinite loop running printing the distance in centimeters (by default the distance returned by the library is in meters, therefore we multiply it by 100 to get the value in centimeters) while the script sleeps for 1 second between each print.</p><!--kg-card-begin: markdown--><pre><code>while True:
    print('Distance to nearest object is', sensor.distance * 100 , 'cm')
    sleep(1)
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/dcTgZP8Jq17tiUYtPk4hJZABWo0tQ7oxjG30j8_7_2pwtBDwtdQ7W2NuT5TuBJQ0TonUKXHr4lQP66oJW1GeNooij-V_LnqUTj9Ih-JSH_ahTxttu8UbnIHwHXNIz8JE2YyR_a03" class="kg-image" alt="HC-SR04 Ultrasonic Range Sensor with Raspberry Pi"></figure><p>If you wish to check the source to see how the library does the calculation and the rest processes on the class DistanceSensor of gpiozero have a look at <a href="https://gpiozero.readthedocs.io/en/stable/_modules/gpiozero/input_devices.html#DistanceSensor">this</a>. With that we will wrap up today's post! I will see you on a different one with more accessories to explore and learn through.</p>]]></content:encoded></item><item><title><![CDATA[Mama I got a Raspberry Pi finally!]]></title><description><![CDATA[Raspberry Pi Series]]></description><link>https://blog.baivaru.net/mama-i-got-a-raspberry-pi-finally/</link><guid isPermaLink="false">601dacb76e796a0841957195</guid><category><![CDATA[Python]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[Guide]]></category><category><![CDATA[Raspberry Pi]]></category><category><![CDATA[Electronics]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Sat, 06 Feb 2021 07:29:45 GMT</pubDate><media:content url="https://blog.baivaru.net/content/images/2021/02/raspberry-pi-computer-logo-rt-1600x900.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baivaru.net/content/images/2021/02/raspberry-pi-computer-logo-rt-1600x900.jpg" alt="Mama I got a Raspberry Pi finally!"><p>A Guide by: @<a href="https://t.me/eyaadh">eyaadh</a> </p><h1 id="introduction-">Introduction:</h1><p>I am a kind of person who when interested in something, studies and learns as much as I can about that particular topic/thing until I am confident I have known enough of what is there to offer, perhaps that is how I got my nickname “The Scientist”. For quite awhile now, I have been eagerly waiting to get my hands on a Raspberry pi and finally I had the liberty of owning one - a week back.</p><p>The reason I decided to write about the experiments I did on Raspberry Pi and my case study notes is mostly just because I believe a huge part of studying is also putting the theory you learn in practical and documenting it. And also for the satisfaction of being able to explain and share a knowledge I have gained. After all there is a famous say which states something along the lines "Sharing knowledge ensures the entry of new".</p><p>Also do not be shy because Robert Mugabe also once said "No matter how bad you are, you are not useless. You can still be used as a Bad Example!"</p><h1 id="what-is-a-raspberry-pi">What is a Raspberry Pi?</h1><p>With that being said let’s briefly look at what a raspberry pi is. Raspberry Pi is a series of small single-board computers developed in the United Kingdom by the Raspberry Pi Foundation in association with Broadcom. Early on, the Raspberry Pi project leaned towards the promotion of teaching basic computer science in schools and in developing countries as a part of the charity which Raspberry Pi foundation was doing. Later, the original model became far more popular than anticipated, selling outside its target market for uses such as robotics just because it is the go-to microcomputer for all ages and abilities starting out in the wonderful world of programming and electronics.</p><p>There are five key models of the Raspberry Pi microcomputer on the market today - the Raspberry Pi 400, Raspberry Pi 4 Model B, the smaller Raspberry Pi Model 3 A+, their tiny sibling the Raspberry Pi Zero W and the brand new micro-controller Raspberry Pi Pico.</p><p>As I was getting my hands dirty with this small yet powerful microcomputer I was much more interested in learning everything about their bold claim of being able to use code to control real-world ‘things’ via the Raspberry Pi’s GPIO.</p><h1 id="what-exactly-is-a-gpio">What exactly is a GPIO?</h1><p>General purpose input-output (GPIO) on a Raspberry Pi are a set of 40 pins on newer models or otherwise 26 pins on older models. These pins are a physical interface between the Raspberry Pi and connected electronic circuits. In other words, you can think of them as switches that you can turn on or off (input) or that the Pi can turn on or off (output).</p><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/rNGrw-1RLhuTvMG_o4O1BXZEDLmp-6f2utNoy8B000-NJvYiWAg3V3ElznZtSpM6lSTZkaIgD6YuWU0dW-hzlF1GTNQc6KoEAUbHLBpy90w3fVVVe-d198tFqlV3rl8aw1rFVJgT" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>Any GPIO pins set as output/input can be set/read as high (3V3) or low (0V) respectively. This is something you should always remember since introducing any voltage higher than 3V3 or randomly plugging wires and power sources into your Pi can damage it. For this very reason it is always important to be aware of which pin is which and an easier way of having this reference from pi is by running the command “pinout” on the terminal(assuming you have Rasbian as your OS). Trust me I felt like a rocket scientist the day I found about it and that I did not have to google each time I needed the pin out structure.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/F_Vu3iCde4Y1hSLrNNPx11z3Ww5idP7wim_fkYLl4loRefhRQcm7hgh1jRUUYAjngfjPQ8LYWgqcaetEiFL9NhVVo6BoId4Pb2RMBt56Kv72BuyPKQXFaIaGzAEtavG1qxW5YK5U" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>As you have already guessed there are a number of programming languages and tools that can be used to control GPIO pins. I am specifically interested in programming/developing applications to use these pins with Python.</p><h1 id="developing-for-gpio-in-python">Developing for GPIO in Python</h1><p>Before we jump on to the Python package that we are going to use, let me also explain my setup. To begin with I have a Raspberry Pi 3B V1.2 with Rasbian installed. I have also enabled SSH on the pi so that I can code remotely.</p><p>To enable SSH you could simply follow the below steps on terminal:</p><!--kg-card-begin: markdown--><pre><code>1. Enter sudo raspi-config in a terminal window
2. Select Interfacing Options
3. Navigate to and select SSH
4. Choose Yes
5. Select Ok
6. Choose Finish
</code></pre>
<!--kg-card-end: markdown--><p>On my coding terminal I am using VSCode with <a href="https://github.com/SchoofsKelvin/vscode-sshfs">SSH FS</a> extension installed. This extension allows "mounting" a remote folder (in this case our Pi) over SSH as a local Workspace folder.</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/8noxRkyDUCVlyvi4IwDFY1cIPfHxkJrihED6iKnKyCGkwOOeMnbmkMAaO0QdaI-snVpqLZjFisf9TCzbOGcpxT-3uMb54FjctnzKGW7ZSWI8fz2JzIrynRrb7wYucOY3KCEr9ODO" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><h1 id="gpiozero">GPIOZERO</h1><p><a href="https://gpiozero.readthedocs.io/en/stable/installing.html">GPIOZero </a>is a wrapper around <a href="https://sourceforge.net/projects/raspberry-gpio-python/">RPi.GPIO</a>, which is a python library that allows people to control GPIO pins from their python programs. Authors of the library say gpiozero shares the same philosophy as PyGame Zero, which requires minimal boilerplate code to get started with. When they are confident in it, who are we to deny? Therefore, for most of it - we will be using gpiozero as this would keep our snippets clean, elegant and easy to read/understand.</p><h1 id="turning-on-an-led-with-your-raspberry-pi-s-gpio-pins">Turning on an LED with your Raspberry Pi's GPIO Pins</h1><p>I am going to do a series of posts under this same umbrella explaining projects I have done using several tools and sensors on raspberry pi. In each post I am going to explain the accessories, the reasons behind using them, schematics, the codes that I have used and most importantly from where I got the accessories. To begin with something simple we are going to light a led using raspberry pi.</p><h3 id="accessories-required-for-this-project-">Accessories required for this project:</h3><h4 id="breadboard">Breadboard</h4><p>A breadboard is a solderless thin plastic board with holes used for temporary prototypes with electronics and test circuit designs. Most electronic components in electronic circuits can be interconnected by inserting their leads or terminals into the holes and then making connections through wires where appropriate. The breadboard has strips of metal underneath the board and connects the holes on the top of the board.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2021/02/Picture1.png" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>From where I got it:<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=269">http://gadgets.mv/index.php?route=product/product&amp;product_id=269</a></p><h4 id="led">LED</h4><p>A light-emitting diode (LED) is a semiconductor device that emits visible light when an electrical current passes through it. There are a handful of identifiers for finding the positive and negative pins on an LED. You can try to find the longer leg, which should indicate the positive, anode pin.</p><p>Or, if someone's trimmed the legs, try finding the flat edge on the LED's outer casing. The pin nearest the flat edge will be the negative, cathode pin.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/U3rlvcavxclCoZ0r6KCxGcFGE-BeIg5csTuSV0mDk7NDXkkTK-oDaCh_jnyfbi4qxZtGe4VnnVrbLT93Vrbq4WLUgzLTLNxVwqui4PcNbu43EKTkJKTC4ucZUVi_KSAHon2LF8HL" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>LEDs will only work if power is supplied the correct way round (i.e. if the ‘polarity’ is correct). You will not break the LEDs if you connect them the wrong way round – they will just not light. If you find that they do not light in your circuit, it may be because they have been connected the wrong way round.</p><p>From where I got it:<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=216">http://gadgets.mv/index.php?route=product/product&amp;product_id=216</a></p><h4 id="resistor">Resistor</h4><p>An LED can only pass so much current before it will destroy itself. The maximum current varies by the LED's size and colour. On the other hand a Raspberry Pi can only supply a small current (about 60mA). The LEDs will want to draw more, and if allowed to, it can cause real harm to your Raspberry Pi, in fact even break it. Therefore putting the resistors in the circuit will ensure that only this small current will flow and the Raspberry Pi will not be damaged.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/FvkVcmrnx0dLo2nz-uozSqIdsnCmYe6I2LIJU-AEeAe6ZHc10S_UAvCCrJB12Uy1x2T2vWY3KqAqciM0gnYNuhE-wnEXYQw_50WtX56LAV5fA5OyQFsL7Cuqzzaw-PnRUeEMabUW" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p><br>The maths to calculate the correct resistor value is fairly straight-forward, but in most cases the value you get out of your calculation won’t exactly match the available resistors in your hand. In such a case you can use the nearest higher available resistor, this is absolutely fine to do in almost all instances. If you do not want to do that you can also create your own resistor value using networks of other resistors, you’ll only ever want to do this out of curiosity!</p><figure class="kg-card kg-image-card"><img src="https://lh3.googleusercontent.com/xKh1XqFooqYRgqdngGiFWPA76WV4MEsHpUMy7N9cL9ajrEyn--im6SWeBhDG4vyTRvznkZ9Bj7pYsL_I3FtM_fdBY7JQREaFVxEJ49BBs2YDflAMQazmw-NGcrnIS9szyVCMxX73" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>From where I got it:<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=104">http://gadgets.mv/index.php?route=product/product&amp;product_id=104</a></p><h4 id="jumper-wires">Jumper Wires</h4><p>Jumper wires are simply wires that have connector pins at each end, allowing them to be used to connect two points to each other without soldering. Jumper wires are typically used with breadboards and other prototyping tools in order to make it easy to change a circuit as needed. Fairly simple. In fact, it doesn’t get much more basic than jumper wires.</p><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/X7Tvr7c_3ugXYKahtVBKHoSdqOkXWKUVPMwclLBe6kczcrwsIprrQEEmBCt1iWTk3I-omrU0V0WjEE3Ig4m-5SiRzV3Sqb6PKRd2wC3rQ3IdVe8DjqsR0Smw3tlNd4oDgRhdsz8y" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>From where I got it:<br><a href="http://gadgets.mv/index.php?route=product/product&amp;product_id=152">http://gadgets.mv/index.php?route=product/product&amp;product_id=152</a></p><h3 id="building-the-circuit">Building the Circuit</h3><figure class="kg-card kg-image-card"><img src="https://lh5.googleusercontent.com/S-yu1a7Rk1CsxC-aN29LwHiFO1I8tRSRjRVZQZRmjip6n__7gumi1S_BC2zPzj_Qf88RYrYWbzqjB7wwtemrzFPxGl2ji4Ml0ru5QDGnRkhkdD4oAiK5rgQBbFXaqcU4zLgBrg4j" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>I recommend that you turn your Raspberry Pi off for this part of this experiment, just in case you accidentally short something out. After all that is the best practice.</p><p>Here for this circuit we will be using one of the ‘ground’ (GND) pins to act like the ‘negative’ or 0 volt. Go ahead and connect a jumper wire from the 6th pin of the GPIO header of your raspberry pi to the rail, marked with blue, on the breadboard. Then connect the 1KΩ resistor from the same row on the breadboard to a column. Let me explain you why we use a 1KΩ resistor in this circuit with a simple calculation using ohms law (I am lazy so I used <a href="https://ohmslawcalculator.com/led-resistor-calculator">https://ohmslawcalculator.com/led-resistor-calculator</a>). What we are looking for here is that the current through the led to be at an acceptable range for pi without causing it any damage yet light the LED, I explained why we should be worried about this earlier at the section of explaining what resistors are.</p><figure class="kg-card kg-image-card"><img src="https://lh6.googleusercontent.com/T0hHlyuiucexQdmCzjB3awbM7pMMtASshCqzuhXLnQbkbfhmLs7QwPgx6GgtXtZTl9awYtscvR7AAW2vnVUDdAQoIpafbC51jIBkaZzH_Rba3tCgHSGfXG9uPm6PHOiKbTiF2v5i" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><p>Now that we are sure it is safe, push the LEDs legs into the breadboard, where the cathode of the LED (long leg) is in the same column as the resistor we plugged in just now. The ‘positive’ end will be provided by a GPIO pin. Here we will be using pin 38 of the GPIO header which is GPIO 20 i.e. connect a jumper wire from pin 38 of GPIO header to the same column of bread board which has the anode of the LED (short leg).</p><p>Do not worry if you lost me for a bit there, for the ease of understanding and to have a look at everything I said above in a physical representation see the below schematics.</p><figure class="kg-card kg-image-card"><img src="https://lh4.googleusercontent.com/VlfdeOQY7lqYmavQtBmnvBdCYQFh5mUNKhNibTC4qQy5k5jLDV1Z-Yq3gSrecgzw0roNCcoH2VW8bddZr1hlnSfaO7FX0mEa2F0w4YADYoARe1CqR02qlvJek9ZaPCyI96RYKHPx" class="kg-image" alt="Mama I got a Raspberry Pi finally!"></figure><h3 id="the-code">The Code</h3><!--kg-card-begin: markdown--><pre><code>import time
from gpiozero import LED

led = LED(20)

while True:
    led.on()
    time.sleep(1)
    led.off()
    time.sleep(1)
</code></pre>
<!--kg-card-end: markdown--><h4 id="explanation-of-the-code-">Explanation of The Code:</h4><p>So, what is happening in the code?  Let’s go through it:</p><!--kg-card-begin: markdown--><pre><code>import time
from gpiozero import LED
</code></pre>
<!--kg-card-end: markdown--><p>The first two lines tell the Python interpreter (the thing that runs the Python code) the ‘libraries’ that our script will be using.  A ‘library’ gives a programming language extra commands that can be used to do something different that it previously did not know how to do. This is like adding a new channel to your TV so you can watch something different. This process of “telling” is also known as importing. Here we are importing the time library so that we can pause the script later on and gpiozero that will tell the script how to work with the Raspberry Pi’s GPIO pins.</p><!--kg-card-begin: markdown--><pre><code>led = LED(20)

</code></pre>
<!--kg-card-end: markdown--><p>Here on this line we define a variable telling the script which GPIO pin of the Raspberry Pi our LEDs anode is connected to.</p><!--kg-card-begin: markdown--><pre><code>while True:
    led.on()
    time.sleep(1)
    led.off()
    time.sleep(1)
</code></pre>
<!--kg-card-end: markdown--><p>And then we have an indefinite loop running within which led.on() is where it turns the GPIO pin ‘on’. What this actually means is that the pin is made to provide power of 3.3volts.  This is enough to turn the LED in our circuit on. time.sleep(1) pauses the Python program for 1 second and led.off() turns the GPIO pin ‘off’, meaning that the pin is no longer supplying any power.</p><p>This loop will run in a circle continuously until you press CTRL + C on your keyboard.</p><h3 id="conclusion">Conclusion</h3><p><br>To wrap up what an achievement eh? When I got this working I felt more like Tony Stark from Iron Man. Well, either way that is not all. We have more to learn and in the next post we are going to dig and dive more into exploring with a few other accessories we have got. At this very moment I would also like to thank <a href="http://gadgets.mv/">http://gadgets.mv/</a> for being the only partner whom I could trust in getting the accessories required for the value of money unlike many other shops out there in Maldives. </p>]]></content:encoded></item><item><title><![CDATA[How to Use Baivaru TV]]></title><description><![CDATA[How to use BaivaruTV]]></description><link>https://blog.baivaru.net/how-to-use-baivarutv/</link><guid isPermaLink="false">5e8de29da30f71085fba5104</guid><category><![CDATA[Guide]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Wed, 08 Apr 2020 15:01:20 GMT</pubDate><media:content url="https://blog.baivaru.net/content/images/2020/04/baivaru-tv-trsprnt.png" medium="image"/><content:encoded><![CDATA[<img src="https://blog.baivaru.net/content/images/2020/04/baivaru-tv-trsprnt.png" alt="How to Use Baivaru TV"><p>In order to use BaivaruTV, you need to install Kodi Media Player.<br><br>1. Download and install Kodi<br>a. <a href="http://mirrors.kodi.tv/releases/windows/win64/kodi-18.6-Leia-x64.exe">Windows</a><br>b. <a href="http://mirrors.kodi.tv/releases/osx/x86_64/kodi-18.6-Leia-x86_64.dmg">OSX</a><br>c. <a href="http://mirrors.kodi.tv/releases/darwin/ios-arm64/org.xbmc.kodi-ios_18.6-0_iphoneos-arm64.deb">iOS</a><br>d. <a href="http://mirrors.kodi.tv/releases/android/arm64-v8a/kodi-18.6-Leia-arm64-v8a.apk">Android</a></p><p>2. Download the BaivaruTV add-on file from <a href="https://tv.baiva.ru">here</a> (<a href="https://tv.baivaru.net">mirror</a>). Make sure to download the latest patch.</p><p>3. Open Kodi &gt; Settings &gt; Add-ons &gt; Enable unknown sources</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-50.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Main Menu</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-51.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Enable Unknown Sources</figcaption></figure><p></p><p>4. Add-ons &gt; Add-on browser &gt; Install from zip &gt; select the file you downloaded in Step 2</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-52.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Main Menu - Add-ons Option</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-53.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Add-ons menu</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-54.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Add-on browser - Install from Zip file</figcaption></figure><p></p><p>5. Go to Add-ons &gt; Video add-ons &gt; BaivaruTV &gt; Settings</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-55.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>BaivaruTV Add-on</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-56.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>BaivaruTV Add-ons Settings</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-57.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>BaivaruTV Add-ons Settings - Token</figcaption></figure><p>6. The default token will be 1234. You need to replace this with your token.</p><p>7. To get your token go to <a href="https://t.me/baivarumediabot">@baivarumediabot</a> on telegram and message the command /kodi. Copy and paste this token in the kodi app.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-60.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Getting Token from Baivaru Media Bot</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-58.png" class="kg-image" alt="How to Use Baivaru TV"><figcaption>Saving Settings</figcaption></figure><p>8. Enjoy streaming your favorite movie without having to download them, absolutely for free! If you are confused about the steps watch the video tutorial. And if you encounter any errors/bugs (hidden features) send a message to us at Telegram @<a href="https://t.me/BaivaruTV">BaivaruTV</a>.</p>]]></content:encoded></item><item><title><![CDATA[An In-Depth Guide: Baivaru Viber Bot Skeleton]]></title><description><![CDATA[Baivaru Viber Bot Skeleton]]></description><link>https://blog.baivaru.net/viber-skeleton/</link><guid isPermaLink="false">5e8b320fa30f71085fba4ee9</guid><category><![CDATA[Guide]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[API]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Mon, 06 Apr 2020 15:50:30 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1530210124550-912dc1381cb8?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1530210124550-912dc1381cb8?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"><p>Project Developed by: @<a href="https://t.me/eyaadh">eyaadh</a><br>Guide by: @<a href="https://t.me/eyaadh">eyaadh</a><br>Proof read and fixes by: @<a href="https://t.me/suicide_router">izaya</a> and @<a href="https://t.me/tiashe">tiashe</a></p><h3 id="introduction"><u><strong>Introduction</strong></u></h3><p>What is a bot you ask? A bot is a software application that is programmed to do certain tasks. That doesn’t sound enough of an explanation does it? Bots are automated, which means they run according to their instructions without a human user needing to start them up. Bots often imitate or replace a human user's behavior. Typically, they do repetitive tasks and they can do them much faster than human users could.</p><p>Now that we understand what bots are, let me also tell you that Viber’s bot platform is open and free for developers to create bots in their ecosystem. As social media and messaging apps have long become our main way to keep in touch with one another and, as such, we count on the service providers and brands on these platforms to offer us the most personal connections possible. Brands have found the answer to this in chat bots – a way for them to simulate conversation with a human through what is essentially a computer program that operates under a specific set of rules. </p><p>We are going to use Python for this project since that is all that I know in the world of computer programming. Let’s also not forget that Viber already has an official Python library which is synchronous, however my interests are in doing something asynchronous. Let me pause for a minute once again, before jumping into the fun part of  explaining you the difference between synchronous and asynchronous execution.</p><h3 id="synchronous-vs-asynchronous-execution"><u>Synchronous vs Asynchronous Execution</u></h3><p>Basically, when you execute a task synchronously - it executes one step at a time. Even with conditional branching, loops and function calls, you can still think about the code in terms of taking one execution step at a time. When each step is complete, the program moves on to the next one.</p><p>And when you execute a task asynchronously, it still takes one execution step at a time. The difference is that the system may not wait for an execution step to be completed before moving on to the next one. This means that the program will move on to future execution steps even though a previous step hasn’t yet finished and is still running elsewhere. This also means that the program knows what to do when a previous step does finish running.</p><p>Why do we want to write asynchronous programs you say? — because it could increase the performance of your program. Let’s say you have a single core machine on which you are running your app. The app receives a request, and you need to make two database queries to fulfill that request. Each query takes 50ms of time. With a synchronous program, you would make the second request only after completing the first — total time 100ms. With an asynchronous program, you could fire off both the queries one after the other — total time 50ms. Now it’s your turn to use your mighty brain to understand why my interests are in doing this project asynchronously rather than using the already existing synchronous library.</p><h3 id="viber-rest-api"><u>Viber REST API</u></h3><p>In order to develop our Viber bot asynchronously we are going to use the Viber REST API which requires the following:<br><br>1.    <strong>An Active Viber account</strong>on a platform which supports bots (iOS/Android). This account will automatically be set as the account administrator during the account creation process.<br>2.    <strong>Active bot</strong> - Create the bot from <a href="https://partners.viber.com/login?returnUrl=%2Faccount%2Fcreate-bot-account">here</a>.<br>3.    <strong>Account authentication token</strong> - unique account identifier used to validate your account in all API requests. Once your account is created your authentication token will appear in the account’s “edit info” screen (for admins only). Each request posted to Viber by the account will need to contain the token.<br>4.    <strong>Setup account webhook</strong>– I hear you ask what a webhook is, let me explain you that too. A webhook (also called a web callback or HTTP push API) is a way for an application to provide other applications with real-time information. A webhook delivers data to other applications as it happens, meaning you get data immediately. Unlike typical APIs where you would need to poll for data very frequently in order to get it real-time.</p><h3 id="environment-setup"><u>Environment Setup</u></h3><p>Well those are what you need to begin with this development and let me also remind you again that I am using Python 3.8.1 for this demonstration. At this point I would also like to emphasize on the importance on using Python Virtual Environments as the main purpose of virtual environments is to manage settings and dependencies of a particular project regardless of other Python projects you are doing. If you are using an IDE such as PyCharm you need not worry about Virtual Environments much as virtualenv tool comes bundled with PyCharm, so the user doesn't need to install it and typically would create the virtual environment for you as you create a new project within it. (A huge thank you to Mr. Athphane who taught me these stuffs which made my life so easy at debugging since I started using them, and now it’s your turn to listen and learn).</p><h3 id="viber-message-flow"><u>Viber message flow</u></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-3.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"><figcaption>Don’t ask me to explain the above diagram just yet, I understood as much as you did, and you are not alone trust me</figcaption></figure><h3 id="the-project"><u>The Project</u></h3><p>For the ease of explanation, I am going to refer the modules on the <a href="https://github.com/baivaru/aiohttp_viber">repository</a> that I had publicized for the very purpose of this documentation. To begin with let me give you a brief explanation of the directory structure it contains, and the contents each directory has.</p><h3 id="directory-structure"><u>Directory Structure</u></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.baivaru.net/content/images/2020/04/image-4.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"><figcaption>Project root structure</figcaption></figure><p><strong>utils -</strong> The name utils define exactly what this directory is for. All the utilities that helps the application to work through is kept in this directory.<br><br><strong>api -</strong> api consists of modules that deals with viber API.<br><br><strong>database - </strong>This directory contains the modules that concerns the DB/RDBMS the application uses. For the purpose of this demonstration I am using TinyDB which is a lightweight document-oriented database just like MongoDB (which would be my preferred DBMS for larger scale projects) however you are free to use whichever you prefer.<br><br><strong>helpers -</strong> Helpers directory consists of modules that connects to 3rd party APIs/sources to help the application gather the data it requires. For this demonstration we scrape data and the scraper module is present in this directory.<br><br><strong>webserver - </strong>This directory consists of the modules that are required for the webhook server that the application uses.<br><br><strong>working_dir - </strong>This directory basically consists of the config.ini file/s. Also, if there are temporary files that are generated by the application, we tend to leave them within this directory at the course of their existence.</p><h3 id="modules"><u>Modules</u></h3><p><u>Commonly Shared Variables</u><br>Now that you have a good idea of the directory structures let’s begin with the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/common.py#L5">ViberCommon()</a> defined on <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/common.py">common.py</a> located under <a href="https://github.com/baivaru/aiohttp_viber/tree/master/viber/utils">/viber/utils/</a>.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-6.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>The purpose of this module is for sharing commonly used variables across the application such as the API keys, webhook URL and etc. You might have already noticed that I am loading the values these variables share from an external source. We load these variables from external - as a best practice since we do not want to hard code them to our program no do, we want to share our secret keys, passwords, etc. with the source as a best practice.</p><p>The configuration file - <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/working_dir/config.ini.sample">config.ini</a>(above mentioned external source) located under the <a href="https://github.com/baivaru/aiohttp_viber/tree/master/viber/working_dir">viber/working_dir/</a>consists of sections, each led by a [section] header, followed by key/value entries separated by a specific string (= or : by default). By default, section names are case sensitive, but keys are not. Leading and trailing whitespace is removed from keys and values. Values can be omitted; in which case the key/value delimiter may also be left out. Values can also span multiple lines, as long as they are indented deeper than the first line of the value.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-8.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>For this portion of the document we will only concentrate on keys which are under first section - [viber].</p><p>These are the keys that are required for setting up our application for receiving updates i.e. callback data from Viber.       <br><br><strong>auth_token -</strong> as explained earlier unique account identifier used to validate your account in all API requests.<br><strong>webhook_uri -</strong> the URL for webhook.<br><strong>name - </strong>the name you would like to give your bot.<br><strong>avatar - </strong>in simpler terms is the bloody profile picture for the bot.<br><br>To parse the configurations from this .ini file we use the library configparse. And this is done on <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/__init__.py">__init__.py</a>for <a href="https://github.com/baivaru/aiohttp_viber/tree/master/viber/utils">viber/utils/</a>.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-9.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><u>Web Server for webhook</u><br>Now that we have the required keys and other settings loaded up and shared, let’s look at setting up the webserver for webhook.</p><p>It is important at this point that I also highlight for “security” reasons - only URLs with valid and official SSL certificate from a trusted CA is allowed by Viber for webhook. In case you are on a linux environment certbot might be your best friend to get a valid SSL certificate, however if you are using windows like I do you could make use of Ngrok as a reverse proxy tunnel for your project. We are going to run our python webserver on port 8080 therefore while you create the ngrok tunnel, point it to port 8080 of the local host and the tunnel address ngrok provide would be the webhook URL that is on the config.ini file.</p><p>Note: We are not going to discuss either on how to setup certbot no ngrok within this demonstration however you could refer <a href="https://ngrok.com/docs">this tutorial for ngrok</a> and <a href="https://certbot.eff.org/lets-encrypt/ubuntubionic-webproduct">this one for certbot</a>.</p><p>For our webserver we are going to use the library aiohttp. I hear you ask why not flask or Django - The key part of the aiohttp framework is that it is asynchronous, it can concurrently handle hundreds of requests per second without too much hassle. In comparison to frameworks such as flask, it’s incredibly performant. Use your mighty brain once again to conclude why in this case I chose aiohttp over other famous frameworks.<br><br>aiohttp server is built around aiohttp.web.Application instance. It is used for registering startup/cleanup signals, connecting routes etc.<br><br>You will hear me talk about handlers for aiohttp, a handler is a callable that accepts a single Request argument and returns a web Response derived instance.</p><p>A handler can also be a coroutine, in which case aiohttp.web will await the handler.</p><p>Handlers are connected to the web Application via routes. Routes can be registered using route tables and route decorators.</p><p>Our web application for the webhook is defined (line 6 of the below snippet) on webserver directory package (<a href="https://github.com/baivaru/aiohttp_viber/tree/master/viber/utils/webserver">viber/utils/webserver/</a>) as mentioned earlier.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-12.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>The routes that we require for the web server are defined on <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/webserver/routes.py">routes.py</a>under the same directory. (Handler – Line 9 of the below snippet, defining route table – Line 5 of the below snippet, registering route – Line 8 of the below snippet and adding the routes to the web app line 7 of the above snippet)</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-14.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>We will come back to explaining the handler mentioned here later within the project, for now let’s move forward with running the web server that we had defined. We do this on our main application module package (<a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/__main__.py">viber</a>).</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-15.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>On the coroutine main() that our asyncio loop (line 35-37) runs, you could see that I have used an app runner (line 13-15) to start the web application. At a normal scenario - with aiohttp you would do run_app() to start a web application however run_app() provides a simple blocking API for running an application.</p><p>For starting the application asynchronously or serving on multiple HOST/PORT, app runners exists. As you could see from the above snippet within the same coroutine we are doing a lot more than just starting the web app, we are also starting schedulers to collect data for the helpers that application require and DB initializing for the first run (line 20-31).</p><p>After starting the app runner, we also wait for a good 2 seconds to give the application enough time for the Viber API to be available to set the webhook (line 17). Setting the webhook will be done by calling the set_webhook Viber API endpoint.</p><p>Once a set_webhookrequest is sent, Viber will send a callback to the webhook (in this case our web server) to check its availability and return a response to the user. These callback data (request) are what the <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/webserver/routes.py#L9">root_route_post_handler</a>(request)defined on our routes for the web server receives and handles.</p><p>In case the webhook is offline Viber will re-try to deliver the callback until HTTP status code 200 is received. There will be a retry attempt after 5 seconds, and then another after 1 minute and 5 seconds.</p><p>Any data that is posted to Viber API i.e. calling the Viber API endpoints from our program is handled <a>by the function </a><a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/request_sender.py#L22">post(*args)</a> defined under the module <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/request_sender.py">ViberApiResquestSender()</a>.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-16.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><br><a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/request_sender.py#L22">post(*args)</a> function expects the following arguments:<br><br><strong>uri - </strong>Instance attribute name for the respective Viber API end point defined under the class ViberMessageTypes.<br><strong>payload - </strong>The data which you are posting to the API. Payloads used by the application are defined under the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>.</p><p>As already explained once we set our webhook, 1-on-1 conversation with our bot account will become available thus we will receive callback data from Viber when there is an update. To understand further more on how our application handles these callback data lets jump back to the <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/webserver/routes.py#L9">root_route_post_handler</a>(request) defined under our routes for the web server.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-17.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><br><u>Validation of Data Received</u><br>Each callback will contain a signature on the JSON passed to the callback. The signature is HMAC with SHA256 that will use the authentication token as the key and the JSON as the value. The result will be passed as HTTP Header X-Viber-Content-Signature. We could use this to validate if the received callback data is from a valid source or otherwise bogus (line 12, 15 and <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/request_sender.py#L30">validate_signature function</a>(*args) from <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/request_sender.py">ViberApiResquestSender()</a>module to calculate and compare the signatures as explained).</p><p><u>Handlers</u>:<br>When the received data is confirmed from a valid source we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/hadlers.py#L15">on_event(*args)</a>from <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/hadlers.py">ViberHandlers()</a>module. Basically, each callback data that is received from Viber contains a parameter called event - which tells us what kind of an update it is and the respective event handler tells the application what needs to be done when a certain update is received.</p><p><a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/hadlers.py#L15">on_event(*args)</a>function expects the callback data from Viber in JSON format(We collect these data on <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/webserver/routes.py#L10">Line 10</a> of the <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/webserver/routes.py">routes.py</a>) and this function checks for the following events and assigns the task to its respective event handler function:<br><br><strong>Subscribed -</strong> Before the bot can send messages to a user, the user will need to subscribe to the bot account (Viber tends to call their bots, Public Accounts).<br><strong>Unsubscribed -</strong> The user will have the option to unsubscribe from the Public Account. This will trigger an unsubscribed callback.<br><strong>Message - </strong> This event is received when the bot account receives any form of an incoming message.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-19.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Each of the below explained handlers expects the same callback data from Viber in JSON format as received by <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/hadlers.py#L15">on_event(*args)</a>function. Ok, now let’s go through each handler one by one and investigate what they do:</p><h3 id="on_subscription-args-"><u>on_subscription(*args)</u></h3><p>When the received event is subscribed, we call this handler. The callback data received would be as below:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-20.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-21.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Viber recommends that we record the subscriber ID of each subscriber, as there’s no API for fetching all subscriber IDs for a bot (<a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/hadlers.py#L38">Line 38</a> of handlers.py we do this, it’s important we save these data – god knows what, you might even want to send a broadcast message to all your subscribers and these data comes in handy at such a situation).<br><br><u>Text Message (Welcome message)</u><br>Also, we do send a welcome message to the new user/subscriber. To do this we will first prepare the message object that needs to be posted to Viber.<br>In this case the welcome message is a text message the posted raw data to Viber API should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-22.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p></p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-23.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>To generate a text message object with above formatted raw data we call <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L32">text_message</a>(*args) function from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>with the following arguments:</p><p>receiver: Unique Viber user id for receiver<br>text: text to include with the body of the message<br>tracking_data:  Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message, the keyboard to include</p><p><u>General Parameters for Message Data</u><br>At this point, before we move any further lets also briefly look at available general parameters for the data that we post when we send a message (These parameters are common for all the message types i.e. text, media and etc)</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-24.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Each API request must include an HTTP Header called X-Viber-Auth-Token containing the account’s authentication token however the message objects that are returned from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a> does not contain the auth token. Therefore for each message object we create either it is a text message or otherwise - we add the token and do a bit of housekeeping and final preparation of the payload by calling <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L176">prepare_payload</a>(*args) function from <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py">ViberCommands()</a>module. This function expects the following arguments:</p><p>message: message object<br>sender_name: senders name to display (you could leave this as None if you are defining sender)<br>sender_avatar: The sender’s avatar URL (you could leave this as None if you are defining sender)<br>sender: a dictionary with sender’s name and avatar (you could leave this as None if you are defining senders name and avatar with the above arguments)<br>receiver: Unique Viber user id for receiver<br>chat_id: you could leave this as None, it is used for internal usage.</p><p>Once the required payload is ready, we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/request_sender.py#L22">post(*args)</a>defined under the module <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/request_sender.py">ViberApiResquestSender()</a> with arguments ‘send_message’ and the prepared payload to send the welcome message. This would be the same process that we will follow within the app to send any type of message.</p><h3 id="on_unsubscribed-args-"><u>on_unsubscribed(*args)</u></h3><p>If the received event is unsubscribed, we call this handler. Received callback data would be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-27.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-28.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>We already know that the bot can only send messages to a user who is subscribed to it, therefore when once a user unsubscribes we remove that particular users details from our users collection from the DB (<a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/hadlers.py#L43">Line 43</a> of handlers.py).</p><h3 id="on_message-args-"><u>on_message(*args)</u></h3><p>If the received event is a message, we call this handler.<br><br>For now, we are only going to deal with the text messages that are received. A text message could be a command that was sent to the bot, or otherwise a response by a user to a conversation the bot has started (tracked using tracking data).</p><p><u>Validating Text (Bot Commands)</u><br>The main purpose in adding more than one bot command for this demonstration is to demo the different types of messages the bot can send, and this is where the helper modules come in play - to collect some real data with which we can demo the message types. Either way I do not plan to go in depth detailed explanation on helper modules since most of these modules are scrapers and it is for a different tutorial. Also, I hope and pray that our scraping magician and idiot Managing Director - Mr. PhoenixAtom writes a separate article on scraping.</p><p>As mentioned earlier for now we will only deal with text messages that are received. If the received text message does not contain tracking data we call the <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L18">text_validator(*args)</a>function from <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py">ViberCommands()</a>module. This function expects the same <a>callback data from Viber in JSON format as received by </a><a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/hadlers.py#L15">on_event(*args)</a> function. Purpose of this function is to differentiate the commands to other text messages. We use the prefix “!” for commands, meaning we assume any text message starting with “!” as a command (<a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L21">Line 21</a> of the commands.py file). When the received text is a command we then call <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L24">commands_checker(*args)</a>from <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py">ViberCommands()</a>module. This function expects the following arguments:</p><p>command: String value of the command.<br>receiver: Unique Viber user id for receiver</p><p>This function basically checks the received commands and perform respective relevant tasks according to the given/received command.<br><br><u>Rich Media Message / Carousel Content Message</u><br>The Rich Media message type allows sending messages with pre-defined layout, including height (rows number), width (columns number), text, images and buttons.</p><p>Commands (<a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L26">bills</a>, <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L36">resolutions</a>, <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L46">emergency_debates</a>, <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L56">approvals</a> and <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/commands.py#L66">others</a>) formulates Rich Media Messages.</p><p>Below is an example of a Carousel Content Message, that allows a user to scroll through a list of items, each composed of an image, description and call to action button.</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-32.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Each item on the list shown to the user is a button in the Rich Media message’s “Buttons” array. Sending one button is also permitted. The parameters for Rich Media message and its buttons are also used for Keyboards.</p><p>Also, you need to keep in mind that each button is limited to a maximum of 7 rows on Rich Media messages, and that forwarding is not supported for Rich Media messages.</p><p>Posted raw data to Viber API for Rich Media Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-35.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-36.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><br>Within our application to generate rich media messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L49">rich_media(*args)</a> from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver: Unique Viber user id for receiver<br>data_list: list of data that needs to be included in the buttons for rich media messages.</p><p>For this demonstration to formulate these messages we scrape data from majilis.gov.mv and this is handled by the helper module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/database/majilis_collection.py#L4">MajilisCollection()</a>. Since data scraping in real time is slow, we use <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/__main__.py#L20">schedulers</a> to scrape data the mentioned data in given <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/__main__.py#L21">schedules</a> and <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/database/majilis_collection.py#L6">record</a> them in our DB i.e. when ever a concerned command for the data is received we <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/database/majilis_collection.py#L19">collect</a> them from DB and send them for a faster response.</p><p><u>Picture message<br></u>For the purpose of this demonstration I am using <a href="https://unsplash.com/documentation">unsplash.com</a> (helper module: <a href="https://github.com/eyaadh/aiohttp_viber/blob/b2beb157d8e161b1e86c77405dda3a749c348b7e/viber/utils/helpers/unsplash.py#L5">UnsplashPhotos()</a>) to get random pictures i.e. to show how we can formulate and send a picture message (command: <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L92">photo</a>).<br><br>Posted raw data to Viber API for Picture Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-37.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-38.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Within our application to generate picture messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L153">picture_message(*args)</a> from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:</p><p>receiver: Unique Viber user id for receiver<br>text: lets call this the caption for the picture we are      sending<br>media: URL of the image (JPEG)<br>thumb: URL of a reduced size image (JPEG)<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message, the keyboard to include</p><p><u>Video Message</u><br>For the purpose of this demonstration I am using <a href="https://pixabay.com/api/docs/">pixabay.com</a> (helper module: <a href="https://github.com/eyaadh/aiohttp_viber/blob/b2beb157d8e161b1e86c77405dda3a749c348b7e/viber/utils/helpers/pixabay.py#L6">PixbayVideos()</a>) to get random videos i.e. to show how we can formulate and send a video message (command: <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L109">video</a>).</p><p>Posted raw data to Viber API for Video Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-39.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-40.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Within our application to generate video messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L173">video_message(*args)</a>from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver: Unique Viber user id for receiver<br>media: URL of the video (MP4, H264)<br>size:  Size of the video in bytes<br>thumbnail:  URL of a reduced size image (JPEG)<br>duration:  Video duration in seconds; will be displayed to the receiver<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message,      the keyboard to include</p><p><u>File Message</u><br>To demonstrate file message objects, we scrape data from gazette.gov.mv (this is done by the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/database/gazette_collections.py#L4">GazetteCollection()</a>). File messages are demonstrated with the command <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L76">gazette</a>. The trailing process for the command also makes use of keyboards and tracking data however we will come back to these two topics later within the documentation, for now we will only concentrate on the <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L24">portion of file messages</a>.</p><p>Posted raw data to Viber API for File Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-41.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-42.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Within our application to generate file messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L111">file_message(*args)</a>from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver: Unique Viber user id for receiver<br>url:  Size of the file in bytes<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message,      the keyboard to include</p><p>You might have noticed that we do not feed in size parameter for the function though it is required by the raw data. I did this since some of the web servers tend not to return proper headers with content-length which basically is the file size, i.e. the application will download the file to a temporary location and calculates its size on its own.<br><br><u>Location message</u><br>To demonstrate location messages, I have used FourSquare REST API – and its handled by the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/helpers/foursqure.py#L5">FourSquare()</a>. I had so much fun writing this part of the demonstration, as beautiful FourSquare’s REST API is it’s for anther tutorial. <a>The trailing processes of command </a><a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a> for our application make use of <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L92">location messages</a>.</p><p>Posted raw data to Viber API for Location Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-43.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-44.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><a>Within our application to generate a location messages we call the function </a><a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L194">location_message(*args)</a> from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver: Unique Viber user id for receiver<br>lat: latitude<br>lon: longitude<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message, the keyboard to include</p><p><u>Contact message</u><br>The trailing processes of command <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a> for our application also make use of <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L101">contact message</a>.<br><br>Posted raw data to Viber API for Contact Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-45.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-46.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p><br>Within our application to generate a contact messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L233">contact_message(*args)</a>from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver:  Unique Viber user id for receiver<br>name:  Name of the contact<br>contact: Phone number of the contact<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message, the keyboard to include</p><p><u>Sticker message</u><br>The trailing processes of command <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a> for our application also make use of <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L35">sticker_message</a>.<br><br>Posted raw data to Viber API for Sticker Messages should be as the following example:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-47.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-48.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>Within our application to generate a contact messages we call the function <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/msg_types.py#L215">sticker_message(*args)</a>from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/msg_types.py#L7">ViberMessageTypes()</a>. This function expects the following arguments:<br><br>receiver:  Unique Viber user id for receiver<br>sticker_id:  Unique Viber sticker ID<br>tracking_data: Allow the account to track messages and user’s replies. Sent tracking data value will be passed back with user’s reply<br>keyboard: if you are sending a keyboard with the message, the keyboard to include</p><p><u>Keyboards</u><br>The Viber API allows sending a custom keyboard using the send_message API, to supply the user with a set of predefined replies or actions. The keyboard can be attached to any message type or sent on its own. Once received, the keyboard will appear to the user instead of the device’s native keyboard. The keyboards are fully customizable and can be created and designed specifically for the account’s needs. The client will always display the last keyboard that was sent to it.</p><p>As you have already noticed from the above explained message types and their respective message objects, keyboards can be attached to any message type and be sent and displayed together.</p><p>Following is an example of the posted raw data to Viber API to send a keyboard with a text message:</p><figure class="kg-card kg-image-card"><img src="https://blog.baivaru.net/content/images/2020/04/image-49.png" class="kg-image" alt="An In-Depth Guide: Baivaru Viber Bot Skeleton"></figure><p>To demonstrate the same on our application I have used predefined keyboards on the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/keyboards.py#L1">ViberKeyboards()</a>. <a>Commands </a><a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L76">gazette</a>, <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a> and <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L140">admin</a> make use of keyboards.<br><br><u>Tracking Data</u><br>Basically, tracking data allow the bot to track messages and user’s replies, in short to start conversation style messaging we put a tracker on the message sent so that the reply/response by the user can be tracked.</p><p>I have demonstrated this with the commands <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L76">gazette</a>, <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a>and <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L140">admin</a>however I am only going to explain you how the command <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a>works.</p><p>Basically, the idea of this module is to recommend you with venues near you, when once you send your current location as an attachment (location attachment). As you send the command the bot will respond requesting you to send back the location, as it sends this text message it also adds the <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L128">tracking data – “foursquare”</a> i.e. the response/reply you send to the bot will have the same tracking data.</p><p>When once a message received with tracking data <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/hadlers.py#L46">on_message(*args)</a>handler assigns these data to the function <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/tracking_data.py#L16">attend(*args)</a>from the module <a href="https://github.com/baivaru/aiohttp_viber/blob/d63b4abee7c817cf062bbe3217b461cf533c0d27/viber/utils/api/tracking_data.py#L11">ViberTrackingDataAttendant()</a>. This function expects the following arguments:</p><p>tracking_data: tracking data that was assigned to the received message.<br>data: callback data from Viber in JSON format as received by <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L15">on_event(*args)</a>function.</p><p>For the command <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/commands.py#L127">nearme</a> we first <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L33">check</a> if the received message type is a location message, if not we send a sticker message followed by a text message which tells that the user that the bot is expecting a location message not a text message, again we assign tracking data to this response as well so that the data that is received can be validated. If we do not assign the tracking data to this message the conversation track is broken unless you have a better logic in place to check for them data. As you can see this can run in a lengthy loop and to negate and break it we have also placed the command - <a href="https://github.com/baivaru/aiohttp_viber/blob/master/viber/utils/api/tracking_data.py#L34">!negatenearme</a>. which would basically send a text message without any tracking data.</p><h3 id="final-thoughts"><u>Final Thoughts</u></h3><p>Well that pretty much concludes the project as we have already covered most of what Viber REST API has to offer. At least with which you could build a decent Viber bot. There are a few more API endpoints with which you could get user details and account details of the bot, which I would rather prefer covering on a different project.</p><p>Now let me end up this doc with a question and a statement, do I think this could be done any better? Definitely, it can be done better and I never get a project of mine totally finished – not because I am done reaching the end goals, but I learn something new everyday and find a better way of doing what I had done so far and I believe its your turn to make it better and for me to learn from you.</p>]]></content:encoded></item><item><title><![CDATA[Baivaru Talks #1]]></title><description><![CDATA[Warning: It's a very long post.]]></description><link>https://blog.baivaru.net/baivarutalks-1/</link><guid isPermaLink="false">5e77986fcc7d5d37ee336b75</guid><category><![CDATA[Ramblings]]></category><dc:creator><![CDATA[Baivaru]]></dc:creator><pubDate>Sun, 22 Mar 2020 18:14:44 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1504639725590-34d0984388bd?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=2000&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1504639725590-34d0984388bd?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=2000&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" alt="Baivaru Talks #1"><p>Sitting on my bed in a very uncomfortable position to make sure my internet stays stable while I write this. I don't like writing drafts, so I just do it on the site and click Publish. So yeah, it's going to be a <strong>ramble </strong>+ shameless <strong>plug </strong>+ <strong>Q&amp;A</strong><br><br>Warning: This is going to be very <strong>long</strong>. Sit down. We are going to do this twice a year to answer any questions and provide an update on our team. This is a very <strong>detailed </strong>blog post.<br><br>As much as I don't want to talk about it, the hot topic right now is Coronavirus. I am going to point out a few things before anything else. <br>1. Like I am doing, <strong>stay home, stay inside.</strong> <br>2. Please, for the love of god, <strong>follow the advice from the relevant authorities</strong>. <br>3. <strong>Wash your hands regularly</strong>, <strong>don't touch your face and mouth</strong>, practice <strong>#SocialDistancing</strong> and stay safe.<br>4. Stop wasting time on Netflix, come visit BaivaruMedia<br><br>Why <strong><a href="https://t.me/BaivaruMedia">BaivaruMedia </a></strong>over Netflix? You don't need your credit card to check out our stuff. Also, we provide loads of stuff! Have an urgent request? Just holler at one of the admins in the request group. We are mostly very friendly and accommodating. That is until you become an asshole and stop following the community rules and guidelines. <br><br>What else do we have? There is <a href="https://t.me/MvEargasm"><strong>Baivaru Music</strong></a>, <a href="https://t.me/BaivaruVaahaka"><strong>Baivaru Vaahaka</strong></a>, <a href="https://t.me/BaivaruWares"><strong>Baivaru Software</strong></a>, <strong><a href="https://t.me/BaivaruAnime">Baivaru Anime</a></strong>, <a href="https://t.me/BaivaruGames"><strong>Baivaru Games</strong></a>, <a href="https://t.me/BaivaruTutorials"><strong>Baivaru Tutorials</strong></a> and even a group to discuss and ask tech related questions, <a href="https://t.me/BaivaruTechTips"><strong>Baivaru Tech Tips</strong></a>.<br><br>Do we get paid to do this? <strong>No</strong>, we don't get paid. This is just a hobby and way of community service for us. Most of the things we do are to learn something or to demonstrate the usage of something. <br><br>What are we working on now? We are currently working on several projects. The most promising include a <strong>machine learning</strong> powered bot that recommends you movies based on your likes and preferences. One of our newest addition to the team, Ashraq is working hard on it. Another promising project is the <strong><a href="https://kodi.tv">Kodi</a></strong> plugin being developed by Iyad that streams the movies on Baivaru Media directly through Kodi Media Player. We are also working on several <a href="https://facebook.com/BaivaruEsports"><strong>Esports</strong></a> projects and Youtube related projects. Hammad is building our Esports roster and getting ready for tournaments and events. Esports CsGo roster is about to be announced later this year, hopefully around June. <br><br>You want to learn how we build our bots and automate things? Sure, we will be making some of our bot skeletons including Telegram and Viber, opensource very soon with a detailed tutorial on how to build modules on top of it. <br><br>Who are the team members as of now? I'll make a list for you to easily understand. There are a lot of people, but I feel that everyone of them deserves the recognition, so here goes.<br><br>1. <strong>Aruham</strong> - Managing Director: Currently working on maintaining requests and overseeing all projects, channels, teams. Codes a bit here and there. <br>2. <strong>Iyad</strong> - CEO: Currently working on Kodi plugin for Baivaru Media, Viber API and <a href="https://t.me/Megadlbot"><strong>Megatron</strong></a>, Seedr, <a href="https://t.me/MegaStreamerBot"><strong>MegaStreamerBot</strong></a>, Kittenz and several other prominent projects.<br>3. <strong>Athfan</strong> - CTO: Currently working on Baivaru Media Bot and Baivaru Bot. Keeps adding new modules to his <strong>opensource userbot</strong> available <a href="https://github.com/athphane/userbot"><strong>here</strong></a>.<br>4. <strong>Yushau</strong> - COO: The dude hasn't been seen for months but he comes around every now and then to remind people of deadlines and whatnot. Spends most of his time on Witcher 3 for some reason. <br>5. <strong>Hammadh</strong> - Director of Esports: Currently working on managing several Esports rosters, helping out the graphics team and also request handling.<br>6. <strong>Suhail</strong> - Director of Technical Uploads: Currently working on the Software channel, Tutorials channel and Gaming channel.<br>7. <strong>Ashraq </strong>- Director of Machine Learning: Currently working on perfecting the recommendation model for Movie Recommend Bot and also working on Dhivehi spell checker. <br>8. <strong>Axyaah</strong> - Director of Music: Currently working on BaivaruMusic channel and keeping us entertained at HQ<br>9. <strong>Aiham</strong> - Director of Creative Design: Currently quarantined in Fun Island, was working on several logos and graphics projects. <br>10. <strong>Nishfan</strong> - Moderator and Technical Uploads: Currently working on Tutorials channel<br>11. <strong>DragonSlayer </strong>- Moderator at BaivaruRequests: No idea what his real name is but the dude helps out in the request group. <br><br>I would like to thank each and every member of our team, for their hard work, enthusiasm and positive attitude. I would also like to thank you, the readers, the subscribers and the followers. Without you we would just be any other channel. Thank you for your continuous support and cooperation.<br><br>I remind everyone to continue following the instructions of the authorities during these unsettling days. Don’t go out unless absolutely necessary and make sure to follow good hygiene. A huge shout out from Baivaru to all those that are working hard during these days to keep us safe. Thank you!<br><br>Do give a share and let your family and friends know all about Baivaru!</p>]]></content:encoded></item></channel></rss>