diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index bf61796bd..dae218ea8 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -1688,7 +1688,7 @@ void ApiWrap::applyLastParticipantsList(
 					user,
 					MegagroupInfo::Restricted{ restrictedRights });
 			}
-			if (user->botInfo) {
+			if (user->isBot()) {
 				channel->mgInfo->bots.insert(user);
 				if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) {
 					channel->mgInfo->botStatus = 2;
@@ -1736,7 +1736,7 @@ void ApiWrap::applyBotsList(
 		}
 
 		auto user = _session->data().user(userId);
-		if (user->botInfo) {
+		if (user->isBot()) {
 			channel->mgInfo->bots.insert(user);
 			botStatus = 2;// (botStatus > 0/* || !i.key()->botInfo->readsAllHistory*/) ? 2 : 1;
 			if (!user->botInfo->inited) {
@@ -3983,9 +3983,7 @@ void ApiWrap::addChatParticipants(
 			}).afterDelay(crl::time(5)).send();
 		}
 	} else if (const auto channel = peer->asChannel()) {
-		const auto bot = ranges::find_if(users, [](not_null<UserData*> user) {
-			return user->botInfo != nullptr;
-		});
+		const auto bot = ranges::find_if(users, &UserData::isBot);
 		if (!peer->isMegagroup() && bot != end(users)) {
 			ShowAddParticipantsError("USER_BOT", peer, users);
 			return;
@@ -5028,7 +5026,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
 }
 
 void ApiWrap::sendBotStart(not_null<UserData*> bot, PeerData *chat) {
-	Expects(bot->botInfo != nullptr);
+	Expects(bot->isBot());
 	Expects(chat == nullptr || !bot->botInfo->startGroupToken.isEmpty());
 
 	if (chat && chat->isChannel() && !chat->isMegagroup()) {
diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp
index 6072abffa..bb2210096 100644
--- a/Telegram/SourceFiles/boxes/add_contact_box.cpp
+++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp
@@ -83,7 +83,7 @@ void ShowAddParticipantsError(
 	if (error == qstr("USER_BOT")) {
 		const auto channel = chat->asChannel();
 		if ((users.size() == 1)
-			&& (users.front()->botInfo != nullptr)
+			&& users.front()->isBot()
 			&& channel
 			&& !channel->isMegagroup()
 			&& channel->canAddAdmins()) {
@@ -117,9 +117,7 @@ void ShowAddParticipantsError(
 			return;
 		}
 	}
-	const auto bot = ranges::find_if(users, [](not_null<UserData*> user) {
-		return user->botInfo != nullptr;
-	});
+	const auto bot = ranges::find_if(users, &UserData::isBot);
 	const auto hasBot = (bot != end(users));
 	const auto text = [&] {
 		if (error == qstr("USER_BOT")) {
diff --git a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
index 6aee81a4d..40b7d0a29 100644
--- a/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
+++ b/Telegram/SourceFiles/boxes/peer_list_controllers.cpp
@@ -58,10 +58,10 @@ void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
 }
 
 void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
-	if (bot->botInfo && !bot->botInfo->startGroupToken.isEmpty()) {
-		Auth().api().sendBotStart(bot, chat);
+	if (bot->isBot() && !bot->botInfo->startGroupToken.isEmpty()) {
+		chat->session().api().sendBotStart(bot, chat);
 	} else {
-		Auth().api().addChatParticipants(chat, { 1, bot });
+		chat->session().api().addChatParticipants(chat, { 1, bot });
 	}
 	Ui::hideLayer();
 	Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
@@ -474,7 +474,7 @@ bool AddBotToGroupBoxController::needToCreateRow(
 }
 
 bool AddBotToGroupBoxController::SharingBotGame(not_null<UserData*> bot) {
-	auto &info = bot->botInfo;
+	const auto &info = bot->botInfo;
 	return (info && !info->shareGameShortName.isEmpty());
 }
 
diff --git a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
index abe56d344..9c440cf42 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_participant_box.cpp
@@ -196,8 +196,8 @@ void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
 		st::rightsPhotoMargin.top() + st::rightsNameTop,
 		namew,
 		width());
-	auto statusText = [this] {
-		if (_user->botInfo) {
+	const auto statusText = [&] {
+		if (_user->isBot()) {
 			const auto seesAllMessages = _user->botInfo->readsAllHistory
 				|| _hasAdminRights;
 			return (seesAllMessages
@@ -205,14 +205,14 @@ void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
 				: tr::lng_status_bot_not_reads_all)(tr::now);
 		}
 		return Data::OnlineText(_user->onlineTill, base::unixtime::now());
-	};
+	}();
 	p.setFont(st::contactsStatusFont);
 	p.setPen(st::contactsStatusFg);
 	p.drawTextLeft(
 		namex,
 		st::rightsPhotoMargin.top() + st::rightsStatusTop,
 		width(),
-		statusText());
+		statusText);
 }
 
 EditParticipantBox::EditParticipantBox(
diff --git a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp
index 84af36b0f..a41d87c9e 100644
--- a/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp
+++ b/Telegram/SourceFiles/chat_helpers/bot_keyboard.cpp
@@ -159,7 +159,7 @@ bool BotKeyboard::moderateKeyActivate(int key) {
 				}
 			} else if (key == Qt::Key_Q) {
 				if (const auto user = item->history()->peer->asUser()) {
-					if (user->botInfo && item->from() == user) {
+					if (user->isBot() && item->from() == user) {
 						App::sendBotCommand(user, user, qsl("/translate"));
 						return true;
 					}
diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
index eebbb1ff0..a1478dd88 100644
--- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
+++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
@@ -298,36 +298,42 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
 		int32 cnt = 0;
 		if (_chat) {
 			if (_chat->noParticipantInfo()) {
-				Auth().api().requestFullPeer(_chat);
+				_chat->session().api().requestFullPeer(_chat);
 			} else if (!_chat->participants.empty()) {
 				for (const auto user : _chat->participants) {
-					if (!user->botInfo) continue;
-					if (!user->botInfo->inited) {
-						Auth().api().requestFullPeer(user);
+					if (!user->isBot()) {
+						continue;
+					} else if (!user->botInfo->inited) {
+						user->session().api().requestFullPeer(user);
+					}
+					if (user->botInfo->commands.isEmpty()) {
+						continue;
 					}
-					if (user->botInfo->commands.isEmpty()) continue;
 					bots.insert(user, true);
 					cnt += user->botInfo->commands.size();
 				}
 			}
-		} else if (_user && _user->botInfo) {
+		} else if (_user && _user->isBot()) {
 			if (!_user->botInfo->inited) {
-				Auth().api().requestFullPeer(_user);
+				_user->session().api().requestFullPeer(_user);
 			}
 			cnt = _user->botInfo->commands.size();
 			bots.insert(_user, true);
 		} else if (_channel && _channel->isMegagroup()) {
 			if (_channel->mgInfo->bots.empty()) {
 				if (!_channel->mgInfo->botStatus) {
-					Auth().api().requestBots(_channel);
+					_channel->session().api().requestBots(_channel);
 				}
 			} else {
-				for_const (auto user, _channel->mgInfo->bots) {
-					if (!user->botInfo) continue;
-					if (!user->botInfo->inited) {
-						Auth().api().requestFullPeer(user);
+				for (const auto user : _channel->mgInfo->bots) {
+					if (!user->isBot()) {
+						continue;
+					} else if (!user->botInfo->inited) {
+						user->session().api().requestFullPeer(user);
+					}
+					if (user->botInfo->commands.isEmpty()) {
+						continue;
 					}
-					if (user->botInfo->commands.isEmpty()) continue;
 					bots.insert(user, true);
 					cnt += user->botInfo->commands.size();
 				}
@@ -338,12 +344,16 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
 			int32 botStatus = _chat ? _chat->botStatus : ((_channel && _channel->isMegagroup()) ? _channel->mgInfo->botStatus : -1);
 			if (_chat) {
 				for (const auto &user : _chat->lastAuthors) {
-					if (!user->botInfo) continue;
-					if (!bots.contains(user)) continue;
-					if (!user->botInfo->inited) {
-						Auth().api().requestFullPeer(user);
+					if (!user->isBot()) {
+						continue;
+					} else if (!bots.contains(user)) {
+						continue;
+					} else if (!user->botInfo->inited) {
+						user->session().api().requestFullPeer(user);
+					}
+					if (user->botInfo->commands.isEmpty()) {
+						continue;
 					}
-					if (user->botInfo->commands.isEmpty()) continue;
 					bots.remove(user);
 					for (auto j = 0, l = user->botInfo->commands.size(); j != l; ++j) {
 						if (!listAllSuggestions) {
diff --git a/Telegram/SourceFiles/chat_helpers/message_field.cpp b/Telegram/SourceFiles/chat_helpers/message_field.cpp
index a4f9428db..37d944ec8 100644
--- a/Telegram/SourceFiles/chat_helpers/message_field.cpp
+++ b/Telegram/SourceFiles/chat_helpers/message_field.cpp
@@ -445,8 +445,9 @@ InlineBotQuery ParseInlineBotQuery(not_null<const Ui::InputField*> field) {
 			if (result.lookingUpBot) {
 				result.query = QString();
 				return result;
-			} else if (result.bot && (!result.bot->botInfo
-				|| result.bot->botInfo->inlinePlaceholder.isEmpty())) {
+			} else if (result.bot
+				&& (!result.bot->isBot()
+					|| result.bot->botInfo->inlinePlaceholder.isEmpty())) {
 				result.bot = nullptr;
 			} else {
 				result.query = inlineUsernameEqualsText
diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp
index c93ee8af3..4247ee52b 100644
--- a/Telegram/SourceFiles/data/data_channel.cpp
+++ b/Telegram/SourceFiles/data/data_channel.cpp
@@ -200,7 +200,7 @@ void ChannelData::applyEditAdmin(
 		if (!base::contains(mgInfo->lastParticipants, user)) {
 			mgInfo->lastParticipants.push_front(user);
 			setMembersCount(membersCount() + 1);
-			if (user->botInfo && !mgInfo->bots.contains(user)) {
+			if (user->isBot() && !mgInfo->bots.contains(user)) {
 				mgInfo->bots.insert(user);
 				if (mgInfo->botStatus != 0 && mgInfo->botStatus < 2) {
 					mgInfo->botStatus = 2;
@@ -242,7 +242,7 @@ void ChannelData::applyEditAdmin(
 		if (adminsCount() > 1) {
 			setAdminsCount(adminsCount() - 1);
 		}
-		if (!isMegagroup() && user->botInfo && membersCount() > 1) {
+		if (!isMegagroup() && user->isBot() && membersCount() > 1) {
 			// Removing bot admin removes it from channel.
 			setMembersCount(membersCount() - 1);
 		}
diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp
index 4b3dbfa2c..143ba1332 100644
--- a/Telegram/SourceFiles/data/data_chat.cpp
+++ b/Telegram/SourceFiles/data/data_chat.cpp
@@ -266,7 +266,7 @@ void ApplyChatUpdate(
 				history->clearLastKeyboard();
 			}
 		}
-		if (chat->botStatus > 0 && user->botInfo) {
+		if (chat->botStatus > 0 && user->isBot()) {
 			chat->refreshBotStatus();
 		}
 	}
diff --git a/Telegram/SourceFiles/data/data_peer_values.cpp b/Telegram/SourceFiles/data/data_peer_values.cpp
index 9fb8cfc30..cdf1e8ead 100644
--- a/Telegram/SourceFiles/data/data_peer_values.cpp
+++ b/Telegram/SourceFiles/data/data_peer_values.cpp
@@ -286,7 +286,7 @@ crl::time OnlineChangeTimeout(TimeId online, TimeId now) {
 }
 
 crl::time OnlineChangeTimeout(not_null<UserData*> user, TimeId now) {
-	if (user->isServiceUser() || user->botInfo) {
+	if (user->isServiceUser() || user->isBot()) {
 		return kMaxOnlineChangeTimeout;
 	}
 	return OnlineChangeTimeout(user->onlineTill, now);
@@ -361,7 +361,7 @@ bool OnlineTextActive(TimeId online, TimeId now) {
 }
 
 bool OnlineTextActive(not_null<UserData*> user, TimeId now) {
-	if (user->isServiceUser() || user->botInfo) {
+	if (user->isServiceUser() || user->isBot()) {
 		return false;
 	}
 	return OnlineTextActive(user->onlineTill, now);
diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp
index e7e5d2ed5..61c7caf5d 100644
--- a/Telegram/SourceFiles/data/data_session.cpp
+++ b/Telegram/SourceFiles/data/data_session.cpp
@@ -74,7 +74,7 @@ void CheckForSwitchInlineButton(not_null<HistoryItem*> item) {
 		return;
 	}
 	if (const auto user = item->history()->peer->asUser()) {
-		if (!user->botInfo || !user->botInfo->inlineReturnPeerId) {
+		if (!user->isBot() || !user->botInfo->inlineReturnPeerId) {
 			return;
 		}
 		if (const auto markup = item->Get<HistoryMessageReplyMarkup>()) {
@@ -2898,7 +2898,7 @@ void Session::applyUpdate(const MTPDupdateChatParticipants &update) {
 	if (const auto chat = chatLoaded(chatId)) {
 		ApplyChatUpdate(chat, update);
 		for (const auto user : chat->participants) {
-			if (user->botInfo && !user->botInfo->inited) {
+			if (user->isBot() && !user->botInfo->inited) {
 				_session->api().requestFullPeer(user);
 			}
 		}
diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp
index 4377b738a..685e037e9 100644
--- a/Telegram/SourceFiles/data/data_user.cpp
+++ b/Telegram/SourceFiles/data/data_user.cpp
@@ -152,8 +152,10 @@ void UserData::setBotInfoVersion(int version) {
 void UserData::setBotInfo(const MTPBotInfo &info) {
 	switch (info.type()) {
 	case mtpc_botInfo: {
-		const auto &d(info.c_botInfo());
-		if (peerFromUser(d.vuser_id().v) != id || !botInfo) return;
+		const auto &d = info.c_botInfo();
+		if (peerFromUser(d.vuser_id().v) != id || !isBot()) {
+			return;
+		}
 
 		QString desc = qs(d.vdescription());
 		if (botInfo->description != desc) {
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
index 2a417e3ef..fc61c0633 100644
--- a/Telegram/SourceFiles/facades.cpp
+++ b/Telegram/SourceFiles/facades.cpp
@@ -128,7 +128,7 @@ void activateBotCommand(
 					if (samePeer) {
 						Notify::switchInlineBotButtonReceived(QString::fromUtf8(button->data), bot, msgId);
 						return true;
-					} else if (bot->botInfo && bot->botInfo->inlineReturnPeerId) {
+					} else if (bot->isBot() && bot->botInfo->inlineReturnPeerId) {
 						if (Notify::switchInlineBotButtonReceived(QString::fromUtf8(button->data))) {
 							return true;
 						}
diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp
index 0c9b02f0b..d952f413d 100644
--- a/Telegram/SourceFiles/history/history.cpp
+++ b/Telegram/SourceFiles/history/history.cpp
@@ -70,7 +70,7 @@ History::History(not_null<Data::Session*> owner, PeerId peerId)
 , _mute(owner->notifyIsMuted(peer))
 , _sendActionText(st::dialogsTextWidthMin) {
 	if (const auto user = peer->asUser()) {
-		if (user->botInfo) {
+		if (user->isBot()) {
 			_outboxReadBefore = std::numeric_limits<MsgId>::max();
 		}
 	}
@@ -908,7 +908,7 @@ not_null<HistoryItem*> History::addNewItem(
 				return nullptr;
 			};
 			if (auto megagroup = peer->asMegagroup()) {
-				if (user->botInfo) {
+				if (user->isBot()) {
 					auto mgInfo = megagroup->mgInfo.get();
 					Assert(mgInfo != nullptr);
 					mgInfo->bots.insert(user);
@@ -1025,7 +1025,7 @@ void History::applyServiceChanges(
 						Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
 						owner().addNewMegagroupParticipant(megagroup, user);
 					}
-					if (user->botInfo) {
+					if (user->isBot()) {
 						peer->asChannel()->mgInfo->bots.insert(user);
 						if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
 							peer->asChannel()->mgInfo->botStatus = 2;
@@ -1047,7 +1047,7 @@ void History::applyServiceChanges(
 					Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
 					owner().addNewMegagroupParticipant(megagroup, user);
 				}
-				if (user->botInfo) {
+				if (user->isBot()) {
 					mgInfo->bots.insert(user);
 					if (mgInfo->botStatus != 0 && mgInfo->botStatus < 2) {
 						mgInfo->botStatus = 2;
diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp
index e8109eb89..fa5cc7949 100644
--- a/Telegram/SourceFiles/history/history_item.cpp
+++ b/Telegram/SourceFiles/history/history_item.cpp
@@ -371,7 +371,7 @@ UserData *HistoryItem::getMessageBot() const {
 	if (!bot) {
 		bot = history()->peer->asUser();
 	}
-	return (bot && bot->botInfo) ? bot : nullptr;
+	return (bot && bot->isBot()) ? bot : nullptr;
 };
 
 void HistoryItem::destroy() {
@@ -571,7 +571,7 @@ bool HistoryItem::suggestReport() const {
 	} else if (const auto channel = history()->peer->asChannel()) {
 		return true;
 	} else if (const auto user = history()->peer->asUser()) {
-		return user->botInfo != nullptr;
+		return user->isBot();
 	}
 	return false;
 }
@@ -699,7 +699,7 @@ bool HistoryItem::unread() const {
 				return false;
 			}
 			if (const auto user = history()->peer->asUser()) {
-				if (user->botInfo) {
+				if (user->isBot()) {
 					return false;
 				}
 			} else if (const auto channel = history()->peer->asChannel()) {
diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp
index 01c6676ab..e64ff69ec 100644
--- a/Telegram/SourceFiles/history/history_message.cpp
+++ b/Telegram/SourceFiles/history/history_message.cpp
@@ -264,7 +264,7 @@ MTPDmessage::Flags NewMessageFlags(not_null<PeerData*> peer) {
 	MTPDmessage::Flags result = MTPDmessage_ClientFlag::f_sending | 0;
 	if (!peer->isSelf()) {
 		result |= MTPDmessage::Flag::f_out;
-		//if (p->isChat() || (p->isUser() && !p->asUser()->botInfo)) {
+		//if (p->isChat() || (p->isUser() && !p->asUser()->isBot())) {
 		//	result |= MTPDmessage::Flag::f_unread;
 		//}
 	}
diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp
index 85afb53e1..109502d6a 100644
--- a/Telegram/SourceFiles/history/history_widget.cpp
+++ b/Telegram/SourceFiles/history/history_widget.cpp
@@ -1372,7 +1372,7 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U
 			return true;
 		}
 	} else if (auto bot = _peer ? _peer->asUser() : nullptr) {
-		const auto toPeerId = bot->botInfo
+		const auto toPeerId = bot->isBot()
 			? bot->botInfo->inlineReturnPeerId
 			: PeerId(0);
 		if (!toPeerId) {
@@ -2874,7 +2874,7 @@ void HistoryWidget::unblockUser() {
 void HistoryWidget::sendBotStartCommand() {
 	if (!_peer
 		|| !_peer->isUser()
-		|| !_peer->asUser()->botInfo
+		|| !_peer->asUser()->isBot()
 		|| !_canSendMessages) {
 		updateControlsVisibility();
 		return;
@@ -3233,7 +3233,7 @@ void HistoryWidget::sendBotCommand(PeerData *peer, UserData *bot, const QString
 	bool lastKeyboardUsed = (_keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard->forMsgId() == FullMsgId(_channel, replyTo));
 
 	QString toSend = cmd;
-	if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) {
+	if (bot && (!bot->isUser() || !bot->asUser()->isBot())) {
 		bot = nullptr;
 	}
 	QString username = bot ? bot->asUser()->username : QString();
@@ -3386,7 +3386,7 @@ bool HistoryWidget::insertBotCommand(const QString &cmd) {
 			: (App::hoveredLinkItem()
 				? App::hoveredLinkItem()->data()->fromOriginal().get()
 				: nullptr);
-		if (bot && (!bot->isUser() || !bot->asUser()->botInfo)) {
+		if (bot && (!bot->isUser() || !bot->asUser()->isBot())) {
 			bot = nullptr;
 		}
 		auto username = bot ? bot->asUser()->username : QString();
@@ -3501,7 +3501,7 @@ void HistoryWidget::inlineBotResolveDone(
 //	Notify::inlineBotRequesting(false);
 	const auto resolvedBot = [&]() -> UserData* {
 		if (const auto result = session().data().processUsers(data.vusers())) {
-			if (result->botInfo
+			if (result->isBot()
 				&& !result->botInfo->inlinePlaceholder.isEmpty()) {
 				return result;
 			}
@@ -3534,7 +3534,7 @@ bool HistoryWidget::inlineBotResolveFail(QString name, const RPCError &error) {
 bool HistoryWidget::isBotStart() const {
 	const auto user = _peer ? _peer->asUser() : nullptr;
 	if (!user
-		|| !user->botInfo
+		|| !user->isBot()
 		|| !_canSendMessages) {
 		return false;
 	} else if (!user->botInfo->startToken.isEmpty()) {
@@ -3600,7 +3600,7 @@ void HistoryWidget::updateSendButtonType() {
 
 bool HistoryWidget::updateCmdStartShown() {
 	bool cmdStartShown = false;
-	if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isMegagroup() && _peer->asChannel()->mgInfo->botStatus > 0) || (_peer->isUser() && _peer->asUser()->botInfo))) {
+	if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isMegagroup() && _peer->asChannel()->mgInfo->botStatus > 0) || (_peer->isUser() && _peer->asUser()->isBot()))) {
 		if (!isBotStart() && !isBlocked() && !_keyboard->hasMarkup() && !_keyboard->forceReply()) {
 			if (!HasSendText(_field)) {
 				cmdStartShown = true;
@@ -3956,7 +3956,7 @@ void HistoryWidget::onCheckFieldAutocomplete() {
 			Local::readRecentHashtagsAndBots();
 		} else if (autocomplete.query[0] == '/'
 			&& _peer->isUser()
-			&& !_peer->asUser()->botInfo) {
+			&& !_peer->asUser()->isBot()) {
 			return;
 		}
 	}
diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp
index 2bd7e8dd7..baa9112e9 100644
--- a/Telegram/SourceFiles/history/view/history_view_message.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_message.cpp
@@ -1417,7 +1417,7 @@ bool Message::displayFastShare() const {
 				&& forwarded->originalSender
 				&& forwarded->originalSender->isChannel()
 				&& !forwarded->originalSender->isMegagroup();
-		} else if (user->botInfo && !item->out()) {
+		} else if (user->isBot() && !item->out()) {
 			if (const auto media = this->media()) {
 				return media->allowsFastShare();
 			}
@@ -1835,7 +1835,7 @@ TimeId Message::displayedEditDate(
 	if (hasViaBotOrInlineMarkup) {
 		return TimeId(0);
 	} else if (const auto fromUser = message()->from()->asUser()) {
-		if (fromUser->botInfo) {
+		if (fromUser->isBot()) {
 			return TimeId(0);
 		}
 	}
diff --git a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp
index e212ff22c..0c14bff01 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_actions.cpp
+++ b/Telegram/SourceFiles/info/profile/info_profile_actions.cpp
@@ -261,7 +261,7 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
 			tr::lng_info_mobile_label(),
 			PhoneOrHiddenValue(user),
 			tr::lng_profile_copy_phone(tr::now));
-		if (user->botInfo) {
+		if (user->isBot()) {
 			addInfoLine(tr::lng_info_about_label(), AboutValue(user));
 		} else {
 			addInfoLine(tr::lng_info_bio_label(), BioValue(user));
@@ -535,7 +535,7 @@ void ActionsFiller::addDeleteConversationAction(
 
 void ActionsFiller::addBotCommandActions(not_null<UserData*> user) {
 	auto findBotCommand = [user](const QString &command) {
-		if (!user->botInfo) {
+		if (!user->isBot()) {
 			return QString();
 		}
 		for_const (auto &data, user->botInfo->commands) {
@@ -616,7 +616,7 @@ void ActionsFiller::addBlockAction(not_null<UserData*> user) {
 	auto callback = [=] {
 		if (user->isBlocked()) {
 			Window::PeerMenuUnblockUserWithBotRestart(user);
-			if (user->botInfo) {
+			if (user->isBot()) {
 				Ui::showPeerHistory(user, ShowAtUnreadMsgId);
 			}
 		} else if (user->isBot()) {
@@ -667,7 +667,7 @@ void ActionsFiller::addJoinChannelAction(
 }
 
 void ActionsFiller::fillUserActions(not_null<UserData*> user) {
-	if (user->botInfo) {
+	if (user->isBot()) {
 		addInviteToGroupAction(user);
 	}
 	addShareContactAction(user);
diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp
index a158004c9..987946e5b 100644
--- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp
+++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp
@@ -98,7 +98,7 @@ rpl::producer<TextWithEntities> UsernameValue(not_null<UserData*> user) {
 
 rpl::producer<QString> PlainAboutValue(not_null<PeerData*> peer) {
 	if (const auto user = peer->asUser()) {
-		if (!user->botInfo) {
+		if (!user->isBot()) {
 			return rpl::single(QString());
 		}
 	}
diff --git a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp
index 939e54275..7f25fc6b1 100644
--- a/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp
+++ b/Telegram/SourceFiles/inline_bots/inline_results_widget.cpp
@@ -732,7 +732,7 @@ void Inner::updateInlineItems() {
 }
 
 void Inner::onSwitchPm() {
-	if (_inlineBot && _inlineBot->botInfo) {
+	if (_inlineBot && _inlineBot->isBot()) {
 		_inlineBot->botInfo->startToken = _switchPmStartToken;
 		Ui::showPeerHistory(_inlineBot, ShowAndStartBotMsgId);
 	}
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index e9f2e8909..33a2a12ca 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -3243,7 +3243,7 @@ void MainWidget::openPeerByName(
 
 	if (const auto peer = session().data().peerByUsername(username)) {
 		if (msgId == ShowAtGameShareMsgId) {
-			if (peer->isUser() && peer->asUser()->botInfo && !startToken.isEmpty()) {
+			if (peer->isUser() && peer->asUser()->isBot() && !startToken.isEmpty()) {
 				peer->asUser()->botInfo->shareGameShortName = startToken;
 				AddBotToGroupBoxController::Start(peer->asUser());
 			} else {
@@ -3254,10 +3254,10 @@ void MainWidget::openPeerByName(
 				});
 			}
 		} else if (msgId == ShowAtProfileMsgId && !peer->isChannel()) {
-			if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
+			if (peer->isUser() && peer->asUser()->isBot() && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
 				peer->asUser()->botInfo->startGroupToken = startToken;
 				AddBotToGroupBoxController::Start(peer->asUser());
-			} else if (peer->isUser() && peer->asUser()->botInfo) {
+			} else if (peer->isUser() && peer->asUser()->isBot()) {
 				// Always open bot chats, even from mention links.
 				InvokeQueued(this, [this, peer] {
 					_controller->showPeerHistory(
@@ -3271,7 +3271,7 @@ void MainWidget::openPeerByName(
 			if (msgId == ShowAtProfileMsgId || !peer->isChannel()) { // show specific posts only in channels / supergroups
 				msgId = ShowAtUnreadMsgId;
 			}
-			if (peer->isUser() && peer->asUser()->botInfo) {
+			if (peer->isUser() && peer->asUser()->isBot()) {
 				peer->asUser()->botInfo->startToken = startToken;
 				if (peer == _history->peer()) {
 					_history->updateControlsVisibility();
@@ -3316,10 +3316,10 @@ void MainWidget::usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, c
 	MsgId msgId = msgIdAndStartToken.first;
 	QString startToken = msgIdAndStartToken.second;
 	if (msgId == ShowAtProfileMsgId && !peer->isChannel()) {
-		if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
+		if (peer->isUser() && peer->asUser()->isBot() && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) {
 			peer->asUser()->botInfo->startGroupToken = startToken;
 			AddBotToGroupBoxController::Start(peer->asUser());
-		} else if (peer->isUser() && peer->asUser()->botInfo) {
+		} else if (peer->isUser() && peer->asUser()->isBot()) {
 			// Always open bot chats, even from mention links.
 			InvokeQueued(this, [this, peer] {
 				_controller->showPeerHistory(
@@ -3333,7 +3333,7 @@ void MainWidget::usernameResolveDone(QPair<MsgId, QString> msgIdAndStartToken, c
 		if (msgId == ShowAtProfileMsgId || !peer->isChannel()) { // show specific posts only in channels / supergroups
 			msgId = ShowAtUnreadMsgId;
 		}
-		if (peer->isUser() && peer->asUser()->botInfo) {
+		if (peer->isUser() && peer->asUser()->isBot()) {
 			peer->asUser()->botInfo->startToken = startToken;
 			if (peer == _history->peer()) {
 				_history->updateControlsVisibility();
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index 60365dea9..9d0bdab0e 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -1608,7 +1608,7 @@ void OverlayWidget::refreshCaption(HistoryItem *item) {
 	}
 	const auto asBot = [&] {
 		if (const auto author = item->author()->asUser()) {
-			return author->botInfo != nullptr;
+			return author->isBot();
 		}
 		return false;
 	}();
diff --git a/Telegram/SourceFiles/profile/profile_block_group_members.cpp b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
index e503d4d11..a884eb7c3 100644
--- a/Telegram/SourceFiles/profile/profile_block_group_members.cpp
+++ b/Telegram/SourceFiles/profile/profile_block_group_members.cpp
@@ -132,7 +132,8 @@ void GroupMembersWidget::refreshUserOnline(UserData *user) {
 	_now = base::unixtime::now();
 
 	auto member = getMember(it.value());
-	member->statusHasOnlineColor = !user->botInfo && Data::OnlineTextActive(user->onlineTill, _now);
+	member->statusHasOnlineColor = !user->isBot()
+		&& Data::OnlineTextActive(user->onlineTill, _now);
 	member->onlineTill = user->onlineTill;
 	member->onlineForSort = user->isSelf()
 		? std::numeric_limits<TimeId>::max()
@@ -159,7 +160,7 @@ void GroupMembersWidget::updateItemStatusText(Item *item) {
 	auto member = getMember(item);
 	auto user = member->user();
 	if (member->statusText.isEmpty() || (member->onlineTextTill <= _now)) {
-		if (user->botInfo) {
+		if (user->isBot()) {
 			auto seesAllMessages = (user->botInfo->readsAllHistory || (member->adminState != Item::AdminState::None));
 			member->statusText = seesAllMessages
 				? tr::lng_status_bot_reads_all(tr::now)
@@ -229,7 +230,7 @@ void GroupMembersWidget::updateOnlineCount() {
 	for_const (auto item, items()) {
 		auto member = getMember(item);
 		auto user = member->user();
-		auto isOnline = !user->botInfo && Data::OnlineTextActive(member->onlineTill, _now);
+		auto isOnline = !user->isBot() && Data::OnlineTextActive(member->onlineTill, _now);
 		if (member->statusHasOnlineColor != isOnline) {
 			member->statusHasOnlineColor = isOnline;
 			member->statusText = QString();
@@ -391,7 +392,7 @@ void GroupMembersWidget::setItemFlags(
 		item->adminState = adminState;
 		auto user = item->peer->asUser();
 		Assert(user != nullptr);
-		if (user->botInfo) {
+		if (user->isBot()) {
 			// Update "has access to messages" status.
 			item->statusText = QString();
 			updateItemStatusText(item);
@@ -412,7 +413,7 @@ auto GroupMembersWidget::computeMember(not_null<UserData*> user)
 	if (it == _membersByUser.cend()) {
 		auto member = new Member(user);
 		it = _membersByUser.insert(user, member);
-		member->statusHasOnlineColor = !user->botInfo
+		member->statusHasOnlineColor = !user->isBot()
 			&& Data::OnlineTextActive(user->onlineTill, _now);
 		member->onlineTill = user->onlineTill;
 		member->onlineForSort = Data::SortByOnlineValue(user, _now);
@@ -434,7 +435,7 @@ void GroupMembersWidget::onUpdateOnlineDisplay() {
 				}
 			}
 			auto member = getMember(item);
-			bool isOnline = !member->user()->botInfo
+			bool isOnline = !member->user()->isBot()
 				&& Data::OnlineTextActive(member->onlineTill, _now);
 			if (!isOnline) {
 				changed = true;
diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp
index 8bbec1835..7a3c1c3b0 100644
--- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp
+++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp
@@ -293,7 +293,7 @@ std::unique_ptr<PeerListRow> BlockedBoxController::createRow(
 			return App::formatPhone(user->phone());
 		} else if (!user->username.isEmpty()) {
 			return '@' + user->username;
-		} else if (user->botInfo) {
+		} else if (user->isBot()) {
 			return tr::lng_status_bot(tr::now);
 		}
 		return tr::lng_blocked_list_unknown_phone(tr::now);
diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp
index 9699d5d75..9d00f3c76 100644
--- a/Telegram/SourceFiles/storage/localstorage.cpp
+++ b/Telegram/SourceFiles/storage/localstorage.cpp
@@ -4540,7 +4540,7 @@ void readRecentHashtagsAndBots() {
 				if (!peer) {
 					return; // Broken data.
 				} else if (peer->isUser()
-					&& peer->asUser()->botInfo
+					&& peer->asUser()->isBot()
 					&& !peer->asUser()->botInfo->inlinePlaceholder.isEmpty()
 					&& !peer->asUser()->username.isEmpty()) {
 					bots.push_back(peer->asUser());
diff --git a/Telegram/SourceFiles/storage/serialize_common.cpp b/Telegram/SourceFiles/storage/serialize_common.cpp
index c08650d15..b349d75a5 100644
--- a/Telegram/SourceFiles/storage/serialize_common.cpp
+++ b/Telegram/SourceFiles/storage/serialize_common.cpp
@@ -123,7 +123,7 @@ void writePeer(QDataStream &stream, PeerData *peer) {
 			stream << qint32(user->flags());
 		}
 		if (AppVersion >= 9016) {
-			const auto botInlinePlaceholder = user->botInfo
+			const auto botInlinePlaceholder = user->isBot()
 				? user->botInfo->inlinePlaceholder
 				: QString();
 			stream << botInlinePlaceholder;
@@ -131,7 +131,7 @@ void writePeer(QDataStream &stream, PeerData *peer) {
 		stream
 			<< qint32(user->onlineTill)
 			<< qint32(user->isContact() ? 1 : 0)
-			<< qint32(user->botInfo ? user->botInfo->version : -1);
+			<< qint32(user->isBot() ? user->botInfo->version : -1);
 	} else if (const auto chat = peer->asChat()) {
 		stream
 			<< chat->name
@@ -203,7 +203,7 @@ PeerData *readPeer(int streamAppVersion, QDataStream &stream) {
 			user->onlineTill = onlineTill;
 			user->setIsContact(contact == 1);
 			user->setBotInfoVersion(botInfoVersion);
-			if (!inlinePlaceholder.isEmpty() && user->botInfo) {
+			if (!inlinePlaceholder.isEmpty() && user->isBot()) {
 				user->botInfo->inlinePlaceholder = inlinePlaceholder;
 			}
 
diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp
index 718fa78ea..894a20e11 100644
--- a/Telegram/SourceFiles/support/support_helper.cpp
+++ b/Telegram/SourceFiles/support/support_helper.cpp
@@ -168,7 +168,7 @@ Data::Draft OccupiedDraft(const QString &normalizedName) {
 	if (!history) {
 		return false;
 	} else if (const auto user = history->peer->asUser()) {
-		return !user->botInfo;
+		return !user->isBot();
 	}
 	return false;
 }
diff --git a/Telegram/SourceFiles/ui/text_options.cpp b/Telegram/SourceFiles/ui/text_options.cpp
index 03da7556f..3d7c3414d 100644
--- a/Telegram/SourceFiles/ui/text_options.cpp
+++ b/Telegram/SourceFiles/ui/text_options.cpp
@@ -140,7 +140,7 @@ bool UseBotTextOptions(
 		not_null<History*> history,
 		not_null<PeerData*> author) {
 	if (const auto user = history->peer->asUser()) {
-		if (user->botInfo) {
+		if (user->isBot()) {
 			return true;
 		}
 	} else if (const auto chat = history->peer->asChat()) {
@@ -153,7 +153,7 @@ bool UseBotTextOptions(
 		}
 	}
 	if (const auto user = author->asUser()) {
-		if (user->botInfo) {
+		if (user->isBot()) {
 			return true;
 		}
 	}