<?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>Forem: Ali Salehi</title>
    <description>The latest articles on Forem by Ali Salehi (@mrali109).</description>
    <link>https://forem.com/mrali109</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%2F1233340%2F808dd6d8-050f-4b5d-b1f4-9e2d72c1d268.jpg</url>
      <title>Forem: Ali Salehi</title>
      <link>https://forem.com/mrali109</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mrali109"/>
    <language>en</language>
    <item>
      <title>Update handling in WTelegramClient</title>
      <dc:creator>Ali Salehi</dc:creator>
      <pubDate>Tue, 09 Jan 2024 10:15:35 +0000</pubDate>
      <link>https://forem.com/mrali109/update-handling-in-wtelegramclient-461o</link>
      <guid>https://forem.com/mrali109/update-handling-in-wtelegramclient-461o</guid>
      <description>&lt;p&gt;in the &lt;a href="https://dev.to/mrali109/introduction-to-c-user-bots-with-wtelegramclient-2c5c"&gt;previous article&lt;/a&gt; we talked about starting to work with WTC and setting up the basic requirements. in this article we are going through the process of handling updates for beginners. lets get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  setup
&lt;/h2&gt;

&lt;p&gt;we have our basic hello world code from previous article here:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WTelegram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoginUserIfNeeded&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"session_pathname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mysessionFILE.session"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"api_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"YOUR_API_ID"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"api_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"YOUR_API_HASH"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"phone_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"+12025550156"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"verification_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Code: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;()!;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// if sign-up is required&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// if sign-up is required&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"secret!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// if user has enabled 2FA&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;                  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/MrAliSalehi/HelloWtc/blob/master/Program.cs"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;don't forget to replace your phone number, your &lt;a href="https://dev.to/mrali109/introduction-to-c-user-bots-with-wtelegramclient-2c5c#:~:text=2.required%20properties"&gt;api_id &amp;amp; api_hash&lt;/a&gt; and also your 2FA password.&lt;/p&gt;

&lt;h2&gt;
  
  
  subscribing to updates
&lt;/h2&gt;

&lt;p&gt;the first thing we need to do, is to tell the WTC that we want to listen to the incoming updates, to do that we simply subscribe to an Event called &lt;code&gt;OnUpdate&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnUpdate&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;UpdateHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;UpdateHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdatesBase&lt;/span&gt; &lt;span class="n"&gt;updatesBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;lets talk about what just happened here, first we have our &lt;code&gt;client&lt;/code&gt; which at this point "might" be logged-in, we don't know yet, when we are subscribing (&lt;code&gt;+=&lt;/code&gt;) to an Event which &lt;strong&gt;gives&lt;/strong&gt; us an object of type &lt;code&gt;UpdatesBase&lt;/code&gt; and needs us to return a &lt;code&gt;Task&lt;/code&gt;, basically a &lt;code&gt;Func&amp;lt;UpdatesBase, Task&amp;gt;&lt;/code&gt; (we'll talk about that in the future) and then we are returning right after the subscription.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if your code is not async you can do &lt;code&gt;return Task.CompletedTask;&lt;/code&gt; and remove the &lt;code&gt;async&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Updates
&lt;/h2&gt;

&lt;p&gt;Telegram Type system by many people is considered Complex, or Confusing, and maybe it is, you just have to work with it for a relatively long time (that literally the definition of complexity but whatever). but I believe it would be much much more complex IF we didn't have &lt;code&gt;pattern-matching&lt;/code&gt; in C#, BUT WE DO!&lt;/p&gt;

&lt;p&gt;lets look at the basic types in WTC.&lt;br&gt;
first we have something called &lt;code&gt;UpdatesBase&lt;/code&gt;, It derives from &lt;code&gt;IObject&lt;/code&gt;. an empty interface, this is due to serialization reasons, but you don't need to worry about this, you just need know this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;every &lt;strong&gt;Telegram&lt;/strong&gt; object inside the WTC, drives from &lt;code&gt;IObject&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;lets look at its fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;UpdateList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ChatBase&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Chats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are going to talk about the most important one: &lt;code&gt;UpdateList&lt;/code&gt;,&lt;br&gt;
as the name says, this is an list of &lt;code&gt;Update&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;all the updates that we need are going to be inside this array.&lt;br&gt;
if you receive one message, this is going to be an array with one item inside it, if you get 10 messages in a very short period of time, lets say in &lt;code&gt;200 milli seconds&lt;/code&gt;, this array is going to be filled with &lt;code&gt;10&lt;/code&gt; items.&lt;/p&gt;

