Enhanced Java telegram bots runner built on top of the Telegram Bots library.
- I want separate projects per bots.
- I want to easily switch between long polling and webhook methods without recompiling the application.
- I want to easily disable bots without recompiling the application.
- I want yaml configs to store bot tokens and other data.
- I want different profiles for configs.
- I want command system with roles support.
- I want localization support.
@tgbotsmodulebot (source code)
-
Add gradle dependency:
implementation 'com.annimon:tgbots-module:7.10.0'
-
Or if you don't want to use webhooks:
implementation ('com.annimon:tgbots-module:7.10.0') { exclude group: 'org.telegram', module: 'telegrambots-webhook' }
-
Implement
BotModule
interface:public class TestBot implements BotModule { @Override public BotHandler botHandler(Config config) { return new TestBotHandler(); } }
-
[Optional] Add main method to run single project:
public class TestBot implements BotModule { public static void main(String[] args) { final var profile = (args.length >= 1) ? args[0] : ""; Runner.run(profile, List.of(new TestBot())); } // ... }
-
[Optional] Add yaml configuration support:
import lombok.Data; import com.fasterxml.jackson.annotation.JsonProperty; import javax.validation.constraints.NotBlank; @Data public class BotConfig { @NotBlank @JsonProperty(required = true) private String token; @NotBlank @JsonProperty(required = true) private String username; }
testbot.yaml
token: 123456789:ABCDEFGHIJKLM_NOPQRSTUVWXYZ01234567 username: bot
public class TestBot implements BotModule { // ... @Override public BotHandler botHandler(Config config) { final var configLoader = new YamlConfigLoaderService(); final var configFile = configLoader.configFile("testbot", config.getProfile()); final var botConfig = configLoader.loadFile(configFile, BotConfig.class); final var botModuleOptions = BotModuleOptions.createDefault(botConfig.getToken()); return new TestBotHandler(botModuleOptions, botConfig); } }
-
Fill in
config.yaml
(See Webhooks examples):log-level: FINE webhook: enabled: false port: env(PORT:8443) externalUrl: https://123.45.67.890:$port internalUrl: http://0.0.0.0:$port keystorePath: cert/keystore.jks keystorePassword: env(KEYSTORE_PASSWORD) modules: - com.annimon.testbot.TestBot
-
Happy bots developing:
public class TestBotHandler extends BotHandler { private final BotConfig botConfig; public TestBotHandler(BotModuleOptions botModuleOptions, BotConfig botConfig) { super(botModuleOptions); this.botConfig = botConfig; } @Override public BotApiMethod<?> onUpdate(@NotNull Update update) { // your code here return null; } }
Now you can easily switch between webhook and long polling methods by changing the webhook:
enabled
flag in config,yaml
.
Or you can create config-test.yaml
and run the test
profile:
java -cp tgbots-module.jar:testbot.jar:yourfavoritebot.jar com.annimon.telegrambots.Runner test
Heroku starts on a random port, you can get a value from the environment property PORT
:
webhook:
enabled: true
port: env(PORT)
externalUrl: https://yourappname.herokuapp.com
internalUrl: http://0.0.0.0:$port
Use certgen.sh
to generate a certificate (replace SERVERIPADDRESS
with the server's IP address):
JKS=keystore.jks
CERT=public_cert.pem
openssl req -newkey rsa:2048 -sha256 -nodes \
-keyout private.key -x509 \
-days 365 \
-out $CERT \
-subj "/C=US/ST=Utah/L=Location/O=Organization/CN=SERVERIPADDRESS"
openssl pkcs12 -export \
-in $CERT \
-inkey private.key \
-certfile $CERT \
-out keystore.p12
keytool -importkeystore \
-srckeystore keystore.p12 \
-srcstoretype pkcs12 \
-sigalg SHA1withRSA \
-destkeystore $JKS \
-deststoretype pkcs12
rm keystore.p12 private.key
The keystore password will be asked several times during the generation of the certificate. Don't forget to export
it:
export KEYSTORE_PASSWORD=mysupersecretpasswordis123456
Specify generated keystore.jks
and public_cert.pem
paths and your SERVERIPADDRESS
in config.yaml
:
webhook:
enabled: true
port: 8443
externalUrl: https://SERVERIPADDRESS:$port
internalUrl: http://0.0.0.0:$port
keystorePath: cert/keystore.jks
keystorePassword: env(KEYSTORE_PASSWORD)
certificatePublicKeyPath: cert/public_cert.pem