We are going to use SQLite JDBC because it's simple to set up. Download the latest .jar file and import it. We have one game so far, so we need to create a game table that holds usernames and scores.
Create game table:
String sql = "CREATE TABLE IF NOT EXISTS games ("
+ " username text NOT NULL UNIQUE,\n"
+ " guess_score INTEGER NOT NULL);";
Insert new player into game table (0 score for all games):
String sql = "INSERT INTO " + TABLE_GAME +
"(username,guess_score) VALUES(?,0)";
Increment score for player by 1:
String sql = "UPDATE " + TABLE_GAME +
" SET " + game_name + " = " + game_name + " + 1 "+
" WHERE username = ?";
Get scores for player:
String sql = "SELECT " + game_name + " "
+ "FROM " + TABLE_GAME + " WHERE username = ?";
Let's put all the SQL code together and get a working database! The basic functions we need are:
These functions will use the SQL mentioned above.
The final Database class will look like this:
Database.java
import java.sql.*;
public class Database {
private static Database db = null;
public static Database getInstance() {
if (db == null) {
db = new Database();
}
return db;
}
private final String DB_NAME = "jdbc:sqlite:database.db";
private final String TABLE_GAME = "game";
public Database() {
createDatabase();
createGameTable();
}
private void createDatabase() {
try {
DriverManager.getConnection(DB_NAME);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private void createGameTable() {
// SQL statement for creating a new table
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_GAME + "("
+ " username text NOT NULL UNIQUE,\n"
+ " guess_score INTEGER NOT NULL);";
try (Connection conn = DriverManager.getConnection(DB_NAME);
Statement stmt = conn.createStatement()) {
// create a new table
stmt.execute(sql);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private Connection connect() {
// SQLite connection string
Connection conn = null;
try {
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection(DB_NAME);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return conn;
}
// com.bit.telebot.game methods
private void createGameEntry(String username) {
String sql = "INSERT INTO " + TABLE_GAME +
"(username,guess_score) VALUES(?,0)";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.executeUpdate();
} catch (Exception e) {
//System.out.println(e.getMessage());
}
}
private void incrementScore(String username, String game_name, int val) {
// try to update the type score for the username, if not successful it means that
// that user is not in db, so add em with a 1 score for type
createGameEntry(username);
String sql = "UPDATE " + TABLE_GAME +
" SET " + game_name + " = " + game_name + " + " + val + " " +
" WHERE username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.executeUpdate();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void incrementGuessScore(String username) {
incrementScore(username, "guess_score", 1);
}
private long getScore(String username, String game_name) {
createGameEntry(username);
String sql = "SELECT " + game_name + " "
+ "FROM " + TABLE_GAME + " WHERE username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// set the value
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
// loop through the result set
if (rs.next()) {
return rs.getInt(game_name);
}
return -1;
} catch (SQLException e) {
System.out.println(e.getMessage());
return -2;
}
}
public long getGuessScore(String username) {
return getScore(username, "guess_score");
}
}
I would go through how everything works, but we want to get to the juicy section of the steak! The Database code is mostly self explanatory. If you struggle to understand how it works read this. Ok, so let's get to saving information! In the GameHandler class will call
Database.getInstance().incrementGuessScore(username);
whenever the user was correct in their guess:
GameHandler check function
// check if guess game answered correctly
else if (game.guessGame != null && message_text_lower.contains(game.guessGame.getAnswer())) {
Database.getInstance().incrementGuessScore(username);
// reset the guess game!
game.guessGame = null;
kodeCentralBot.sendMessage(Long.toString(chatId), username + " has won!");
}
Ok, so now the database will keep track of scores, but how do we see them? Let's add another command /scores which will retrieve the guess scores for that user and return a message:
GameHanlder check function
else if (message_text_lower.equals("/scores")) {
Database d = Database.getInstance();
kodeCentralBot.sendMessage(Long.toString(chatId), "Guess: " + d.getGuessScore(username));
}
Main.java
import org.telegram.telegrambots.ApiContextInitializer;
import org.telegram.telegrambots.meta.TelegramBotsApi;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
public class Main {
public static void main(String[] args) {
// Initialize Api Context
ApiContextInitializer.init();
// Instantiate Telegram Bots API
TelegramBotsApi botsApi = new TelegramBotsApi();
// Register our bot
try {
botsApi.registerBot(new KodeCentralBot());
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
}
KodeCentralBot.java
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.methods.send.SendPhoto;
import org.telegram.telegrambots.meta.api.objects.Update;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class KodeCentralBot extends TelegramLongPollingBot {
public void onUpdateReceived(Update update) {
// We check if the update has a message and the message has text
if (update.hasMessage() && update.getMessage().hasText()) {
// NEW:
GameHandler.check(this, update);
}
}
private void log(String username, String chatId, String textReceived, String botResponse) {
System.out.println("----------------------------\n");
// print out in PM/AM time
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd h:mm a");
Date date = new Date();
System.out.println(dateFormat.format(date));
System.out.println("Message from " + username + ". (id = " + chatId + ") \n Text - " + textReceived);
System.out.println("Bot answer: \n Text - " + botResponse);
}
public void sendPhoto(String chatId, String url) {
SendPhoto sendPhoto = new SendPhoto();
sendPhoto.setChatId(chatId);
sendPhoto.setPhoto(url);
try {
execute(sendPhoto);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
public void sendMessage(String chatId, String message) {
SendMessage sendMessageRequest = new SendMessage();
sendMessageRequest.setChatId(chatId);
sendMessageRequest.setText(message);
try {
execute(sendMessageRequest);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
public String getBotUsername() {
// Return bot username
// If bot username is @KodeCentralBot, it must return 'KodeCentralBot'
return "KodeCentralBot";
}
@Override
public String getBotToken() {
// Return bot token from BotFather
return "token";
}
}
GameHandler.java
import org.telegram.telegrambots.meta.api.objects.Message;
import org.telegram.telegrambots.meta.api.objects.Update;
import java.util.HashMap;
public class GameHandler {
private static class Game {
// for upcoming tutorial
private ImageGuess guessGame = null;
}
// to play separate games on separate groups
private static HashMap<Long, Game> games = new HashMap<Long, Game>();
public static void check(KodeCentralBot kodeCentralBot, Update update) {
// create a new game if this group doesn't have one already, otherwise grab from HashMap
Game game = new Game();
long chatId = update.getMessage().getChatId();
if (games.containsKey(chatId))
game = games.get(chatId);
else {
games.put(chatId, game);
}
// variables
Message message = update.getMessage();
String message_text = message.getText();
String message_text_lower = message_text.toLowerCase();
String username = message.getFrom().getUserName();
// check if starting a new guess game
if (message_text_lower.equals("/guess") || message_text_lower.equals("???? guess")) {
// only create a new guess game if there isn't one
if (game.guessGame == null) {
game.guessGame = ImageGuess.random();
}
kodeCentralBot.sendPhoto(Long.toString(chatId), game.guessGame.getUrl());
}
// check if guess game answered correctly
else if (game.guessGame != null && message_text_lower.contains(game.guessGame.getAnswer())) {
Database.getInstance().incrementGuessScore(username);
// reset the guess game!
game.guessGame = null;
kodeCentralBot.sendMessage(Long.toString(chatId), username + " has won!");
} else if (message_text_lower.equals("/scores")) {
Database d = Database.getInstance();
kodeCentralBot.sendMessage(Long.toString(chatId), "Guess: " + d.getGuessScore(username));
}
}
}
Database.java
import java.sql.*;
public class Database {
private static Database db = null;
public static Database getInstance() {
if (db == null) {
db = new Database();
}
return db;
}
private final String DB_NAME = "jdbc:sqlite:database.db";
private final String TABLE_GAME = "game";
public Database() {
createDatabase();
createGameTable();
}
private void createDatabase() {
try {
DriverManager.getConnection(DB_NAME);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private void createGameTable() {
// SQL statement for creating a new table
String sql = "CREATE TABLE IF NOT EXISTS " + TABLE_GAME + "("
+ " username text NOT NULL UNIQUE,\n"
+ " guess_score INTEGER NOT NULL);";
try (Connection conn = DriverManager.getConnection(DB_NAME);
Statement stmt = conn.createStatement()) {
// create a new table
stmt.execute(sql);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
private Connection connect() {
// SQLite connection string
Connection conn = null;
try {
Class.forName("org.sqlite.JDBC");
conn = DriverManager.getConnection(DB_NAME);
} catch (Exception e) {
System.out.println(e.getMessage());
}
return conn;
}
// com.bit.telebot.game methods
private void createGameEntry(String username) {
String sql = "INSERT INTO " + TABLE_GAME +
"(username,guess_score) VALUES(?,0)";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.executeUpdate();
} catch (Exception e) {
//System.out.println(e.getMessage());
}
}
private void incrementScore(String username, String game_name, int val) {
// try to update the type score for the username, if not successful it means that
// that user is not in db, so add em with a 1 score for type
createGameEntry(username);
String sql = "UPDATE " + TABLE_GAME +
" SET " + game_name + " = " + game_name + " + " + val + " " +
" WHERE username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, username);
pstmt.executeUpdate();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public void incrementGuessScore(String username) {
incrementScore(username, "guess_score", 1);
}
private long getScore(String username, String game_name) {
createGameEntry(username);
String sql = "SELECT " + game_name + " "
+ "FROM " + TABLE_GAME + " WHERE username = ?";
try (Connection conn = this.connect();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// set the value
pstmt.setString(1, username);
ResultSet rs = pstmt.executeQuery();
// loop through the result set
if (rs.next()) {
return rs.getInt(game_name);
}
return -1;
} catch (SQLException e) {
System.out.println(e.getMessage());
return -2;
}
}
public long getGuessScore(String username) {
return getScore(username, "guess_score");
}
}
ImageGuess.java
import java.util.ArrayList;
import java.util.Random;
class ImageGuess {
private String url;
private String answer;
public ImageGuess(String url, String answer) {
this.url = url;
this.answer = answer;
}
public String getUrl() {
return url;
}
public String getAnswer() {
return answer;
}
private static ArrayList<ImageGuess> l = new ArrayList<ImageGuess>();
private static void initList() {
l.add(new ImageGuess("https://bit.ly/2R9FiRU", "zebra"));
l.add(new ImageGuess("https://bit.ly/2RCc3Gu", "horse"));
l.add(new ImageGuess("https://bit.ly/2RxAcOD", "shark"));
// and so forth...
}
// get a random image
static ImageGuess random() {
if (l.isEmpty())
initList();
return l.get(new Random().nextInt(l.size()));
}
}
I included all files in case yours got messed up along the way.
And there you have it! Your own bot that can now keep track of games and scores! See you soon!