&lt;p&gt;but if you are getting 1 message every seconds, your &lt;code&gt;UpdateHandler&lt;/code&gt; will be called 10 times with 1 message each time.&lt;/p&gt;

&lt;p&gt;so it is important to check the whole array of update and not just the &lt;code&gt;first&lt;/code&gt; or &lt;code&gt;last&lt;/code&gt; item.&lt;br&gt;
so we'll write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;UpdateHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdatesBase&lt;/span&gt; &lt;span class="n"&gt;updatesBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;updatesBase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;take a closer look, the &lt;code&gt;update&lt;/code&gt; variable is an &lt;code&gt;Update?&lt;/code&gt;. what is it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Update&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IObject&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this is very similar to the concept of &lt;code&gt;IObject&lt;/code&gt;, as you can see its an &lt;code&gt;abstract&lt;/code&gt; class that has no items inside it, just like the &lt;code&gt;IObject&lt;/code&gt;, this is the base definition of &lt;strong&gt;every Update&lt;/strong&gt; inside the WTC.&lt;br&gt;
remember that I said:&lt;br&gt;
every &lt;strong&gt;object&lt;/strong&gt; is an &lt;code&gt;IObject&lt;/code&gt;.&lt;br&gt;
but also every &lt;strong&gt;update&lt;/strong&gt; drives from &lt;code&gt;Update&lt;/code&gt;, for the same reasons!&lt;/p&gt;

&lt;p&gt;so what should we do with it ? this is where the &lt;code&gt;pattern-matching&lt;/code&gt; comes into play, we can &lt;strong&gt;cast&lt;/strong&gt; this object to whatever we think it might be!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;you can hover over this type in your IDE and see that types it &lt;strong&gt;CAN&lt;/strong&gt; be, for example: &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0KIYFLrM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2yweqyf7iefdio4oiz9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0KIYFLrM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2yweqyf7iefdio4oiz9o.png" alt="types" width="546" height="527"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;this is what it looks like in my IDE, tons of types! but don't let it scare you, we don't need all of them! in fact we only need a few!&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  reading the updates
&lt;/h2&gt;

&lt;p&gt;alright lets start with something simple, we want to see all the new text messages!&lt;/p&gt;

&lt;p&gt;we can do the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;updatesBase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in this code, we are &lt;strong&gt;Safe&lt;/strong&gt; casting the &lt;code&gt;update&lt;/code&gt; to the type &lt;code&gt;UpdateNewMessage&lt;/code&gt; which is responsible for the incoming &amp;amp; &lt;strong&gt;outgoing&lt;/strong&gt; new messages inside a (basic) group or private chat.&lt;br&gt;
with the &lt;code&gt;if statement&lt;/code&gt; we indicate that if the &lt;code&gt;update&lt;/code&gt; is not what we wanted, do not PANIC, don't throw any exceptions, just relax and continue to the next update, if we did something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;updatesBase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UpdateList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;newMsg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it would cause some problems, since we are &lt;strong&gt;hard casting&lt;/strong&gt; here, compiler would assume that it is 100% the given type, so it wont check for anything first,  but we are not 100% sure that the update is &lt;code&gt;UpdateNewMessage&lt;/code&gt;, are we? it could be one of those many types that we saw earlier, so it will throw error and potentially break our application.&lt;br&gt;
so its much cleaner and safer to do the pattern matching with the if statement ( or even switch-statements if you have multiple types to handle).&lt;/p&gt;

&lt;p&gt;lets see what we have inside the &lt;code&gt;newMessage&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;MessageBase&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;pts_count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;ignore the pts stuff here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;we are seeing a new type: &lt;code&gt;MessageBase&lt;/code&gt;, you are going to see a lot of &lt;code&gt;..Base&lt;/code&gt; types while working with Telegram API, (average OOP moment 😂)&lt;br&gt;
but this one is not completely useless to us, it contains some information about the message, the 2 important ones are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Peer&lt;/span&gt; &lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the &lt;code&gt;Peer&lt;/code&gt; is itself another long discussion but for now, lets say its a &lt;code&gt;Person&lt;/code&gt; for the sake of simplicity, this &lt;code&gt;Peer&lt;/code&gt; only has one field: &lt;code&gt;ID&lt;/code&gt; of the person(a unique identifier).&lt;br&gt;
and the &lt;code&gt;date&lt;/code&gt; is the time when the message was &lt;strong&gt;sent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;so we can print them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"msg from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fromId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you will see something like this in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msg from 5298595170 at 1/7/2024 6:56:44 AM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so we got the data and the &lt;code&gt;sender id&lt;/code&gt;, but where the heck is the text? &lt;/p&gt;

