<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dmytro Filipenko</title>
    <description>The latest articles on DEV Community by Dmytro Filipenko (@dmfilipenko).</description>
    <link>https://dev.to/dmfilipenko</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F191562%2Fe89ed4d0-7947-4024-b27d-b8e88274bdfd.jpg</url>
      <title>DEV Community: Dmytro Filipenko</title>
      <link>https://dev.to/dmfilipenko</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dmfilipenko"/>
    <language>en</language>
    <item>
      <title>Small automation with Telegram Bot for price analytics</title>
      <dc:creator>Dmytro Filipenko</dc:creator>
      <pubDate>Wed, 22 Jul 2020 02:06:46 +0000</pubDate>
      <link>https://dev.to/dmfilipenko/small-automation-with-telegram-bot-for-price-analytics-5do1</link>
      <guid>https://dev.to/dmfilipenko/small-automation-with-telegram-bot-for-price-analytics-5do1</guid>
      <description>&lt;p&gt;How much time did you deal with a situation when realtors are trying to cheat on you? When do they announce prices, which is much higher than it should be?&lt;/p&gt;

&lt;p&gt;Right now(July 2020), I'm in position when with my spouse, we start looking for a new apartment. Here in Singapore, the primary source of rent flats – it's PropertyGuru. &lt;/p&gt;

&lt;p&gt;Luckily for us, they are providing some insights about price history. But, just looking at a list of prices, it's quite hard to guess what is an average price. For better perception, I've decided to visualize this table. Box plot would ideal for this purpose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--G7HXAE41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Michelsonmorley-boxplot.svg/600px-Michelsonmorley-boxplot.svg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--G7HXAE41--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://upload.wikimedia.org/wikipedia/commons/thumb/f/fa/Michelsonmorley-boxplot.svg/600px-Michelsonmorley-boxplot.svg.png" alt="Box plot"&gt;&lt;/a&gt;&lt;/p&gt;
Example from Wikipedia



&lt;p&gt;It's showing the distribution of your numerical data. &lt;/p&gt;

&lt;p&gt;So. How it works.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I'm sending a link on any apartment&lt;br&gt;
&lt;a href="https://www.propertyguru.com.sg/listing/22013261/for-rent-the-seawind-telok-kurau"&gt;https://www.propertyguru.com.sg/listing/22013261/for-rent-the-seawind-telok-kurau&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And in 10-20 seconds I get a box plot with a chart.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Super simple but very efficient. It's very easy to understand if the mean price is 2k and realtor is asking 3k, it's a sign that someone's trying to make it more expensive than it really is.&lt;/p&gt;

</description>
      <category>telegram</category>
      <category>bot</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How I build Telegram Bot for budget and what lessons I have learned.
