Do You remember the games on smartphones where You must have to guess the word wich unites four pictures? How many hours I lost in such games.

And now I want to repeat this game in Telegram. Let's start.

The first step is to plan database structure for my char bot. I decided to create the following tables:

  • Admins - table for users with administrative priveligies;
  • Users - table for ordinary users, witch connected to chat bot
  • Levels - table for game levels
  • InviteReferral - table for referral links

The image with database schema below:

I will use PHP for my chat bot script.

The script will be executed only if any user send anything to chat bot, after completing the script will be finished. The script will not keep any information between executables, so I need a field state in table Users. The script will use this field to save the current state of the game.

Let's describe the fields in the tables in my database:

Table Admins.

The table Admins contain the information about administrative users which can add and edit levels and has access to game statistic. The table has the following fields:

Field Name Comments
id Unique identificator of the record. Primary Key.
login Admin login name.
pwsd HASH of Admin password
role Admin role (it's for the future)
full_name The full name of Admin or Admin description
add_dt Date and time the Admin was added
last_logon_dt Date and time the Admin was logged in last time

Table Levels.

The table Levels contain the information about all levels in the game. The table has the following fields:

Field Name Comments
id Unique identificator of the record. Primary Key.
level Level number
image File name of the image for the level
letters Number of letters in the hidden word
answer The hidden word
hint The description of the hidden word

Table Users.

The table contain information about users which are connected to the game chat bot. The table has the following fields:

Field Name Comments
id Unique identificator of the record. Primary Key.
chat_id Unique identificator of the user's chat.
level Current user's level number.
answer Answer for the current user's level.
image Image for the current user's level.
letters Letters quantity in the hidden word for the current user's level.
state Current php script state of the user.
add_dt Date and time when the user was added to the game.
last_dt Date and time when the user was in the game last time.
msg_dt Date and time when any message was sent to the user.
hints Quantity of the hints for the user duaring the game.
wrong_answers Quantity of the wrong answers for the current level for the user.
used_hints Quantity of the used hints by user.
total_wrong_answers Quantity of all wrong answers for all passed levels for the user.
disabled The status of the user disabed or enabled.

Table InviteReferral.

The table InviteReferrals contain the invites which current users of the game chat bot can send to their friends to invite them to the game. The table has the following fields:

Field Name Comments
id Unique identificator of the record. Primary Key.
old_user_chat_id Char id of the user in the game which create invitation link.
new_user_chat_id Chat id of the user which was invited to the game.
add_dt Date and time when the invitation link was created.

 

Next, I need to create a new chat bot in Telegram with special bot named BotFather. (There are a lot of issues about it in the Internet.)

After creating a chat bot, I got a special unique bot token, like this:

6370256020:BAXZHlaEGiPAVfnfl51xFjcqG5Idlb3lgu0 - this bot token is not real.

Next, I need to read a Telegram API for chat bots, and got description for this functions:

  • sendMessage for sending message to user and show buttons in chat;
  • sendPhoto for sending image to user;

Let's write functions for this actions:

function showMessage($website, $chat_id, $message) {
// $website - it's a link to telegram website with bot token, like this: https://api.telegram.org/bot6370256020:BAXZHlaEGiPAVfnfl51xFjcqG5Idlb3lgu0
// $chat_id - it's a unic number for user's chat, I'll got it from a request to my script
// $message - a text to show for user
        $resp = array("remove_keyboard" => true);
        $reply = json_encode($resp);
        file_get_contents($website."/sendMessage?parse_mode=HTML&disable_web_page_preview=true&chat_id=".$chat_id."&text=".$message."&reply_markup=".$reply);
}
    
function showButton($website, $chat_id, $message, $button) {
// $website - it's a link to telegram website with bot token, like this: https://api.telegram.org/bot6370256020:BAXZHlaEGiPAVfnfl51xFjcqG5Idlb3lgu0
// $chat_id - it's a unic number for user's chat, I'll got it from a request to my script
// $button - a button to show for user
        $keyboard = array(array($button));
        $resp = array("keyboard" => $keyboard, "resize_keyboard" => true, "one_time_keyboard" => false);
        $reply = json_encode($resp);
        $sendto = $website."/sendmessage?parse_mode=HTML&chat_id=".$chat_id."&text=".$message."&reply_markup=".$reply;
        file_get_contents($sendto);
}
        
function showImage($website, $chat_id, $message, $image) {
// $website - it's a link to telegram website with bot token, like this: https://api.telegram.org/bot6370256020:BAXZHlaEGiPAVfnfl51xFjcqG5Idlb3lgu0
// $chat_id - it's a unic number for user's chat, I'll got it from a request to my script
// $image - an image to show for user
        $resp = array("remove_keyboard" => true);
        $reply = json_encode($resp);
        $sendto = $website."/sendphoto?parse_mode=Markdown&chat_id=".$chat_id."&photo=https://www.domain.com/oneword/images/".$image."&caption=".$message."&reply_markup=".$reply;
        file_get_contents($sendto);
}

Further, I need to parse the data JSON which is sending by Telegram while requesting my script.

Here is my code:

$botToken = "6370256020:BAXZHlaEGiPAVfnfl51xFjcqG5Idlb3lgu0";
$webSite = "https://api.telegram.org/bot".$botToken;
$content = file_get_contents("php://input");
$update = json_decode($content, TRUE);
$message = $update["message"];
$chat_id = $message["chat"]["id"];
$text = $message["text"];
$callback_query = $update["callback_query"];
$data = $callback_query["data"];
$chat_id_in = $callback_query["message"]["chat"]["id"];

And finally, the main part of my script:

// initialize variable $state
$state = 0;  

// searching user in table Users
$query = "SELECT * FROM en_Users WHERE chat_id='".$chat_id."'";
if ($chat_id == "") {
	$query = "SELECT * FROM en_Users WHERE chat_id='".$chat_id_in."'";
}
	
$result = mysqli_query($link, $query);
$num = mysqli_num_rows($result);

if ($num == 1) {
// if user exist in the table, this part of the script will be execited
	$f = mysqli_fetch_array($result);
	$state = $f['state'];
	$user_id = $f['user_id'];
	$level = $f['level'];
		
	if (!strcasecmp($text, 'Next')) {
		$query = "SELECT * FROM en_Levels WHERE level = ".$level;
		$result = mysqli_query($link, $query);
		$num = mysqli_num_rows($result);
		if ($num > 0) {
			$f2 = mysqli_fetch_array($result);
			$query = "UPDATE en_Users SET answer='".$f2['answer']."', image='".$f2['image']."', letters=".$f2['letters']." WHERE chat_id='".$chat_id."'";
			mysqli_query($link, $query);
			$query = "SELECT * FROM en_Users WHERE chat_id='".$chat_id."'";
			$result = mysqli_query($link, $query);
			$f = mysqli_fetch_array($result);
			$state = $f['state'];
			$user_id = $f['user_id'];
			$level = $f['level'];
			$state = 0;
		}
	}
		
	if (!strcasecmp($text, 'Get hint')) {
		if ($f['hints'] > 0) {
			$state = 2;
		} else {
			$str = "Unfortunately, you have used up all the hints.".PHP_EOL."You can get more hints by inviting your friends into the game using the link https://t.me/ENOneWordGamebot?start=".$chat_id;
			showMessage($webSite, $chat_id, $str);
		}
	}
		
	if (!strcasecmp($text, '/help')) {
		$str = "Good day, Dear Player!".PHP_EOL;
		$str = $str."The game 'One Word' is an association game. You got 4 pictures and you must guess the word that combines these pictures.".PHP_EOL;
		$str = $str."You also have tips. The maximum number of hints is 10. After 3 incorrect versions of the hidden word, you will be offered the opportunity to take a hint. ";
		$str = $str."The first hint will reveal the first and last letter of the intended word. The second hint will give a description of the intended word.";
		$str = $str."If all 10 hints are spent, they can be restored by sending a link to the game. You will receive a link to invite other players after exhausting all 10 hints.";
		showMessage($webSite, $chat_id, urlencode($str));
		$state = 0;
	}
		
	if (!strcasecmp($text, '/about')) {
		$str = "Good day, Dear Player!".PHP_EOL;
		$str = $str."You can send your wishes and suggestions for improving the game to This email address is being protected from spambots. You need JavaScript enabled to view it..".PHP_EOL;
		$str = $str."We are also considering proposals for cooperation.";
		showMessage($webSite, $chat_id, urlencode($str));
		$state = 0;
	}
		
	if (!strcasecmp($text, '/invite')) {
		$str = "To invite a friend to join the game, simply send him this link:".PHP_EOL;
		$str = $str."https://t.me/ENOneWordGamebot?start=".$chat_id.PHP_EOL;
		$str = $str."When your friend start the game, you will have 10 hints again.";
		showMessage($webSite, $chat_id, urlencode($str));
		$state = 0;
	}
		
	if (!strcasecmp($text, '/disable')) {
		$query = "UPDATE en_Users SET Disabled=1 WHERE chat_id='".$chat_id."'";
		mysqli_query($link, $query);
		$str = "Notifications are turned off.".PHP_EOL."To enable notifications, enter the command /enable";
		showMessage($webSite, $chat_id, urlencode($str));
		$state = 0;
	}
		
	if (!strcasecmp($text, '/enable')) {
		$query = "UPDATE en_Users SET Disabled=0 WHERE chat_id='".$chat_id."'";
		mysqli_query($link, $query);
		$str = "Notifications are turned on.".PHP_EOL;
		showMessage($webSite, $chat_id, urlencode($str));
		$state = 0;
	}
		
	if (!strcasecmp($text, '/gethint')) {
		$url = requestURL($chat_id);
		$message_id = showAdvertising($webSite, $chat_id, "Watch the advertising to restore 10 hints.", "Watch ad", $url);
		$query = "UPDATE en_Users SET message_id='".$message_id."' WHERE chat_id='".$chat_id."'";
		mysqli_query($link, $query);
	}
		
	if (!strcasecmp($text, '/hint')) {
		if ($f['hints'] > 0) {
			$str = "You have ".($f['hints']-1)." ";
			switch ($f['hints']) {
				case 1:
					$str = $str."hint.";
					break;
				default:
					$str = $str."hints.";
			}
			showMessage($webSite, $chat_id, $str);
			$state = 2;
		} else {
			$str = urlencode("Unfortunately, you have used up all the hints.".PHP_EOL."You can get more hints by inviting your friends into the game using the link https://t.me/ENOneWordGamebot?start=".$chat_id);
			showMessage($webSite, $chat_id, $str);
		}
	}
	switch($state) {
		case 0:
			$query = "SELECT * FROM en_Levels WHERE level=".$level;
			$result = mysqli_query($link, $query);
			$num = mysqli_num_rows($result);
			if ($num>0) {
				$f1 = mysqli_fetch_array($result);
				showMessage($webSite, $chat_id, "Level ".$level.".");
				showImage($webSite, $chat_id, 'This word has '.$f1['letters'].' letters', $f1['image']);
				$query = "UPDATE en_Users SET answer='".$f1['answer']."', image='".$f1['image']."', letters=".$f1['letters']." WHERE chat_id='".$chat_id."'";
				mysqli_query($link, $query);
				$state = 1;
			} else {
				showButton($webSite, $chat_id, urlencode("Congratulations! You have completed all existing levels!".PHP_EOL."But new levels will appear soon.".PHP_EOL."Press 'Next' button for check new levels."), "Next");
			}
			break;
		case 1:
			$input = trim($text);
			$input = mb_strtolower($input, 'UTF-8');
			if (!strcasecmp($input, $f['answer'])) {
				showMessage($webSite, $chat_id, urlencode("You absolutely correctly guessed the hidden word!"));
				$query = "UPDATE en_Users SET level=level+1, wrong_answers=0, used_hints=0 WHERE chat_id='".$chat_id."'";
				mysqli_query($link, $query);
				$level=$level+1;
				$query = "SELECT * FROM en_Levels WHERE level=".$level;
				$result = mysqli_query($link, $query);
				$num = mysqli_num_rows($result);
				if ($num > 0) {
					$f1 = mysqli_fetch_array($result);
					showMessage($webSite, $chat_id, "Level ".$level.".");
					showImage($webSite, $chat_id, 'This word has '.$f1['letters'].' letters', $f1['image']);
					$query = "UPDATE en_Users SET answer='".$f1['answer']."', image='".$f1['image']."', letters=".$f1['letters']." WHERE chat_id='".$chat_id."'";
					mysqli_query($link, $query);
				} else {
					showButton($webSite, $chat_id, urlencode("Congratulations! You have completed all existing levels!".PHP_EOL."But new levels will appear soon.".PHP_EOL."Press 'Next' button for check new levels."), "Next");
				}
			} else {
				$query = "SELECT COUNT(*) FROM en_Levels";
				$result = mysqli_query($link, $query);
				$maxlevel = mysqli_result($result, 0);
				if ($level<=$maxlevel) {
					showMessage($webSite, $chat_id, "Another word was guessed. Try again.");
					$query = "UPDATE en_Users SET wrong_answers=wrong_answers+1, total_wrong_answers=total_wrong_answers+1 WHERE chat_id='".$chat_id."'";
					mysqli_query($link, $query);
					showImage($webSite, $chat_id, 'This word has '.$f['letters'].' letters.', $f['image']);
					if ($f['wrong_answers'] >= 3) {
						if ($f['hints'] > 0) {
							switch ($f['hints']) {
								case 1:
									$str_hints = "hint.";
									break;
								default:
									$str_hints = "hints.";
							}
							showButton($webSite, $chat_id, "You has ".$f['hints']." ".$str_hints." You can use them.", "Get hint");
						} else {
							$str = urlencode("Unfortunately, you have used up all the hints.".PHP_EOL."You can get more hints by inviting your friends into the game using the link https://t.me/ENOneWordGamebot?start=".$chat_id);
							showMessage($webSite, $chat_id, $str);
						}
					}
				} else {
					showButton($webSite, $chat_id, urlencode("Congratulations! You have completed all existing levels!".PHP_EOL."But new levels will appear soon.".PHP_EOL."Press 'Next' button for check new levels."), "Next");
				}
			}
			break;
		case 2:
			$used_hints = $f['used_hints'];
			$used_hints = $used_hints + 1;
			if ($used_hints == 1) {
				$str_first_letter = mb_substr($f['answer'], 0, 1, 'UTF-8');
				$str_last_letter = mb_substr($f['answer'], -1, 1, 'UTF-8');
				$str_midle_letters = "";
				for($i=0;$i < $f['letters']-2;$i++) {
					$str_midle_letters = $str_midle_letters."* ";
				}
				$str_hint = $str_first_letter." ".$str_midle_letters.$str_last_letter;
				showMessage($webSite, $chat_id, $str_hint);
				$query = "UPDATE en_Users SET hints = hints-1, used_hints=".$used_hints." WHERE chat_id='".$chat_id."'";
				mysqli_query($link, $query);
			} else if ($used_hints == 2) {
				$str_first_letter = mb_substr($f['answer'], 0, 1, 'UTF-8');
				$str_last_letter = mb_substr($f['answer'], -1, 1, 'UTF-8');
				$str_midle_letters = "";
				for($i=0;$i < $f['letters']-2;$i++) {
					$str_midle_letters = $str_midle_letters."* ";
				}
				$str_hint = $str_first_letter." ".$str_midle_letters.$str_last_letter.PHP_EOL;
				$query = "SELECT * FROM en_Levels WHERE level=".$f['level'];
				$result3 = mysqli_query($link, $query);
				$f3 = mysqli_fetch_array($result3);
				$str_hint = $str_hint.$f3['hint'];
				showMessage($webSite, $chat_id, urlencode($str_hint));
				$query = "UPDATE en_Users SET hints = hints-1, used_hints=".$used_hints." WHERE chat_id='".$chat_id."'";
				mysqli_query($link, $query);
			} else {
				showMessage($webSite, $chat_id, "I don’t even know what else I can suggest here...");
			}
			$state = 1;
			break;
		default:
			$state = 1;
			break;
	}
} else {
// if user does not exist in the table Users, the user will be added into the table
	$cmd = substr($text, 0, 6);
	$options = trim(substr($text, 6));
		
	if (strlen($options) > 0) {
		$query = "SELECT * FROM en_Users WHERE chat_id ='".$options."'";
		$result = mysqli_query($link, $query);
		$num = mysqli_num_rows($result);
		if ($num == 1) {
			$query = "UPDATE en_Users SET hints=10 WHERE chat_id='".$options."'";
			mysqli_query($link, $query);
			showMessage($webSite, $options, "A user has start the game at your invitation. Thank you! You have 10 hints again.");
			$refdate = date("Y-m-d H:i:s"); 
			$query = "INSERT INTO en_InviteReferral (old_user_chat_id, new_user_chat_id, add_dt) VALUES ('".$options."', '".$chat_id."', '".$refdate."')";
			mysqli_query($link, $query);
		}
	}
		
	if (!strnatcasecmp ($cmd, "/start")) {
		$level = 1;
		$adddate = date("Y-m-d H:i:s");  
		$query = "INSERT INTO en_Users (chat_id, add_dt) VALUES ('".$chat_id."', '".$adddate."')";
		mysqli_query($link, $query);
		$str = "Welcome!".PHP_EOL;
		$str = $str."You have connected to the chat game 'One Word'.".PHP_EOL;
		$str = $str."The rules are very simple - 4 pictures will be displayed and you will need to find a word that combines all these pictures.".PHP_EOL;
		$str = $str."Good luck in the game!";
		showMessage($webSite, $chat_id, urlencode($str));
			
		$query = "SELECT * FROM en_Levels WHERE level=".$level;
		$result = mysqli_query($link, $query);
		$f1 = mysqli_fetch_array($result);
		showMessage($webSite, $chat_id, "Level ".$level.".");
		showImage($webSite, $chat_id, 'This word has '.$f1['letters'].' letters', $f1['image']);
		$query = "UPDATE en_Users SET answer='".$f1['answer']."', image='".$f1['image']."', letters=".$f1['letters']." WHERE chat_id='".$chat_id."'";
		mysqli_query($link, $query);
		$state = 1;
	}	
}
	
$date = date("Y-m-d H:i:s");
$query = "UPDATE en_Users SET state=".$state.", last_dt='".$date."' WHERE chat_id='".$chat_id."'";
$result = mysqli_query($link, $query);

The file structure of my game is:

/ -- root folder
    image/ -- folder for level images
    bot.php - file with the main script
    dbconnect.php - file with parameters for connecting to datebase

The actual version on the script is here.

The MySQL scripts for creating database You can get here.

Some screenshots from my game:

And the last one the link to my game in telegram. I'll be glad to see You in my game!

If You have any questions or suggestions to mage this gam better, please send me a message.