&lt;p&gt;not that fast, there is another type&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DSeL331R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8tzlwz7qg0da28k1iiq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DSeL331R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y8tzlwz7qg0da28k1iiq.png" alt="crying kid meme" width="227" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;the &lt;code&gt;newMessage.message&lt;/code&gt; can be one of these 3 things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;code&gt;MessageEmpty&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;Message&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt; &lt;code&gt;MessageService&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for now, we will be using &lt;code&gt;Message&lt;/code&gt;, so we can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"msg from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fromId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so now the &lt;code&gt;msg&lt;/code&gt; contains the information we need, but first lets make this code a bit clear and more readable, we can return early when the update is something that we don't need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fromId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"msg from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fromId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$" text: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;using the &lt;code&gt;not&lt;/code&gt; operator we indicate that if the &lt;code&gt;update&lt;/code&gt; is not what we wanted, just continue iterating over the list, and the same thing for the &lt;code&gt;newMessage.message&lt;/code&gt; and then finally we can print out all the text messages!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msg from 1548097770 at 1/7/2024 8:44:50 AM text: HELLO WTC!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The alternative
&lt;/h3&gt;

&lt;p&gt;now that you've learned the update handling in the &lt;strong&gt;hard way&lt;/strong&gt;, let me introduce you to the easy way:&lt;/p&gt;

&lt;p&gt;there is an extension package called &lt;code&gt;WTelegramClient.Extensions.Updates&lt;/code&gt;, go ahead and install it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;gt; dotnet add package WTelegramClient.Extensions.Updates&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;using this package you can simply do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterUpdateType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;updateBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"msg from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;//or..&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterUpdateType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;OnNewMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;OnNewMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateNewMessage&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UpdatesBase&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;updateBase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"msg from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Peer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so you can basically filter any &lt;code&gt;Update&lt;/code&gt; type that you want, there are other filters for &lt;code&gt;Chat&lt;/code&gt; types and more features, I recommend check it out:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/MrAliSalehi/WTelegramClient.Extensions.Updates"&gt;WTelegramClient.Extensions.Updates&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  different types of content
&lt;/h3&gt;

&lt;p&gt;so far we've learned how to print out the text messages, but there are other things to capture (e.x Documents, Photos, Videos..etc).&lt;br&gt;
we'll cover a few of them in the following section.&lt;/p&gt;
&lt;h4&gt;
  
  
  Photos
&lt;/h4&gt;

&lt;p&gt;first we want to put all the new pictures inside a Directory, lets call it &lt;code&gt;photos&lt;/code&gt;, so we should create it first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//beginning&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;photoDirectory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"photos"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photoDirectory&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDirectory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photoDirectory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// ..login&lt;/span&gt;
&lt;span class="c1"&gt;//..update handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;simply check if the directory doesn't exist, create it!&lt;/p&gt;