</title>
      <dc:creator>Dmytro Filipenko</dc:creator>
      <pubDate>Thu, 16 Jul 2020 03:51:30 +0000</pubDate>
      <link>https://dev.to/dmfilipenko/how-i-build-telegram-bot-for-budget-and-what-lessons-i-have-learned-288o</link>
      <guid>https://dev.to/dmfilipenko/how-i-build-telegram-bot-for-budget-and-what-lessons-i-have-learned-288o</guid>
      <description>&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;For the past few weeks, I was working on a small side project – home budget in Google Spreadsheets, which I can easily add through Telegram Bot. &lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;
      &lt;div class="ltag__twitter-tweet__media ltag__twitter-tweet__media__video-wrapper"&gt;
        &lt;div class="ltag__twitter-tweet__media--video-preview"&gt;
          &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AYfWx3VQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/ext_tw_video_thumb/1277465462012403712/pu/img/TyH-y4Wd0AfNC0-q.jpg" alt="unknown tweet media content"&gt;
          &lt;img src="/assets/play-butt.svg" class="ltag__twitter-tweet__play-butt" alt="Play butt"&gt;
        &lt;/div&gt;
        &lt;div class="ltag__twitter-tweet__video"&gt;
          
            
          
        &lt;/div&gt;
      &lt;/div&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nXaYZC_D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/816392434305241088/tG9pIt33_normal.jpg" alt="Filipenko profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Filipenko
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/dmfilipenko"&gt;@dmfilipenko&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Finally, I got some results. Still, a lot of stuff to improve. Allow creating a tables by your own, change records, but for my purpose, it's quite enough. 
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      04:56 AM - 29 Jun 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1277465910505140224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-reply-action.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1277465910505140224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      1
      &lt;a href="https://twitter.com/intent/like?tweet_id=1277465910505140224" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-like-action.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
      6
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  Why did I decide to go with this stack?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Google Spreadsheets&lt;/strong&gt; – compelling and extensible. &lt;br&gt;
You can easily set up a massive variety of calculations and aggregations. It's an example of one of my formulae, which I'm using to calculate expenses per month per selected category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SUM(
     IFERROR(
         FILTER(
            'Expenses'!D2:D,
            'Expenses'!C2:C =
            CELL(
                "contents",
                INDIRECT(
                     CONCATENATE(
                        "A",
                        ROW(

                        )
                    )
                )
            )
        ),
        0
    ),
    B1 = 'Expenses'!A2:A
)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So, before I started. I've created one document with three spreadsheets: &lt;strong&gt;expenses&lt;/strong&gt;, &lt;strong&gt;category of expenses&lt;/strong&gt;, and &lt;strong&gt;subscriptions&lt;/strong&gt;. Then I've added all these aggregation formulas to calculate expenses by months automatically. And at the beginning, I've manually added all rows by opening google spreadsheets, usually from mobile, less often from the desktop. &lt;/p&gt;

&lt;p&gt;But overall, this process took so much time, open google spreadsheet app, select &lt;em&gt;expenses sheet&lt;/em&gt;, and start filling new row. It's working quite slowly from mobile.&lt;/p&gt;

&lt;p&gt;So I've decided to automate this process somehow. First I tried to use &lt;a href="https://developers.google.com/apps-script"&gt;Google Apps Script&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Google Apps Script allows you to get access to your spreadsheets, manipulate rows and columns. You could use your Javascript to write your &lt;em&gt;Apps Script&lt;/em&gt;. It's a quite good solution, but I wanted to have more flexibility. I didn't want to operate in the context of &lt;em&gt;Google App Script&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;I went with a Telegram Bot API. To write it more easily &lt;a href="https://github.com/telegraf/telegraf"&gt;Telegraf&lt;/a&gt; can help you to do this. &lt;/p&gt;

&lt;p&gt;I first challenge was how to add Google Auth to a telegram bot. &lt;a href="https://developers.google.com/identity/protocols/oauth2"&gt;Google OAuth 2.0 documentaion&lt;/a&gt; provide you such images &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v8w7fDUY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1nqhs2jn5g3p0tik6vdg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v8w7fDUY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1nqhs2jn5g3p0tik6vdg.png" alt="Google Auth workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me make it real simple.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;I generate a google authorization link, with callback URL among query params, it's done by google SDK.
Example: 
&lt;strong&gt;&lt;a href="https://accounts.google.com/signin/oauth/oauthchooseaccount?access_type=offline&amp;amp;state=9999999&amp;amp;prompt=consent&amp;amp;scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets&amp;amp;response_type=code&amp;amp;client_id=105404325697-1fs9rpeuhah4u4h8dfm4ma0p2ckpclb5.apps.googleusercontent.com&amp;amp;redirect_uri=https%3A%2F%2Fyour.url%2Foauth2callback&amp;amp;o2v=2&amp;amp;as=asda123casa&amp;amp;flowName=GeneralOAuthFlow"&gt;https://accounts.google.com/signin/oauth/oauthchooseaccount?access_type=offline&amp;amp;state=9999999&amp;amp;prompt=consent&amp;amp;scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fspreadsheets&amp;amp;response_type=code&amp;amp;client_id=105404325697-1fs9rpeuhah4u4h8dfm4ma0p2ckpclb5.apps.googleusercontent.com&amp;amp;redirect_uri=https%3A%2F%2Fyour.url%2Foauth2callback&amp;amp;o2v=2&amp;amp;as=asda123casa&amp;amp;flowName=GeneralOAuthFlow&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Then user follow this link, grant permission or deny&lt;/li&gt;
&lt;li&gt;Google redirects me back to &lt;code&gt;redirect_uri&lt;/code&gt; which was part of generated URL&lt;/li&gt;
&lt;li&gt;On a server, I handle authorization token or error status and save it to DB.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why it was most complicated part for me? I've spent a few days to realize how to connect Google Oauth + Telegram + NodeJS server. How to save tokens to DB, and exact tokens need to be saved. &lt;/p&gt;

