From eb3d159ddec76b869b872fead80ef994abb609e8 Mon Sep 17 00:00:00 2001 From: sokomishalov Date: Wed, 30 Oct 2019 12:16:16 +0300 Subject: [PATCH 01/18] upgrade spring boot to 2.2.0.RELEASE replaced Optional bean with ObjectProvider in autoconfiguration --- telegrambots-spring-boot-starter/pom.xml | 2 +- .../TelegramBotStarterConfiguration.java | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/telegrambots-spring-boot-starter/pom.xml b/telegrambots-spring-boot-starter/pom.xml index c28a9bdf..565c59df 100644 --- a/telegrambots-spring-boot-starter/pom.xml +++ b/telegrambots-spring-boot-starter/pom.xml @@ -70,7 +70,7 @@ UTF-8 UTF-8 - 2.1.6.RELEASE + 2.2.0.RELEASE diff --git a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java index 5fe34191..6aea31d0 100644 --- a/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java +++ b/telegrambots-spring-boot-starter/src/main/java/org/telegram/telegrambots/starter/TelegramBotStarterConfiguration.java @@ -2,8 +2,9 @@ package org.telegram.telegrambots.starter; import java.util.Collections; import java.util.List; -import java.util.Optional; + +import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; @@ -11,12 +12,11 @@ import org.springframework.context.annotation.Configuration; import org.telegram.telegrambots.meta.TelegramBotsApi; import org.telegram.telegrambots.meta.generics.LongPollingBot; import org.telegram.telegrambots.meta.generics.WebhookBot; - /** * #TelegramBotsApi added to spring context as well */ @Configuration -@ConditionalOnProperty(prefix="telegrambots",name = "enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnProperty(prefix = "telegrambots", name = "enabled", havingValue = "true", matchIfMissing = true) public class TelegramBotStarterConfiguration { @Bean @@ -26,12 +26,12 @@ public class TelegramBotStarterConfiguration { } @Bean - @ConditionalOnMissingBean - public TelegramBotInitializer telegramBotInitializer(TelegramBotsApi telegramBotsApi, - Optional> longPollingBots, - Optional> webHookBots) { - return new TelegramBotInitializer(telegramBotsApi, - longPollingBots.orElseGet(Collections::emptyList), - webHookBots.orElseGet(Collections::emptyList)); + @ConditionalOnMissingBean + public TelegramBotInitializer telegramBotInitializer(TelegramBotsApi telegramBotsApi, + ObjectProvider> longPollingBots, + ObjectProvider> webHookBots) { + return new TelegramBotInitializer(telegramBotsApi, + longPollingBots.getIfAvailable(Collections::emptyList), + webHookBots.getIfAvailable(Collections::emptyList)); } } From 55e27c1167c9e903b1675f0b63aaf2033f575af0 Mon Sep 17 00:00:00 2001 From: galimru Date: Mon, 27 Jan 2020 21:15:04 +0400 Subject: [PATCH 02/18] added the fix to workaround openjdk bug which thrown internal error (ref #629) --- .../telegrambots/updatesreceivers/DefaultBotSession.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java b/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java index 0f9f6334..94e83313 100644 --- a/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java +++ b/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java @@ -274,6 +274,14 @@ public class DefaultBotSession implements BotSession { } catch (InterruptedException e) { log.info(e.getLocalizedMessage(), e); interrupt(); + } catch (InternalError e) { + // handle InternalError to workaround OpenJDK bug (resolved since 13.0) + // https://bugs.openjdk.java.net/browse/JDK-8173620 + Throwable cause = e.getCause(); + if (cause instanceof IOException) { + log.error(e.getLocalizedMessage(), e); + } + throw e; } return Collections.emptyList(); } From 1b18b1ccdb418a7c0ed007c68a16d926d66c254f Mon Sep 17 00:00:00 2001 From: galimru Date: Tue, 28 Jan 2020 12:59:27 +0400 Subject: [PATCH 03/18] unwrap cause from internal exception and prevent from breaking thread (ref #629) --- .../updatesreceivers/DefaultBotSession.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java b/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java index 94e83313..da98f1b8 100644 --- a/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java +++ b/telegrambots/src/main/java/org/telegram/telegrambots/updatesreceivers/DefaultBotSession.java @@ -26,6 +26,7 @@ import org.telegram.telegrambots.meta.generics.UpdatesReader; import java.io.IOException; import java.io.InvalidObjectException; +import java.lang.reflect.InvocationTargetException; import java.net.SocketException; import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; @@ -277,12 +278,12 @@ public class DefaultBotSession implements BotSession { } catch (InternalError e) { // handle InternalError to workaround OpenJDK bug (resolved since 13.0) // https://bugs.openjdk.java.net/browse/JDK-8173620 - Throwable cause = e.getCause(); - if (cause instanceof IOException) { - log.error(e.getLocalizedMessage(), e); - } - throw e; + if (e.getCause() instanceof InvocationTargetException) { + Throwable cause = e.getCause().getCause(); + log.error(cause.getLocalizedMessage(), cause); + } else throw e; } + return Collections.emptyList(); } } From 5120595cb0e3b497075aaecdae9c015a25108898 Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Sat, 29 Feb 2020 16:22:48 -0800 Subject: [PATCH 04/18] Move the commit to the end of the update pipeline --- .../org/telegram/abilitybots/api/bot/BaseAbilityBot.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java index a237616d..5a1baf07 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java @@ -3,9 +3,6 @@ package org.telegram.abilitybots.api.bot; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList.Builder; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Multimap; -import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -193,6 +190,9 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability .map(this::consumeUpdate) .forEach(this::postConsumption); + // Commit to DB now after all the actions have been dealt + db.commit(); + long processingTime = System.currentTimeMillis() - millisStarted; log.info(format("[%s] Processing of update [%s] ended at %s%n---> Processing time: [%d ms] <---%n", botUsername, update.getUpdateId(), now(), processingTime)); } @@ -480,7 +480,6 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability return user; }); - db.commit(); return update; } From 21822f7803506edcc8ca182b9b673bbe1a055f6b Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Sat, 29 Feb 2020 16:27:05 -0800 Subject: [PATCH 05/18] Remove redundant commits to DB --- .../org/telegram/abilitybots/api/bot/DefaultAbilities.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/DefaultAbilities.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/DefaultAbilities.java index 3405cfb8..bdcf9456 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/DefaultAbilities.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/DefaultAbilities.java @@ -60,7 +60,6 @@ import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_UNBA import static org.telegram.abilitybots.api.util.AbilityMessageCodes.ABILITY_UNBAN_SUCCESS; import static org.telegram.abilitybots.api.util.AbilityMessageCodes.USER_NOT_FOUND; import static org.telegram.abilitybots.api.util.AbilityUtils.addTag; -import static org.telegram.abilitybots.api.util.AbilityUtils.commitTo; import static org.telegram.abilitybots.api.util.AbilityUtils.escape; import static org.telegram.abilitybots.api.util.AbilityUtils.getLocalizedMessage; import static org.telegram.abilitybots.api.util.AbilityUtils.shortName; @@ -288,7 +287,6 @@ public final class DefaultAbilities implements AbilityExtension { sendMd(ABILITY_BAN_SUCCESS, ctx, escape(bannedUser)); } }) - .post(commitTo(bot.db)) .build(); } @@ -315,7 +313,6 @@ public final class DefaultAbilities implements AbilityExtension { bot.silent.sendMd(getLocalizedMessage(ABILITY_UNBAN_SUCCESS, ctx.user().getLanguageCode(), escape(username)), ctx.chatId()); } }) - .post(commitTo(bot.db)) .build(); } @@ -339,7 +336,7 @@ public final class DefaultAbilities implements AbilityExtension { admins.add(userId); sendMd(ABILITY_PROMOTE_SUCCESS, ctx, escape(username)); } - }).post(commitTo(bot.db)) + }) .build(); } @@ -363,7 +360,6 @@ public final class DefaultAbilities implements AbilityExtension { sendMd(ABILITY_DEMOTE_FAIL, ctx, escape(username)); } }) - .post(commitTo(bot.db)) .build(); } @@ -389,7 +385,6 @@ public final class DefaultAbilities implements AbilityExtension { send(ABILITY_CLAIM_SUCCESS, ctx); } }) - .post(commitTo(bot.db)) .build(); } From cc0e0c977198a16b9768d33b6354cfdfc1dbb7df Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Thu, 5 Mar 2020 17:01:06 +0100 Subject: [PATCH 06/18] Revert: Added deprecated constructor with the old style (e526b9db) This commit causes a bug if using the normal constructors without overriding getBotUsername and since it's no longer abstract it doesn't force you to implement the method, even though it is needed in any case aside from the deprecated one --- .../TelegramLongPollingCommandBot.java | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/telegrambots-extensions/src/main/java/org/telegram/telegrambots/extensions/bots/commandbot/TelegramLongPollingCommandBot.java b/telegrambots-extensions/src/main/java/org/telegram/telegrambots/extensions/bots/commandbot/TelegramLongPollingCommandBot.java index 1796b364..05de2c72 100644 --- a/telegrambots-extensions/src/main/java/org/telegram/telegrambots/extensions/bots/commandbot/TelegramLongPollingCommandBot.java +++ b/telegrambots-extensions/src/main/java/org/telegram/telegrambots/extensions/bots/commandbot/TelegramLongPollingCommandBot.java @@ -22,7 +22,6 @@ import java.util.function.BiConsumer; */ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingBot implements ICommandRegistry { private final CommandRegistry commandRegistry; - private String botUsername; /** * Creates a TelegramLongPollingCommandBot using default options @@ -33,19 +32,6 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB this(ApiContext.getInstance(DefaultBotOptions.class)); } - /** - * Creates a TelegramLongPollingCommandBot using default options - * Use ICommandRegistry's methods on this bot to register commands - * - * @param botUsername Username of the bot - * @deprecated Overwrite {@link #getBotUsername() getBotUsername} instead - */ - @Deprecated - public TelegramLongPollingCommandBot(String botUsername){ - this(); - this.botUsername = botUsername; - } - /** * Creates a TelegramLongPollingCommandBot with custom options and allowing commands with * usernames @@ -152,9 +138,7 @@ public abstract class TelegramLongPollingCommandBot extends TelegramLongPollingB * @return Bot username */ @Override - public String getBotUsername(){ - return this.botUsername; - }; + public abstract String getBotUsername(); /** * Process all updates, that are not commands. From e4bb479972206786d038c80a4720626fd9e0ac0d Mon Sep 17 00:00:00 2001 From: chase Date: Thu, 29 Aug 2019 19:10:37 +0200 Subject: [PATCH 07/18] Add Introduction and The Libary and the bot section --- .../understanding-the-library/Bot_curl.png | Bin 0 -> 8643 bytes .../Bot_intellij.png | Bin 0 -> 14683 bytes .../Telegram-Diagram.png | Bin 0 -> 20457 bytes .../Understanding-The-Library.md | 55 ++++++++++++++++++ 4 files changed, 55 insertions(+) create mode 100644 TelegramBots.wiki/understanding-the-library/Bot_curl.png create mode 100644 TelegramBots.wiki/understanding-the-library/Bot_intellij.png create mode 100644 TelegramBots.wiki/understanding-the-library/Telegram-Diagram.png create mode 100644 TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md diff --git a/TelegramBots.wiki/understanding-the-library/Bot_curl.png b/TelegramBots.wiki/understanding-the-library/Bot_curl.png new file mode 100644 index 0000000000000000000000000000000000000000..db14c332d4a4cfc1ccb1a857f826eb44750660d5 GIT binary patch literal 8643 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 G0{URIf+UYWcM}gOs1ZQ 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 literal 0 HcmV?d00001 diff --git a/TelegramBots.wiki/understanding-the-library/Telegram-Diagram.png b/TelegramBots.wiki/understanding-the-library/Telegram-Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..27de21a171a308917728308ee285bcf138869fe6 GIT binary patch literal 20457 zcmd_SXIPV6(>5AJ#Eu0-K|rNQM^IEch)9P}LN6j9(xuk`f>=O6A@trMlpqj#5f$m3 zfOMsWju49UZ(Z@e?}z6-j=kUSIrjTw?{D)bn(JC^*37J#^PH8pa3$$8CuvT?V6Zc? zG7nW@Fj6@fjHKZBG4M^KLU<(%MyBSjuH|U$Ds6A{{F$PyiK!I~#*gUF&lS9|7sEBO z^Sq?7GsGmOH|^D{$nygD*8Y%aQO4_5np#wPh<%BHjmBn{J&B|e<>p+4Fb33)#JQus z4BpokD0~HvulaSKJLz?NH?YnX_FcSY20z77xx8b`=f7h+;H_@QFYXT#6a3<0^89!_|`ok)S|G`oyq%^f~1TKM(KOB?$jmT5~tt$i~XX0=@`r8 z)mr^n{P|t_P;HJ9$7^&S#s~R0F<7bir#Ex8Z@cv!yZ+H3#cb$&j&>Ej;4DjBYUbIu zrdqpY&U-Ny(wZdqC2vqPB~jI8X}$3aEs`h~qn@+0{%oPrby*L7V(Z!6wWHo% z?@@Hxdv&818B2HbIF}w9I)!SYQ`kt#E|qKh@>RaBqBB2Dk|Xa@k!zsplTFB#ZoI4MmKK$o^W*am8iV=Rvp+Vkedo*aV&MtlwoMW_{y>WUOT%|;*2_la zm1}SON)21sn`CR%d}UwAol7W==-toXxRg8M_H|nM0or;@pHE-vK4lEANm1Q%Z9NUA z%-LYxTQ|b#{ExGRVkR5MkLlW!B^uwSDL`@C6qQ|L?@N1GN|k#Mz zXD0W{Ay>`Tmy|h0jnrM%uY3;fYUC}nC{vQ>TErO#Fa_}-X){gzl!a(tgxU8#bke-+ zoMqBn$%|q3ZX#pj-eWvA!Xne9Luwg%b^hF$RtKDlADQF1iFeDdRWJJ#p*0( z@Nq_24Y@H@?T@LE7u;4oOvsVm@!F4>UfcHN&E4B$ed@^eL(lanv3E1vjA@T6}$k|xUl#a z4xYHFgw+qaVvc#QW;L;T)RX6U~&uab^JpCji`&_@!j?*-`7Q4$Wd_Oba78aK;0 zV7WpXigqZ`YL;Tgy7ONOJw@F_3=sSgX?jUk=b-_bRl`zhd@R(;gXMEXCmC5u_O3zG zL8T}7sj}dbo^|pJm6+~)LCZRdb@V#G=PdOERr20jH*JtpX6LE3)>@Wl5BlulPB2?Y z79vI6swL`mor7}_-))-;xwQA+j5jF^bmj%?Y2uaQCW=t0|TG%puhs=6>!qD#O1?V$5+ z*0rBMKEgUS3CQApb4k$*9?@i{M`8BnU(9Y7RK3ti=Tk(lY6sjk1rHPpvzE`nk3&Kf z*Pgr1iv3EphRDulEGR~Eo3IV`y6I6!WMk~|oK9}tuo&K|RPehIA2~!B-l2(|-_&>9 zHgdpPc?X4BoRX_Sv&gogONQFT(}5t3-^PuRePV<5%%`wd5-z9Fvf*l~-Iw2lS4&GK zu%*-csv1tHVoz$RFbnSAPmaRzvuf9s={V=`q^e6Q{Cq6_LR_4rmf1El$wcZR=>9qm zdja)B^sf$Et}t_;GYlGJsuNV^to1D8ed9YWo6@)lrS=-bE#7j>oMKC`VEDfH?t;V# z8)-;2Smmn?Qz^4;&3DWMlLwy##S~UO%EsHZ1q?)_C@%K1;`~kBijK=QS#0HHUAQ7^ zflzDZNz~7KdL9L*C+d`GHl}iPpwL=3f)0+*FI<#MHVHZsp)8uHY!D)CkO=;f{@A*3 z*)CLvHua>IsP=vmdfZNG(W=HhQWg1?XNWUFv)5$^i zPIKBEWr-DnFiQfvETcn1d1}zwJ+NJ*jPkD|Oy>%gppK16r`{ykE1N z)VmW_zmuPO_eU6Az6w&UkntLJc4u~`nj3>PFfz>a36o`gIuyW9eM=cw=H$zymxbXr z0nMwfR5QErmFjs%Dn+!1Gi8h)?UAL|Byx^wUYF(XRcD*rY?{DQp>3>$XnV(cx;*p^ zbk3Yl^j(x?3wzUS;l1>5p8(8EoEz+jvB>ZxY`Ko}&TX1OliqVH?CN7^D__-)(tB+N zg1991p&Yor{DHFcva#FjH}uAsX)h(#*}v|{H1JeD3t;!YxgVF?i&vSu`VIx}W#?oy zRSiO0&bd>+H3>4*;Osi+>DtjT$dE;7z*kI+hYpr@Qy&o9<`UbwcaFAOqI8&KqfPRB zH6B{u)EmrS&bClinSH3>d{_C>vLws-Fl&D*<&wlMbH%K|Wwo*z#GWW!b;pz`>doNE zS3@>BU9-+-$XYJ~0S(+>O@6n&@o;rJ_-5eHet|`dbN#!%Z&^o54C~-p2!1;$Qh%>? z?o<Hw&pqyGof^;br|ogs zaMm>AV1Y+Fi=~Oe^b{AtpIWJT?cPSuoAZp6C;c5qochh{1E_+R5>Ei$7AQzXTIlta-*#DZr>sf^`?0Gtc*e=|%KOZ-T%fWSaCap{~Sav2! z#PAxw>cbcsu1!JyoAraT*q*wkArfmf)EA~KnhpNj>nIC@_m$X=<(sxd%x0wqcca+U zij5nBQ`%yI!xcYKwepRYhTj6URD0mnlMegjbW~JSVXPd|j$LjZtfZ&EW`n=S z6ecbuuv|qbe%cn}JFU{2^tC=4_P$cpFfO3mZ6fHN<64(=EH^2Pz5CbCFQ>L?3{-qC zP-h+yw-ay!{Y>;Ii{Y|VQh!&_!7dkC58aJ-pUZahes$?8s_Z@$EDo^{sHQ>#7R;X* z1bh75m+aIXr@7v$ZE&*f61s53vi&G+SnSr28jz+f_h<8K((rekfVg}IlBQ-QnJ zgPz)BMUfQ=o~yE8zAz>({R;K5gZ)hh`bbUq__#XkR%U0Q+RrMH&Ec?lCz4OhqWiy% z7ppf%1wvW`SncfCVNr;g`t0X@t5YrfMxT#Dod|9X_Sa+>?yp7)1U3Ejl4c|HQfu^W ztn11X;!E1a&pzbW?r+C^oBT85Va72qQZ7&+pa76uI-AgloI6ijqyFnFkb+@q_bX=k zV6gbAjX}%RojouV8*x5m(lub=+K>W@?*5V_jx|u_R`lvDT})3@t{)^~pPfkuJNCG# z70O*s7nl#J{fL;^UcX-4N!U_Y2bkz35ReQveI!chhv*h~030^#Q~cFaa{pT|E&L|= z6#reU^3*&jZ1^ouHL6#8MU@4jpbK!qz>WS7eDsc-Ii%ssSEi86!n2eLwfzc9(F*Gf z!(U7oZt=PahhxQV?HSxIH)}32w4cN1(R95%a_bgChe3UCUaCW3on#Nsy+)#dE*8xy z?hi}=K2n1{kAi)1J;m(mHOUl;#~SJD66w_jYv9-`R5eG!%`wy>6R;~6kg%e^Up&f; z3V*Uu$FTqFbxNCMCbfZUauy+V`8ri8MfYqm@B#*_Qz_5Ob3;nUyoMU>d7rOr1J7nQ50NlWL)o-=bnwW!TBva5a@q$eGgAYfU6=e7z31A8d!{&P;@^ z4cn}}%GH7V5TT_qNy*n|allsfyQiK!o*+<%zk#OsPV};vSJl&wguD-o((KU+my*%? zkAkmeH!yhXc`SUCR+&~DlVn$7;M6J*Pln4lOt*Fg-5b>^oJw&m)MpUtUjbeuM`*dK z$fTwI(>FX1`+12Irs?lRT@Us)oqAQIAs-q#`90VjFDwnZP28QlN!Aup^IF}N!4oeu z*43M>#{4!({hR$6xzIZf(+c|Tv+2y*+{f;UdaJwz=O4$`hQy5zoh0N}lh)_^U3Ob% z>99;vsVa(zq9V&%0wbGkIOmRzGskh+*u;-{>qgq5iB$r@o`5*PKBX3#svhK}Di_QJMCz0(rbrHoh+a=9_dwVk>3-ZZb zhr|@B%rK1H9H9|$U$YV8sSnl(o$g4)IJ67g#B7DsPzKj-k2p?0sLZcFz?4X!>fnEj%teU(uIe{Agn=zv+Q~1aL84Cju~ILX~Y93YeQ-I{~*JVrT^c^ zFvR9degI)s}0=9DQE@O?%vH+q2Rdr3GII{jxu<+*3qH^C+$-X$@~j&1jq zx{LU5nUr7t{(D!78H6&qCOzZ>UiE3cLUZxof@m|#9q>>2#Zo1*ne&q{a*A{>(h*MA z<-0Q4CqN8_46@8qYou10Xdg4Bp`5K6&dBntLF?Bpr}R+7=9unSqSSTas|fz=#dq+b zD_M?6EoaWIO?jKzM@>M1=hquS#F#B#!o`fp`DBBs%aoBeS~@NF^SKsbx^13ddt7cR zM@vF>ZjVF7pOc!DHnBGAA>?TGx35J8Mkp?3G0&2V{eHn+F_YqT(EjXyB>S1ZfO1Bz zbN9r+ts7Od^3%EA4B#x5ig#bV(M%3jlUq6|M|;nv*XT7}MrMLLdd%%Ss#%lQFSM5+ zwefFrtl7TSKlCGJSVg{jygrcs$=BnieAR{{Pj=shQX$kZ#%Tr}tm}94u}XFAX7Bid zDnT^MOH2#>DV4Dl3(k+SFH2-EN?&*TvMv|dbtOGB(Mu=7G#iVp-JvYG&Kiz+Le6Zy zIdqr0Q17&r=YGls$ZfmN`+3smUJk4;?l)IB5`)208r0Gwh|5o=gQ54rmlZX$YRl|~K|J?RUlu&atT~mm9;JED9 z*QY_}K9elKKq=E5OeeI~bTg6Csd-a?x$ZHXLim?>Ev8=pIkMg!VLep1;DdHH_!5?@ z^2wrdVkp0|R{LZh%MSg`Y%DL@XDV!p0?kgZ+1oyy@$C}CjwxU!@?Gd$mMrHg5Seo~3X$N6=s=wg)n;vwGfs^`4>__NtVoWA01z1cr*(o(H#Ax4Jx z7X#GeKS$)vO?!O{KkuvhLI(g951cGi9<|}T2D%nK>g%qNxbZG`6agV*a{KuFh6VX8_vB-YOLCuu@wv6Dh4M8CBFL-; z_DgItO+5M{lhg~+ERK|*=PalS1;xzLG5CTtI+VM2gaSkJO!O`PU#`LxlcDmE*Nx_` z=LNA#?yJ*RQh)+eZz4$!V*;0DZqCO4Tyb3sOWb{UGttw&De}}N>-zTny|o_f^Pit@ z9A!>u(pc*lGf~tPw=kzr5DM$Ikzh;BU{5@vf9bt9e4J3qL-l<}4t*%4Hzf>u%W?~Ydx42rX<*eLxyy(xC#sI|DFiqq+T+5f}E^j7>~9}|Gle- z`z=&sADO$-LTgcbw_>Ls7HdhlwuM`Fy>|e~+7QT^nJr#jQZf92SE8_iZt~o>k|K${ z>J5W=g`Df-Y6T)}rWaJS7oDcXI^NObaBk(yp=72u7|g&VyS{wu!aHbfQ^<)Jc8dU`)o~%`EHf=74@uZf)*24QIp6mH2_wV<&0WfCT5Cy-J!?G;- zms0;I8M0Ahy1=WaxB>-c-5{$3O1)GgoxQN&C${^Of=1Z2VAORYD3qIe365U>=(Xog z_xuxy9Mc6i&PcOD>|SGC$C!H1ZbH0S!5~XWL(X%gWe9d5zrYgpdv{TBYTb(kmsOFG zAA|y;4`AN*UPRK(KaEj0C8JWlTe7#@F2-(>5MO+^fvT{u^5;p3Y*zPe0}I0rBlDeL zQ^Zcf?f5rM?bF(PNVZh7&y*<+44k?p3SVAR^k*o>p4LzoR?AevxzrHixy2k@#!}S< zH|zTHbe({=m#V(z0b5@~02PNLh>U0VHpe;~%7w$)W;@2(4J(J%3wN#Sa*s;L z0v$CA@85}js8B+sAv|E$B8}KVS|?Z6_K)H}+B|xjmG`)8@s)YJP5*nmuv&mL+Iht2 zUKqSp8P1+Oy5!isM}6>oy#9>Zm@5#^AM9b>*XQC4Fhgq$C_W2CW?Z+aw=}$2!xs4* zWYm_QU!D+Xn;$Ss#DN1f9wFu-oRDJ6sIa9Bav=%7W9B$CLSViAUd_sx5s*;{tS46f zQn;JBvNf-^b&W5 z@hGLueY&^yvpY4us)a1qS^yq8M7WZ!C7c1!QPVA#5jMFkky9xUUVVM*^BMhw%L(Ar z5{|8F+n)2AYKd$qSrpyLDiUy*o_R%U(}+$Kp;uNZrO5c4Vb$MYT{@CMYg@&ehTzl&Yg5gkQvTmDCoU@8^zlV8WD6xU=b7lO#*H*=yplerWQLlnh*xP|*FJ{~ zw%jpB>{ugi#!zC5D*3Z$CkM$#63M%-fE<#Fku~1#+ZA+9j>F+JVX}w(VBPQ_{iAWi z(gs0wG3x;Dy)SJRXZOf}z!6!)GfBhj?KDJ|ZIP{(Mc{wvCVVQT!){R(M08%2Lq%7H zxe`USfX4>-5zpQ_#(Qzq;ZJ5&4WWX-BLW~n?0(6irK~RcWn{1*H;NK*L$O!W6;m@<^#J?l!5q7wst1>@=0eNkCBIWroVO{%Y=971;Kg6C2l>f&fOUg@-$k6sdTTFs6h4)(XziH0NER? z;YFUl-EH^Aa!+xWB{3Za7A_-y;V@nZ=q#WcQsDtcxU*D=iHSW`yL<;}Xmy3Z|L9Z* zv);i%T6;hjIY^Dv?q6kL4gaX;*ZuOuMMvNoBCQTjFoz<)dP9fK?(2D}F_pyUpHFNL z<3%&Ahe`mrvW7fw8beuxEcE4PFO^oJ%%MndpJQ7DsLauHzHoUs(F=KQt%AeoU-=dQ zb^sU{a2FFFuwwX8@DHrBzt!PAXLzu!*%TT0*|bvBdEtAq(|ljJ=b@>n|Bqr!rc|h? zDB*@_UEa|8AX`3LA@HG~qj z#Qn9KA|Pm~AhZkdyRDi8F^C!5jCTwLz$BXV?0s=Y>0ouH3o1@d*mhxpg2?W#FBvV5 zA`an&&oLmdn0Kk&iT463Xx<(tP%$3B;kZqUsI0H(11!;fNaHZ!r$5>uTKBD&3r-%50wj^5r|_FfjBdVU08rR=A7%v_9+ zu%(rSqK>(;iC{H(`9QE6Dr;K|4z0ZId+YsyqK5bV4k4i~TObq60vg`+!EL$rU|%k? zC%Bci{_xCps&-dfwt=D>_PW`O)#&>jJHtLF{F4(2ra%Gj$(1oIby7 z{3NtOnkeXp%4kYT<) znb0xW6y`LB+@wmrfjarOpa*Pg_tt*CW{BY?6{pBhibsP`gVNLhfk12ngD^n3)w#vq zv+e6lmUN&2WVsJt1K8U;SMRaBujz-xAodls4PeC|(_`1)^)3 z+^qU zZnI?a0=ARYVIgtEbhw2w*C9ZAXgEmfdYclLX zv*d{&Iw1{3MMb~@Z1;o*s*!v`u9gFCgBE~-0Qt44IGvOt0`T3KJLanG6E?Mb&Lf_L zw$QX^chDfs^DeF30!ltf*gBbiK79qCl>i$8G|BuS0ss$?QT>((uG{*@;2$G6wNu_+ zyg4nrlwY~j{qD-`irs~|984dD_wO&~J-LiBx8yg$zv^|@N*JqUD z7@Kb@Jo_&Of;EUuEn@}*V*FrEDhY1WSK^Ty0|FsCv&!D+7VgU2j@t6|K3yk}{>g?y z49{MJ_pY=7e@gNAN*Rc(Bl^D|rbFZaF-8ZmVSLf=W>tLx3ZAyn1kv!b$~Nq*5xU1o?EBJwaPj!(}w5ys!aq6vkT(wYv=iFrMn9|EkXPaJfTyQ*;ZY06f)esuG08zjz>W z3L#Dg%f8$$$gu(b3=n*z%>Wik^`j8IkGF$pJtdKKb#iuJb7%n{r0KPv%Y@pWmLoDm zw3POC?5)qt&AYNQ6CewV;wHO%uEb^pUFS!R7hb}6@8u}n|9KQ@zT&C}kT?qo!_s+9 zJW*#JYa{~_Dh>$b*<5cn#Jm+d&Z_=l5RWuRG=ve1IQ!3>6=y)MeSnmy19szG!d7NEHEmWDeq^d1Ymc{*4*O!Y?0UE5Ks3gJ)d$0+D? z^K?t6?@Z^Fj&>)%rk{gLvHG{g-kZnv8}xu&Pqo_{$LEJn|`oWum} zFiMV>M~TeG-gKx0q+^jiQP6TjL^hsh-8gMRM#cuOA0rPLIq{98?{QVo8*Lyfg_zQ~20GUtFWdnUdo}BLcoM6G`Au#x%5eBLm@n&1 zvqWSGQ1$4z2D=GbN_3V)_HAw@(?*H|A9;P}U_RZEHECd&z83*-K$QS~{dtfU zXNLbNYGCif4jmBLvnVc=rA{pBDEkb|-?3lcWlDHy-teG;hL)BN%=;a1`7qdoO~our zTY`uX-Y!zl{_Q0$ok`Hpk=XFEQv;m~F*$J?o{BWge@*Y+_#yyCoa$+vg2yj_XOAJ2 z&COYi0E*&J{N<&a zUIh5$6Ia2S4Onot3vVa?@mfH@-|2wIg~6B!wFf)3+ne48n{f?XdS&pBTCJcVAmYG7 z_yq_#s##0t0c!+i(v>C~2Aa_-ZT)m=V}quvKd2!ap@ z@z~$OJ2kUq-iM!mFG7?~z!C_GL;L63+=hX-OqmD~8wGP6CKfHg9YK`Py|FmtKvQHh zA~;a8s30L8{Ac~>WXabSAP^D=asvS?6g}TpKmT6nPoLikIjx7wcr$q+U-16AAq*kC))q7`X%$^><@?7TRW-rXNuw17ZJ+CFif^SWcINF=g- zqFr#Fb8pF|mcvWJhxAX=L6AG(7Zx`8W_;&h!Jff(FhedxL_EfnMAb=4(4B*J`1ip0!JcNQUP{D@- znw!}ab`vjbGgxdM&@cg119gljRS}4z$_3He5U{v93a=!<@&I#$3lb%?FpU>GC`Y5w z_VoA6+OLiPYzk@$@$xX3ey-NX2NMk;9d5(BTLgYkJpvXY7ebW5*&L0$Zs5i2={G-- zQp|Xa?IZxnJ|%9-HCc##$a;J$icprgw_vtCeXn*FOjdw6uhWXF2IFo z=;}$J%0idHd)H3Mcz=JhcHSXzCr*-zWQl0$S+~Ge)^^W2Dj9=gl#b5xSKV2}(K4dO zCi!0V`u%gTz(`Wb_^$&?Nd5c|r9WfZwemL1fbyCSx44Ec*BRL<^eKQclN@>BV*u!b zxP~+I!dg(m305#dTmk8Dv{^znbP55-`TK|8db`jvFvcHV#QsPYat!y-UVHO~KqsLo zLURSO`Ky+Wv=`)u#UPslnhxO$AR-3tk(J?3+Zo`4`;0?GKx_vDW8N0S5A8BFB=b)& z!pO3hCMf-R-ab*YJH<0!TDzAA_Hybqw9&VG^c>pwD}W~3(^H>)y$<#S$Q7ROXU1Q_ z`Y?logK-Utaraf^BRK7V33)=!>@rOB_YYG3yLab6B}^XxpD=b4-;l(XS_3dPASFmC>A@M7d*B704wl)a zLN7DRM?3><10LQ0+7iVLLYevrJD>s{0{tXqfc=O0@DWy9c;+FI)sZvg&h})^cX;m? z&4xaP>+8qoSFJXK<$@p;MA|$$bRZTA1+&e7SZ!)U&yNOfQ{gFXw6~zNMm!p9BZXrd zfB($ai^{!#98`=XrT+a_*vN^uyEp2Z3S##OaVcvk;Gpx~T|wvP_f5CO(&?W4!36D( z>5muW^zS?HJGUvwU!qp;B8-CnqNZWAF7G!`UiAdyAW%FnxcqdC#iO)9cgi@i}0FKt?Zq z9opKmUO*?M7qtt@gJ3^H{sk!rFCD+0m!4@c+_zVn(7+hv!C6s+ReH}~68d)aR01I! z5x|wQQ=Wu8Fuw-r`%}>5xr>dy9D_)_ZIIU~L>_r9e6ULpoI9_W}vSt!7PyNRro1``g1HV0Rq0Ygpgf z#8j;Y1dHwej*Bb;VPCxW{+1hV2E}Xq?OenUcS!a1CjSc6EGkZ;J~4&}r^tq}IPLBL zA02KzB(iS}^5<6+3<(522pjSL^3zk^u@?xu@pj}7i$5LY7PXJhJ5!DSlYv-`R5%Gv zzLx~K2mn(?7tIEK0}ILo!pcdai3eag!z{?oK?c{!L6iZn^MaPmFkAu@VY%b_`T&Fm zAQ)ZASEoNPSq~JZPaNRK{izK)sX_GbYw0)$;PpFzDFuPN$PJ+UKaK#d6IKet+=5~e zOb7K~p=ltXLpH#f6^DWj&DRD8DZG>KV~~U=>g;_T%rMss(F5CD&t`^cBKL z_JFJ58QdL3ZtBxHc1lRa8nSWemb5ndJ%3RHdHh>5Ah7BK6v4BK)0b}n{u_iNC9H%& z0Q!Oxdn~231qGasMz%VXhLJ-;Ii~NqQm+HD`&qunpP=HH%`xvG=l^TB%?0L|&! zM4pY(*w>{31~3=zGTH?!(F%0_3*aLbAfw=Ht~%DeF7n4W7lZmVS!lD~MT>dYWGE+s zH1u+T-NYm92*fYXvjUUns`oaAq_P_6^2?`bMjSdsK%E{FU+Y3;#B-FijM>#xp6LScSdJ2eC;^8IV6Y!=ASUTaXLDY% z+Csyher9FW3vfaw(Aj&a010GMMs*C#;IQ3Oog z49wOZlpD>1%$B>kiW@{aTv`Q5tOR>Ma8}O&P6=$GI8-9}lF%V$C?ClU^3c=eizP#j zEnKCP)?N^61Dw7}@m92YZjrTkGGxJ*Z+Y$hP7$%9oHA=hu~h*77AV+3Yf~n1Z^The z1#kWt3h7QDUtcKtU!9?K-r0f@On%G0XHechpI-@TGS#JSoDaGxpb9AkcqapJn6e;x=?Ar_ zYhM`l;UQxCW&3NHVrQ~2_Jzn#XJ#INE&Cx}P`C*4mzdjT!N9f40bO&07*BrJUyq@~ z9?H`p=JCqyr_btq$#hDrqC=a~K%Lucq5P{wQX6sVBe2Il*`yMGit-vpUi;W!D8gTG z9|b3?8oBRPp9l8d3}w}#>c=Y1fqQtzzs6d}RJ!?MXkOAZ=@bb# zZj+9N4Udxls}J7`3iclVpXwlK*jM%c>Ke#2)|H?WtA25#1;5^CNk$2(+KLF8do?wG zXgfZUJwA#n{8Ex=#VIlJQu6bq{jZyeA{H+vOV^Jf)~U%5>(qLZdQ&RiD?1mfa7DlC zZnN{})Wx;M`zae@cvAb+Rk>!zacZ=!W^@bV8`sAF5%=Y15^P}>@H;b+plD>z2**^B zXf`Jxv&PRIpQX`QVzNUT(A&p0J%$}tw-(=@dwBtSeE?MCjV6tA2{qu@7fMYAA~?Mt zu9)a1$@agddh=DCYORGKD2Mw}=-An;jPk_WB3yQ4)z@)O?y_8OkMUyxy$4-C00kYR zBcKXsfAC^}&UHkCallK-liy1oVA~eW3PRB*eowBuPOfhOWXwd0HhjLE{qWj9efs;l z%3w`!giXH2C$y?@bR%~6rjOFJ1Q;9qrbhWDlz=2m0B@L#f+FJ zr8IwbiZ0s~UbBHA&zS$Rddwoc`A&AT8QUPr{FEMllb3BIgGglMe|MDil{JVxS#?wOrkz zG@tR5%YJ>WtG^6fQ_xU<8!V>8`qb%+oW`yEh>^J#R@^zY`z&W?f47KgqQBmDD;tRq)Ruaww_;ViE{T^1UE8D=1V~x)^nEl>8EFXNQv&`vX+E7 zo^IG`poFXCY!;e(!1-4Ku_#JtC|?Ns9~DJ$0rZJ&B-fScTFd<6_SN(n14DVeEOV0+!WFp>R4B+bnrN5=Yh;R?RXs=@+ez4AM@XLagH7P zcR$x#J00WWyI9(&1TNd`R3{%PoZ1k5{!iO;sKUL{Stk9*L%<|Xu#{I*3>z@8ljoM=L`ndtWYkf1 zh71Y@hzIN0qw)~o4_#zY0=0$uAm;+0M?n1(D7T<|`>@z*fUk!+g|>vEjD)BQSC2=0 z14nx{K>4acEr`gz*WUJejGz-5)Il4LH+NDWdQ)&2B;LIsYAD?dh6GM-$A^|^ke^;85umbiAT#!y z+MxO;5NdEW|M%jen+28`H0d82Zl+3a z%((BZM*;Ug4tOTlv;CZ1b*RT7b?p@J*K_!~F1PgQkO7)ePUN2J=ZJ3jx9{eWrh8HK zI~0H0Y27%-bo8}+O}@ZG)2pBQij~sCm=JTHzuaA5LsO9$`0m&tB@Aqs-3)a?xL4u- z@k^Y+s&Okn-P5~`51HIgIkz+C`#Hid9cp{Zc$||0e0O*ZNaJ$@bZpX%{?+(er_iA- zJ5v2mzqi2V^)SQo>%sbn`Qs;m)Sa<+5>tQ};J zW$hp_bNv1DHMn+0Z1uU!ZUQPqoq!S<-{^_&Ov;~|204*wOhq@;M8Gka-@5Sa}UqF~cWyZlFUrSJ{*=n<$OOG_* z(|_bl zrvl-T5U$u`io$?Pw+;%Vit`q zGpHI0qQhNqu6I|A2 zs9df7_u);?@F!S&Rc9AKr7(n50ptu^Sq9+eCrJvCG=ROtaHpOIDbyxAJpQ}W9^5kQ zNgZ1MXZAxb@&dFI3I+haOKAnB1Qqsx z%e2iz+$@sz&-FYok!!Y~TOpTH$pMIWfggh^J|Q{)ba`9<~0e7qi@6Z9HO$Xd!owfHdfT&{{-X|}?ZPjGJ1V(d{H=ZJ5_F;1AcL24#2%S*L z<{?D~j-nVivL4eXFz8hm_u9^dm1r zbwxTcDAmt-E}8M>6q~PO_2<#}<=2{`99ig!r|Ha1Z#S85as`m@1uzee74@;;Uhb{B ziLC07NX@J9ZQ4BTr95-R)7GaOa{F*zfaExd{l=^jFB|S9HkEyj7@=1Jm*yOe!*_qW zW9341)TvjSg72c4!&E8+^52{0R1Ea)45SPuHJv*_q&9s5x;)?k^*L0lx~p4O{u52X zMO4x1ekl^QRznes6gezig9lHxPsl}^#G{XtSk)Sqh<%@0kTGnL#~qu*D6y*0hAtAC z=FhN?rg-58a%?1I0W2WDA7gT9S-v_&LN~&?W#cuarPZvfSgM8$ZYAo*&-X`4^5E7E z!OLc<{4abgLKhFLzz<`b$KNuUW7R+fTdwf+iNQNn2hUr4k!y6xD?yTOt{Pt1G2N@=spoieY zvlixRH2-;V>uK=q{e)<`VGq4~&RUrHCpaw;es#>?N=Xe2E0KRx1sl%#6m ztx3sMb&2$~GS%5VF6TG*6;WWR`E4p~c$1Rh+qqlCLjE>stDbZn*AhRglxqHNSrLx> zprAUtIxiS*St2O9@Rd-qX3BK)dp4Z~bADzq{kH=96TZQ%y<$!t*2C}}o24&BNozCf z3nO@PPZr3F7*1%zS1~!%7O3diu>E}a3=5hkY_Mp9R@t0O$P!MY&YZAog2~WldWqeh zQ_qjh+U9L4L74+$9B-W88Q<`kk9$$6F2uPaAg6A>M)RA)Gt^dcK&;sv^^aG@ysz$Z zTF`2S_om2c^IQ}qX*4V`rVqDH>wuD&`QiM{%a!Px8?4I{pit{4q@ydA$vTrU&&CMuzNhQ9cxmep^`tbwP*UreD0Xq(d z($BYN&It{o@U`?ECC8`C+K@xB>IqHs7*_4U?#K^S#a)+C-|{>*C1y+FtD75D)HgOn zg*`>KV!<@7{gFqcL^cPdd+7_jlzwvOTc_&EWE}VNaADRNPtM{M8x1|H_3HawH5@(D zbyw0kTFP?sS*rySkm+Arb${Ck759HTvE0tOj>uo=%*$sT@C)s7{+NPlMV6g<5Tt7P zJSOnBcLKvNHpsbq1{oeppKX=ZbDl`tepGo!v$~>kF{}06GA&blY@Tn+l>`l`I0Z8! z#}SLZYWP^s+mbwmKo`I6DZNguy61yzYvZ$5yLTqsnn}sFX6xj>Yrp;;CVST6^~&n2 z@2#Z-5!)7bxc#Ip#w`2p(o>o*ALE-)HQOvmi$Cy>u^afutBIg0f9bQ7Z9V4m^bd;S%l@DK?N^Q7~= zP(b{tq+d?Q +![](Bot_intellij.png) + +(you better be grateful for that picture. Spend an eternity trying to find a username) + +We can also go ahead and just call the bot api directly:
+![](Bot_curl.png) + +We get the same result. The library just handily maps it to an object for us to work with. + +So how do we find out how to do things with the library? + +## Understanding how the API is mapped in the library From 791826fb0238b8af7ccb1f6787419f59b9a38145 Mon Sep 17 00:00:00 2001 From: Chase Date: Sun, 1 Mar 2020 11:10:44 +0100 Subject: [PATCH 08/18] Add mapping section --- TelegramBots.wiki/_Sidebar.md | 1 + .../Understanding-The-Library.md | 26 +++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/TelegramBots.wiki/_Sidebar.md b/TelegramBots.wiki/_Sidebar.md index 6368e265..7698a5d4 100644 --- a/TelegramBots.wiki/_Sidebar.md +++ b/TelegramBots.wiki/_Sidebar.md @@ -4,6 +4,7 @@ * [[Using HTTP Proxy]] * [[FAQ]] * [[Handling Bot Tokens]] + * [[Understanding the Library]] * AbilityBot * [[Simple Example]] * [[Hello Ability]] diff --git a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md index 2eea9613..59e6f92f 100644 --- a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md +++ b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md @@ -1,8 +1,8 @@ # Understanding the Library -This little handy guide will not teach you how to a particular thing in the library. +This little handy guide will not teach you how to do a particular thing in the library. It will also not teach you how to create bots or anything in the liking of that. -For that take a look at the Getting Started guide +For that take a look at the [Getting Started] guide This guide will give you a general understanding on how the library function and will answer a lot of frequently asked questions. I recommend everyone who wants to work with this library more to read this guide. @@ -53,3 +53,25 @@ We get the same result. The library just handily maps it to an object for us to So how do we find out how to do things with the library? ## Understanding how the API is mapped in the library +The base for all our operations is the [telegram bot api documentations](https://core.telegram.org/bots/api) . This 220 kB monster of a website will tell us almost everything we need to know about how to use the api. + +It is split into multiple sections. We can ignore the sections *Authorizing your bot", "Making Requests" and "Getting Updates". These things are done for us by the library. + +So, let's see how we can send a poll for example. First, lets take a look at the *Available Methods*. It already gives us a bunch of send methods + +* sendMessage +* sendPhoto +* sendAudio +* sendDocument +* sendVideo +* sendAnimation +* sendVoice +* sendVideoNote +* sendMediaGroup +* sendLocation +* sendVenue +* sendContact +* sendPoll +* sendChatAction + +One of them sticks out to us. *sendPoll* looks promising, and when we take a look at the description \ No newline at end of file From 7b03a2889d0a07ef54c423aa01934ad8ff3285c8 Mon Sep 17 00:00:00 2001 From: Chase Date: Tue, 3 Mar 2020 19:20:14 +0100 Subject: [PATCH 09/18] Add poll example --- .../Understanding-The-Library.md | 46 +++++++++++++++++- .../poll_example.png | Bin 0 -> 3327 bytes .../understanding-the-library/poll_params.png | Bin 0 -> 41740 bytes 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 TelegramBots.wiki/understanding-the-library/poll_example.png create mode 100644 TelegramBots.wiki/understanding-the-library/poll_params.png diff --git a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md index 59e6f92f..4301bf0e 100644 --- a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md +++ b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md @@ -74,4 +74,48 @@ So, let's see how we can send a poll for example. First, lets take a look at the * sendPoll * sendChatAction -One of them sticks out to us. *sendPoll* looks promising, and when we take a look at the description \ No newline at end of file +One of them sticks out to us. *sendPoll* looks promising, and when we take a look at the description + +`Use this method to send a native poll. On success, the sent Message is returned` + +That looks like the thing we need. So let's see what we need to send it +![](poll_params.png) + +So as we can see, we need to set 3 things. The id of the chat we want to send it to, a question as a string and an Array of Strings. +This will result in an anonymous regular type poll without mutliselection looking like this when sent: + +![](poll_example.png) + +We can customize a bunch of other things like create quizzes, send closed polls or reply to a certain message. Now, how is this api object mapped in the library? How *do* we create a poll? + +Pretty straight forward. We take our libary, look for the "Go To Class" or "SearchClass" option and type in the name of the Method we are looking for. This will quickly yield a "SendPoll" method. + +**Every** Method, listed under *Available Methods* has such a Class. And if we go ahead and scroll down a bit we find a set of fields for the class + +```java +@JsonProperty(CHATID_FIELD) +private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername) +@JsonProperty(QUESTION_FIELD) +private String question; ///< Poll question, 1-255 characters +@JsonProperty(OPTIONS_FIELD) +private List options = new ArrayList<>(); ///< List of answer options, 2-10 strings 1-100 characters each +@JsonProperty(ISANONYMOUS_FIELD) +private Boolean isAnonymous; ///< Optional True, if the poll needs to be anonymous, defaults to True +@JsonProperty(TYPE_FIELD) +private String type; ///< Optional Poll type, “quiz” or “regular”, defaults to “regular” +@JsonProperty(ALLOWMULTIPLEANSWERS_FIELD) +private Boolean allowMultipleAnswers; ///< Optional True, if the poll allows multiple answers, ignored for polls in quiz mode, defaults to False +@JsonProperty(CORRECTOPTIONID_FIELD) +private Integer correctOptionId; ///< Optional 0-based identifier of the correct answer option, required for polls in quiz mode +@JsonProperty(ISCLOSED_FIELD) +private Boolean isClosed; ///< Optional Pass True, if the poll needs to be immediately closed +@JsonProperty(DISABLENOTIFICATION_FIELD) +private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound. +@JsonProperty(REPLYTOMESSAGEID_FIELD) +private Integer replyToMessageId; ///< Optional. If the message is a reply, ID of the original message +@JsonProperty(REPLYMARKUP_FIELD) +@JsonDeserialize() +private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard +``` + +This is a lot at first glance, but if we remember back at the table from the documentation, everything is there. We have the 3 required fields on top (chatId, question and the list of options and everything) else below \ No newline at end of file diff --git a/TelegramBots.wiki/understanding-the-library/poll_example.png b/TelegramBots.wiki/understanding-the-library/poll_example.png new file mode 100644 index 0000000000000000000000000000000000000000..6eda89c7527b9fb5961005e42aa1c1a7923d5c71 GIT binary patch literal 3327 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
  • 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 Date: Wed, 4 Mar 2020 17:21:23 +0100 Subject: [PATCH 10/18] Add last updated date --- .../understanding-the-library/Understanding-The-Library.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md index 4301bf0e..94a59003 100644 --- a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md +++ b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md @@ -1,4 +1,6 @@ # Understanding the Library +Last updated: 2020-03-04 + This little handy guide will not teach you how to do a particular thing in the library. It will also not teach you how to create bots or anything in the liking of that. From 2568822d5855f4d8a1af9d3fb6fcdd5c7193acb2 Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Wed, 4 Mar 2020 17:21:43 +0100 Subject: [PATCH 11/18] Add comments to code --- .../understanding-the-library/Understanding-The-Library.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md index 94a59003..e643a4cc 100644 --- a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md +++ b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md @@ -35,10 +35,13 @@ we can also do directly calling the library. Take this piece of code: ```java +// We initialize our bot in a separate method. See this as the initialization code from the getting started guide AbsSender ourBot = getOurBot(); +// We create the Method class. This one doesn't need any parameters to be able to be send GetMe getMe = new GetMe(); +// At last, we just need to execute the method and get the result User bot = ourBot.execute(getMe); ``` From 10ed2b5bf50c5755d325549cc8127ef54eeb926f Mon Sep 17 00:00:00 2001 From: Lukas Prediger Date: Wed, 4 Mar 2020 17:34:11 +0100 Subject: [PATCH 12/18] Finish first version --- .../Understanding-The-Library.md | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md index e643a4cc..fed7b4dd 100644 --- a/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md +++ b/TelegramBots.wiki/understanding-the-library/Understanding-The-Library.md @@ -123,4 +123,45 @@ private Integer replyToMessageId; ///< Optional. If the message is a reply, ID o private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard ``` -This is a lot at first glance, but if we remember back at the table from the documentation, everything is there. We have the 3 required fields on top (chatId, question and the list of options and everything) else below \ No newline at end of file +This is a lot at first glance, but if we remember back at the table from the documentation, everything is there. We have the 3 required fields on top (chatId, question and the list of options and everything) else below + +Let's reproduce our poll from earlier. We create the Method object and set all required fields. This particular class already allows us to set everything in a constructor, this is normally the case for required fields. All other fields can be set by using the setter method (**Attention** Calling a setter overrides the last value in a field. You can call setter multiple times on a method object, but it's normally not correct to do so) + +```java +AbsSender ourBot = getOurBot(); + +List options = new List<>(); +options.add("Yes"); +options.add("No"); + +// Let's just assume we get the chatMessage as a parameter. For example from the message received, or from a database +SendPoll ourPoll = new SendPoll(someChatId, "Some Question", options); + +ourBot.execute(ourPoll); +``` +This will send the message as expected to telegram and finally to the given chat. But what about return values? + +If we go back to the documentation and look at the description it says: +`Use this method to send a native poll. On success, the sent Message is returned` +Message links us to the Message object. An object so big that i wont be showing it's documentation in this guide. It can be found here: [Telegram Bot Api: Message Object](https://core.telegram.org/bots/api#message) + +Just the documentation tells us that it returns a Message object. How do we get that object? Easy. Execute() returns it. + +```java +Message thePollMessage = ourBot.execute(ourPoll); +``` +This again works for any method that returns a value. SendMessage, SendPhoto, SendPoll, GetMe, GetChatMember etc. + +## But what about Photos? +Some methods aren't quite as straight forward to use. Let's take a bit of time to look at methods that upload files to telegram. Namely: SendPhoto, SendAnimation, SendSticker, SendDocument, SendVideo, SendVideoNote, SendAudio and SendVoice. All of these require what telegram calls an "InputFile". This can either be a FileId of a previous send file, a url to the file on a public sever or the actual file. In the Library this is mapped using different set methods in the above classes. Currently sending by FileId, sending by java.io.File and sending by InputStream is supported. Sending by URL is not supported as of writing this guide + +### FileId +Using a fileId is pretty straight forward. The FileId is returned from telegram upon sending a File. Just set the given FileId and execute the method. Make sure that the FileId actually point to a file of the correct type + +### File +The classic approach of creating a java.io.File by Path on your hard drive or by loading a classpath resource. + +### InputStream +Sending a file by InputStream will cause the library to read the stream and then converting it into the Request. It's the same as sending a java.io.File, but more convenient some times. + +For more information on how to send Files, take a look at the [FAQ: How to send Photos](../FAQ.md). The basic concept will be the same across all Methods. From 2083b29ae5f7470a611827623a3f80e9a5dcfae4 Mon Sep 17 00:00:00 2001 From: Anton Petrov Date: Mon, 6 Apr 2020 15:29:38 +0300 Subject: [PATCH 13/18] Update wiki pages --- TelegramBots.wiki/abilities/Ability-Toggle.md | 11 +++-- TelegramBots.wiki/abilities/Bot-Testing.md | 49 ++++++++++--------- .../abilities/Database-Handling.md | 4 +- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/TelegramBots.wiki/abilities/Ability-Toggle.md b/TelegramBots.wiki/abilities/Ability-Toggle.md index 0c15864c..c792a4f3 100644 --- a/TelegramBots.wiki/abilities/Ability-Toggle.md +++ b/TelegramBots.wiki/abilities/Ability-Toggle.md @@ -9,8 +9,10 @@ The barebone toggle is used to **turn off** all the default abilities that come import org.telegram.abilitybots.api.toggle.BareboneToggle; public class YourAwesomeBot extends AbilityBot { + + private static final BareboneToggle toggle = new BareboneToggle(); + public YourAwesomeBot(String token, String username) { - BareboneToggle toggle = new BareboneToggle(); super(token, username, toggle); } @@ -25,11 +27,12 @@ The custom toggle allows you to customize or turn off the names of the abilities import org.telegram.abilitybots.api.toggle.CustomToggle; public class YourAwesomeBot extends AbilityBot { - public YourAwesomeBot(String token, String username) { - CustomToggle toggle = new CustomToggle() + + private static final CustomToggle toggle = new CustomToggle() .turnOff("ban") .toggle("promote", "upgrade"); - + + public YourAwesomeBot(String token, String username) { super(token, username, toggle); } diff --git a/TelegramBots.wiki/abilities/Bot-Testing.md b/TelegramBots.wiki/abilities/Bot-Testing.md index a226ea99..4713518d 100644 --- a/TelegramBots.wiki/abilities/Bot-Testing.md +++ b/TelegramBots.wiki/abilities/Bot-Testing.md @@ -54,21 +54,20 @@ public Ability saysHelloWorld() { The test for this ability would be: ```java -@Test + @Test public void canSayHelloWorld() { Update upd = new Update(); - // Create a new EndUser - EndUser is a class similar to Telegram User, but contains - // some utility methods like fullName() and shortName() for ease of use - EndUser endUser = EndUser.endUser(USER_ID, "Abbas", "Abou Daya", "addo37"); + // Create a new User - User is a class similar to Telegram User + User user = new User(USER_ID, "Abbas", false, "Abou Daya", "addo37", null); // This is the context that you're used to, it is the necessary conumer item for the ability - MessageContext context = MessageContext.newContext(upd, endUser, CHAT_ID); + MessageContext context = MessageContext.newContext(upd, user, CHAT_ID); // We consume a context in the lamda declaration, so we pass the context to the action logic bot.saysHelloWorld().action().accept(context); - // We verify that the sender was called only ONCE and sent Hello World to CHAT_ID - // The sender here is a mock! - Mockito.verify(sender, times(1)).send("Hello World!", CHAT_ID); + // We verify that the silent sender was called only ONCE and sent Hello World to CHAT_ID + // The silent sender here is a mock! + Mockito.verify(silent, times(1)).send("Hello World!", CHAT_ID); } ``` @@ -85,10 +84,10 @@ import org.junit.Test; import org.mockito.Mockito; import org.telegram.abilitybots.api.db.DBContext; import org.telegram.abilitybots.api.db.MapDBContext; -import org.telegram.abilitybots.api.objects.EndUser; import org.telegram.abilitybots.api.objects.MessageContext; -import org.telegram.abilitybots.api.sender.MessageSender; +import org.telegram.abilitybots.api.sender.SilentSender; import org.telegram.telegrambots.meta.api.objects.Update; +import org.telegram.telegrambots.meta.api.objects.User; import static org.mockito.Mockito.*; @@ -98,36 +97,36 @@ public class ExampleBotTest { // Your bot handle here private ExampleBot bot; - // Your sender here - private MessageSender sender; + // Your sender here. Also you can create MessageSender + private SilentSender silent; @Before public void setUp() { // Create your bot bot = new ExampleBot(); // Create a new sender as a mock - sender = mock(MessageSender.class); - // Set your bot sender to the mocked sender + silent = mock(SilentSender.class); + // Set your bot silent sender to the mocked sender // THIS is the line that prevents your bot from communicating with Telegram servers when it's running its own abilities // All method calls will go through the mocked interface -> which would do nothing except logging the fact that you've called this function with the specific arguments - bot.sender = sender; + // Create setter in your bot + bot.setSilentSender(silent); } @Test public void canSayHelloWorld() { Update upd = new Update(); - // Create a new EndUser - EndUser is a class similar to Telegram User, but contains - // some utility methods like fullName() and shortName() for ease of use - EndUser endUser = EndUser.endUser(USER_ID, "Abbas", "Abou Daya", "addo37"); + // Create a new User - User is a class similar to Telegram User + User user = new User(USER_ID, "Abbas", false, "Abou Daya", "addo37", null); // This is the context that you're used to, it is the necessary conumer item for the ability - MessageContext context = MessageContext.newContext(upd, endUser, CHAT_ID); + MessageContext context = MessageContext.newContext(upd, user, CHAT_ID); // We consume a context in the lamda declaration, so we pass the context to the action logic bot.saysHelloWorld().action().accept(context); - // We verify that the sender was called only ONCE and sent Hello World to CHAT_ID - // The sender here is a mock! - Mockito.verify(sender, times(1)).send("Hello World!", CHAT_ID); + // We verify that the silent sender was called only ONCE and sent Hello World to CHAT_ID + // The silent sender here is a mock! + Mockito.verify(silent, times(1)).send("Hello World!", CHAT_ID); } } ``` @@ -178,11 +177,13 @@ public class ExampleBotTest { private DBContext db; private MessageSender sender; -@Before + @Before public void setUp() { bot = new ExampleBot(db); sender = mock(MessageSender.class); - bot.silent = new SilentSender(sender); + SilentSender silent = new SilentSender(sender); + // Create setter in your bot + bot.setSilentSender(silent); ... } diff --git a/TelegramBots.wiki/abilities/Database-Handling.md b/TelegramBots.wiki/abilities/Database-Handling.md index 9681e739..b4a6e467 100644 --- a/TelegramBots.wiki/abilities/Database-Handling.md +++ b/TelegramBots.wiki/abilities/Database-Handling.md @@ -22,7 +22,7 @@ We'll be introducing an ability that maintains a special counter for every user. // db.getMap takes in a string, this must be unique and the same everytime you want to call the exact same map // TODO: Using integer as a key in this db map is not recommended, it won't be serialized/deserialized properly if you ever decide to recover/backup db Map countMap = db.getMap("COUNTERS"); - int userId = ctx.user().id(); + int userId = ctx.user().getId(); // Get and increment counter, put it back in the map Integer counter = countMap.compute(String.valueOf(userId), (id, count) -> count == null ? 1 : ++count); @@ -41,7 +41,7 @@ We'll be introducing an ability that maintains a special counter for every user. */ // Send formatted will enable markdown - String message = String.format("%s, your count is now *%d*!", ctx.user().shortName(), counter); + String message = String.format("%s, your count is now *%d*!", ctx.user().getUserName(), counter); silent.send(message, ctx.chatId()); }) .build(); From 43082ebeeab0f642fbbc84b1a54abeb9a017db88 Mon Sep 17 00:00:00 2001 From: Chase22 Date: Fri, 10 Apr 2020 11:08:26 +0200 Subject: [PATCH 14/18] Fix gradle string in ability example The current version is 4.7. Also the compile configuration is deprecated and was replaced by implementation. See: https://docs.gradle.org/current/userguide/java_plugin.html#tab:configurations --- TelegramBots.wiki/abilities/Simple-Example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TelegramBots.wiki/abilities/Simple-Example.md b/TelegramBots.wiki/abilities/Simple-Example.md index 3e3407c6..870b0f9d 100644 --- a/TelegramBots.wiki/abilities/Simple-Example.md +++ b/TelegramBots.wiki/abilities/Simple-Example.md @@ -14,7 +14,7 @@ As with any Java project, you will need to set your dependencies. ``` * **Gradle** ```groovy - compile group: 'org.telegram', name: 'telegrambots-abilities', version: 'permissions' + implementation group: 'org.telegram', name: 'telegrambots-abilities', version: '4.7' ``` * [JitPack](https://jitpack.io/#rubenlagus/TelegramBots) From 571d58e13f5c462dee449310909c760277476a91 Mon Sep 17 00:00:00 2001 From: rubenlagus Date: Fri, 24 Apr 2020 09:03:23 +0100 Subject: [PATCH 15/18] Update version Api 4.8 --- README.md | 8 +- TelegramBots.wiki/Changelog.md | 3 + TelegramBots.wiki/Getting-Started.md | 4 +- TelegramBots.wiki/abilities/Simple-Example.md | 2 +- pom.xml | 2 +- telegrambots-abilities/README.md | 8 +- telegrambots-abilities/pom.xml | 4 +- telegrambots-chat-session-bot/README.md | 2 +- telegrambots-chat-session-bot/pom.xml | 4 +- telegrambots-extensions/README.md | 4 +- telegrambots-extensions/pom.xml | 4 +- telegrambots-meta/pom.xml | 2 +- .../meta/api/methods/polls/SendPoll.java | 73 +++++++++++++++++-- .../meta/api/methods/send/SendDice.java | 16 ++++ .../telegrambots/meta/api/objects/Dice.java | 8 ++ .../meta/api/objects/polls/Poll.java | 41 ++++++++++- telegrambots-spring-boot-starter/pom.xml | 4 +- telegrambots/pom.xml | 4 +- 18 files changed, 160 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index df809a84..29baada6 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,16 @@ Just import add the library to your project with one of these options: org.telegram telegrambots - 4.7 + 4.8 ``` ```gradle - compile "org.telegram:telegrambots:4.7" + compile "org.telegram:telegrambots:4.8" ``` - 2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.7) - 3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.7) + 2. Using Jitpack from [here](https://jitpack.io/#rubenlagus/TelegramBots/4.8) + 3. Download the jar(including all dependencies) from [here](https://mvnrepository.com/artifact/org.telegram/telegrambots/4.8) In order to use Long Polling mode, just create your own bot extending `org.telegram.telegrambots.bots.TelegramLongPollingBot`. diff --git a/TelegramBots.wiki/Changelog.md b/TelegramBots.wiki/Changelog.md index 1a666552..2e7fd9d2 100644 --- a/TelegramBots.wiki/Changelog.md +++ b/TelegramBots.wiki/Changelog.md @@ -1,3 +1,6 @@ +### 4.8 ### +1. Update Api version [4.8](https://core.telegram.org/bots/api-changelog#april-24-2020) + ### 4.7 ### 1. Update Api version [4.7](https://core.telegram.org/bots/api-changelog#march-30-2020) diff --git a/TelegramBots.wiki/Getting-Started.md b/TelegramBots.wiki/Getting-Started.md index 9eba8666..58dbf7cc 100644 --- a/TelegramBots.wiki/Getting-Started.md +++ b/TelegramBots.wiki/Getting-Started.md @@ -11,13 +11,13 @@ First you need ot get the library and add it to your project. There are few poss org.telegram telegrambots - 4.7 + 4.8 ``` * With **Gradle**: ```groovy - compile group: 'org.telegram', name: 'telegrambots', version: '4.7' + compile group: 'org.telegram', name: 'telegrambots', version: '4.8' ``` 2. Don't like **Maven Central Repository**? It can also be taken from [Jitpack](https://jitpack.io/#rubenlagus/TelegramBots). diff --git a/TelegramBots.wiki/abilities/Simple-Example.md b/TelegramBots.wiki/abilities/Simple-Example.md index 3e3407c6..3b6d492b 100644 --- a/TelegramBots.wiki/abilities/Simple-Example.md +++ b/TelegramBots.wiki/abilities/Simple-Example.md @@ -9,7 +9,7 @@ As with any Java project, you will need to set your dependencies. org.telegram telegrambots-abilities - 4.7 + 4.8 ``` * **Gradle** diff --git a/pom.xml b/pom.xml index 593ae589..8ad6e84e 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots pom - 4.7 + 4.8 telegrambots diff --git a/telegrambots-abilities/README.md b/telegrambots-abilities/README.md index 018a1d6c..869c3b17 100644 --- a/telegrambots-abilities/README.md +++ b/telegrambots-abilities/README.md @@ -18,19 +18,19 @@ Usage org.telegram telegrambots-abilities - 4.7 + 4.8 ``` **Gradle** ```gradle - compile "org.telegram:telegrambots-abilities:4.7" + compile "org.telegram:telegrambots-abilities:4.8" ``` -**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.7) +**JitPack** - [JitPack](https://jitpack.io/#rubenlagus/TelegramBots/v4.8) -**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.7) +**Plain imports** - [Here](https://github.com/rubenlagus/TelegramBots/releases/tag/v4.8) Motivation ---------- diff --git a/telegrambots-abilities/pom.xml b/telegrambots-abilities/pom.xml index de5452d8..c5481717 100644 --- a/telegrambots-abilities/pom.xml +++ b/telegrambots-abilities/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambots-abilities @@ -84,7 +84,7 @@ org.telegram telegrambots - 4.7 + 4.8 org.apache.commons diff --git a/telegrambots-chat-session-bot/README.md b/telegrambots-chat-session-bot/README.md index c8ca3f29..200dada6 100644 --- a/telegrambots-chat-session-bot/README.md +++ b/telegrambots-chat-session-bot/README.md @@ -15,7 +15,7 @@ Usage org.telegram telegrambots-chat-session-bot - 4.7 + 4.8 ``` diff --git a/telegrambots-chat-session-bot/pom.xml b/telegrambots-chat-session-bot/pom.xml index d8ebd720..5d3f6274 100644 --- a/telegrambots-chat-session-bot/pom.xml +++ b/telegrambots-chat-session-bot/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambots-chat-session-bot @@ -84,7 +84,7 @@ org.telegram telegrambots - 4.7 + 4.8 diff --git a/telegrambots-extensions/README.md b/telegrambots-extensions/README.md index ec5e4e06..e1fdc519 100644 --- a/telegrambots-extensions/README.md +++ b/telegrambots-extensions/README.md @@ -16,12 +16,12 @@ Just import add the library to your project with one of these options: org.telegram telegrambotsextensions - 4.7 + 4.8 ``` 2. Using Gradle: ```gradle - compile "org.telegram:telegrambotsextensions:4.7" + compile "org.telegram:telegrambotsextensions:4.8" ``` \ No newline at end of file diff --git a/telegrambots-extensions/pom.xml b/telegrambots-extensions/pom.xml index 495e12e6..6f20fabf 100644 --- a/telegrambots-extensions/pom.xml +++ b/telegrambots-extensions/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambotsextensions @@ -75,7 +75,7 @@ org.telegram telegrambots - 4.7 + 4.8 diff --git a/telegrambots-meta/pom.xml b/telegrambots-meta/pom.xml index 889dbd23..c06aeda4 100644 --- a/telegrambots-meta/pom.xml +++ b/telegrambots-meta/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambots-meta diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/polls/SendPoll.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/polls/SendPoll.java index 73ccff35..8a6dd3a9 100644 --- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/polls/SendPoll.java +++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/polls/SendPoll.java @@ -39,6 +39,10 @@ public class SendPoll extends BotApiMethod { private static final String DISABLENOTIFICATION_FIELD = "disable_notification"; private static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id"; private static final String REPLYMARKUP_FIELD = "reply_markup"; + private static final String OPENPERIOD_FIELD = "open_period"; + private static final String CLOSEDATE_FIELD = "close_date"; + private static final String EXPLANATION_FIELD = "explanation"; + private static final String EXPLANATIONPARSEMODE_FIELD = "explanation_parse_mode"; /** * Unique identifier for the target chat or username of the target channel (in the format @channelusername). @@ -67,7 +71,14 @@ public class SendPoll extends BotApiMethod { @JsonProperty(REPLYMARKUP_FIELD) @JsonDeserialize() private ReplyKeyboard replyMarkup; ///< Optional. JSON-serialized object for a custom reply keyboard - + @JsonProperty(OPENPERIOD_FIELD) + private Integer openPeriod; ///< Optional. Amount of time in seconds the poll will be active after creation, 5-600. Can't be used together with close_date. + @JsonProperty(CLOSEDATE_FIELD) + private Integer closeDate; ///< Optional. Point in time (Unix timestamp) when the poll will be automatically closed. Must be at least 5 and no more than 600 seconds in the future. Can't be used together with open_period. + @JsonProperty(EXPLANATION_FIELD) + private String explanation; ///< Optional. Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters with at most 2 line feeds after entities parsing + @JsonProperty(EXPLANATIONPARSEMODE_FIELD) + private String explanationParseMode; ///< Optional. Mode for parsing entities in the explanation. See formatting options for more details. public SendPoll() { super(); @@ -196,6 +207,42 @@ public class SendPoll extends BotApiMethod { return this; } + public Integer getOpenPeriod() { + return openPeriod; + } + + public SendPoll setOpenPeriod(Integer openPeriod) { + this.openPeriod = openPeriod; + return this; + } + + public Integer getCloseDate() { + return closeDate; + } + + public SendPoll setCloseDate(Integer closeDate) { + this.closeDate = closeDate; + return this; + } + + public String getExplanation() { + return explanation; + } + + public SendPoll setExplanation(String explanation) { + this.explanation = explanation; + return this; + } + + public String getExplanationParseMode() { + return explanationParseMode; + } + + public SendPoll setExplanationParseMode(String explanationParseMode) { + this.explanationParseMode = explanationParseMode; + return this; + } + @Override public String getMethod() { return PATH; @@ -228,6 +275,15 @@ public class SendPoll extends BotApiMethod { if (options == null || options.size() < 2 || options.size() > 10) { throw new TelegramApiValidationException("Options parameter must be between 2 and 10 item", this); } + if (openPeriod != null && closeDate != null) { + throw new TelegramApiValidationException("Only one of Open Period and Close Date are allowed", this); + } + if (openPeriod != null && (openPeriod < 5 || openPeriod > 600)) { + throw new TelegramApiValidationException("Open period can only be between 5 and 600", this); + } + if (explanation != null && explanation.length() > 200) { + throw new TelegramApiValidationException("Explanation can only have up to 200 characters", this); + } if (options.parallelStream().anyMatch(x -> x.isEmpty() || x.length() > 100)) { throw new TelegramApiValidationException("Options parameter values must be between 1 and 100 chars length", this); } @@ -236,7 +292,6 @@ public class SendPoll extends BotApiMethod { } } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -252,13 +307,17 @@ public class SendPoll extends BotApiMethod { Objects.equals(isClosed, sendPoll.isClosed) && Objects.equals(disableNotification, sendPoll.disableNotification) && Objects.equals(replyToMessageId, sendPoll.replyToMessageId) && - Objects.equals(replyMarkup, sendPoll.replyMarkup); + Objects.equals(replyMarkup, sendPoll.replyMarkup) && + Objects.equals(openPeriod, sendPoll.openPeriod) && + Objects.equals(closeDate, sendPoll.closeDate) && + Objects.equals(explanation, sendPoll.explanation) && + Objects.equals(explanationParseMode, sendPoll.explanationParseMode); } @Override public int hashCode() { - return Objects.hash(chatId, question, options, isAnonymous, type, allowMultipleAnswers, correctOptionId, - isClosed, disableNotification, replyToMessageId, replyMarkup); + return Objects.hash(chatId, question, options, isAnonymous, type, allowMultipleAnswers, correctOptionId, isClosed, + disableNotification, replyToMessageId, replyMarkup, openPeriod, closeDate, explanation, explanationParseMode); } @Override @@ -275,6 +334,10 @@ public class SendPoll extends BotApiMethod { ", disableNotification=" + disableNotification + ", replyToMessageId=" + replyToMessageId + ", replyMarkup=" + replyMarkup + + ", openPeriod=" + openPeriod + + ", closeDate=" + closeDate + + ", explanation='" + explanation + '\'' + + ", explanationParseMode='" + explanationParseMode + '\'' + '}'; } } diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java index f2a391f7..24d14cf8 100644 --- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java +++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java @@ -21,12 +21,15 @@ public class SendDice extends BotApiMethod { public static final String PATH = "sendDice"; private static final String CHATID_FIELD = "chat_id"; + private static final String EMOJI_FIELD = "emoji"; private static final String DISABLENOTIFICATION_FIELD = "disable_notification"; private static final String REPLYTOMESSAGEID_FIELD = "reply_to_message_id"; private static final String REPLYMARKUP_FIELD = "reply_markup"; @JsonProperty(CHATID_FIELD) private String chatId; ///< Unique identifier for the target chat or username of the target channel (in the format @channelusername) + @JsonProperty(EMOJI_FIELD) + private String emoji; ///< Optional. Emoji on which the dice throw animation is based. Currently, must be one of “🎲” or “🎯”. Defauts to “🎲” @JsonProperty(DISABLENOTIFICATION_FIELD) private Boolean disableNotification; ///< Optional. Sends the message silently. Users will receive a notification with no sound. @JsonProperty(REPLYTOMESSAGEID_FIELD) @@ -84,6 +87,15 @@ public class SendDice extends BotApiMethod { return this; } + public String getEmoji() { + return emoji; + } + + public SendDice setEmoji(String emoji) { + this.emoji = emoji; + return this; + } + @Override public String getMethod() { return PATH; @@ -109,6 +121,9 @@ public class SendDice extends BotApiMethod { if (chatId == null) { throw new TelegramApiValidationException("ChatId parameter can't be empty", this); } + if (emoji != null && !emoji.equals("“\uD83C\uDFB2") && !emoji.equals("\uD83C\uDFAF")) { + throw new TelegramApiValidationException("Only \uD83C\uDFB2 and \uD83C\uDFAF are allowed in Emoji field ", this); + } if (replyMarkup != null) { replyMarkup.validate(); } @@ -118,6 +133,7 @@ public class SendDice extends BotApiMethod { public String toString() { return "SendDice{" + "chatId='" + chatId + '\'' + + ", emoji='" + emoji + '\'' + ", disableNotification=" + disableNotification + ", replyToMessageId=" + replyToMessageId + ", replyMarkup=" + replyMarkup + diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/Dice.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/Dice.java index 4efed1a5..2b57eb80 100644 --- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/Dice.java +++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/Dice.java @@ -11,9 +11,12 @@ import org.telegram.telegrambots.meta.api.interfaces.BotApiObject; */ public class Dice implements BotApiObject { private static final String VALUE_FIELD = "value"; + private static final String EMOJI_FIELD = "emoji"; @JsonProperty(VALUE_FIELD) private Integer value; ///< Value of the dice, 1-6 + @JsonProperty(EMOJI_FIELD) + private String emoji; ///< Emoji on which the dice throw animation is based public Dice() { super(); @@ -23,10 +26,15 @@ public class Dice implements BotApiObject { return value; } + public String getEmoji() { + return emoji; + } + @Override public String toString() { return "Dice{" + "value=" + value + + ", emoji='" + emoji + '\'' + '}'; } } diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/polls/Poll.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/polls/Poll.java index bdf3b97b..f4c62de0 100644 --- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/polls/Poll.java +++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/objects/polls/Poll.java @@ -2,6 +2,7 @@ package org.telegram.telegrambots.meta.api.objects.polls; import com.fasterxml.jackson.annotation.JsonProperty; import org.telegram.telegrambots.meta.api.interfaces.BotApiObject; +import org.telegram.telegrambots.meta.api.objects.MessageEntity; import java.util.List; import java.util.Objects; @@ -22,6 +23,10 @@ public class Poll implements BotApiObject { private static final String TYPE_FIELD = "type"; private static final String ALLOWSMULTIPLEANSWERS_FIELD = "allows_multiple_answers"; private static final String CORRECTOPTIONID_FIELD = "correct_option_id"; + private static final String OPENPERIOD_FIELD = "open_period"; + private static final String CLOSEDATE_FIELD = "close_date"; + private static final String EXPLANATION_FIELD = "explanation"; + private static final String EXPLANATIONENTITIES_FIELD = "explanation_entities"; @JsonProperty(ID_FIELD) private String id; ///< Unique poll identifier @@ -47,6 +52,14 @@ public class Poll implements BotApiObject { */ @JsonProperty(CORRECTOPTIONID_FIELD) private Integer correctOptionId; ///< True, if the poll allows multiple answers + @JsonProperty(OPENPERIOD_FIELD) + private Integer openPeriod; ///< Optional. Amount of time in seconds the poll will be active after creation + @JsonProperty(CLOSEDATE_FIELD) + private Integer closeDate; ///< Optional. Point in time (Unix timestamp) when the poll will be automatically closed + @JsonProperty(EXPLANATION_FIELD) + private String explanation; ///< Optional. Text that is shown when a user chooses an incorrect answer or taps on the lamp icon in a quiz-style poll, 0-200 characters + @JsonProperty(EXPLANATIONENTITIES_FIELD) + private List explanationEntities; ///< Optional. Special entities like usernames, URLs, bot commands, etc. that appear in the explanation public Poll() { } @@ -123,6 +136,22 @@ public class Poll implements BotApiObject { this.correctOptionId = correctOptionId; } + public Integer getOpenPeriod() { + return openPeriod; + } + + public Integer getCloseDate() { + return closeDate; + } + + public String getExplanation() { + return explanation; + } + + public List getExplanationEntities() { + return explanationEntities; + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -136,12 +165,16 @@ public class Poll implements BotApiObject { Objects.equals(isAnonymous, poll.isAnonymous) && Objects.equals(type, poll.type) && Objects.equals(allowMultipleAnswers, poll.allowMultipleAnswers) && - Objects.equals(correctOptionId, poll.correctOptionId); + Objects.equals(correctOptionId, poll.correctOptionId) && + Objects.equals(openPeriod, poll.openPeriod) && + Objects.equals(closeDate, poll.closeDate) && + Objects.equals(explanation, poll.explanation) && + Objects.equals(explanationEntities, poll.explanationEntities); } @Override public int hashCode() { - return Objects.hash(id, question, options, totalVoterCount, isClosed, isAnonymous, type, allowMultipleAnswers, correctOptionId); + return Objects.hash(id, question, options, totalVoterCount, isClosed, isAnonymous, type, allowMultipleAnswers, correctOptionId, openPeriod, closeDate, explanation, explanationEntities); } @Override @@ -156,6 +189,10 @@ public class Poll implements BotApiObject { ", type='" + type + '\'' + ", allowMultipleAnswers=" + allowMultipleAnswers + ", correctOptionId=" + correctOptionId + + ", openPeriod=" + openPeriod + + ", closeDate=" + closeDate + + ", explanation='" + explanation + '\'' + + ", explanationEntities=" + explanationEntities + '}'; } } diff --git a/telegrambots-spring-boot-starter/pom.xml b/telegrambots-spring-boot-starter/pom.xml index 46c70b31..d9bbc0ff 100644 --- a/telegrambots-spring-boot-starter/pom.xml +++ b/telegrambots-spring-boot-starter/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambots-spring-boot-starter @@ -78,7 +78,7 @@ org.telegram telegrambots - 4.7 + 4.8 org.springframework.boot diff --git a/telegrambots/pom.xml b/telegrambots/pom.xml index 045612a3..bc0d00b5 100644 --- a/telegrambots/pom.xml +++ b/telegrambots/pom.xml @@ -7,7 +7,7 @@ org.telegram Bots - 4.7 + 4.8 telegrambots @@ -95,7 +95,7 @@ org.telegram telegrambots-meta - 4.7 + 4.8 com.fasterxml.jackson.core From f351e6330730b1990ce2ea3de337eaef121a0f54 Mon Sep 17 00:00:00 2001 From: rubenlagus Date: Sun, 26 Apr 2020 00:33:15 +0100 Subject: [PATCH 16/18] Fix bug --- .../telegram/telegrambots/meta/api/methods/send/SendDice.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java index 24d14cf8..b1366ee2 100644 --- a/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java +++ b/telegrambots-meta/src/main/java/org/telegram/telegrambots/meta/api/methods/send/SendDice.java @@ -121,7 +121,7 @@ public class SendDice extends BotApiMethod { if (chatId == null) { throw new TelegramApiValidationException("ChatId parameter can't be empty", this); } - if (emoji != null && !emoji.equals("“\uD83C\uDFB2") && !emoji.equals("\uD83C\uDFAF")) { + if (emoji != null && !emoji.equals("\uD83C\uDFB2") && !emoji.equals("\uD83C\uDFAF")) { throw new TelegramApiValidationException("Only \uD83C\uDFB2 and \uD83C\uDFAF are allowed in Emoji field ", this); } if (replyMarkup != null) { From 05566742c0a1e56a02b292b7903882e450e105f9 Mon Sep 17 00:00:00 2001 From: Abbas Abou Daya Date: Sat, 25 Apr 2020 17:32:38 -0700 Subject: [PATCH 17/18] Fix handling of poll updates without user information --- .../telegram/abilitybots/api/bot/BaseAbilityBot.java | 4 ++++ .../org/telegram/abilitybots/api/objects/Flag.java | 4 ++++ .../telegram/abilitybots/api/util/AbilityUtils.java | 10 ++++++++++ 3 files changed, 18 insertions(+) diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java index a237616d..2ec9b661 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/bot/BaseAbilityBot.java @@ -465,6 +465,10 @@ public abstract class BaseAbilityBot extends DefaultAbsSender implements Ability Update addUser(Update update) { User endUser = AbilityUtils.getUser(update); + if (endUser.equals(EMPTY_USER)) { + // Can't add an empty user, return the update as is + return update; + } users().compute(endUser.getId(), (id, user) -> { if (user == null) { diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Flag.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Flag.java index 3712dc9a..9930ad7e 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Flag.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/objects/Flag.java @@ -25,6 +25,10 @@ public enum Flag implements Predicate { EDITED_MESSAGE(Update::hasEditedMessage), INLINE_QUERY(Update::hasInlineQuery), CHOSEN_INLINE_QUERY(Update::hasChosenInlineQuery), + SHIPPING_QUERY(Update::hasShippingQuery), + PRECHECKOUT_QUERY(Update::hasPreCheckoutQuery), + POLL(Update::hasPoll), + POLL_ANSWER(Update::hasPollAnswer), // Message Flags REPLY(upd -> MESSAGE.test(upd) && upd.getMessage().isReply()), diff --git a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java index ec213667..241bf141 100644 --- a/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java +++ b/telegrambots-abilities/src/main/java/org/telegram/abilitybots/api/util/AbilityUtils.java @@ -24,6 +24,8 @@ import static org.telegram.abilitybots.api.objects.Flag.*; * Helper and utility methods */ public final class AbilityUtils { + public static User EMPTY_USER = new User(); + private AbilityUtils() { } @@ -69,6 +71,14 @@ public final class AbilityUtils { return update.getEditedMessage().getFrom(); } else if (CHOSEN_INLINE_QUERY.test(update)) { return update.getChosenInlineQuery().getFrom(); + } else if (SHIPPING_QUERY.test(update)) { + return update.getShippingQuery().getFrom(); + } else if (PRECHECKOUT_QUERY.test(update)) { + return update.getPreCheckoutQuery().getFrom(); + } else if (POLL_ANSWER.test(update)) { + return update.getPollAnswer().getUser(); + } else if (POLL.test(update)) { + return EMPTY_USER; } else { throw new IllegalStateException("Could not retrieve originating user from update"); } From f84ec0b020ad6da89c86381b493f7932a0f66bc3 Mon Sep 17 00:00:00 2001 From: rubenlagus Date: Sun, 26 Apr 2020 02:11:41 +0100 Subject: [PATCH 18/18] Version 4.8.1 --- Bots.ipr | 102 +++++++++++------- README.md | 8 +- TelegramBots.wiki/Changelog.md | 6 +- TelegramBots.wiki/Getting-Started.md | 4 +- TelegramBots.wiki/abilities/Simple-Example.md | 4 +- pom.xml | 2 +- telegrambots-abilities/README.md | 8 +- telegrambots-abilities/pom.xml | 4 +- telegrambots-chat-session-bot/README.md | 2 +- telegrambots-chat-session-bot/pom.xml | 4 +- telegrambots-extensions/README.md | 4 +- telegrambots-extensions/pom.xml | 4 +- telegrambots-meta/pom.xml | 2 +- telegrambots-spring-boot-starter/pom.xml | 6 +- .../starter/TelegramBotInitializer.java | 5 + telegrambots/pom.xml | 4 +- 16 files changed, 102 insertions(+), 67 deletions(-) diff --git a/Bots.ipr b/Bots.ipr index 946ddb9d..7aff4efa 100644 --- a/Bots.ipr +++ b/Bots.ipr @@ -22,10 +22,10 @@ - - + + @@ -224,6 +224,8 @@ + + @@ -791,6 +793,30 @@