&lt;p&gt;now we can look for the photos in our &lt;code&gt;UpdateHandler&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;newMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaPhoto&lt;/span&gt; &lt;span class="n"&gt;messageMediaPhoto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;okay so the &lt;code&gt;msg.media&lt;/code&gt; is a &lt;code&gt;MessageMedia&lt;/code&gt; which is just another &lt;code&gt;Base&lt;/code&gt; class, this one can be a lot of things as well. but now we only want the photos so we casted it to &lt;code&gt;MessageMediaPhoto&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;the &lt;code&gt;messageMediaPhoto&lt;/code&gt; has a field called &lt;code&gt;photo&lt;/code&gt; which is yet another &lt;code&gt;Base&lt;/code&gt; class.&lt;br&gt;
the &lt;code&gt;photo&lt;/code&gt; field can be 2 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PhotoEmpty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Photo&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;the first one is completely useless, in almost all the cases you want the &lt;code&gt;Photo&lt;/code&gt;, so instead of nesting &lt;code&gt;if statements&lt;/code&gt; we can write it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaPhoto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Photo&lt;/span&gt; &lt;span class="n"&gt;thePicture&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are simply checking if the type is &lt;code&gt;MessageMediaPhoto&lt;/code&gt; &lt;strong&gt;AND&lt;/strong&gt; its &lt;code&gt;photo&lt;/code&gt; field is of type &lt;code&gt;Photo&lt;/code&gt; in a single &lt;code&gt;if-statement&lt;/code&gt;&lt;br&gt;
and finally we are accessing it through the &lt;code&gt;thePicture&lt;/code&gt; variable.&lt;br&gt;
keep in mind that if the &lt;code&gt;msg.media&lt;/code&gt; is not the specified type, the &lt;code&gt;{photo: Photo thePicture}&lt;/code&gt; part is not going to be executed, so you wont be able to use &lt;code&gt;thePicture&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;this is equivalent to this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaPhoto&lt;/span&gt; &lt;span class="n"&gt;messageMediaPhoto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messageMediaPhoto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Photo&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are just checking the 2 conditions at the same level, you can also write it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaPhoto&lt;/span&gt; &lt;span class="n"&gt;messageMediaPhoto&lt;/span&gt;
    &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;messageMediaPhoto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;Photo&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;thePicture&lt;/code&gt; has everything you need to know about a picture, lets download it in our desired Directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaPhoto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Photo&lt;/span&gt; &lt;span class="n"&gt;thePicture&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;photoDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;thePicture&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.jpg"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FileStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenOrCreate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DownloadFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thePicture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;not much to explain here, we are creating a path using the photo id (you can name it whatever you want) and we are creating a &lt;code&gt;FileStream&lt;/code&gt; using that path and using the &lt;code&gt;DownloadFileAsync&lt;/code&gt; helper method we are downloading it.&lt;br&gt;
you can test this and go to the &lt;code&gt;../bin/Debug/net/photos&lt;/code&gt; and see the photos you've downloaded!&lt;/p&gt;
&lt;h4&gt;
  
  
  Documents
&lt;/h4&gt;

&lt;p&gt;in telegram terms, documents are basically any type of media except photo. so videos, GIFs, audio, voice, stickers ...etc.&lt;/p&gt;

&lt;p&gt;so process is very similar to downloading photos, first create the directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;docDirectory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"documents"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docDirectory&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDirectory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docDirectory&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then check for the document type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;...)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c1"&gt;//..&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;MessageMediaDocument&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;document&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Document&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="c1"&gt;//either Document or DocumentEmpty, same as PhotoBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Filename&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mime_type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;docDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;FileStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FileMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenOrCreate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DownloadFileAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;so what we did here is a bit different, for the file name we can check if the &lt;code&gt;FileName&lt;/code&gt; has a value (&lt;code&gt;??&lt;/code&gt;) if so, we don't need to check for its &lt;code&gt;type&lt;/code&gt;, if it doesn't have any name, we split the &lt;code&gt;mime_type&lt;/code&gt; by &lt;code&gt;/&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;mime types are represented like this &lt;code&gt;Video/mp4&lt;/code&gt; or &lt;code&gt;Photo/jpg&lt;/code&gt; ..etc&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and then we get the second index of the &lt;code&gt;Split&lt;/code&gt; so that we can only get the &lt;code&gt;type&lt;/code&gt; and with that we create a file name, then make a &lt;code&gt;FileStream&lt;/code&gt; and download the file. exactly the same as Photo, you can also go ahead and store the different types in separate directories based on this &lt;code&gt;mime_type&lt;/code&gt; but we are not going to do that here.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blocking
&lt;/h2&gt;

&lt;p&gt;you we've made it, we handled our updates, lets run the application;&lt;/p&gt;

&lt;p&gt;what happened? why did the problem aborted immediately? well because we don't &lt;code&gt;block&lt;/code&gt; our thread.&lt;br&gt;
after registering our handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnUpdate&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;UpdateHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there is basically no logic to tell the program: "wait until we tell you to exit" or something like that.&lt;br&gt;
how can we fix it?&lt;/p&gt;