&lt;h3&gt;
  
  
  Server
&lt;/h3&gt;

&lt;p&gt;I'm using &lt;strong&gt;fastify&lt;/strong&gt; as a web server, coz I need only API, and &lt;strong&gt;fastify&lt;/strong&gt; doing a good job. For hosting, I've used &lt;strong&gt;Heroku&lt;/strong&gt;. It allow me to reduce DevOps work. As far I'm using the free plan, they keep my server in a sleep mode if the server not doing any activities for 15 minutes. So, for my case, it's not a problem, but when I'm adding new expenses, I need to wait for 30-40 sec while Heroku woke up a server. For DB – mongo, I need to save user, all metadata for user, such as &lt;code&gt;documentId&lt;/code&gt;, &lt;code&gt;sheetName&lt;/code&gt; and some service information. &lt;br&gt;
With Heroku is very easy to add monitoring, logging, error aggregation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Telegram API
&lt;/h3&gt;

&lt;p&gt;For working with TelegramBOT API I used &lt;a href="https://github.com/telegraf/telegraf"&gt;Telegraf&lt;/a&gt;. It's quite powerful, but a lack of documentation potentially could be a problem.&lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nXaYZC_D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/816392434305241088/tG9pIt33_normal.jpg" alt="Filipenko profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Filipenko
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/dmfilipenko"&gt;@dmfilipenko&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Before this, I tried it once-or-two, and I wasn't so amazed. But with the Expense task, I discover a few things. &lt;br&gt;1. First of all, NodeJS wrapper for a telegram API. &lt;br&gt;&lt;a href="https://t.co/Fors4rLlOd"&gt;telegraf.js.org&lt;/a&gt;&lt;br&gt;The functionality of this library is quite powerful but lack of documentation.
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      02:54 AM - 22 Jun 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1274898622031642624" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-reply-action.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1274898622031642624" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      3
      &lt;a href="https://twitter.com/intent/like?tweet_id=1274898622031642624" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-like-action.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
      0
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;
&lt;br&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nXaYZC_D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/816392434305241088/tG9pIt33_normal.jpg" alt="Filipenko profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Filipenko
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="comment-mentioned-user" href="https://dev.to/dmfilipenko"&gt;@dmfilipenko&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P4t6ys1m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Let me clarify. Documentation for a telegraf is quite good, in terms of what you can use. But, for me, it's more important not just what, but how you can use it. Examples, where each method could be used, it's also a significant part of proper documentation.
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      05:30 AM - 22 Jun 2020
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1274937722734428160" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-reply-action.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1274937722734428160" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-retweet-action.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      0
      &lt;a href="https://twitter.com/intent/like?tweet_id=1274937722734428160" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="/assets/twitter-like-action.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
      0
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;
&lt;br&gt;
For some questions, I used examples to understand how it's working. If you don't want to invent everything from scratch you can use &lt;a href="https://github.com/backmeupplz/telegraf-template"&gt;Telegram BOT template&lt;/a&gt;.

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;I'm planning to add some text recognition. I want to take a photo of the bills and get a total number. I'm still trying to figure whats better to use for this task. Some &lt;code&gt;OCR&lt;/code&gt; solution as &lt;code&gt;Tesseract&lt;/code&gt; or &lt;code&gt;EasyOCR&lt;/code&gt;. Also, one way to solve this to train some simple ML models on bills to find a boundary with the total price, and OCR tried to extract total amount.&lt;/p&gt;

</description>
      <category>telegram</category>
      <category>bot</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