&lt;p&gt;the most simplest solution could be this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnUpdate&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;UpdateHandler&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;yes, put an infinite loop after registering the handler and just sleep for some amount of seconds, doesn't matter you can put &lt;code&gt;TimeSpan.FromDays(99999)&lt;/code&gt;, just the enough amount to not put any pressure on the CPU.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;but this is not a perfect solution!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;for a long term running or a production grade application I personally would recommend something like a &lt;a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-8.0&amp;amp;tabs=visual-studio"&gt;Background Service&lt;/a&gt; (which we are going to cover in the next articles).&lt;br&gt;
for testing, I think anything that &lt;em&gt;works&lt;/em&gt;, is fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;so we managed to handle basic updates that are coming into our account, we didn't do much, but we did the hard part, after this its going to be much more easier.&lt;br&gt;
if you did not find what you were looking for here, you might want to take a look at these links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiz0u.github.io/WTelegramClient/"&gt;documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiz0u.github.io/WTelegramClient/EXAMPLES"&gt;examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wiz0u/WTelegramClient"&gt;GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;if you still didn't find it, don't worry, leave a comment and tell us what could be the topic of the next article!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;all the code written in this article is available &lt;a href="https://github.com/MrAliSalehi/UpdatesWtc"&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introduction to C# User Bots with WTelegramClient</title>
      <dc:creator>Ali Salehi</dc:creator>
      <pubDate>Sun, 17 Dec 2023 19:30:16 +0000</pubDate>
      <link>https://forem.com/mrali109/introduction-to-c-user-bots-with-wtelegramclient-2c5c</link>
      <guid>https://forem.com/mrali109/introduction-to-c-user-bots-with-wtelegramclient-2c5c</guid>
      <description>&lt;p&gt;In the dynamic landscape of bot development, Telegram stands out as a popular platform, offering a rich(and sometimes confusing) set of APIs for creating fascinating User Bots. If you're venturing into Telegram API development using C#, the &lt;code&gt;WTelegramClient&lt;/code&gt;(AKA &lt;em&gt;WTC&lt;/em&gt;) library is a powerful tool that deserves your attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different Types of Bots In Telegram
&lt;/h2&gt;

&lt;p&gt;before we continue, lets talk about Different bots in Telegram Ecosystem, what the heck is "User Bot" or "Client Bot" or "API" Bot ? what's the difference?&lt;/p&gt;

&lt;h3&gt;
  
  
  First One
&lt;/h3&gt;

&lt;p&gt;Telegram allows you to create bots (daaah?) that runs on the cloud and can receives and send content;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;some popular examples of these bots are &lt;a href="https://t.me/BotFather"&gt;BotFather&lt;/a&gt; or &lt;a href="https://t.me/chatIDrobot"&gt;ChatId Bot&lt;/a&gt; which is used to get the users numerical IDS and many other bots.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;these bots are known as "API bots" or "Telegram Bots" mainly because they have a separate and dedicated API that is much simpler and easier to work with, which is not the topic of this article. BUT there is also another type of Bot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Second One
&lt;/h3&gt;

&lt;p&gt;the second types are the one that can log-in to your account via your phone number, these bots are known as "&lt;strong&gt;&lt;em&gt;User Bots&lt;/em&gt;&lt;/strong&gt;" / "&lt;strong&gt;&lt;em&gt;Client Bots&lt;/em&gt;&lt;/strong&gt;" or in some cases "&lt;strong&gt;&lt;em&gt;Self Bot&lt;/em&gt;&lt;/strong&gt;" because, well they are basically what the Official Client Applications use on Android Or other platforms, that's right, Your Telegram App in your Phone is using "&lt;strong&gt;Client API&lt;/strong&gt;" to interact with Telegram, which is what we are going to talk about in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what &lt;code&gt;WTelegramClient&lt;/code&gt; can do ? what roles it plays?
&lt;/h2&gt;

&lt;p&gt;well, It can do anything! you can create Both User Bots and API Bots. But it is mainly used to create user bots; and That's what we are going to do now!&lt;/p&gt;

&lt;p&gt;WTC handles all the low-level details of Communications between Telegram and your C# code and gives you a nice and &lt;em&gt;Right amount&lt;/em&gt; of abstractions to work with, what I mean by "Right Amount"? well, it's not something like other libraries(e.g: &lt;a href="https://docs.telethon.dev/en/stable/"&gt;telethon&lt;/a&gt; which is a great tool BTW ) that abstract most of the details and exposes a little bit of information.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;well isn't that a good thing? you might say&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;yes and no, too much abstraction "can" take away the flexibility, at least this is what I saw in my experience. The &lt;code&gt;WTelegramClient&lt;/code&gt; library only abstract the painful part of The Code and lets you do whatever you want to do with the rest! you can build basically a fully functional Client Application that can do 100% of the official client features. with less pain indeed.&lt;/p&gt;

&lt;p&gt;alright enough with the talking and theory BS, Lets Write some Code!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating A &lt;code&gt;Hello world&lt;/code&gt; application in WTC
&lt;/h2&gt;

&lt;h2&gt;
  
  
  1. Install The Library
&lt;/h2&gt;

&lt;p&gt;first of all add the WTC (&lt;a href="https://www.nuget.org/packages/WTelegramClient/"&gt;nuget&lt;/a&gt;) to your dependencies:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ dotnet add package WTelegramClient&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;great! now that you installed the library its time to gather some information.&lt;/p&gt;

&lt;h2&gt;
  
  
  2.required properties
&lt;/h2&gt;

&lt;p&gt;in order to write Telegram User Bots, unlike regular "Bot APIs" you need 2 unique things besides your &lt;strong&gt;phone number&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Hash&lt;/li&gt;
&lt;li&gt;API ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;what are these? well we are not going into detail but these are used to Identify who is sending the request to telegram and who created the application in the first place.&lt;br&gt;
to fetch these you can easily go to the &lt;a href="https://my.telegram.org/"&gt;Telegram Site&lt;/a&gt;, Enter your phone number, enter the code and after that you see 3 options: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API development tools&lt;/li&gt;
&lt;li&gt;Delete account&lt;/li&gt;
&lt;li&gt;Log out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;click &lt;code&gt;Delete Account&lt;/code&gt; and .. no Just Kidding, &lt;strong&gt;click the First one which&lt;/strong&gt; will redirect you to &lt;a href="https://my.telegram.org/apps"&gt;this url&lt;/a&gt; then you can create a application with whatever name you want and WALLA!, you got your &lt;strong&gt;Api_id&lt;/strong&gt; and &lt;strong&gt;api_hash&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;now that we have these things we can continue writing our code.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. writing the Basic
&lt;/h2&gt;

&lt;p&gt;first we need to provide our information to WTC, so we create a function called &lt;code&gt;Config&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"api_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"YOUR_API_ID"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"api_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"YOUR_API_HASH"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"phone_number"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"+12025550156"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"verification_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Code: "&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// if sign-up is required&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Doe"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// if sign-up is required&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"secret!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// if user has enabled 2FA&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                  &lt;span class="c1"&gt;// let WTelegramClient decide the default config&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;this function accepts a string and also returns a string, its like a &lt;code&gt;Dictionary&amp;lt;String, String&amp;gt;&lt;/code&gt;, we are just mapping the WTC requirements to their proper values, so here you can put your ApiHash, ApiId, Phone and your 2FA password.&lt;/p&gt;

&lt;p&gt;and now we can create our first instance of WTC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;WTelegram&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;simple as that! notice that we are not doing &lt;code&gt;Client(Config());&lt;/code&gt; but rather we are passing the &lt;code&gt;Function&lt;/code&gt; itself and not its returning value! that's really important because WTC will automatically determine which piece of data it needs!&lt;br&gt;
also don't forget the &lt;code&gt;using&lt;/code&gt; at the beginning, otherwise you might face some issues related to resources not getting released!&lt;/p&gt;

&lt;p&gt;alright, we have a client now, what can we do with it ? nothing...yet.&lt;br&gt;
if you run the code now, nothing will happen, why? because you didn't &lt;strong&gt;login&lt;/strong&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  4.login
&lt;/h2&gt;

&lt;p&gt;logging in to telegram is simple as writing a single line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LoginUserIfNeeded&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;notice that you also have a &lt;code&gt;client.LoginBotIfNeeded()&lt;/code&gt; which is used for creating "API bots", cool!.&lt;br&gt;
now if we run the code you should see something similar to this in the console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WTelegramClient {version} running under .NET {version}
Connecting to {IP of the DC}
4&amp;gt;Sending   InvokeWithLayer`1                        #D8BE
4&amp;gt;Receiving RpcResult                                2023-12-14 14:18:19Z
             → Config                                #D8BE
Connected to DC 4... default_p2p_contacts, revoke_pm_inbox

....
             → Auth_SentCode                         #AE32
A verification code has been sent via App
Code: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now its the time to enter the code that telegram sent to your account, note that you "can't" create new accounts with unofficial clients, this means you have to create your account with an official client first and then use the "Client API", unfortunately!&lt;/p&gt;

&lt;p&gt;after entering the code, if you have a 2FA password enabled, you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;→ RpcError 401 SESSION_PASSWORD_NEEDED  #66D1
→ Account_Password                      #878D

Verifying encryption key safety... (this should happen only once per DC)
This account has enabled 2FA. A password is needed. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now if you wrote the correct password in the &lt;code&gt;Config&lt;/code&gt; function, you should be able to login successfully and see the client disposing without errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;4&amp;gt;Disposing the client
4&amp;gt;Sending   MsgsAck                                  2023-12-14  (svc)

Process finished with exit code 0.

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

&lt;/div&gt;



&lt;p&gt;BUT if you entered the wrong password you will get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;→ RpcError 400 PASSWORD_HASH_INVALID    #B05E
Wrong password!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;don't worry, just check your password and run the program again!&lt;/p&gt;

&lt;h2&gt;
  
  
  5.the session
&lt;/h2&gt;

&lt;p&gt;before we move on, lets talk a little bit about sessions, what are they? well go to the &lt;code&gt;bin&lt;/code&gt; directory in your project, next to the &lt;code&gt;Debug/Release&lt;/code&gt; directories, you see a file named &lt;code&gt;WTelegram.session&lt;/code&gt; which &lt;strong&gt;if&lt;/strong&gt; you logged in successfully you should see it and its size should be more than 0 Bytes.&lt;/p&gt;

&lt;p&gt;this is there WTC stores everything related to your state, Authentication and some other details.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;some libraries store information about messages, chats, &lt;code&gt;access_hashes&lt;/code&gt; (which we will discuss later) ..etc. WTC does NOT store these information and its up to the users of this library to handle them&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;using this file, you can login once and the next time resume the existing session instead of login.&lt;br&gt;
now go ahead and run your program one more time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loaded previous session
WTelegramClient {version} running under .NET {version}
Connecting to {DC IP}
....
4&amp;gt;Disposing the client
Process finished with exit code 0.

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

&lt;/div&gt;



&lt;p&gt;notice the first line :&lt;code&gt;Loaded previous session&lt;/code&gt;, you are using the pre-stored data to connect to the telegram, without entering the code again, that why our login method is called &lt;code&gt;client.LoginUserIfNeeded()&lt;/code&gt; and not &lt;code&gt;client.LoginUser()&lt;/code&gt;, we only login if we don't have a valid session file present in the &lt;strong&gt;default session path&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  changing the default session path
&lt;/h3&gt;

&lt;p&gt;you can also change this &lt;code&gt;path&lt;/code&gt;, for example I want the session to be next to my application.exe file, we need to add one more line to the &lt;code&gt;Config&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// create the path&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// the new "parameter"&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"session_pathname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mysessionFILE.session"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// other stuff&lt;/span&gt;
        &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now if you run the program again, you should see that it doesn't say &lt;code&gt;Loaded previous session&lt;/code&gt; and its asking for a code, because we moved the session to a new place.&lt;br&gt;
after this if we run it one more time, it reads the &lt;code&gt;mysessionFILE.session&lt;/code&gt; and does not ask for the code again! pretty cool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;if you are facing any issue related to the session not being parsed or corruption, just try to delete the session file and login again!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  6. HELLO WORLD, finally
&lt;/h2&gt;

&lt;p&gt;now that we are familiar with sessions, lets just print hello world!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;//login stuff&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SendMessageAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;InputPeer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello WTC world!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;now run the program and take a look at your saved messages inside the official client, can you see the "hello WTC world!" ? you should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;well congratulations! you finally made it! welcome to the world of Telegram Client Development where you will suffer every single second trying to understand the &lt;a href="https://core.telegram.org/methods"&gt;telegram documentations&lt;/a&gt; and figure out how to do things! but don't worry, we will help you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wiz0u.github.io/WTelegramClient/EXAMPLES"&gt;Examples of different methods&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://t.me/WTelegramClient"&gt;WTC Telegram Chat&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wiz0u.github.io/WTelegramClient/"&gt;WTC Documentations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/wiz0u/WTelegramClient"&gt;Github Page&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://core.telegram.org/api"&gt;Telegram Documentations&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://core.telegram.org/methods"&gt;All Telegram Method&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;all the code written in this article are available &lt;a href="https://github.com/MrAliSalehi/HelloWtc"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>telegram</category>
      <category>opensource</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
